import { NextRequest, NextResponse } from "next/server"; import { assertLocalRequest } from "@/lib/api/localOnly"; import { enqueueJob, cancelAllQueued } from "@/lib/whisperjav/queue"; import { rawDb } from "@/lib/db/client"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; /** Enqueue WhisperJAV for many codes at once. Each code becomes a * separate row in whisperjav_jobs; the single-worker loop processes * them sequentially. Codes that already have a generated subtitle * are skipped (alreadyExists), not failed. */ export async function POST(req: NextRequest) { const blocked = assertLocalRequest(req); if (blocked) return blocked; const body = await req.json().catch(() => ({})); const rawCodes = Array.isArray(body.codes) ? body.codes : []; const codes = rawCodes .filter((c: unknown): c is string => typeof c === "string" && c.trim().length > 0) .map((c: string) => c.trim()); if (codes.length === 0) { return NextResponse.json({ enqueued: 0, skipped: 0, errors: [] }); } let enqueued = 0; let skipped = 0; const errors: Array<{ code: string; error: string }> = []; for (const code of codes) { try { // Always part 0 for batch — multi-part videos are uncommon and // the user can hit individual codes via the player picker for // those edge cases. const result = await enqueueJob({ code, partIdx: 0, overwrite: false }); if ("alreadyExists" in result) skipped++; else enqueued++; } catch (e) { errors.push({ code, error: (e as Error).message }); } } return NextResponse.json({ enqueued, skipped, errors }); } /** Cancel every queued (not-yet-running) job. Useful when the user * wants to stop a batch mid-flight. The currently-running job is * left alone — kill it via the per-job cancel endpoint. */ export async function DELETE(req: NextRequest) { const blocked = assertLocalRequest(req); if (blocked) return blocked; const cancelled = cancelAllQueued(); return NextResponse.json({ cancelled }); } /** Lightweight queue-state probe used by the batch UI: how many jobs * are queued/running right now, plus the active row's id. */ export async function GET(req: NextRequest) { const blocked = assertLocalRequest(req); if (blocked) return blocked; const queued = (rawDb .prepare(`SELECT COUNT(*) AS n FROM whisperjav_jobs WHERE status = 'queued'`) .get() as { n: number }).n; const running = rawDb .prepare(`SELECT id, code, started_at, stage, stage_index, stage_total FROM whisperjav_jobs WHERE status = 'running' ORDER BY started_at DESC LIMIT 1`) .get() as { id: string; code: string; started_at: number | null; stage: string | null; stage_index: number | null; stage_total: number | null } | undefined; return NextResponse.json({ queued, running: running ?? null }); }