diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index 7d8e517..d810a8b 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -397,22 +397,29 @@ async function getSpotifyToken() { 'https://open.spotify.com/get_access_token?reason=transport&productType=web_player', { headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36', Accept: 'application/json', + 'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8', + Cookie: 'sp_t=1', + Referer: 'https://open.spotify.com/', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'same-origin', }, signal: AbortSignal.timeout(8000), } ); - if (!r.ok) throw new Error(`Spotify public token fehlgeschlagen (${r.status})`); + if (!r.ok) throw new Error(`Spotify token fehlgeschlagen (${r.status}) — Server-IP möglicherweise von Spotify geblockt`); const d = await r.json(); - if (!d.accessToken) throw new Error('Kein Spotify-Token erhalten — Spotify möglicherweise nicht erreichbar'); + if (!d.accessToken) throw new Error('Kein Spotify-Token erhalten'); _spTok = d.accessToken; _spTokExp = d.accessTokenExpirationTimestampMs || (Date.now() + 3600000); return _spTok; } function parseSpotifyUrl(url) { - const m = url.match(/open\.spotify\.com\/(track|album|playlist)\/([A-Za-z0-9]+)/); + // Handles locale prefixes: open.spotify.com/intl-de/track/... or open.spotify.com/track/... + const m = url.match(/open\.spotify\.com\/(?:[a-z]{2,5}-[a-z]{2,5}\/)?(?:intl-[a-z-]+\/)?(track|album|playlist)\/([A-Za-z0-9]+)/); if (!m) throw new Error('Ungültige Spotify-URL — erwartet: open.spotify.com/track|album|playlist/...'); return { type: m[1], id: m[2] }; }