import { NextResponse, type NextRequest } from 'next/server' import { getPayload } from 'payload' import config from '@payload-config' import { downloadAndUploadImage } from '@/lib/utils/media-download' import { getYouTubeThumbnail } from '@/lib/utils/youtube' /** * POST /api/youtube/thumbnails/bulk * * Bulk-Download von YouTube-Thumbnails für alle YouTubeContent-Einträge * die noch kein Thumbnail haben. Erfordert Super-Admin-Rechte. * * Query-Parameter: * - dryRun=true: Zeigt nur was passieren würde, ohne tatsächlich herunterzuladen */ export async function POST(req: NextRequest) { try { const payload = await getPayload({ config }) const { user } = await payload.auth({ headers: req.headers }) if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const typedUser = user as { isSuperAdmin?: boolean } if (!typedUser.isSuperAdmin) { return NextResponse.json({ error: 'Super-Admin erforderlich' }, { status: 403 }) } const dryRun = req.nextUrl.searchParams.get('dryRun') === 'true' // Find all YouTubeContent without thumbnail that have a videoId const contentWithoutThumbnail = await payload.find({ collection: 'youtube-content', where: { thumbnail: { exists: false }, 'youtube.videoId': { exists: true }, }, limit: 500, depth: 0, }) const results = { processed: 0, downloaded: 0, skipped: 0, errors: 0, dryRun } for (const doc of contentWithoutThumbnail.docs) { results.processed++ const videoId = doc.youtube?.videoId if (!videoId) { results.skipped++ continue } if (dryRun) { results.downloaded++ continue } try { const thumbnailUrl = getYouTubeThumbnail(videoId, 'hq') const filename = `yt-thumb-${videoId}.jpg` const tenantId = typeof doc.tenant === 'object' ? doc.tenant?.id : doc.tenant const mediaId = await downloadAndUploadImage(payload, { url: thumbnailUrl, filename, alt: `Thumbnail: ${typeof doc.title === 'string' ? doc.title : doc.title?.de || videoId}`, tenantId: tenantId || undefined, }) if (mediaId) { await payload.update({ collection: 'youtube-content', id: doc.id, data: { thumbnail: mediaId }, depth: 0, }) results.downloaded++ } else { results.errors++ } } catch { results.errors++ } // Rate-limit delay (500ms between downloads) await new Promise((resolve) => setTimeout(resolve, 500)) } return NextResponse.json(results) } catch (error) { console.error('[yt-thumbnail-bulk] Error:', error) return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }) } }