diff --git a/server/src/index.ts b/server/src/index.ts index a3798fc..c133789 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -231,67 +231,6 @@ function provenBank(req: IncomingMessage, claimed: unknown, forget: unknown): { return proven; } -function send(res: ServerResponse, status: number, body: unknown): void { - res.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); - res.end(status === 204 ? undefined : JSON.stringify(body)); -} - -function readBytes(req: IncomingMessage, limit: number, tooBig: string): Promise { - return new Promise((resolve, reject) => { - const declared = Number(req.headers['content-length'] ?? 0); - if (declared > limit) { - reject(new RoomError(tooBig, 413)); - req.destroy(); - return; - } - let size = 0; - const chunks: Buffer[] = []; - req.on('data', (chunk: Buffer) => { - size += chunk.length; - if (size > limit) { - reject(new RoomError(tooBig, 413)); - req.destroy(); - return; - } - chunks.push(chunk); - }); - req.on('end', () => resolve(Buffer.concat(chunks))); - req.on('error', reject); - }); -} - -async function readBody(req: IncomingMessage): Promise> { - const bytes = await readBytes(req, BODY_LIMIT, 'That is more than a move needs.'); - if (bytes.length === 0) return {}; - try { - return JSON.parse(bytes.toString('utf8')) as Record; - } catch { - throw new RoomError('The request was not JSON.'); - } -} - -/** A report, an answer, or a call to the table is worth waking the keeper for; the desk's own replies are not. */ -function ringBell(title: string, detail: { fingerprint: string[]; tags: Record; extra: Record }): void { - Sentry.captureMessage(title, { level: 'error', ...detail }); -} - -/** The seats a browser claims, kept to the ones its tokens prove. */ -function provenSeats(raw: unknown): { roomId: string; seat: string }[] { - const claims = Array.isArray(raw) ? raw.slice(0, 50) : []; - const proven: { roomId: string; seat: string }[] = []; - for (const claim of claims) { - if (typeof claim !== 'object' || claim === null) continue; - const c = claim as Record; - try { - const room = rooms.get(String(c.roomId ?? '')); - proven.push({ roomId: room.id, seat: rooms.seatOf(room, typeof c.token === 'string' ? c.token : undefined).id }); - } catch { - // A seat this browser cannot prove is not its business. - } - } - return proven; -} - /** The seats a browser claims, kept to the ones its tokens prove. */ function provenSeats(raw: unknown): { roomId: string; seat: string }[] { const claims = Array.isArray(raw) ? raw.slice(0, 50) : []; @@ -427,6 +366,7 @@ async function handle(req: IncomingMessage, res: ServerResponse): Promise return send(res, 200, found); } throw new RoomError('Not here.', 404); + } if (parts[0] !== 'api' || parts[1] !== 'rooms') throw new RoomError('Not here.', 404); if (parts.length === 2 && req.method === 'POST') { diff --git a/server/src/rooms.test.ts b/server/src/rooms.test.ts index f5eda56..58cbd72 100644 --- a/server/src/rooms.test.ts +++ b/server/src/rooms.test.ts @@ -168,7 +168,7 @@ describe('a seat a browser lost', () => { rooms.seen(other.room, other.token, 'home'); expect(rooms.findSeats('Bo', 'home', other.room.id).seated.map((s) => s.roomId)).toEqual([other.room.id]); expect(rooms.findSeats('Bo', 'home').seated.map((s) => s.roomId).sort()).toEqual([other.room.id, room.id].sort()); - room.over = true; + room.state!.over = { winner: 'A', reason: 'the test says so' }; expect(rooms.findSeats('Bo', 'home').seated.map((s) => s.roomId)).toEqual([other.room.id]); }); }); diff --git a/server/src/rooms.ts b/server/src/rooms.ts index 7c2d6ef..c00bac2 100644 --- a/server/src/rooms.ts +++ b/server/src/rooms.ts @@ -318,7 +318,7 @@ export class Rooms { } catch { continue; } - if (room.over) continue; + if (room.state?.over) continue; const seat = room.seats.find((s) => (!s.bot || s.standIn) && s.name.toLowerCase() === wanted); if (seat) found.push({ room, seat }); }