""" WebSocket server for moderation chat """ import socketio import logging from typing import Dict, Set logger = logging.getLogger(__name__) # Create Socket.IO server sio = socketio.AsyncServer( async_mode='asgi', cors_allowed_origins='*', logger=False, engineio_logger=False ) # Track connected moderators connected_moderators: Dict[str, Set[str]] = {} # {room: {sid1, sid2, ...}} @sio.event async def connect(sid, environ): """Handle client connection""" logger.info(f"[WebSocket] Client connected: {sid}") @sio.event async def disconnect(sid): """Handle client disconnection""" logger.info(f"[WebSocket] Client disconnected: {sid}") # Remove from all rooms for room, sids in connected_moderators.items(): if sid in sids: sids.remove(sid) await sio.emit('user_left', {'sid': sid}, room=room, skip_sid=sid) @sio.event async def join_moderation_chat(sid, data): """Join moderation chat room""" try: user_id = data.get('userId') username = data.get('username') if not user_id: return room = 'moderation_chat' await sio.enter_room(sid, room) if room not in connected_moderators: connected_moderators[room] = set() connected_moderators[room].add(sid) logger.info(f"[WebSocket] {username} ({user_id}) joined moderation chat") # Notify others await sio.emit('user_joined', { 'userId': user_id, 'username': username, 'sid': sid }, room=room, skip_sid=sid) except Exception as e: logger.error(f"[WebSocket] Error joining chat: {e}") @sio.event async def leave_moderation_chat(sid, data): """Leave moderation chat room""" try: room = 'moderation_chat' await sio.leave_room(sid, room) if room in connected_moderators and sid in connected_moderators[room]: connected_moderators[room].remove(sid) # Notify others await sio.emit('user_left', {'sid': sid}, room=room, skip_sid=sid) except Exception as e: logger.error(f"[WebSocket] Error leaving chat: {e}") @sio.event async def moderation_message(sid, data): """Handle moderation chat message""" try: room = 'moderation_chat' message_data = { 'userId': data.get('userId'), 'username': data.get('username'), 'message': data.get('message'), 'timestamp': data.get('timestamp') } # Broadcast to all in room await sio.emit('moderation_message', message_data, room=room) logger.info(f"[WebSocket] Message from {data.get('username')}: {data.get('message')[:50]}...") except Exception as e: logger.error(f"[WebSocket] Error sending message: {e}") @sio.event async def typing(sid, data): """Handle typing indicator""" try: room = 'moderation_chat' await sio.emit('typing', { 'userId': data.get('userId'), 'username': data.get('username'), 'isTyping': data.get('isTyping', True) }, room=room, skip_sid=sid) except Exception as e: logger.error(f"[WebSocket] Error handling typing: {e}") def get_socketio_app(): """Get Socket.IO ASGI app""" return socketio.ASGIApp(sio)