Files
Dune/app/api/rooms/[code]/messages/route.ts
T

76 lines
2.4 KiB
TypeScript

import { env } from 'cloudflare:workers';
import { requestOrigin } from '@/lib/request-origin';
import { authenticate } from '@/db/rooms';
import { readTableTalk, sendTableTalk, TableTalkError } from '@/db/table-talk';
import { RuleError } from '@/game/engine';
const noStore = { 'Cache-Control': 'no-store' };
async function handle(req: Request, write: boolean) {
try {
const url = new URL(req.url);
if (
write &&
req.headers.get('origin') &&
req.headers.get('origin') !== requestOrigin(req, env.DUNE_PUBLIC_ORIGIN)
)
throw new TableTalkError('Invalid request origin.', 403);
const code = url.pathname.split('/').at(-2)!.toUpperCase();
if (!/^[A-Z2-9]{8}$/.test(code))
throw new TableTalkError('Invalid room code.', 400);
const token =
req.headers
.get('cookie')
?.split(';')
.map((part) => part.trim())
.find((part) => part.startsWith(`dune_${code}=`))
?.split('=')[1] ?? '';
const auth = await authenticate(code, token);
if (write) {
const raw = await req.text();
if (raw.length > 6500)
throw new TableTalkError('Request too large.', 413);
return Response.json(await sendTableTalk(code, auth, JSON.parse(raw)), {
headers: noStore,
});
}
if (
[...url.searchParams.keys()].some(
(key) => !['recipient', 'before'].includes(key),
)
)
throw new TableTalkError('Invalid conversation request.', 400);
return Response.json(
await readTableTalk(
code,
auth,
url.searchParams.get('recipient'),
url.searchParams.get('before'),
),
{ headers: noStore },
);
} catch (error) {
return Response.json(
{
error:
error instanceof TableTalkError || error instanceof RuleError
? error.message
: error instanceof SyntaxError
? 'Invalid JSON.'
: 'Table discussion is temporarily unavailable.',
},
{
status:
error instanceof TableTalkError
? error.status
: error instanceof RuleError
? 409
: error instanceof SyntaxError
? 400
: 500,
headers: noStore,
},
);
}
}
export const GET = (req: Request) => handle(req, false);
export const POST = (req: Request) => handle(req, true);