Files
flimmer/src/app/api/cron/sync/route.ts
T
Florian Wilde 969353ab32 feat: täglicher Abgleich mit TMDB
Frischt laufende Serien auf, meldet neue Episoden und neu verfügbare
Watchlist-Titel, räumt Papierkorb und abgelaufene Sitzungen.

Grundsatz: Der Lauf darf nie an einem einzelnen Titel scheitern. Fehler werden
gezählt und protokolliert, der Lauf macht weiter.

Neue Episoden werden nur gemeldet, wenn sie zeitlich nicht in ferner
Vergangenheit liegen — sonst löste der erste Abgleich einer alten Serie hundert
Meldungen aus.

Der Zeitplan ist ein einfacher Timer statt einer Cron-Bibliothek: Flimmer
braucht genau einen täglichen Lauf. Wer mehr will, stösst /api/cron/sync von
aussen an.
2026-09-01 20:24:47 +02:00

39 lines
1.2 KiB
TypeScript

import { NextResponse } from "next/server";
import { env } from "@/lib/env";
import { getSessionUser } from "@/lib/auth";
import { runSync } from "@/lib/sync";
export const dynamic = "force-dynamic";
export const maxDuration = 300;
/**
* Abgleich von außen anstoßen.
*
* curl -X POST -H "Authorization: Bearer $CRON_SECRET" \
* https://flimmer.example/api/cron/sync
*
* Zugelassen ist entweder das Cron-Geheimnis oder eine angemeldete
* Administration — Letzteres für den Knopf im Verwaltungsbereich.
*/
async function authorize(request: Request): Promise<boolean> {
const header = request.headers.get("authorization");
if (env.scheduler.cronSecret && header === `Bearer ${env.scheduler.cronSecret}`) return true;
const user = await getSessionUser();
return user?.role === "ADMIN";
}
export async function POST(request: Request) {
if (!(await authorize(request))) {
return NextResponse.json({ error: "Nicht berechtigt." }, { status: 401 });
}
const stats = await runSync();
return NextResponse.json({ ok: stats.errors.length === 0, ...stats });
}
/** GET erlaubt einfache Uptime-Cron-Dienste, die kein POST können. */
export async function GET(request: Request) {
return POST(request);
}