Fix: Enhance release year migration with fuzzy search, more retries, and detailed logging
This commit is contained in:
@@ -12,13 +12,13 @@ const prisma = new PrismaClient();
|
|||||||
|
|
||||||
const MUSICBRAINZ_API_BASE = 'https://musicbrainz.org/ws/2';
|
const MUSICBRAINZ_API_BASE = 'https://musicbrainz.org/ws/2';
|
||||||
const USER_AGENT = 'hoerdle/0.1.0 ( elpatron@mailbox.org )';
|
const USER_AGENT = 'hoerdle/0.1.0 ( elpatron@mailbox.org )';
|
||||||
const RATE_LIMIT_DELAY = 100; // 100ms between requests (conservative)
|
const RATE_LIMIT_DELAY = 250; // 250ms between requests (very conservative)
|
||||||
|
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchWithRetry(url, maxRetries = 5) {
|
async function fetchWithRetry(url, maxRetries = 10) {
|
||||||
let lastError = null;
|
let lastError = null;
|
||||||
|
|
||||||
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||||
@@ -52,29 +52,40 @@ async function fetchWithRetry(url, maxRetries = 5) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getReleaseYear(artist, title) {
|
async function getReleaseYear(artist, title) {
|
||||||
try {
|
const search = async (query, type) => {
|
||||||
const query = `artist:"${artist}" AND recording:"${title}"`;
|
const url = `${MUSICBRAINZ_API_BASE}/recording?query=${encodeURIComponent(query)}&fmt=json&limit=5`;
|
||||||
const url = `${MUSICBRAINZ_API_BASE}/recording?query=${encodeURIComponent(query)}&fmt=json&limit=10`;
|
|
||||||
|
|
||||||
await sleep(RATE_LIMIT_DELAY);
|
await sleep(RATE_LIMIT_DELAY);
|
||||||
|
|
||||||
const response = await fetchWithRetry(url);
|
const response = await fetchWithRetry(url);
|
||||||
|
if (!response.ok) throw new Error(`API Error ${response.status}: ${response.statusText}`);
|
||||||
|
return response.json();
|
||||||
|
};
|
||||||
|
|
||||||
if (!response.ok) {
|
try {
|
||||||
console.error(`MusicBrainz API error: ${response.status} ${response.statusText}`);
|
// 1. Strict Search
|
||||||
return null;
|
let data = await search(`artist:"${artist}" AND recording:"${title}"`, 'strict');
|
||||||
|
|
||||||
|
// 2. Fallback: Fuzzy Search if no recordings found
|
||||||
|
if (!data.recordings || data.recordings.length === 0) {
|
||||||
|
// Remove special chars and quotes for fuzzy search
|
||||||
|
const cleanArtist = artist.replace(/[^\w\s]/g, ' ').replace(/\s+/g, ' ').trim();
|
||||||
|
const cleanTitle = title.replace(/[^\w\s]/g, ' ').replace(/\s+/g, ' ').trim();
|
||||||
|
|
||||||
|
// Only try fuzzy if the cleaned strings are valid
|
||||||
|
if (cleanArtist && cleanTitle) {
|
||||||
|
console.log(` Trying fuzzy search for: ${cleanTitle} by ${cleanArtist}`);
|
||||||
|
data = await search(`artist:${cleanArtist} AND recording:${cleanTitle}`, 'fuzzy');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (!data.recordings || data.recordings.length === 0) {
|
if (!data.recordings || data.recordings.length === 0) {
|
||||||
// console.log(`No recordings found for "${title}" by "${artist}"`);
|
console.log(` ❌ No recordings found for "${title}" by "${artist}"`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let earliestYear = null;
|
let earliestYear = null;
|
||||||
|
|
||||||
for (const recording of data.recordings) {
|
for (const recording of data.recordings) {
|
||||||
|
// Check releases linked to recording
|
||||||
if (recording.releases && recording.releases.length > 0) {
|
if (recording.releases && recording.releases.length > 0) {
|
||||||
for (const release of recording.releases) {
|
for (const release of recording.releases) {
|
||||||
if (release.date) {
|
if (release.date) {
|
||||||
@@ -86,6 +97,7 @@ async function getReleaseYear(artist, title) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check first-release-date on recording itself
|
||||||
if (recording['first-release-date']) {
|
if (recording['first-release-date']) {
|
||||||
const year = parseInt(recording['first-release-date'].split('-')[0]);
|
const year = parseInt(recording['first-release-date'].split('-')[0]);
|
||||||
if (!isNaN(year) && (earliestYear === null || year < earliestYear)) {
|
if (!isNaN(year) && (earliestYear === null || year < earliestYear)) {
|
||||||
@@ -94,9 +106,15 @@ async function getReleaseYear(artist, title) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (earliestYear) {
|
||||||
|
// console.log(` ✅ Found year: ${earliestYear}`);
|
||||||
|
} else {
|
||||||
|
console.log(` ⚠️ Recordings found but NO YEAR for "${title}" by "${artist}"`);
|
||||||
|
}
|
||||||
|
|
||||||
return earliestYear;
|
return earliestYear;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error fetching release year for "${title}" by "${artist}":`, error.message);
|
console.error(` ❌ Error fetching release year for "${title}" by "${artist}":`, error.message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user