Spaces:
No application file
No application file
File size: 1,617 Bytes
972b772 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import { Router, Request, Response } from "express";
import { getJob, updateJob } from "./jobStore";
import { refreshLibrary } from "./jellyfinClient";
const router = Router();
/**
* Marks a job ready and kicks Jellyfin to rescan the library.
*
* This is called directly by the in-process downloader in downloadRoutes.ts,
* but it's also exposed as a real HTTP endpoint below so a future external
* downloader/worker (or a manual retry) can report completion the same way.
*/
export async function markDownloadComplete(jobId: string): Promise<void> {
const job = getJob(jobId);
if (!job) return;
updateJob(jobId, { status: "ready", progress: 100 });
try {
await refreshLibrary();
} catch (err: any) {
// The file is still safely on disk even if Jellyfin's refresh call fails
// (e.g. Jellyfin isn't configured yet) — surface it on the job, but don't
// mark the download itself as failed.
updateJob(jobId, {
error: `Saved, but Jellyfin refresh failed: ${err?.message || "unknown error"}`,
});
}
}
// POST /api/webhook/download-complete — { jobId }
// External callers (a worker, a manual curl, etc.) can report completion here.
router.post("/webhook/download-complete", async (req: Request, res: Response) => {
const { jobId } = req.body || {};
if (typeof jobId !== "string") {
return res.status(400).json({ error: "'jobId' is required." });
}
const job = getJob(jobId);
if (!job) {
return res.status(404).json({ error: "No job with that id." });
}
await markDownloadComplete(jobId);
res.json({ ok: true });
});
export default router;
|