import { NextResponse } from "next/server"; import { refreshAllChannelSnapshotsAction } from "../../../channels/actions"; import { channelExists } from "yt-dlp-transcript-common/controller/channels"; import { requestRefreshReport } from "yt-dlp-transcript-common/jobs/snapshotScheduler"; import { getPaths } from "yt-dlp-transcript-common/lib/paths"; import { OpsInputError, opsFail, ops, optBool, optString, reqSlug, } from "../_lib"; export const dynamic = "force-dynamic"; // POST { slug: string } | { all: true } // // BOTH FORMS ANSWER ONCE QUEUED, with the job ids `--wait` follows — the ops // rule (_lib.ts: a job-starting route returns a jobId and never streams). // Every regeneration runs on the one serial refresh-report queue (release 17), // so holding the request until a report is on disk meant waiting for every // walk queued ahead of it: past five minutes, and fetch's own header timeout // ends the CLI with an error while the job goes on to succeed. // // `{ slug }` → `{ ok, jobId, started }`: the job this call queued, or the one // already queued for the channel (`started: false`; it has not started // reading, so it is as fresh). `{ all: true }` → the bulk `{ queued, jobIds, // skipped }` the /channels header button shows. export async function POST(request: Request) { return ops(request, ["slug", "all"], async (body) => { const all = optBool(body, "all"); const slug = optString(body, "slug"); if (all) { if (slug) { throw new OpsInputError('send either "slug" or "all", not both'); } const result = await refreshAllChannelSnapshotsAction(); return NextResponse.json({ ok: true, ...result }); } if (!slug?.trim()) { throw new OpsInputError('"slug" is required (or send { "all": true })'); } // Re-read through reqSlug now that we know it is the single-channel form: // the shape check belongs on the value that reaches a path.join. const checked = reqSlug(body, "slug"); const paths = getPaths(); if (!(await channelExists(paths, checked))) { return opsFail(`Channel "${checked}" not found`, 404); } const requested = await requestRefreshReport(paths, checked); if (!requested.ok) return opsFail(requested.error); return NextResponse.json({ ok: true, jobId: requested.jobId, started: requested.started, }); }); }