From 55be92480540dcfb08e739b21f8fba9661b433da Mon Sep 17 00:00:00 2001 From: Honey Date: Tue, 28 Apr 2026 01:01:03 +0200 Subject: [PATCH] fix: iTunes functions fall back to direct Apple API when backend not configured _iGet now tries backend proxy first (if backendUrl set), falls back to direct Apple API URL so iTunes search/lookup/charts work regardless of backend config. Co-Authored-By: Claude Sonnet 4.6 --- src/api.js | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/api.js b/src/api.js index 58c1f37..9be995b 100644 --- a/src/api.js +++ b/src/api.js @@ -39,49 +39,71 @@ export async function ndAuth() { return S._ndToken; } -// ─── ITUNES (proxied through backend to avoid Apple's browser origin block) ─── -function _iBase() { return S.cfg.backendUrl || ''; } +// ─── ITUNES ─── +// Try backend proxy first (avoids Apple's 403 browser-origin block). +// Fall back to direct Apple API if no backend is configured or proxy fails. +const ITUNES = 'https://itunes.apple.com'; +const APPLE_RSS = 'https://rss.applemarketingtools.com'; -async function _iGet(path) { +async function _fetch(url) { try { - const r = await fetch(_iBase() + path); - if (!r.ok) return {}; - return await r.json(); + const r = await fetch(url); + const text = await r.text(); + if (!text) return {}; + return JSON.parse(text); } catch { return {}; } } +async function _iGet(proxyPath, directUrl) { + const base = S.cfg.backendUrl; + if (base) { + const d = await _fetch(base + proxyPath); + if (d && Object.keys(d).length) return d; + } + return directUrl ? _fetch(directUrl) : {}; +} + export async function itunesSearch(query, entity='musicTrack', limit=25) { - const d = await _iGet(`/api/itunes/search?term=${encodeURIComponent(query)}&entity=${entity}&limit=${limit}`); + const qs = `term=${encodeURIComponent(query)}&media=music&entity=${entity}&limit=${limit}&country=us&explicit=Yes`; + const d = await _iGet(`/api/itunes/search?term=${encodeURIComponent(query)}&entity=${entity}&limit=${limit}`, + `${ITUNES}/search?${qs}`); return d.results || []; } export async function itunesLookupAlbum(collectionId) { - const d = await _iGet(`/api/itunes/lookup?id=${collectionId}&entity=song`); + const d = await _iGet(`/api/itunes/lookup?id=${collectionId}&entity=song`, + `${ITUNES}/lookup?id=${collectionId}&entity=song&explicit=Yes`); return (d.results || []).filter(x => x.wrapperType === 'track'); } export async function itunesLookupArtistSongs(artistId, limit=15) { - const d = await _iGet(`/api/itunes/lookup?id=${artistId}&entity=song&limit=${limit}`); + const d = await _iGet(`/api/itunes/lookup?id=${artistId}&entity=song&limit=${limit}`, + `${ITUNES}/lookup?id=${artistId}&entity=song&limit=${limit}&country=us&explicit=Yes`); return (d.results || []).filter(x => x.wrapperType === 'track'); } export async function itunesLookupArtistAlbums(artistId, limit=200) { - const d = await _iGet(`/api/itunes/lookup?id=${artistId}&entity=album&limit=${limit}`); + const d = await _iGet(`/api/itunes/lookup?id=${artistId}&entity=album&limit=${limit}`, + `${ITUNES}/lookup?id=${artistId}&entity=album&limit=${limit}&country=us`); return (d.results || []).filter(x => x.wrapperType === 'collection' && x.collectionType === 'Album'); } export async function itunesTopCharts() { for (const country of ['de', 'us']) { - const d = await _iGet(`/api/itunes/charts?type=albums&country=${country}`); - if (d.results?.length) return d.results; + const d = await _iGet(`/api/itunes/charts?type=albums&country=${country}`, + `${APPLE_RSS}/api/v2/${country}/music/most-played/50/albums.json`); + const results = d.results || d.feed?.results; + if (results?.length) return results; } return []; } export async function itunesTopSongs() { for (const country of ['de', 'us']) { - const d = await _iGet(`/api/itunes/charts?type=songs&country=${country}`); - if (d.results?.length) return d.results; + const d = await _iGet(`/api/itunes/charts?type=songs&country=${country}`, + `${APPLE_RSS}/api/v2/${country}/music/most-played/50/songs.json`); + const results = d.results || d.feed?.results; + if (results?.length) return results; } return []; }