"""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( "Quiz

Ask your instructor for the link

" "

This quiz link is missing or no longer valid.

" ) 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