import { NextRequest, NextResponse } from 'next/server' import { getLibrary, resolveLibraryRoot, resolveAndJail } from '@/lib/libraries' import { getComicPageBuffer } from '@/lib/comics' import { requireLibraryAccess } from '@/lib/auth' import { getDb } from '@/lib/db' const EXT_TO_MIME: Record = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.webp': 'image/webp', '.gif': 'image/gif', } export async function GET(request: NextRequest) { const { searchParams } = request.nextUrl const libraryId = searchParams.get('libraryId') const issueKey = searchParams.get('issueKey') const pageIndexStr = searchParams.get('pageIndex') if (!libraryId || !issueKey || pageIndexStr === null) { return NextResponse.json({ error: 'Missing libraryId, issueKey, or pageIndex' }, { status: 400 }) } const pageIndex = parseInt(pageIndexStr, 10) if (isNaN(pageIndex) || pageIndex < 0) { return NextResponse.json({ error: 'Invalid pageIndex' }, { status: 400 }) } const auth = await requireLibraryAccess(request, libraryId) if (auth instanceof NextResponse) return auth const library = getLibrary(libraryId) if (!library) { return NextResponse.json({ error: 'Library not found' }, { status: 404 }) } const db = getDb() const row = db .prepare('SELECT file_path FROM media_items WHERE item_key = ? AND item_type = ?') .get(issueKey, 'comic_issue') as { file_path: string | null } | undefined if (!row?.file_path) { return NextResponse.json({ error: 'Issue not found' }, { status: 404 }) } const root = resolveLibraryRoot(library) let absPath: string try { absPath = resolveAndJail(root, row.file_path) } catch { return NextResponse.json({ error: 'Forbidden' }, { status: 403 }) } const result = getComicPageBuffer(absPath, pageIndex) if (!result) { return NextResponse.json({ error: 'Page not found' }, { status: 404 }) } const mimeType = EXT_TO_MIME[result.ext] ?? 'image/jpeg' return new NextResponse(result.buffer as unknown as BodyInit, { status: 200, headers: { 'Content-Type': mimeType, 'Content-Length': String(result.buffer.length), 'Cache-Control': 'public, max-age=86400', }, }) }