import { NextResponse } from 'next/server'; import { parseChzzkChannelId } from '@/lib/chzzk/channel'; import { cancelScheduledDisconnectRoomChat, ensureRoomChat, } from '@/lib/chzzk/chat-session'; import { createRoom, findRoomByChannelId, getRoom, toPublicRoom, } from '@/lib/rooms/store'; export const runtime = 'nodejs'; /** * 치지직 채널 ID(또는 라이브 URL)로 룸 입장. * 없으면 전달된 치즈 설정으로 새 룸을 만들고 채팅 연결을 시도한다. */ export async function POST(request: Request) { const body = (await request.json().catch(() => ({}))) as { channelIdOrUrl?: string; cheesePerDice?: number; multiplyByCheese?: boolean; maxMultiplier?: number; }; const raw = body.channelIdOrUrl || ''; const channelId = parseChzzkChannelId(raw); if (!channelId) { return NextResponse.json( { error: '유효한 치지직 채널 ID 또는 라이브 URL이 필요합니다. 예: https://chzzk.naver.com/live/{채널ID}', }, { status: 400 }, ); } let room = findRoomByChannelId(channelId); let created = false; if (!room) { created = true; room = createRoom({ chzzkEnabled: true, liveUrl: raw.trim(), channelId, cheesePerDice: body.cheesePerDice, multiplyByCheese: body.multiplyByCheese, maxMultiplier: body.maxMultiplier, }); } // 이전 세션 leave가 늦게 와도 끊기지 않게 예약 해제 + 실제 WS 생존 여부 확인 cancelScheduledDisconnectRoomChat(room.id); if (room.settings.chzzkEnabled) { try { await ensureRoomChat(room.id); } catch (e) { if (created) { return NextResponse.json( { error: e instanceof Error ? e.message : '채팅 연결에 실패했습니다. 방송 중인지 확인해 주세요.', room: toPublicRoom(room), created, }, { status: 502 }, ); } } } const latest = getRoom(room.id) ?? room; return NextResponse.json({ room: toPublicRoom(latest), created, }); }