video sekcija: strani /video/<slug> z 20s napovednikom (predvajljiv na strani, VideoObject) in gumbom na YouTube; API /api/yt-videos; ingest skripta za FOLX YouTube kanal

This commit is contained in:
folx bot
2026-08-23 10:08:17 +02:00
parent 3c9da492a2
commit c8b7def69c
7 changed files with 1812 additions and 1 deletions
+31
View File
@@ -391,6 +391,37 @@ export async function registerRoutes(
const LIBRARY_ID = process.env.BUNNY_LIBRARY_ID || "476412";
const CDN_HOST = process.env.BUNNY_CDN_HOST || "vz-7982dfc4-cc8.b-cdn.net";
// ---- FOLX YouTube video sekcija (napovednik na strani, cel video na YouTube) ----
const ytIndexPath = path.join(uploadDir, "video", "index.json");
function ytItems(): any[] {
try {
const raw = fs.readFileSync(ytIndexPath, "utf-8");
const j = JSON.parse(raw);
return Array.isArray(j.items) ? j.items : [];
} catch {
return [];
}
}
app.get("/api/yt-videos", (req, res) => {
const rubrik = String(req.query.rubrik || "").trim();
const page = Math.max(1, parseInt(String(req.query.page || "1")));
const limit = Math.min(48, Math.max(1, parseInt(String(req.query.limit || "24"))));
let items = ytItems();
if (rubrik && rubrik !== "Alle") items = items.filter((i) => i.rubrik === rubrik);
const total = items.length;
const slice = items.slice((page - 1) * limit, page * limit);
const rubriken = Array.from(new Set(ytItems().map((i) => i.rubrik)));
res.set("Cache-Control", "public, max-age=120");
res.json({ items: slice, total, page, totalPages: Math.max(1, Math.ceil(total / limit)), rubriken });
});
app.get("/api/yt-videos/:slug", (req, res) => {
const it = ytItems().find((i) => i.slug === req.params.slug || i.ytId === req.params.slug);
if (!it) return res.status(404).json({ message: "Video nicht gefunden" });
const same = ytItems().filter((x) => x.rubrik === it.rubrik && x.slug !== it.slug).slice(0, 4);
res.set("Cache-Control", "public, max-age=120");
res.json({ item: it, related: same });
});
app.get("/api/videos", async (req, res) => {
try {
const page = parseInt(req.query.page as string) || 1;