fix: enforce Spotify rate limit cooldown server- and client-side

Server tracks _spRateLimitUntil and rejects retries instantly without
hitting Spotify, returning the remaining wait time. Retrying before the
window expired was resetting Spotify's timer (19s → 7s → 48s).

Frontend now shows a live countdown with a note not to retry early.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-12 20:22:10 +02:00
1 parent 5265aa1f33
commit d4c41a9f92
2 files changed
+34 -11

No files matched your search

+21 -7
View File
@@ -63,13 +63,7 @@ export async function resolveSpotifyLink() {
}
if (e.message.startsWith('RATE_LIMITED:')) {
const secs = parseInt(e.message.split(':')[1], 10) || 30;
const mins = secs >= 60 ? `${Math.ceil(secs / 60)} Min.` : `${secs}s`;
inner.innerHTML = `<div style="color:var(--text);padding:16px;background:var(--surface);border-radius:10px;border-left:3px solid var(--warning,#f59e0b)">
<div style="font-weight:600;margin-bottom:6px">⏳ Spotify Rate Limit</div>
<div style="font-size:13px;line-height:1.5;color:var(--text2)">
Spotify hat zu viele Anfragen erhalten. Bitte in ca. <strong>${mins}</strong> erneut versuchen.
</div>
</div>`;
_startRateLimitCountdown(inner, secs);
return;
}
if (e.message === 'EDITORIAL_PLAYLIST') {
@@ -232,6 +226,26 @@ async function _loadSpotifyTrackArtwork(tracks, listEl) {
}
}
function _startRateLimitCountdown(inner, totalSecs) {
const endMs = Date.now() + totalSecs * 1000;
const render = (remaining) => {
const s = Math.max(0, Math.ceil(remaining / 1000));
const label = s >= 60 ? `${Math.ceil(s / 60)} Min.` : `${s}s`;
inner.innerHTML = `<div style="color:var(--text);padding:16px;background:var(--surface);border-radius:10px;border-left:3px solid var(--warning,#f59e0b)">
<div style="font-weight:600;margin-bottom:6px">⏳ Spotify Rate Limit</div>
<div style="font-size:13px;line-height:1.5;color:var(--text2)">
Bitte warte noch <strong id="sp-rl-countdown">${label}</strong> — nicht erneut versuchen, das setzt den Timer zurück.
</div>
</div>`;
};
render(totalSecs * 1000);
const iv = setInterval(() => {
const remaining = endMs - Date.now();
if (remaining <= 0) { clearInterval(iv); render(0); return; }
render(remaining);
}, 1000);
}
function _setArt(el, url) {
if (!el) return;
const img = document.createElement('img');