Fix: Enhance release year migration with fuzzy search, more retries, and detailed logging

This commit is contained in:
Hördle Bot
2025-11-23 22:35:10 +01:00
parent 27ed9eedb2
commit ceae0266b8

View File

@@ -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;
} }
} }