fix(backend): normalize iTunes lookup across all download paths
- Track path: always fetch iTunes when durationMs/trackNum missing (not just genre) - Both paths: strip release suffixes from title before iTunes lookup - Log "Album:" instead of "Album aus Spotify:" (also fires for iTunes global search) - Log duration when fetched from iTunes so it's visible in job log Ensures all importers have consistent yt-dlp search filters (duration filter now always runs when iTunes finds the track). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
86d3999628
commit
4cbfa35655
1 file changed
+14
-7
@@ -576,15 +576,19 @@ app.post('/api/download', async (req, res) => {
|
|||||||
if (extra.album) log(jobId, `📋 Album: "${extra.album}" (${extra.year || '?'})`);
|
if (extra.album) log(jobId, `📋 Album: "${extra.album}" (${extra.year || '?'})`);
|
||||||
meta = { ...meta, ...extra, artworkUrl: spArt || extra.artworkUrl || '', genre: meta.genre || extra.genre || undefined };
|
meta = { ...meta, ...extra, artworkUrl: spArt || extra.artworkUrl || '', genre: meta.genre || extra.genre || undefined };
|
||||||
} else {
|
} else {
|
||||||
log(jobId, `📋 Album aus Spotify: "${meta.album}"`);
|
log(jobId, `📋 Album: "${meta.album}"`);
|
||||||
// Spotify enrichment has no genre, totalTracks, or disc info — fetch from iTunes
|
// Always fetch iTunes when any field is missing — durationMs is required for the yt-dlp
|
||||||
if (!meta.genre || !meta.totalTracks) {
|
// duration filter; without it any unrelated video that matches the title text gets downloaded.
|
||||||
const genreMeta = await lookupItunesTrackMeta(searchArtist, title).catch(() => ({}));
|
if (!meta.genre || !meta.totalTracks || !meta.durationMs || !meta.trackNum) {
|
||||||
|
// Strip release-type suffixes before iTunes lookup so "recognize - Single" → "recognize"
|
||||||
|
const RELEASE_SUFFIX_RE = /\s*[-–]\s*(?:(?:official\s+)?(?:music\s+)?(?:single|ep|lp|album|ost|soundtrack|remaster(?:ed)?|deluxe(?:\s+edition)?|bonus\s+tracks?|b-?sides?|version|edit)\b.*|(?:20|19)\d{2})\s*$/i;
|
||||||
|
const itunesTitle = title.replace(RELEASE_SUFFIX_RE, '').trim() || title;
|
||||||
|
const genreMeta = await lookupItunesTrackMeta(searchArtist, itunesTitle).catch(() => ({}));
|
||||||
if (!meta.genre && genreMeta.genre) { meta.genre = genreMeta.genre; log(jobId, `📋 Genre: "${genreMeta.genre}"`); }
|
if (!meta.genre && genreMeta.genre) { meta.genre = genreMeta.genre; log(jobId, `📋 Genre: "${genreMeta.genre}"`); }
|
||||||
if (!meta.totalTracks && genreMeta.totalTracks) { meta.totalTracks = genreMeta.totalTracks; }
|
if (!meta.totalTracks && genreMeta.totalTracks) { meta.totalTracks = genreMeta.totalTracks; }
|
||||||
if (!meta.discNum && genreMeta.discNum) { meta.discNum = genreMeta.discNum; }
|
if (!meta.discNum && genreMeta.discNum) { meta.discNum = genreMeta.discNum; }
|
||||||
if (!meta.discTotal && genreMeta.discTotal) { meta.discTotal = genreMeta.discTotal; }
|
if (!meta.discTotal && genreMeta.discTotal) { meta.discTotal = genreMeta.discTotal; }
|
||||||
if (!meta.durationMs && genreMeta.durationMs) { meta.durationMs = genreMeta.durationMs; }
|
if (!meta.durationMs && genreMeta.durationMs) { meta.durationMs = genreMeta.durationMs; log(jobId, `📋 Duration: ${Math.round(genreMeta.durationMs/1000)}s`); }
|
||||||
if (!meta.trackNum && genreMeta.trackNum) { meta.trackNum = genreMeta.trackNum; }
|
if (!meta.trackNum && genreMeta.trackNum) { meta.trackNum = genreMeta.trackNum; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,6 +655,9 @@ app.post('/api/download', async (req, res) => {
|
|||||||
const batchResults = await Promise.allSettled(batch.map(async track => {
|
const batchResults = await Promise.allSettled(batch.map(async track => {
|
||||||
const trackTitle = track.trackName || '';
|
const trackTitle = track.trackName || '';
|
||||||
const trackArtist = track.artistName || artist || '';
|
const trackArtist = track.artistName || artist || '';
|
||||||
|
// Strip release-type suffixes before iTunes lookup ("Song - Single" → "Song")
|
||||||
|
const RELEASE_SUFFIX_RE = /\s*[-–]\s*(?:(?:official\s+)?(?:music\s+)?(?:single|ep|lp|album|ost|soundtrack|remaster(?:ed)?|deluxe(?:\s+edition)?|bonus\s+tracks?|b-?sides?|version|edit)\b.*|(?:20|19)\d{2})\s*$/i;
|
||||||
|
const itunesTitle = trackTitle.replace(RELEASE_SUFFIX_RE, '').trim() || trackTitle;
|
||||||
// If the frontend already enriched this track with iTunes data (collectionName +
|
// If the frontend already enriched this track with iTunes data (collectionName +
|
||||||
// trackNumber + durationMs all present), skip the re-lookup to avoid a different
|
// trackNumber + durationMs all present), skip the re-lookup to avoid a different
|
||||||
// iTunes result overriding the already-correct enriched metadata.
|
// iTunes result overriding the already-correct enriched metadata.
|
||||||
@@ -660,7 +667,7 @@ app.post('/api/download', async (req, res) => {
|
|||||||
if (alreadyEnriched) {
|
if (alreadyEnriched) {
|
||||||
log(jobId, `📋 Frontend-Metadaten: "${trackArtist} – ${trackTitle}" (${track.collectionName})`);
|
log(jobId, `📋 Frontend-Metadaten: "${trackArtist} – ${trackTitle}" (${track.collectionName})`);
|
||||||
// Spotify enrichment copies album/trackNum/duration but not genre/totalTracks/disc — fetch those
|
// Spotify enrichment copies album/trackNum/duration but not genre/totalTracks/disc — fetch those
|
||||||
const genreMeta = await lookupItunesTrackMeta(searchArtist, trackTitle).catch(() => ({}));
|
const genreMeta = await lookupItunesTrackMeta(searchArtist, itunesTitle).catch(() => ({}));
|
||||||
itunes = {
|
itunes = {
|
||||||
genre: genreMeta.genre,
|
genre: genreMeta.genre,
|
||||||
totalTracks: genreMeta.totalTracks,
|
totalTracks: genreMeta.totalTracks,
|
||||||
@@ -669,7 +676,7 @@ app.post('/api/download', async (req, res) => {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
log(jobId, `📋 iTunes: "${trackArtist} – ${trackTitle}"`);
|
log(jobId, `📋 iTunes: "${trackArtist} – ${trackTitle}"`);
|
||||||
itunes = await lookupItunesTrackMeta(searchArtist, trackTitle);
|
itunes = await lookupItunesTrackMeta(searchArtist, itunesTitle);
|
||||||
}
|
}
|
||||||
// Prefer iTunes-resolved name (from server lookup or frontend enrichment) for sort tags / folders.
|
// Prefer iTunes-resolved name (from server lookup or frontend enrichment) for sort tags / folders.
|
||||||
// trackArtist stays as rawArtist for main tags and YTM search.
|
// trackArtist stays as rawArtist for main tags and YTM search.
|
||||||
|
|||||||
Reference in new issue
Block a user