"use server"; import { getPaths } from "yt-dlp-transcript-common/lib/paths"; import { isValidSiteId, listSiteIds } from "yt-dlp-transcript-common/lib/site"; import { isReportId } from "yt-dlp-transcript-common/lib/report/schema"; import { REPORT_EXPORT_FORMATS, type ReportExportFormat, } from "yt-dlp-transcript-common/lib/report/views"; import { runManagedFunction, type StreamActionResult, } from "yt-dlp-transcript-common/jobs/streamCommand"; import { exportSiteReports, formatReportExportProblems, } from "yt-dlp-transcript-common/publish/reportExports"; import { REPORTS_PREPARE_QUEUE } from "./reportsQueue"; // EXPORT A REPORT SITE'S REPORTS as a job: each published report as // report.html, report.pdf, report.md and an evidence pack, into // `.export-index/sites//report-exports//`, where compose // publishes them from. The work is publish/reportExports.ts's, the same // `archilyzer reports export` runs. The job FAILS when an export cannot be // written (the log names each); a PDF skipped for want of a browser is a // note in the log, not a failure. // // On prepare's queue: it reads the media cache a prepare writes and prunes. // The spec's `slug` is the SITE id; the replay handler reads `params`. export async function reportsExportAction( siteId: string, opts: { reportId?: string; formats?: string[] } = {}, ): Promise { const paths = getPaths(); const id = siteId.trim(); if (!isValidSiteId(id)) { return { ok: false, error: `"${id}" is not a valid site id` }; } if (!listSiteIds(paths).includes(id)) { return { ok: false, error: `No site "${id}"` }; } if (opts.reportId !== undefined && !isReportId(opts.reportId)) { return { ok: false, error: `"${opts.reportId}" is not a report id` }; } let formats: ReportExportFormat[] | undefined; if (opts.formats !== undefined) { const bad = opts.formats.filter( (f) => !(REPORT_EXPORT_FORMATS as readonly string[]).includes(f), ); if (bad.length > 0 || opts.formats.length === 0) { return { ok: false, error: `formats are some of ${REPORT_EXPORT_FORMATS.join(", ")}${bad.length ? ` (not ${bad.join(", ")})` : ""}`, }; } formats = REPORT_EXPORT_FORMATS.filter((f) => opts.formats!.includes(f)); } return runManagedFunction({ kind: "reports-export", queueKey: REPORTS_PREPARE_QUEUE, paths, spec: { kind: "reports-export", slug: id, params: { siteId: id, ...(opts.reportId ? { reportId: opts.reportId } : {}), ...(formats ? { formats } : {}), }, }, fn: async (onLog, signal) => { const result = await exportSiteReports({ siteId: id, paths, onLog, signal, ...(opts.reportId ? { reportId: opts.reportId } : {}), ...(formats ? { formats } : {}), }); for (const r of result.exported) { for (const note of r.manifest.notes) onLog(`note: ${r.reportId}: ${note}`); } if (result.problems.length === 0) return; for (const line of formatReportExportProblems(result.problems)) onLog(line); throw new Error( `${result.problems.length} problem(s): the reports were not all exported`, ); }, }); }