feat(song): add option to exclude songs from global visibility and improve admin upload validation

This commit is contained in:
Hördle Bot
2025-11-24 19:59:47 +01:00
parent 326023a705
commit 67cf85dc22
7 changed files with 174 additions and 18 deletions

View File

@@ -8,6 +8,10 @@ import { requireAdminAuth } from '@/lib/auth';
const prisma = new PrismaClient();
// Configure route to handle large file uploads
export const runtime = 'nodejs';
export const maxDuration = 60; // 60 seconds timeout for uploads
export async function GET() {
const songs = await prisma.song.findMany({
orderBy: { createdAt: 'desc' },
@@ -37,23 +41,35 @@ export async function GET() {
specials: song.specials.map(ss => ss.special),
averageRating: song.averageRating,
ratingCount: song.ratingCount,
excludeFromGlobal: song.excludeFromGlobal,
}));
return NextResponse.json(songsWithActivations);
}
export async function POST(request: Request) {
console.log('[UPLOAD] Starting song upload request');
// Check authentication
const authError = await requireAdminAuth(request as any);
if (authError) return authError;
if (authError) {
console.log('[UPLOAD] Authentication failed');
return authError;
}
try {
console.log('[UPLOAD] Parsing form data...');
const formData = await request.formData();
const file = formData.get('file') as File;
let title = '';
let artist = '';
const excludeFromGlobal = formData.get('excludeFromGlobal') === 'true';
console.log('[UPLOAD] Received file:', file?.name, 'Size:', file?.size, 'Type:', file?.type);
console.log('[UPLOAD] excludeFromGlobal:', excludeFromGlobal);
if (!file) {
console.error('[UPLOAD] No file provided');
return NextResponse.json({ error: 'No file provided' }, { status: 400 });
}
@@ -81,6 +97,7 @@ export async function POST(request: Request) {
}
const buffer = Buffer.from(await file.arrayBuffer());
console.log('[UPLOAD] Buffer created, size:', buffer.length, 'bytes');
// Validate and extract metadata from file
let metadata;
@@ -208,10 +225,9 @@ export async function POST(request: Request) {
console.error('Failed to extract cover image:', e);
}
// Fetch release year (iTunes first, then MusicBrainz)
// Fetch release year from iTunes
let releaseYear = null;
try {
// Try iTunes first
const { getReleaseYearFromItunes } = await import('@/lib/itunes');
releaseYear = await getReleaseYearFromItunes(artist, title);
@@ -229,6 +245,7 @@ export async function POST(request: Request) {
filename,
coverImage,
releaseYear,
excludeFromGlobal,
},
include: { genres: true, specials: true }
});
@@ -249,7 +266,7 @@ export async function PUT(request: Request) {
if (authError) return authError;
try {
const { id, title, artist, releaseYear, genreIds, specialIds } = await request.json();
const { id, title, artist, releaseYear, genreIds, specialIds, excludeFromGlobal } = await request.json();
if (!id || !title || !artist) {
return NextResponse.json({ error: 'Missing fields' }, { status: 400 });
@@ -262,6 +279,10 @@ export async function PUT(request: Request) {
data.releaseYear = releaseYear;
}
if (excludeFromGlobal !== undefined) {
data.excludeFromGlobal = excludeFromGlobal;
}
if (genreIds) {
data.genres = {
set: genreIds.map((gId: number) => ({ id: gId }))