fix: normalize title comparison in iTunes lookup to handle Spotify dash-variants vs iTunes paren-variants
This commit is contained in:
1 parent
55370ad760
commit
757c7045ba
1 file changed
+22
-4
+22
-4
@@ -67,20 +67,38 @@ async function fetchLyrics(artist, title, album) {
|
|||||||
} catch { return null; }
|
} catch { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize a track title for comparison: unify variant suffixes so that
|
||||||
|
// "don't rush - slowed" and "don't rush (slowed)" are treated as equal.
|
||||||
|
function normalizeTitle(s) {
|
||||||
|
return (s || '')
|
||||||
|
.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
// convert "title - variant" → "title (variant)" so both forms compare equal
|
||||||
|
.replace(/\s+-\s+([^-]+)$/, ' ($1)')
|
||||||
|
// strip all remaining parens/brackets content for the base comparison
|
||||||
|
.replace(/[\[((][^\]))]*[\]))]/g, '')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
// iTunes track lookup — fills in album, year, trackNum, totalTracks, genre when missing
|
// iTunes track lookup — fills in album, year, trackNum, totalTracks, genre when missing
|
||||||
async function lookupItunesTrackMeta(artist, title) {
|
async function lookupItunesTrackMeta(artist, title) {
|
||||||
try {
|
try {
|
||||||
const url = `https://itunes.apple.com/search?term=${encodeURIComponent(artist + ' ' + title)}&media=music&entity=musicTrack&limit=5&country=us&explicit=Yes`;
|
// Search with base title (strip variant suffix) for better iTunes hit rate —
|
||||||
|
// e.g. "don't rush - slowed" → search "don't rush" so iTunes finds the single
|
||||||
|
const baseTitle = title.replace(/\s*[-–]\s*\S[^-]*$/, '').trim() || title;
|
||||||
|
const searchTitle = baseTitle !== title ? baseTitle : title;
|
||||||
|
const url = `https://itunes.apple.com/search?term=${encodeURIComponent(artist + ' ' + searchTitle)}&media=music&entity=musicTrack&limit=10&country=us&explicit=Yes`;
|
||||||
const results = await new Promise((resolve, reject) => {
|
const results = await new Promise((resolve, reject) => {
|
||||||
https.get(url, res => {
|
https.get(url, res => {
|
||||||
let d = ''; res.on('data', c => d += c);
|
let d = ''; res.on('data', c => d += c);
|
||||||
res.on('end', () => { try { resolve(JSON.parse(d).results || []); } catch { reject(new Error('parse')); } });
|
res.on('end', () => { try { resolve(JSON.parse(d).results || []); } catch { reject(new Error('parse')); } });
|
||||||
}).on('error', reject);
|
}).on('error', reject);
|
||||||
});
|
});
|
||||||
const norm = s => s?.toLowerCase().trim() || '';
|
const normT = normalizeTitle(title);
|
||||||
|
const normA = (artist || '').toLowerCase().trim();
|
||||||
const match = results.find(t =>
|
const match = results.find(t =>
|
||||||
norm(t.trackName) === norm(title) &&
|
normalizeTitle(t.trackName) === normT &&
|
||||||
norm(t.artistName).split(' ')[0] === norm(artist).split(' ')[0]
|
(t.artistName || '').toLowerCase().trim().split(' ')[0] === normA.split(' ')[0]
|
||||||
);
|
);
|
||||||
if (!match) return {};
|
if (!match) return {};
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in new issue
Block a user