Files
LinedanceAfspiller/linedance-api/app/websocket/manager.py
2026-04-11 00:38:04 +02:00

79 lines
2.5 KiB
Python

import json
from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends, Query
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.models import Project, ProjectSong
router = APIRouter(prefix="/ws", tags=["websocket"])
class ConnectionManager:
def __init__(self):
# project_id -> liste af aktive forbindelser
self.rooms: dict[str, list[WebSocket]] = {}
async def connect(self, project_id: str, ws: WebSocket):
await ws.accept()
self.rooms.setdefault(project_id, []).append(ws)
def disconnect(self, project_id: str, ws: WebSocket):
if project_id in self.rooms:
self.rooms[project_id].discard(ws) if hasattr(self.rooms[project_id], 'discard') else None
try:
self.rooms[project_id].remove(ws)
except ValueError:
pass
async def broadcast(self, project_id: str, message: dict):
dead = []
for ws in self.rooms.get(project_id, []):
try:
await ws.send_text(json.dumps(message))
except Exception:
dead.append(ws)
for ws in dead:
self.disconnect(project_id, ws)
manager = ConnectionManager()
@router.websocket("/{project_id}")
async def project_live(
project_id: str,
websocket: WebSocket,
db: Session = Depends(get_db),
):
project = db.query(Project).filter(Project.id == project_id).first()
if not project:
await websocket.close(code=4004)
return
await manager.connect(project_id, websocket)
# Send nuværende tilstand med det samme ved opkobling
songs = db.query(ProjectSong).filter_by(project_id=project_id).order_by(ProjectSong.position).all()
await websocket.send_text(json.dumps({
"event": "state",
"project_id": project_id,
"songs": [
{"id": ps.id, "position": ps.position, "status": ps.status, "song_id": ps.song_id}
for ps in songs
],
}))
try:
while True:
await websocket.receive_text() # hold forbindelsen åben
except WebSocketDisconnect:
manager.disconnect(project_id, websocket)
async def notify_status_change(project_id: str, project_song_id: str, new_status: str):
"""Kaldes fra projects-router når en sangs status ændres."""
await manager.broadcast(project_id, {
"event": "status_update",
"project_song_id": project_song_id,
"status": new_status,
})