Implement Specials feature, Admin UI enhancements, and Database Rebuild tool
This commit is contained in:
72
scripts/restore_songs.ts
Normal file
72
scripts/restore_songs.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { parseFile } from 'music-metadata';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
const UPLOADS_DIR = path.join(process.cwd(), 'public/uploads');
|
||||
|
||||
async function restoreSongs() {
|
||||
console.log('Starting song restoration...');
|
||||
|
||||
try {
|
||||
const files = await fs.readdir(UPLOADS_DIR);
|
||||
const mp3Files = files.filter(f => f.endsWith('.mp3'));
|
||||
|
||||
console.log(`Found ${mp3Files.length} MP3 files.`);
|
||||
|
||||
for (const filename of mp3Files) {
|
||||
// Check if song already exists
|
||||
const existing = await prisma.song.findFirst({
|
||||
where: { filename }
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
console.log(`Skipping ${filename} (already exists)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const filePath = path.join(UPLOADS_DIR, filename);
|
||||
|
||||
try {
|
||||
const metadata = await parseFile(filePath);
|
||||
|
||||
const title = metadata.common.title || 'Unknown Title';
|
||||
const artist = metadata.common.artist || 'Unknown Artist';
|
||||
|
||||
// Try to find matching cover
|
||||
// This is a best-effort guess based on timestamp or just null if we can't link it easily
|
||||
// Since we don't store the link between file and cover in filename, we might lose cover association
|
||||
// unless we re-extract it. But we already have cover files.
|
||||
// For now, let's just restore the song entry. Re-extracting cover would duplicate files.
|
||||
// If the user wants covers back perfectly, we might need to re-parse or just leave null.
|
||||
// Let's leave null for now to avoid clutter, or maybe try to find a cover with similar timestamp if possible?
|
||||
// Actually, the cover filename is not easily deducible from song filename.
|
||||
// Let's just restore the song data.
|
||||
|
||||
await prisma.song.create({
|
||||
data: {
|
||||
title,
|
||||
artist,
|
||||
filename,
|
||||
// coverImage: null // We lose the cover link unfortunately, unless we re-extract
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Restored: ${title} - ${artist}`);
|
||||
|
||||
} catch (e) {
|
||||
console.error(`Failed to process ${filename}:`, e);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Restoration complete.');
|
||||
|
||||
} catch (e) {
|
||||
console.error('Error reading uploads directory:', e);
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
restoreSongs();
|
||||
Reference in New Issue
Block a user