fix: use Spotify public web-player token — no Premium/API account needed
Replace Client Credentials flow with Spotify's public web-player token endpoint (open.spotify.com/get_access_token) which works without any account or Premium. Remove Spotify credential fields from UI entirely. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
dc1bec74a1
commit
cfa8a8cd49
4 files changed
+24
-44
No files matched your search
+21
-16
@@ -388,20 +388,26 @@ function enqueue(task) {
|
||||
}
|
||||
|
||||
// ─── SPOTIFY ──────────────────────────────────────────────────────────────────
|
||||
let _spTok = null, _spTokExp = 0, _spCachedId = '';
|
||||
let _spTok = null, _spTokExp = 0;
|
||||
|
||||
async function getSpotifyToken(clientId, clientSecret) {
|
||||
if (_spTok && clientId === _spCachedId && Date.now() < _spTokExp - 30000) return _spTok;
|
||||
const creds = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
|
||||
const r = await fetch('https://accounts.spotify.com/api/token', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Basic ${creds}`, 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: 'grant_type=client_credentials',
|
||||
signal: AbortSignal.timeout(8000),
|
||||
});
|
||||
if (!r.ok) throw new Error(`Spotify Auth fehlgeschlagen (${r.status}) — Client ID/Secret prüfen`);
|
||||
// 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',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(8000),
|
||||
}
|
||||
);
|
||||
if (!r.ok) throw new Error(`Spotify public token fehlgeschlagen (${r.status})`);
|
||||
const d = await r.json();
|
||||
_spTok = d.access_token; _spTokExp = Date.now() + d.expires_in * 1000; _spCachedId = clientId;
|
||||
if (!d.accessToken) throw new Error('Kein Spotify-Token erhalten — Spotify möglicherweise nicht erreichbar');
|
||||
_spTok = d.accessToken;
|
||||
_spTokExp = d.accessTokenExpirationTimestampMs || (Date.now() + 3600000);
|
||||
return _spTok;
|
||||
}
|
||||
|
||||
@@ -418,12 +424,11 @@ app.get('/api/health', (req, res) => {
|
||||
});
|
||||
|
||||
app.post('/api/spotify/resolve', async (req, res) => {
|
||||
const { url, clientId, clientSecret } = req.body;
|
||||
if (!url) return res.status(400).json({ error: 'url required' });
|
||||
if (!clientId || !clientSecret) return res.status(400).json({ error: 'Spotify credentials fehlen (clientId + clientSecret in Einstellungen eintragen)' });
|
||||
const { url } = req.body;
|
||||
if (!url) return res.status(400).json({ error: 'url required' });
|
||||
try {
|
||||
const { type, id } = parseSpotifyUrl(url);
|
||||
const tok = await getSpotifyToken(clientId, clientSecret);
|
||||
const tok = await getSpotifyToken();
|
||||
const spH = { Authorization: `Bearer ${tok}` };
|
||||
const spFetch = (u) => fetch(u, { headers: spH, signal: AbortSignal.timeout(10000) });
|
||||
|
||||
|
||||
Reference in new issue
Block a user