Files
drinkmarble/app/api/rooms/[roomId]/leave/route.ts

60 lines
1.6 KiB
TypeScript

import { NextResponse } from 'next/server';
import { scheduleDisconnectRoomChat } from '@/lib/chzzk/chat-session';
import {
getRoom,
getRoomViewerCount,
removeRoomViewer,
toPublicRoom,
} from '@/lib/rooms/store';
export const runtime = 'nodejs';
type Params = { params: Promise<{ roomId: string }> };
/**
* 탭/창 종료·페이지 이탈 시 호출.
* 마지막 시청자면 치지직 채팅 웹소켓을 유예 후 끊는다 (빠른 재입장 대비).
*/
export async function POST(request: Request, { params }: Params) {
const { roomId } = await params;
const room = getRoom(roomId);
if (!room) {
return NextResponse.json({ ok: true, emptied: true });
}
let clientId = '';
const contentType = request.headers.get('content-type') || '';
try {
if (contentType.includes('application/json')) {
const body = (await request.json()) as { clientId?: string };
clientId = body.clientId?.trim() || '';
} else {
const text = await request.text();
if (text.startsWith('{')) {
const body = JSON.parse(text) as { clientId?: string };
clientId = body.clientId?.trim() || '';
} else {
clientId = new URLSearchParams(text).get('clientId')?.trim() || '';
}
}
} catch {
clientId = '';
}
if (!clientId) {
return NextResponse.json({ ok: true, viewers: getRoomViewerCount(roomId) });
}
const { viewers, emptied } = removeRoomViewer(roomId, clientId);
if (emptied) {
scheduleDisconnectRoomChat(roomId);
}
return NextResponse.json({
ok: true,
viewers,
emptied,
room: toPublicRoom(getRoom(roomId) ?? room),
});
}