diff --git a/moderation/backend-py/websocket_server.py b/moderation/backend-py/websocket_server.py index 01fcb72..0892bf5 100644 --- a/moderation/backend-py/websocket_server.py +++ b/moderation/backend-py/websocket_server.py @@ -16,8 +16,10 @@ logger = logging.getLogger(__name__) sio = socketio.AsyncServer( async_mode='asgi', cors_allowed_origins='*', - logger=False, - engineio_logger=False + logger=True, # Включить логирование для отладки + engineio_logger=True, # Включить логирование Engine.IO + ping_timeout=60, + ping_interval=25 ) # Track connected moderators @@ -36,6 +38,15 @@ def broadcast_online(): sio.emit('online', online_list, namespace='/mod-chat') +# Обработчик для корневого namespace (для отладки) +@sio.on('connect', namespace='/') +async def on_connect_root(sid, environ): + """Handle client connection to root namespace (should not happen)""" + print(f"[WebSocket] ⚠️ Client connected to ROOT namespace: {sid}") + logger.warning(f"[WebSocket] Client connected to ROOT namespace: {sid}") + # Отключаем, т.к. мы используем только /mod-chat + await sio.disconnect(sid, namespace='/') + # Namespace handlers for /mod-chat @sio.on('connect', namespace='/mod-chat') async def on_connect(sid, environ): @@ -44,7 +55,12 @@ async def on_connect(sid, environ): logger.info(f"[WebSocket] Client connected to /mod-chat: {sid}") if environ: print(f"[WebSocket] Environ keys: {list(environ.keys()) if isinstance(environ, dict) else 'N/A'}") + if isinstance(environ, dict): + print(f"[WebSocket] Query string: {environ.get('QUERY_STRING', 'N/A')}") + print(f"[WebSocket] Path: {environ.get('PATH_INFO', 'N/A')}") # Don't authorize immediately - wait for 'auth' event + # Возвращаем True, чтобы разрешить подключение + return True @sio.on('disconnect', namespace='/mod-chat') @@ -60,11 +76,15 @@ async def on_disconnect(sid): @sio.on('auth', namespace='/mod-chat') async def on_auth(sid, data): """Handle authentication for moderation chat""" + print(f"[WebSocket] 📥 Auth запрос от {sid}: {data}") try: username = normalize_username(data.get('username')) if data.get('username') else None telegram_id = data.get('telegramId') + print(f"[WebSocket] Обработка auth: username={username}, telegramId={telegram_id}") + if not username or not telegram_id: + print(f"[WebSocket] ❌ Auth failed: missing username or telegramId") logger.warning(f"[WebSocket] Auth failed: missing username or telegramId") await sio.emit('unauthorized', namespace='/mod-chat', room=sid) await sio.disconnect(sid, namespace='/mod-chat') @@ -72,15 +92,19 @@ async def on_auth(sid, data): # Check if user is owner owner_usernames = settings.OWNER_USERNAMES_LIST + print(f"[WebSocket] Owner usernames: {owner_usernames}") is_owner = username.lower() in [u.lower() for u in owner_usernames] + print(f"[WebSocket] Is owner: {is_owner}") # Check if user is moderation admin admin = await moderation_admins_collection().find_one({ 'telegramId': str(telegram_id) }) is_admin = admin is not None + print(f"[WebSocket] Is admin: {is_admin}, admin data: {admin}") if not is_owner and not is_admin: + print(f"[WebSocket] ❌ Access denied: {username} (telegramId: {telegram_id})") logger.warning(f"[WebSocket] Access denied: {username} (telegramId: {telegram_id})") await sio.emit('unauthorized', namespace='/mod-chat', room=sid) await sio.disconnect(sid, namespace='/mod-chat') @@ -93,11 +117,13 @@ async def on_auth(sid, data): 'isOwner': is_owner } + print(f"[WebSocket] ✅ Auth success: {username} (owner: {is_owner}, admin: {is_admin})") logger.info(f"[WebSocket] Auth success: {username} (owner: {is_owner}, admin: {is_admin})") await sio.emit('ready', namespace='/mod-chat', room=sid) broadcast_online() except Exception as e: + print(f"[WebSocket] ❌ Error in auth: {type(e).__name__}: {e}") logger.error(f"[WebSocket] Error in auth: {e}") import traceback traceback.print_exc()