#!/usr/bin/env python import asyncio import json import websockets def log_message_error(error, message_text): print(f"[E] {error}") print(f" Message: {message_text}") async def parse_client_message(websocket, message_text): """Parse a message (JSON object) from a client.""" try: # Parse JSON message = json.loads(message_text) # Handle message types if message['action'] == 'init': await handle_client_init(websocket, message) else: log_message_error(f"Unknown action '{message['action']}'", message_text) except json.decoder.JSONDecodeError as e: log_message_error(f"JSON decode error: {e}", message_text) except KeyError as e: log_message_error(f"Missing key {e} in JSON message", message_text) async def handle_client_init(websocket, message): """Handle client 'init' message.""" print(f"< init: chat_id='{message['chat_id']}', nickname='{message['nickname']}'") # Send response to client response = json.dumps({ 'type': 'init' }) print(f"> {response}") await websocket.send(response) async def client_handler(websocket, path): """Handle client connection.""" print(f"++ New client {websocket.remote_address}") try: # Read and parse messages until connection is closed async for message_text in websocket: await parse_client_message(websocket, message_text) except websockets.exceptions.ConnectionClosed: # Ignore ConnectionClosed exceptions because we handle this in finally pass finally: print(f"-- Client connection closed {websocket.remote_address}") # Create WebSocket listener start_server = websockets.serve(client_handler, '0.0.0.0', 32715) try: asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() except KeyboardInterrupt: print("[received SIGINT]") pass finally: print("Exiting...")