import { PrismaClient } from '@prisma/client'; import { parseBuffer } from 'music-metadata'; import { readFile, writeFile } from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Adjust path to reach root from scripts/ const prisma = new PrismaClient(); async function migrate() { console.log('Starting cover art migration...'); try { // Find songs without cover image const songs = await prisma.song.findMany({ where: { coverImage: null } }); console.log(`Found ${songs.length} songs without cover image.`); for (const song of songs) { try { const filePath = path.join(process.cwd(), 'public/uploads', song.filename); console.log(`Processing ${song.title} (${song.filename})...`); const buffer = await readFile(filePath); const metadata = await parseBuffer(buffer); const picture = metadata.common.picture?.[0]; if (picture) { const extension = picture.format.split('/')[1] || 'jpg'; const coverFilename = `cover-${Date.now()}-${Math.floor(Math.random() * 1000)}.${extension}`; const coverPath = path.join(process.cwd(), 'public/uploads/covers', coverFilename); // Ensure directory exists await writeFile(coverPath, picture.data); // Update DB await prisma.song.update({ where: { id: song.id }, data: { coverImage: coverFilename } }); console.log(`✅ Extracted cover for ${song.title}`); } else { console.log(`⚠️ No cover found for ${song.title}`); } } catch (e) { console.error(`❌ Failed to process ${song.title}:`, e.message); } } console.log('Migration completed.'); } catch (e) { console.error('Migration failed:', e); } finally { await prisma.$disconnect(); } } migrate();