Spaces:
No application file
No application file
| 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}`); | |
| }); | |