chat / public /js /turnstile.js
incognitolm
Update turnstile.js
b312272
Raw
History Blame
3.03 kB
// turnstile.js — show overlay and handle verification
(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');
}
// Helper: set local cookie so reload won't re-show challenge
function setLocalTurnstileCookie() {
try {
document.cookie = 'turnstile=1; path=/; max-age=' + (24 * 3600);
} catch (e) { /* ignore */ }
}
// Attempt websocket verify first, then fallback to REST if needed.
async function doWebsocketVerify(token) {
return new Promise(resolve => {
if (!window.ws || !window.ws.send || !window.ws.isConnected || !window.ws.on) return resolve(false);
// If websocket not connected, bail
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); };
// Listen for server ack
const unsub = window.ws.on('turnstile:ok', () => { onOk(); });
const unsubErr = window.ws.on('turnstile:error', () => { onErr(); });
// Send verify message
try { window.ws.send({ type: 'turnstile:verify', token }); }
catch (e) { unsub(); unsubErr(); resolve(false); }
// Fallback timeout
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;
}
// Global callback for Cloudflare Turnstile — ensure single handling
window.onTurnstileSuccess = async function(token) {
if (!token || handled) return; handled = true;
// Prefer websocket verify for immediate session validation
let ok = await doWebsocketVerify(token);
if (ok) {
setLocalTurnstileCookie();
hideOverlay();
return;
}
// Fallback to REST verify (sets cookie server-side)
ok = await doRestVerify(token);
if (ok) setLocalTurnstileCookie();
if (ok) hideOverlay();
else {
// If both failed, allow retry by resetting handled after short delay
handled = false;
showOverlay();
}
};
// Initialize visibility
if (hasTurnstileCookie()) hideOverlay(); else showOverlay();
})();