This commit is contained in:
team3
2026-09-30 15:15:00 +02:00
parent 817f39a42c
commit 09ae21c4b2
6 changed files with 66 additions and 10 deletions

View File

@@ -19,16 +19,26 @@ log = logging.getLogger("events")
PUFFER = 16
_abonnenten: set[asyncio.Queue] = set()
# Welche Sitzung hinter einer Verbindung steckt — daraus ergibt sich,
# wer gerade online ist: eine offene Seite mit gewähltem Namen
_sitzungen: dict[asyncio.Queue, str] = {}
def anmelden():
def anmelden(session_id=None):
queue = asyncio.Queue(maxsize=PUFFER)
_abonnenten.add(queue)
if session_id:
_sitzungen[queue] = session_id
return queue
def abmelden(queue):
_abonnenten.discard(queue)
_sitzungen.pop(queue, None)
def sitzungen_online():
return set(_sitzungen.values())
def anzahl():
@@ -60,3 +70,5 @@ async def stream(queue, request):
yield ": ping\n\n"
finally:
abmelden(queue)
# Die anderen Seiten sollen den grünen Punkt ausmachen
senden("users")

View File

@@ -564,8 +564,10 @@ letzter_dreh = {"ergebnis": None, "start": 0.0, "teilnehmer": []}
@app.get("/api/events")
async def ereignisse(request: Request):
queue = events.anmelden()
async def ereignisse(request: Request, filmabend_sid: str | None = Cookie(None)):
queue = events.anmelden(filmabend_sid)
# Die anderen Seiten sollen den grünen Punkt anmachen
events.senden("users")
return StreamingResponse(
events.stream(queue, request),
media_type="text/event-stream",
@@ -833,8 +835,11 @@ def runde(response: Response, filmabend_sid: str | None = Cookie(None)):
sid = sitzung(response, filmabend_sid)
staende = punkte.alle()
leer = punkte.stand(0)
online = users.online_ids(events.sitzungen_online())
return {
"items": [{**u, **staende.get(u["id"], leer)} for u in users.alle()],
"items": [
{**u, **staende.get(u["id"], leer), "online": u["id"] in online} for u in users.alle()
],
"mine": users.aktuell(sid),
"host": users.ist_host(sid),
}
@@ -995,6 +1000,7 @@ def name_waehlen(
sid = sitzung(response, filmabend_sid)
if user_id is None:
users.abwaehlen(sid)
events.senden("users")
return {"mine": None}
film = users.schutz_von(user_id)
@@ -1009,6 +1015,7 @@ def name_waehlen(
benutzer = users.waehlen(sid, user_id)
if not benutzer:
raise HTTPException(status_code=404, detail="Unbekannter Name")
events.senden("users")
return {"mine": benutzer}

View File

@@ -184,6 +184,11 @@ def host_setzen(session_id, an):
return an
def online_ids(session_ids):
"""Die Namen hinter offenen Verbindungen — wer gerade da ist."""
return {besitzer(sid) for sid in session_ids} - {None}
def besitzer(session_id):
"""Die user_id dieser Sitzung, oder None ohne gewählten Namen.

View File

@@ -46,3 +46,23 @@ def test_abwaehlen_macht_wieder_zum_zuschauer(client, film):
# Lesen geht weiter, Schreiben nicht mehr
assert client.get("/api/suggestions").json()["mine"] is None
assert client.post("/api/suggestions", json={"movie_id": film(2)}).status_code == 403
def test_online_ist_wer_eine_seite_offen_hat(client, anmelden):
from app import events
anmelden(client, "Anna")
sid = client.cookies.get("filmabend_sid")
ich = client.get("/api/users").json()["mine"]["id"]
def online():
return {u["id"]: u["online"] for u in client.get("/api/users").json()["items"]}
assert online()[ich] is False
queue = events.anmelden(sid)
assert online()[ich] is True
# Namenswechsel im selben Browser: der alte Name ist offline
anmelden(client, "Ben")
assert online()[ich] is False
events.abmelden(queue)
assert True not in online().values()