""" WebSocket endpoint para alertas en tiempo real. """ import json from typing import Optional from fastapi import APIRouter, Query, WebSocket, WebSocketDisconnect from app.api.websocket.manager import manager from app.core.security import decode_token router = APIRouter() async def get_user_from_token(token: Optional[str]) -> Optional[int]: """ Obtiene el ID de usuario desde un token JWT. Args: token: Token JWT. Returns: ID del usuario o None. """ if not token: return None try: payload = decode_token(token) return int(payload.get("sub")) except Exception: return None @router.websocket("/ws/alertas") async def websocket_alertas( websocket: WebSocket, token: Optional[str] = Query(None), ): """ WebSocket para recibir alertas en tiempo real. Recibe todas las alertas generadas en el sistema. Args: websocket: Conexión WebSocket. token: Token JWT para autenticación (opcional). """ user_id = await get_user_from_token(token) await manager.connect(websocket, "alertas", user_id) # Enviar confirmación await websocket.send_json({ "type": "connected", "channel": "alerts", }) try: while True: data = await websocket.receive_text() try: message = json.loads(data) if message.get("action") == "ping": await websocket.send_json({"type": "pong"}) elif message.get("action") == "acknowledge": # Cliente confirma recepción de alerta alert_id = message.get("alert_id") await websocket.send_json({ "type": "acknowledged", "alert_id": alert_id, }) except json.JSONDecodeError: pass except WebSocketDisconnect: await manager.disconnect(websocket, "alertas", user_id) @router.websocket("/ws/alertas/vehiculo/{vehiculo_id}") async def websocket_alertas_vehiculo( websocket: WebSocket, vehiculo_id: int, token: Optional[str] = Query(None), ): """ WebSocket para alertas de un vehículo específico. Args: websocket: Conexión WebSocket. vehiculo_id: ID del vehículo. token: Token JWT para autenticación (opcional). """ user_id = await get_user_from_token(token) await manager.connect(websocket, "alertas", user_id) await manager.subscribe_vehicle(websocket, vehiculo_id) # Enviar confirmación await websocket.send_json({ "type": "connected", "channel": "vehicle_alerts", "vehicle_id": vehiculo_id, }) try: while True: data = await websocket.receive_text() try: message = json.loads(data) if message.get("action") == "ping": await websocket.send_json({"type": "pong"}) except json.JSONDecodeError: pass except WebSocketDisconnect: await manager.unsubscribe_vehicle(websocket, vehiculo_id) await manager.disconnect(websocket, "alertas", user_id)