Jerryo / src /server /index.ts
EricaLuvGemma's picture
Upload 6 files
972b772 verified
Raw
History Blame Contribute Delete
1.61 kB
import "dotenv/config";
import express, { Request, Response } from "express";
import * as path from "path";
import downloadRoutes from "./downloadRoutes";
import webhookRoutes from "./webhookRoutes";
import jellyfinRoutes from "./jellyfinRoutes";
import { jobEvents, listJobs } from "./jobStore";
const app = express();
const PORT = parseInt(process.env.PORT || "7860", 10); // 7860 = HF Spaces default
app.use(express.json());
app.use(express.static(path.join(__dirname, "..", "public")));
app.use("/api", downloadRoutes);
app.use("/api", webhookRoutes);
app.use("/api", jellyfinRoutes);
// GET /api/events — Server-Sent Events stream of job status changes, so the
// frontend can show "Downloading… Ready. Choose your resolution." live
// without polling.
app.get("/api/events", (req: Request, res: Response) => {
res.set({
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
res.flushHeaders();
// Send current state immediately so a newly-opened tab isn't blank.
res.write(`event: snapshot\ndata: ${JSON.stringify(listJobs())}\n\n`);
const onUpdate = (job: unknown) => {
res.write(`event: update\ndata: ${JSON.stringify(job)}\n\n`);
};
jobEvents.on("update", onUpdate);
const keepAlive = setInterval(() => res.write(": ping\n\n"), 25000);
req.on("close", () => {
clearInterval(keepAlive);
jobEvents.off("update", onUpdate);
});
});
app.get("/healthz", (_req: Request, res: Response) => res.json({ ok: true }));
app.listen(PORT, () => {
console.log(`Domain of Happenings listening on port ${PORT}`);
});