diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index d810a8b..d04a4d1 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -388,42 +388,66 @@ function enqueue(task) { } // ─── SPOTIFY ────────────────────────────────────────────────────────────────── -let _spTok = null, _spTokExp = 0; - -// Uses Spotify's public web-player token — no account or Premium required -async function getSpotifyToken() { - if (_spTok && Date.now() < _spTokExp - 60000) return _spTok; - const r = await fetch( - '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 (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 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'); - _spTok = d.accessToken; - _spTokExp = d.accessTokenExpirationTimestampMs || (Date.now() + 3600000); - return _spTok; -} +// Scrapes Spotify's public embed pages — no token, no account, no Premium needed. +// Embed pages serve __NEXT_DATA__ JSON to anyone (used for website embeds worldwide). function parseSpotifyUrl(url) { - // 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]+)/); + // Handles locale prefixes: /intl-de/track/... and plain /track/... + const m = url.match(/open\.spotify\.com\/(?:[a-z]{2,8}-[a-z]{2,8}\/)?(?: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] }; } +async function fetchSpotifyEmbed(type, id) { + const r = await fetch(`https://open.spotify.com/embed/${type}/${id}`, { + headers: { + '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: 'text/html,application/xhtml+xml', + 'Accept-Language': 'en-US,en;q=0.9', + }, + signal: AbortSignal.timeout(12000), + }); + if (!r.ok) throw new Error(`Spotify-Embed nicht erreichbar (${r.status})`); + const html = await r.text(); + const m = html.match(/