This commit is contained in:
Helva
2026-01-30 22:21:55 +01:00
commit 04c5db785a
8 changed files with 538 additions and 0 deletions
Binary file not shown.
+64
View File
@@ -0,0 +1,64 @@
import asyncio
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse, JSONResponse
app = FastAPI()
clients: set[asyncio.Queue[str]] = set()
current_emotion = "neutral"
def sse(event: str, data: str) -> str:
# SSE format: event + data + blank line
return f"event: {event}\ndata: {data}\n\n"
@app.get("/events")
async def events(request: Request):
"""
Browser connects here via EventSource. We stream emotion updates.
"""
q: asyncio.Queue[str] = asyncio.Queue()
clients.add(q)
async def gen():
try:
# send current state immediately
yield sse("emotion", current_emotion)
while True:
# abort if client disconnected
if await request.is_disconnected():
break
msg = await q.get()
yield sse("emotion", msg)
finally:
clients.discard(q)
headers = {
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no", # helpful behind nginx
}
return StreamingResponse(gen(), media_type="text/event-stream", headers=headers)
@app.post("/api/emotion/{name}")
async def set_emotion(name: str):
global current_emotion
current_emotion = name
# broadcast to all connected clients
dead = []
for q in clients:
try:
q.put_nowait(name)
except Exception:
dead.append(q)
for q in dead:
clients.discard(q)
return JSONResponse({"ok": True, "emotion": current_emotion})
@app.get("/api/emotion")
async def get_emotion():
return {"emotion": current_emotion}