Files
hoerdle/scripts/migrate-covers.mjs

68 lines
2.3 KiB
JavaScript

import { PrismaClient } from '@prisma/client';
import { parseBuffer } from 'music-metadata';
import { readFile, writeFile, mkdir } 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 mkdir(path.dirname(coverPath), { recursive: true });
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();