Add API routes and websocket room manager
This commit is contained in:
@@ -1 +1,75 @@
|
||||
"""Student routes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Request, Response, WebSocket
|
||||
from fastapi.responses import FileResponse, HTMLResponse
|
||||
|
||||
from app import auth
|
||||
from app.config import Settings
|
||||
from app.models import JoinRequest
|
||||
from app.room import RoomManager
|
||||
|
||||
|
||||
def router(settings: Settings, rooms: RoomManager) -> APIRouter:
|
||||
api = APIRouter()
|
||||
|
||||
@api.get("/")
|
||||
async def student_entry(sid: str | None = None):
|
||||
if not sid or not await rooms.session_exists(sid):
|
||||
return HTMLResponse(
|
||||
"<!doctype html><title>Quiz</title><main><h1>Ask your instructor for the link</h1>"
|
||||
"<p>This quiz link is missing or no longer valid.</p></main>"
|
||||
)
|
||||
return FileResponse(Path("static/student.html"))
|
||||
|
||||
@api.get("/api/session/{sid}")
|
||||
async def session_metadata(sid: str):
|
||||
if not await rooms.session_exists(sid):
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
session = await rooms.get_session(sid)
|
||||
return {
|
||||
"title": session["title"],
|
||||
"state": session["state"],
|
||||
"current_question_idx": session["current_question_idx"],
|
||||
"time_limit_default": (await rooms.get_pool_for_session(sid))["time_limit_default"],
|
||||
}
|
||||
|
||||
@api.post("/api/session/{sid}/join")
|
||||
async def join_session(sid: str, body: JoinRequest, response: Response):
|
||||
if not await rooms.session_exists(sid):
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
student_id = body.student_id.strip()
|
||||
name = body.name.strip()
|
||||
cookie_id = str(uuid4())
|
||||
cookie_value = auth.sign_student(settings, sid, student_id, name, cookie_id)
|
||||
await rooms.add_participant(sid, student_id, name, cookie_id)
|
||||
auth.set_student_cookie(settings, response, cookie_value)
|
||||
return {"ok": True, "cookie_id": cookie_id}
|
||||
|
||||
@api.get("/api/session/{sid}/me")
|
||||
async def me(sid: str, request: Request):
|
||||
identity = auth.get_student_identity(settings, request, sid)
|
||||
if not identity:
|
||||
raise HTTPException(status_code=401, detail="Student cookie required")
|
||||
return await rooms.me(sid, identity["student_id"])
|
||||
|
||||
@api.get("/api/session/{sid}/stats")
|
||||
async def stats(sid: str, request: Request, question_idx: int | None = None):
|
||||
if not await rooms.session_exists(sid):
|
||||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
identity = auth.get_student_identity(settings, request, sid)
|
||||
return await rooms.stats(sid, question_idx, identity["student_id"] if identity else None)
|
||||
|
||||
@api.websocket("/ws/student/{sid}")
|
||||
async def student_socket(websocket: WebSocket, sid: str):
|
||||
identity = auth.get_student_identity_ws(settings, websocket, sid)
|
||||
if not identity or not await rooms.session_exists(sid):
|
||||
await websocket.close(code=4001)
|
||||
return
|
||||
await rooms.student_ws(websocket, sid, identity)
|
||||
|
||||
return api
|
||||
|
||||
Reference in New Issue
Block a user