| |
| |
| |
| |
| |
| |
|
|
| import { NextRequest, NextResponse } from 'next/server'; |
| import { sessionManager } from '@/lib/session-manager'; |
| export { OPTIONS } from '@/lib/cors'; |
|
|
| export const runtime = 'nodejs'; |
| export const dynamic = 'force-dynamic'; |
|
|
| export async function POST(request: NextRequest) { |
| try { |
| const body = await request.json(); |
| const { action } = body; |
|
|
| switch (action) { |
| case 'create': |
| return handleCreate(body); |
| case 'join': |
| return handleJoin(body); |
| case 'end': |
| return handleEnd(body); |
| case 'get': |
| return handleGet(body); |
| case 'list': |
| return handleList(); |
| case 'lookup': |
| return handleLookup(body); |
| default: |
| return NextResponse.json({ |
| success: false, |
| error: `Invalid action: ${action}. Valid actions: create, join, end, get, list, lookup` |
| }, { status: 400 }); |
| } |
| } catch (error) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Invalid JSON body' |
| }, { status: 400 }); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| function handleCreate(body: any) { |
| const { teacherId, teacherName, sessionName, description, slideUrls } = body; |
|
|
| |
| if (!teacherId || !teacherName || !sessionName) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Missing required fields: teacherId, teacherName, sessionName' |
| }, { status: 400 }); |
| } |
|
|
| |
| const session = sessionManager.createSession( |
| teacherId, |
| teacherName, |
| sessionName, |
| description, |
| slideUrls || [] |
| ); |
|
|
| return NextResponse.json({ |
| success: true, |
| data: session, |
| message: 'Session created successfully' |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| async function handleLookup(body: any) { |
| const { roomCode } = body; |
| if (!roomCode) { |
| return NextResponse.json({ success: false, error: 'Missing roomCode' }, { status: 400 }); |
| } |
| |
| const byCode = sessionManager.getSessionByRoomCode(String(roomCode)); |
| if (byCode) { |
| return NextResponse.json({ success: true, data: byCode }); |
| } |
| |
| const byId = sessionManager.getSession(String(roomCode)); |
| if (byId) { |
| return NextResponse.json({ success: true, data: byId }); |
| } |
|
|
| |
| try { |
| const diskId = await findSessionIdByRoomCode(String(roomCode)); |
| if (diskId) { |
| |
| |
| const fs = await import('fs/promises'); |
| const path = await import('path'); |
| const storageRoot = process.env.SPACE_ID ? '/data' : path.join(process.cwd(), 'data'); |
| const filePath = path.join(storageRoot, 'sessions', diskId, 'session_url.json'); |
| const dataStr = await fs.readFile(filePath, 'utf-8'); |
| const oldState = JSON.parse(dataStr); |
| return NextResponse.json({ success: true, data: oldState.session }); |
| } |
| } catch (err) {} |
|
|
| return NextResponse.json({ success: false, error: 'Session not found' }, { status: 404 }); |
| } |
|
|
| |
| async function findSessionIdByRoomCode(roomCode: string): Promise<string | null> { |
| try { |
| const fs = await import('fs/promises'); |
| const path = await import('path'); |
| const storageRoot = process.env.SPACE_ID ? '/data' : path.join(process.cwd(), 'data'); |
| const sessionsDir = path.join(storageRoot, 'sessions'); |
| const folders = await fs.readdir(sessionsDir); |
| |
| for (const folder of folders) { |
| try { |
| const filePath = path.join(sessionsDir, folder, 'session_url.json'); |
| const dataStr = await fs.readFile(filePath, 'utf-8'); |
| const state = JSON.parse(dataStr); |
| if (state?.session?.roomCode === roomCode) { |
| return folder; |
| } |
| } catch (err) { } |
| } |
| } catch (err) {} |
| return null; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| async function handleJoin(body: any) { |
| let { sessionId, userId, userName } = body; |
|
|
| |
| if (sessionId && sessionId.length <= 6) { |
| const byCode = sessionManager.getSessionByRoomCode(sessionId); |
| if (byCode) { |
| sessionId = byCode.id; |
| } else { |
| const diskId = await findSessionIdByRoomCode(sessionId); |
| if (diskId) sessionId = diskId; |
| } |
| } |
|
|
| |
| if (!sessionId || !userId || !userName) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Missing required fields: sessionId, userId, userName' |
| }, { status: 400 }); |
| } |
|
|
| |
| const session = sessionManager.getSession(sessionId); |
| if (!session || !session.isActive) { |
| |
| try { |
| const fs = await import('fs/promises'); |
| const path = await import('path'); |
| const storageRoot = process.env.SPACE_ID ? '/data' : path.join(process.cwd(), 'data'); |
| const filePath = path.join(storageRoot, 'sessions', sessionId, 'session_url.json'); |
| const dataStr = await fs.readFile(filePath, 'utf-8'); |
| const oldState = JSON.parse(dataStr); |
| |
| const user = { |
| id: userId, |
| name: userName, |
| role: 'student', |
| sessionId, |
| joinedAt: new Date().toISOString() |
| }; |
|
|
| return NextResponse.json({ |
| success: true, |
| data: { |
| user, |
| ...oldState |
| }, |
| message: 'Joined past session' |
| }); |
| } catch (err) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Session not found or has ended' |
| }, { status: 404 }); |
| } |
| } |
|
|
|
|
|
|
| |
| const user = sessionManager.joinSession(sessionId, userId, userName, 'student'); |
|
|
| |
| const state = sessionManager.getSessionState(sessionId); |
|
|
| return NextResponse.json({ |
| success: true, |
| data: { |
| user, |
| session: state?.session, |
| currentSlide: state?.currentSlide, |
| whiteboardStrokes: state?.whiteboardStrokes, |
| reactions: state?.reactions, |
| activePoll: state?.activePoll |
| }, |
| message: 'Joined session successfully' |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| async function handleEnd(body: any) { |
| const { sessionId } = body; |
|
|
| if (!sessionId) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Missing required field: sessionId' |
| }, { status: 400 }); |
| } |
|
|
| const session = sessionManager.getSession(sessionId); |
| if (!session) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Session not found' |
| }, { status: 404 }); |
| } |
|
|
| await sessionManager.endSession(sessionId); |
|
|
| return NextResponse.json({ |
| success: true, |
| message: 'Session ended successfully' |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| async function handleGet(body: any) { |
| const { sessionId } = body; |
|
|
| if (!sessionId) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Missing required field: sessionId' |
| }, { status: 400 }); |
| } |
|
|
| const state = sessionManager.getSessionState(sessionId); |
| if (!state) { |
| try { |
| const fs = await import('fs/promises'); |
| const path = await import('path'); |
| const storageRoot = process.env.SPACE_ID ? '/data' : path.join(process.cwd(), 'data'); |
| const filePath = path.join(storageRoot, 'sessions', sessionId, 'session_url.json'); |
| const dataStr = await fs.readFile(filePath, 'utf-8'); |
| const oldState = JSON.parse(dataStr); |
| return NextResponse.json({ |
| success: true, |
| data: oldState |
| }); |
| } catch (err) { |
| return NextResponse.json({ |
| success: false, |
| error: 'Session not found' |
| }, { status: 404 }); |
| } |
| } |
|
|
| return NextResponse.json({ |
| success: true, |
| data: state |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
|
|
| async function handleList() { |
| const activeSessions = sessionManager.getAllSessions(); |
| const allSessions = [...activeSessions]; |
|
|
| |
| try { |
| const fs = await import('fs/promises'); |
| const path = await import('path'); |
| const storageRoot = process.env.SPACE_ID ? '/data' : path.join(process.cwd(), 'data'); |
| const sessionsDir = path.join(storageRoot, 'sessions'); |
| const folders = await fs.readdir(sessionsDir).catch(() => []); |
| |
| for (const folder of folders) { |
| |
| if (activeSessions.some(s => s.id === folder)) continue; |
| |
| try { |
| const filePath = path.join(sessionsDir, folder, 'session_url.json'); |
| const dataStr = await fs.readFile(filePath, 'utf-8'); |
| const state = JSON.parse(dataStr); |
| if (state?.session) { |
| allSessions.push(state.session); |
| } |
| } catch (err) {} |
| } |
| } catch (err) {} |
|
|
| return NextResponse.json({ |
| success: true, |
| data: allSessions.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) |
| }); |
| } |
|
|