| |
| (function() { |
| let handled = false; |
| function hasTurnstileCookie() { |
| return document.cookie.split(';').some(c => c.trim().startsWith('turnstile=')); |
| } |
|
|
| const overlay = document.getElementById('turnstile-overlay'); |
| const pageRoot = document.getElementById('app') || document.body; |
|
|
| function hideOverlay() { |
| if (overlay) overlay.style.display = 'none'; |
| if (pageRoot) pageRoot.classList.remove('page-faded'); |
| } |
| function showOverlay() { |
| if (overlay) overlay.style.display = 'flex'; |
| if (pageRoot) pageRoot.classList.add('page-faded'); |
| } |
|
|
| |
| function setLocalTurnstileCookie() { |
| try { |
| document.cookie = 'turnstile=1; path=/; max-age=' + (24 * 3600); |
| } catch (e) { } |
| } |
|
|
| |
| async function doWebsocketVerify(token) { |
| return new Promise(resolve => { |
| if (!window.ws || !window.ws.send || !window.ws.isConnected || !window.ws.on) return resolve(false); |
| |
| if (!window.ws.isConnected()) return resolve(false); |
|
|
| let done = false; |
| const onOk = () => { if (done) return; done = true; try { unsub(); unsubErr(); } catch {} resolve(true); }; |
| const onErr = () => { if (done) return; done = true; try { unsub(); unsubErr(); } catch {} resolve(false); }; |
|
|
| |
| const unsub = window.ws.on('turnstile:ok', () => { onOk(); }); |
| const unsubErr = window.ws.on('turnstile:error', () => { onErr(); }); |
|
|
| |
| try { window.ws.send({ type: 'turnstile:verify', token }); } |
| catch (e) { unsub(); unsubErr(); resolve(false); } |
|
|
| |
| setTimeout(() => { if (!done) { try { unsub(); unsubErr(); } catch {} resolve(false); } }, 3500); |
| }); |
| } |
|
|
| async function doRestVerify(token) { |
| try { |
| const r = await fetch('/api/turnstile', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token }) }); |
| if (r.ok) return true; |
| } catch (e) { console.error('Turnstile REST verify failed', e); } |
| return false; |
| } |
|
|
| |
| window.onTurnstileSuccess = async function(token) { |
| if (!token || handled) return; handled = true; |
|
|
| |
| let ok = await doWebsocketVerify(token); |
| if (ok) { |
| setLocalTurnstileCookie(); |
| hideOverlay(); |
| return; |
| } |
|
|
| |
| ok = await doRestVerify(token); |
| if (ok) setLocalTurnstileCookie(); |
| if (ok) hideOverlay(); |
| else { |
| |
| handled = false; |
| showOverlay(); |
| } |
| }; |
|
|
| |
| if (hasTurnstileCookie()) hideOverlay(); else showOverlay(); |
| })(); |
|
|