167 lines
6.1 KiB
Python
167 lines
6.1 KiB
Python
from flask_socketio import emit, join_room, leave_room
|
|
from flask import request
|
|
import time
|
|
import json
|
|
|
|
class WebSocketHandler:
|
|
def __init__(self, socketio, user_manager):
|
|
self.socketio = socketio
|
|
self.user_manager = user_manager
|
|
self.active_calls = {} # 正在进行的语音通话
|
|
self.setup_handlers()
|
|
|
|
def setup_handlers(self):
|
|
@self.socketio.on('connect')
|
|
def handle_connect(auth=None):
|
|
print(f'Client connected: {request.sid}')
|
|
|
|
@self.socketio.on('disconnect')
|
|
def handle_disconnect():
|
|
account = None
|
|
# 找到断开连接的用户
|
|
for acc, user in self.user_manager.users.items():
|
|
if user.get('socket_id') == request.sid:
|
|
account = acc
|
|
break
|
|
|
|
if account:
|
|
self.user_manager.update_user_status(account, online=False)
|
|
|
|
# 通知好友用户离线
|
|
emit('user_status', {
|
|
'account': account,
|
|
'online': False
|
|
}, broadcast=True)
|
|
|
|
@self.socketio.on('authenticate')
|
|
def handle_authenticate(data):
|
|
account = data.get('account')
|
|
if account in self.user_manager.users:
|
|
self.user_manager.update_user_status(
|
|
account,
|
|
online=True,
|
|
socket_id=request.sid
|
|
)
|
|
|
|
# 通知所有用户此用户上线
|
|
emit('user_status', {
|
|
'account': account,
|
|
'online': True
|
|
}, broadcast=True)
|
|
|
|
@self.socketio.on('private_message')
|
|
def handle_private_message(data):
|
|
to_account = data.get('to')
|
|
message = data.get('message')
|
|
from_account = data.get('from')
|
|
|
|
# 获取接收者的socket_id
|
|
recipient = self.user_manager.get_user(to_account)
|
|
if recipient and recipient.get('socket_id'):
|
|
emit('private_message', {
|
|
'from': from_account,
|
|
'message': message,
|
|
'timestamp': time.time()
|
|
}, room=recipient['socket_id'])
|
|
|
|
# 同时发送给自己(用于确认)
|
|
emit('private_message_sent', {
|
|
'to': to_account,
|
|
'message': message,
|
|
'timestamp': time.time()
|
|
})
|
|
|
|
@self.socketio.on('group_message')
|
|
def handle_group_message(data):
|
|
group_id = data.get('group_id')
|
|
message = data.get('message')
|
|
from_account = data.get('from')
|
|
|
|
emit('group_message', {
|
|
'group_id': group_id,
|
|
'from': from_account,
|
|
'message': message,
|
|
'timestamp': time.time()
|
|
}, room=group_id)
|
|
|
|
@self.socketio.on('join_group')
|
|
def handle_join_group(data):
|
|
group_id = data.get('group_id')
|
|
join_room(group_id)
|
|
|
|
@self.socketio.on('leave_group')
|
|
def handle_leave_group(data):
|
|
group_id = data.get('group_id')
|
|
leave_room(group_id)
|
|
|
|
@self.socketio.on('start_call')
|
|
def handle_start_call(data):
|
|
"""开始语音通话"""
|
|
to_account = data.get('to')
|
|
from_account = data.get('from')
|
|
call_id = data.get('call_id')
|
|
|
|
self.active_calls[call_id] = {
|
|
'participants': [from_account, to_account],
|
|
'start_time': time.time()
|
|
}
|
|
|
|
# 通知对方
|
|
recipient = self.user_manager.get_user(to_account)
|
|
if recipient and recipient.get('socket_id'):
|
|
emit('incoming_call', {
|
|
'from': from_account,
|
|
'call_id': call_id
|
|
}, room=recipient['socket_id'])
|
|
|
|
@self.socketio.on('answer_call')
|
|
def handle_answer_call(data):
|
|
"""接听电话"""
|
|
call_id = data.get('call_id')
|
|
if call_id in self.active_calls:
|
|
emit('call_accepted', {
|
|
'call_id': call_id
|
|
}, room=request.sid)
|
|
|
|
@self.socketio.on('end_call')
|
|
def handle_end_call(data):
|
|
"""结束通话"""
|
|
call_id = data.get('call_id')
|
|
if call_id in self.active_calls:
|
|
# 通知所有参与者
|
|
for participant in self.active_calls[call_id]['participants']:
|
|
user = self.user_manager.get_user(participant)
|
|
if user and user.get('socket_id'):
|
|
emit('call_ended', {
|
|
'call_id': call_id
|
|
}, room=user['socket_id'])
|
|
|
|
del self.active_calls[call_id]
|
|
|
|
@self.socketio.on('webrtc_signal')
|
|
def handle_webrtc_signal(data):
|
|
"""WebRTC信令转发"""
|
|
to_account = data.get('to')
|
|
signal = data.get('signal')
|
|
|
|
recipient = self.user_manager.get_user(to_account)
|
|
if recipient and recipient.get('socket_id'):
|
|
emit('webrtc_signal', signal, room=recipient['socket_id'])
|
|
|
|
@self.socketio.on('file_uploaded')
|
|
def handle_file_uploaded(data):
|
|
"""文件上传完成通知"""
|
|
filename = data.get('filename')
|
|
url = data.get('url')
|
|
to_account = data.get('to')
|
|
from_account = data.get('from')
|
|
|
|
# 通知接收者
|
|
recipient = self.user_manager.get_user(to_account)
|
|
if recipient and recipient.get('socket_id'):
|
|
emit('file_received', {
|
|
'from': from_account,
|
|
'filename': filename,
|
|
'url': url,
|
|
'timestamp': time.time()
|
|
}, room=recipient['socket_id']) |