(function () { function apiOrigin() { var m = document.querySelector('meta[name="auth-api-origin"]'); return m && m.content ? m.content.trim() : ""; } function apiUrl(path) { var o = apiOrigin(); if (path.charAt(0) !== "/") path = "/" + path; return o + path; } function readJsonBody(r) { return r.text().then(function (text) { if (!text || !text.trim()) return {}; try { return JSON.parse(text); } catch (e) { return { error: "INVALID_RESPONSE" }; } }); } function appendTurnstileLoadError(el, message) { if (!el || el.querySelector("[data-ts-load-error]")) return; var p = document.createElement("p"); p.className = "auth-hint"; p.setAttribute("data-ts-load-error", "1"); p.textContent = message; el.appendChild(p); } window.AITOKENS_AUTH = { apiUrl: apiUrl, fetchConfig: function () { return fetch(apiUrl("/api/auth/config"), { credentials: "omit" }) .then(readJsonBody) .catch(function () { return { turnstileSiteKey: "" }; }); }, get: function (path) { return fetch(apiUrl(path), { credentials: "include" }).then(function (r) { return readJsonBody(r).then(function (data) { return { ok: r.ok, status: r.status, data: data }; }); }); }, post: function (path, body) { return fetch(apiUrl(path), { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }).then(function (r) { return readJsonBody(r).then(function (data) { return { ok: r.ok, status: r.status, data: data }; }); }); }, mountTurnstile: function (el, sitekey, cb) { if (!sitekey) { el.innerHTML = '

Configure TURNSTILE_SITE_KEY on the API, or set DEV_SKIP_TURNSTILE=1 in development.

'; if (cb) cb(null); return; } el.innerHTML = ""; var errMsg = "Security check did not load. Allow scripts and frames from challenges.cloudflare.com, disable blockers, and in Cloudflare Turnstile add hostnames aitokens.sale and www.aitokens.sale (add HTTP and HTTPS entries if you use both)."; function run() { if (!window.turnstile || typeof window.turnstile.render !== "function") { appendTurnstileLoadError( el, "Turnstile script is missing. Ensure challenges.cloudflare.com is reachable (not blocked by network or extensions)." ); if (cb) cb(null); return; } var opts = { sitekey: sitekey, theme: "dark", language: "en", appearance: "always", size: "normal", retry: "auto", "error-callback": function () { appendTurnstileLoadError(el, errMsg); }, "timeout-callback": function () { appendTurnstileLoadError(el, "Security check timed out. Refresh the page and try again."); }, }; var id; try { id = window.turnstile.render(el, opts); } catch (e) { appendTurnstileLoadError(el, "Could not start the security check. Verify the site key and hostnames in Cloudflare Turnstile."); if (cb) cb(null); return; } if (cb) cb(id); } if (window.turnstile && window.turnstile.ready) { window.turnstile.ready(run); } else { var tries = 0; var t = setInterval(function () { tries += 1; if (window.turnstile && window.turnstile.ready) { clearInterval(t); window.turnstile.ready(run); } if (tries > 200) { clearInterval(t); el.innerHTML = '

Could not load Turnstile from Cloudflare. Check network, DNS, and ad blockers.

'; if (cb) cb(null); } }, 50); } }, getTurnstileToken: function (widgetId) { if (widgetId == null) return ""; return window.turnstile.getResponse(widgetId) || ""; }, resetTurnstile: function (widgetId) { if (widgetId != null && window.turnstile) window.turnstile.reset(widgetId); }, }; })();