Push reading statuses (PLANNING/CURRENT/COMPLETED) to AniList for all linked series that changed since last sync, or have new books/no sync yet. - Migration 0057: adds reading_status_push to index_jobs type constraint - Migration 0058: creates reading_status_push_results table (pushed/skipped/no_books/error) - API: new reading_status_push module with start_push, get_push_report, get_push_results - Differential detection: synced_at IS NULL OR reading progress updated OR new books added - Same 429 retry logic as reading_status_match (wait 10s, retry once, abort on 2nd 429) - Notifications: ReadingStatusPushCompleted/Failed events - Backoffice: push button in reading status group, job detail report with per-series list - Replay support, badge label, i18n (FR + EN) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
45 lines
2.2 KiB
TypeScript
45 lines
2.2 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { apiFetch, IndexJobDto, rebuildIndex, rebuildThumbnails, regenerateThumbnails, startMetadataBatch, startMetadataRefresh, startReadingStatusMatch, startReadingStatusPush } from "@/lib/api";
|
|
|
|
export async function POST(
|
|
_request: NextRequest,
|
|
{ params }: { params: Promise<{ id: string }> }
|
|
) {
|
|
const { id } = await params;
|
|
try {
|
|
const job = await apiFetch<IndexJobDto>(`/index/jobs/${id}`);
|
|
const libraryId = job.library_id ?? undefined;
|
|
|
|
switch (job.type) {
|
|
case "rebuild":
|
|
return NextResponse.json(await rebuildIndex(libraryId));
|
|
case "full_rebuild":
|
|
return NextResponse.json(await rebuildIndex(libraryId, true));
|
|
case "rescan":
|
|
return NextResponse.json(await rebuildIndex(libraryId, false, true));
|
|
case "scan":
|
|
return NextResponse.json(await rebuildIndex(libraryId));
|
|
case "thumbnail_rebuild":
|
|
return NextResponse.json(await rebuildThumbnails(libraryId));
|
|
case "thumbnail_regenerate":
|
|
return NextResponse.json(await regenerateThumbnails(libraryId));
|
|
case "metadata_batch":
|
|
if (!libraryId) return NextResponse.json({ error: "Library ID required for metadata batch" }, { status: 400 });
|
|
return NextResponse.json(await startMetadataBatch(libraryId));
|
|
case "metadata_refresh":
|
|
if (!libraryId) return NextResponse.json({ error: "Library ID required for metadata refresh" }, { status: 400 });
|
|
return NextResponse.json(await startMetadataRefresh(libraryId));
|
|
case "reading_status_match":
|
|
if (!libraryId) return NextResponse.json({ error: "Library ID required for reading status match" }, { status: 400 });
|
|
return NextResponse.json(await startReadingStatusMatch(libraryId));
|
|
case "reading_status_push":
|
|
if (!libraryId) return NextResponse.json({ error: "Library ID required for reading status push" }, { status: 400 });
|
|
return NextResponse.json(await startReadingStatusPush(libraryId));
|
|
default:
|
|
return NextResponse.json({ error: `Cannot replay job type: ${job.type}` }, { status: 400 });
|
|
}
|
|
} catch (error) {
|
|
return NextResponse.json({ error: "Failed to replay job" }, { status: 500 });
|
|
}
|
|
}
|