diff --git a/backend/lib/ytdlp.js b/backend/lib/ytdlp.js index ecf1cf3..c8daefc 100644 --- a/backend/lib/ytdlp.js +++ b/backend/lib/ytdlp.js @@ -198,7 +198,10 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb log(jobId, `🔗 Direkter Download: ${sourceUrl}`); await spawnYtdlp([sourceUrl, '--no-playlist', ...baseArgs]); const audioFile = hasAudio() ? expectedAudio : null; - if (!audioFile) { log(jobId, '⚠️ Download fehlgeschlagen'); return { success: true, dir }; } + // Direct-link download failed (e.g. YouTube 403 / bot check) — must report FAILURE, not success. + // Previously returned { success: true }, so the job was marked "done/Fertig!" and the UI wrongly + // said the track was added. + if (!audioFile) { log(jobId, '⚠️ Download fehlgeschlagen'); return { success: false, failed: true, dir }; } return embedMetadata({ jobId, audioFile, dir, trackPrefix, safeTitle, rawArtist, artist, mainArtist, album, year, trackNum, totalTracks, discNum, discTotal, compilation, genre, artworkUrl, explicit, title: searchTitle }); } diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index f18ca28..35a27a7 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -657,6 +657,8 @@ app.post('/api/download', async (req, res) => { updateJob(jobId, { status: 'done', progress: 100, message: 'Bereits vorhanden – übersprungen', skipped: true }); } else if (result?.notFound) { updateJob(jobId, { status: 'error', message: 'Nicht eindeutig gefunden — bitte Direktlink im Importer nutzen' }); + } else if (result?.failed) { + updateJob(jobId, { status: 'error', message: 'Download fehlgeschlagen — YouTube hat den Abruf blockiert (403).' }); } else { updateJob(jobId, { status: 'done', progress: 100, message: 'Fertig!' }); }