// src/app/(payload)/api/cron/community-sync/route.ts // Unified Community Sync Cron Endpoint import { NextRequest, NextResponse } from 'next/server' import { runUnifiedSync, getUnifiedSyncStatus, type SupportedPlatform, type UnifiedSyncOptions, } from '@/lib/jobs/UnifiedSyncService' // Geheimer Token für Cron-Authentifizierung const CRON_SECRET = process.env.CRON_SECRET /** * GET /api/cron/community-sync * Wird von externem Cron-Job aufgerufen (z.B. Vercel Cron, cron-job.org) * * Query Parameters: * - platforms: Komma-separierte Liste (youtube,facebook,instagram) * - accountIds: Komma-separierte Account-IDs * - analyzeWithAI: true/false (default: true) * - maxItems: Maximale Items pro Account (default: 100) */ export async function GET(request: NextRequest) { // Auth prüfen wenn CRON_SECRET gesetzt if (CRON_SECRET) { const authHeader = request.headers.get('authorization') if (authHeader !== `Bearer ${CRON_SECRET}`) { console.warn('[Cron] Unauthorized request to community-sync') return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } } // Query-Parameter parsen const searchParams = request.nextUrl.searchParams const options: UnifiedSyncOptions = {} // Plattform-Filter const platformsParam = searchParams.get('platforms') if (platformsParam) { const platforms = platformsParam.split(',').map((p) => p.trim().toLowerCase()) const validPlatforms = platforms.filter((p): p is SupportedPlatform => ['youtube', 'facebook', 'instagram'].includes(p) ) if (validPlatforms.length > 0) { options.platforms = validPlatforms } } // Account-ID Filter const accountIdsParam = searchParams.get('accountIds') if (accountIdsParam) { const ids = accountIdsParam .split(',') .map((id) => parseInt(id.trim(), 10)) .filter((id) => !isNaN(id)) if (ids.length > 0) { options.accountIds = ids } } // AI-Analyse const analyzeParam = searchParams.get('analyzeWithAI') if (analyzeParam !== null) { options.analyzeWithAI = analyzeParam !== 'false' } // Max Items const maxItemsParam = searchParams.get('maxItems') if (maxItemsParam) { const maxItems = parseInt(maxItemsParam, 10) if (!isNaN(maxItems) && maxItems > 0) { options.maxItemsPerAccount = maxItems } } console.log('[Cron] Starting community sync', { options }) const result = await runUnifiedSync(options) if (result.success) { // Gesamtstatistiken berechnen let totalNew = 0 let totalUpdated = 0 let totalErrors = 0 for (const platform of Object.values(result.platforms)) { if (platform) { totalNew += platform.totalNewComments totalUpdated += platform.totalUpdatedComments totalErrors += platform.totalErrors } } return NextResponse.json({ success: true, message: `Sync completed: ${totalNew} new, ${totalUpdated} updated comments across ${result.results.length} accounts`, duration: result.duration, platforms: result.platforms, results: result.results, }) } return NextResponse.json( { success: false, errors: result.errors, partialResults: result.results, }, { status: 500 } ) } /** * POST /api/cron/community-sync * Manueller Sync-Trigger mit erweiterten Optionen */ export async function POST(request: NextRequest) { // Auth prüfen if (CRON_SECRET) { const authHeader = request.headers.get('authorization') if (authHeader !== `Bearer ${CRON_SECRET}`) { console.warn('[Cron] Unauthorized POST to community-sync') return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } } try { const body = await request.json() const options: UnifiedSyncOptions = {} // Optionen aus Body übernehmen if (body.platforms && Array.isArray(body.platforms)) { options.platforms = body.platforms.filter((p: string): p is SupportedPlatform => ['youtube', 'facebook', 'instagram'].includes(p) ) } if (body.accountIds && Array.isArray(body.accountIds)) { options.accountIds = body.accountIds.filter( (id: unknown) => typeof id === 'number' && id > 0 ) } if (typeof body.analyzeWithAI === 'boolean') { options.analyzeWithAI = body.analyzeWithAI } if (typeof body.maxItemsPerAccount === 'number' && body.maxItemsPerAccount > 0) { options.maxItemsPerAccount = body.maxItemsPerAccount } if (body.sinceDate) { const date = new Date(body.sinceDate) if (!isNaN(date.getTime())) { options.sinceDate = date } } console.log('[Cron] Manual community sync triggered', { options }) const result = await runUnifiedSync(options) return NextResponse.json({ success: result.success, startedAt: result.startedAt, completedAt: result.completedAt, duration: result.duration, platforms: result.platforms, results: result.results, errors: result.errors, }) } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error' console.error('[Cron] POST error:', error) return NextResponse.json({ error: message }, { status: 500 }) } } /** * HEAD /api/cron/community-sync * Status-Check für Monitoring */ export async function HEAD() { const status = getUnifiedSyncStatus() return new NextResponse(null, { status: status.isRunning ? 423 : 200, // 423 = Locked (running) headers: { 'X-Sync-Running': status.isRunning.toString(), 'X-Current-Platform': status.currentPlatform || 'none', 'X-Current-Account': status.currentAccount || 'none', 'X-Progress': `${status.progress.percentage}%`, 'X-Last-Run': status.lastRunAt || 'never', }, }) } export const dynamic = 'force-dynamic' export const maxDuration = 300 // 5 Minuten max (Vercel)