From 560d95cfc089b6ef2e9353b7b463c818f994cacb Mon Sep 17 00:00:00 2001 From: floegger Date: Sun, 17 May 2026 19:15:03 +0200 Subject: [PATCH] fix bandcamp login --- audiocontrol/src/components/SettingsPanel.jsx | 84 ++++++++++--- bandcamp-api/app.py | 119 ++++++++++++++++-- scripts/bandcamp-sync.py | 118 ++++++++++++----- 3 files changed, 258 insertions(+), 63 deletions(-) diff --git a/audiocontrol/src/components/SettingsPanel.jsx b/audiocontrol/src/components/SettingsPanel.jsx index 2d5c8dd..cd724d0 100644 --- a/audiocontrol/src/components/SettingsPanel.jsx +++ b/audiocontrol/src/components/SettingsPanel.jsx @@ -251,13 +251,15 @@ function SpotifySection() { // ── Bandcamp credentials ────────────────────────────────────────────────────── function BandcampSection() { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - const [pwdSet, setPwdSet] = useState(false); - const [loaded, setLoaded] = useState(false); - const [saveState, setSaveState] = useState('idle'); - const [testState, setTestState] = useState('idle'); - const [testMsg, setTestMsg] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [cookies, setCookies] = useState(''); + const [pwdSet, setPwdSet] = useState(false); + const [cookiesSet, setCookiesSet] = useState(false); + const [loaded, setLoaded] = useState(false); + const [saveState, setSaveState] = useState('idle'); + const [testState, setTestState] = useState('idle'); + const [testMsg, setTestMsg] = useState(''); useEffect(() => { fetch('/api/bandcamp/credentials') @@ -265,6 +267,7 @@ function BandcampSection() { .then(data => { setEmail(data.email || ''); setPwdSet(!!data.password_set); + setCookiesSet(!!data.cookies_set); setLoaded(true); }) .catch(() => setLoaded(true)); @@ -275,6 +278,7 @@ function BandcampSection() { try { const body = { email }; if (password) body.password = password; + if (cookies) body.cookies = cookies; const r = await fetch('/api/bandcamp/credentials', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -282,16 +286,26 @@ function BandcampSection() { }); if (!r.ok) throw new Error(); setSaveState('ok'); - if (password) setPwdSet(true); - setPassword(''); + if (password) { setPwdSet(true); setPassword(''); } + if (cookies) { setCookiesSet(true); setCookies(''); } } catch { setSaveState('error'); } setTimeout(() => setSaveState('idle'), 4000); }; - const testLogin = async () => { - if (email || password) await save(); + const clearCookies = async () => { + try { + const r = await fetch('/api/bandcamp/credentials', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ cookies: '' }), + }); + if (r.ok) { setCookiesSet(false); setCookies(''); } + } catch {} + }; + + const testConnection = async () => { setTestState('testing'); setTestMsg(''); try { @@ -299,8 +313,8 @@ function BandcampSection() { const data = await r.json(); setTestState(data.ok ? 'ok' : 'error'); setTestMsg(data.ok - ? `Logged in${data.username ? ` as ${data.username}` : ''}` - : (data.error || 'Login failed')); + ? `Connected${data.username ? ` as ${data.username}` : ''}` + : (data.error || 'Connection failed')); } catch { setTestState('error'); setTestMsg('Could not reach bandcamp-api service'); @@ -310,10 +324,42 @@ function BandcampSection() { return ( <> +
+ Session cookies bypass Bandcamp's login captcha and are used first when saved. + Log in at{' '} + + bandcamp.com + + {' '}in your browser, open DevTools (F12) → Network tab → click any bandcamp.com + request → Request Headers → copy the Cookie value and paste it below. +
+ +
+
+
Session Cookies
+
+ {!loaded ? '…' : cookiesSet + ? Saved — + : 'Not saved'} +
+
+