This commit is contained in:
mirai 2026-01-03 12:00:52 +03:00
parent 8b58bf4db3
commit 264d19e932
6 changed files with 5 additions and 31 deletions

View File

@ -7,7 +7,6 @@ from sanic_ext import Extend
from .managers import ConnectionManager from .managers import ConnectionManager
from .stores import MessageStore, UserSessionStore from .stores import MessageStore, UserSessionStore
from .srp_auth import SRPAuthManager from .srp_auth import SRPAuthManager
from .logger import logger
from .routes import register_routes from .routes import register_routes
@ -32,12 +31,10 @@ def create_app(password: str = "", name: str = "cmd-chat-server") -> Sanic:
def register_lifecycle(app: Sanic) -> None: def register_lifecycle(app: Sanic) -> None:
@app.before_server_start @app.before_server_start
async def setup(app: Sanic): async def setup(app: Sanic):
logger.info("Server starting...")
app.ctx.cleanup_task = asyncio.create_task(cleanup_stale_sessions(app)) app.ctx.cleanup_task = asyncio.create_task(cleanup_stale_sessions(app))
@app.after_server_stop @app.after_server_stop
async def teardown(app: Sanic): async def teardown(app: Sanic):
logger.info("Server shutting down...")
if app.ctx.cleanup_task: if app.ctx.cleanup_task:
app.ctx.cleanup_task.cancel() app.ctx.cleanup_task.cancel()
with suppress(asyncio.CancelledError): with suppress(asyncio.CancelledError):

View File

@ -1,6 +0,0 @@
import logging
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)

View File

@ -1,7 +1,6 @@
import asyncio import asyncio
from typing import Optional from typing import Optional
from sanic import Websocket from sanic import Websocket
from .logger import logger
class ConnectionManager: class ConnectionManager:
@ -12,13 +11,11 @@ class ConnectionManager:
async def connect(self, user_id: str, websocket: Websocket) -> None: async def connect(self, user_id: str, websocket: Websocket) -> None:
async with self._lock: async with self._lock:
self.active_connections[user_id] = websocket self.active_connections[user_id] = websocket
logger.info(f"Client connected: {user_id}")
async def disconnect(self, user_id: str) -> None: async def disconnect(self, user_id: str) -> None:
async with self._lock: async with self._lock:
if user_id in self.active_connections: if user_id in self.active_connections:
del self.active_connections[user_id] del self.active_connections[user_id]
logger.info(f"Client disconnected: {user_id}")
async def broadcast(self, message: str, exclude_user: Optional[str] = None) -> None: async def broadcast(self, message: str, exclude_user: Optional[str] = None) -> None:
async with self._lock: async with self._lock:
@ -29,7 +26,6 @@ class ConnectionManager:
try: try:
await connection.send(message) await connection.send(message)
except Exception: except Exception:
logger.exception(f"Failed to send message to {user_id}")
disconnected.append(user_id) disconnected.append(user_id)
for user_id in disconnected: for user_id in disconnected:
@ -43,6 +39,5 @@ class ConnectionManager:
await connection.send(message) await connection.send(message)
return True return True
except Exception: except Exception:
logger.exception(f"Failed to send personal message to {user_id}")
return False return False
return False return False

View File

