Implement Specials feature, Admin UI enhancements, and Database Rebuild tool

This commit is contained in:
Hördle Bot
2025-11-22 16:09:45 +01:00
parent c270f2098f
commit 903d626699
16 changed files with 816 additions and 37 deletions

72
scripts/restore_songs.ts Normal file
View 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();