import { NextResponse } from "next/server"; import { getPayload } from "payload"; import config from "@payload-config"; import { createLiveKitToken, getLiveKitClientUrl } from "@/lib/meeting/livekit"; import { isMeetingParticipantKicked } from "@/lib/meeting/kicks"; import { verifyMeetingToken } from "@/lib/meeting/token"; export const dynamic = "force-dynamic"; type Args = { params: Promise<{ slug: string }> }; /** Exchanges the app's short-lived meeting credential for a LiveKit token. */ export async function POST(request: Request, { params }: Args) { const { slug } = await params; const authorization = request.headers.get("authorization") ?? ""; const appToken = authorization.startsWith("Bearer ") ? authorization.slice(7) : ""; const meetingToken = verifyMeetingToken(appToken); if (!meetingToken || meetingToken.eventSlug !== slug) { return NextResponse.json({ error: "Die Meeting-Sitzung ist ungültig." }, { status: 401 }); } if (isMeetingParticipantKicked(slug, meetingToken.participantId, meetingToken.clientId)) { return NextResponse.json({ error: "Du wurdest aus diesem Meeting entfernt." }, { status: 403 }); } try { const payload = await getPayload({ config }); const { docs } = await payload.find({ collection: "events", where: { slug: { equals: slug } }, limit: 1 }); if (!docs[0]?.isOnline) return NextResponse.json({ error: "Dieser Online-Termin wurde nicht gefunden." }, { status: 404 }); const participantToken = await createLiveKitToken({ eventSlug: slug, participantId: meetingToken.participantId, name: meetingToken.name, role: meetingToken.role, clientId: meetingToken.clientId, }); return NextResponse.json({ serverUrl: getLiveKitClientUrl(), participantToken }); } catch (error) { console.error("meeting LiveKit connect failed", error); return NextResponse.json({ error: "Der Video-Server ist gerade nicht erreichbar." }, { status: 503 }); } }