@ -1,5 +1,4 @@
from typing import Optional from typing import Optional
from .logger import logger
from .factory import create_app from .factory import create_app
@ -10,7 +9,6 @@ def run_server(
workers: int = 1, workers: int = 1,
) -> None: ) -> None:
app = create_app(password=password or "") app = create_app(password=password or "")
logger.info(f"Starting server on {host}:{port}")
app.run( app.run(
host=host, host=host,

View File

@ -1,6 +1,5 @@
from typing import Optional from typing import Optional
from .models import Message, UserSession from .models import Message, UserSession
from .logger import logger
class MessageStore: class MessageStore:
@ -9,7 +8,7 @@ class MessageStore:
def add(self, message: Message) -> None: def add(self, message: Message) -> None:
self._messages.append(message) self._messages.append(message)
logger.info(f"Message added: {message.id} from {message.username}")
def get_all(self) -> list[Message]: def get_all(self) -> list[Message]:
return self._messages.copy() return self._messages.copy()
@ -17,7 +16,7 @@ class MessageStore:
def clear(self) -> None: def clear(self) -> None:
count = len(self._messages) count = len(self._messages)
self._messages.clear() self._messages.clear()
logger.info(f"Cleared {count} messages")
def count(self) -> int: def count(self) -> int:
return len(self._messages) return len(self._messages)
@ -29,7 +28,7 @@ class UserSessionStore:
def add(self, session: UserSession) -> None: def add(self, session: UserSession) -> None:
self._sessions[session.user_id] = session self._sessions[session.user_id] = session
logger.info(f"Session created: {session.user_id} ({session.username})")
def get(self, user_id: str) -> Optional[UserSession]: def get(self, user_id: str) -> Optional[UserSession]:
return self._sessions.get(user_id) return self._sessions.get(user_id)
@ -41,7 +40,7 @@ class UserSessionStore:
def remove(self, user_id: str) -> None: def remove(self, user_id: str) -> None:
if user_id in self._sessions: if user_id in self._sessions:
del self._sessions[user_id] del self._sessions[user_id]
logger.info(f"Session removed: {user_id}")
def cleanup_stale(self, timeout_seconds: int = 3600) -> int: def cleanup_stale(self, timeout_seconds: int = 3600) -> int:
stale_ids = [ stale_ids = [
@ -49,8 +48,6 @@ class UserSessionStore:
] ]
for uid in stale_ids: for uid in stale_ids:
del self._sessions[uid] del self._sessions[uid]
if stale_ids:
logger.info(f"Cleaned up {len(stale_ids)} stale sessions")
return len(stale_ids) return len(stale_ids)
def get_all(self) -> list[UserSession]: def get_all(self) -> list[UserSession]:

View File

@ -7,7 +7,6 @@ from sanic import Sanic, Request, response, Websocket
from sanic.response import HTTPResponse, json as json_response from sanic.response import HTTPResponse, json as json_response
from .models import Message, UserSession from .models import Message, UserSession
from .logger import logger
from .helpers import ( from .helpers import (
get_client_ip, get_client_ip,
send_state, send_state,
@ -31,8 +30,6 @@ async def srp_init(request: Request, app: Sanic) -> HTTPResponse:
user_id, B, salt = app.ctx.srp_manager.init_auth(username, client_public) user_id, B, salt = app.ctx.srp_manager.init_auth(username, client_public)
logger.info(f"SRP init: {username} ({user_id[:8]}...)")
return response.json( return response.json(
{ {
"user_id": user_id, "user_id": user_id,
@ -42,7 +39,6 @@ async def srp_init(request: Request, app: Sanic) -> HTTPResponse:
) )
except Exception: except Exception:
logger.exception("SRP init failed")
return response.json({"error": "SRP init failed"}, status=500) return response.json({"error": "SRP init failed"}, status=500)
@ -70,7 +66,6 @@ async def srp_verify(request: Request, app: Sanic) -> HTTPResponse:
) )
app.ctx.session_store.add(session) app.ctx.session_store.add(session)
logger.info(f"SRP verified: {username} ({user_id[:8]}...)")
return response.json( return response.json(
{ {
@ -80,10 +75,8 @@ async def srp_verify(request: Request, app: Sanic) -> HTTPResponse:
) )
except ValueError as e: except ValueError as e:
logger.warning(f"SRP verify failed: {e}")
return response.json({"error": str(e)}, status=401) return response.json({"error": str(e)}, status=401)
except Exception: except Exception:
logger.exception("SRP verify failed")
return response.json({"error": "SRP verify failed"}, status=500) return response.json({"error": "SRP verify failed"}, status=500)
@ -128,7 +121,7 @@ async def chat_ws(request: Request, ws: Websocket, app: Sanic) -> None:
) )
except Exception: except Exception:
logger.exception(f"WebSocket error for {user_id}") pass
finally: finally:
await manager.disconnect(user_id) await manager.disconnect(user_id)
await manager.broadcast( await manager.broadcast(