From 1ccad71f430063e2dcbbccfc65e29e2deaca93ca Mon Sep 17 00:00:00 2001 From: Tiago <70700766+tiagorangel1@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:42:58 +0100 Subject: [PATCH] add custom fetch and docs improvements --- docs/.vitepress/config.mjs | 2 + docs/guide/benchmark.md | 80 ++++++++++++++++++++++++++++++++++++ docs/guide/philosophy.md | 15 +++++++ docs/guide/widget.md | 10 +++++ widget/src/cap.compat.min.js | 2 +- widget/src/cap.min.js | 2 +- widget/src/package.json | 2 +- widget/src/src/cap.js | 13 ++++-- 8 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 docs/guide/benchmark.md create mode 100644 docs/guide/philosophy.md diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index a5c4acc..475bcfe 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -108,6 +108,7 @@ export default defineConfig({ { text: "Quickstart", link: "/guide/index.md" }, { text: "Effectiveness", link: "/guide/effectiveness.md" }, { text: "Alternatives", link: "/guide/alternatives.md" }, + { text: "Philosophy", link: "/guide/philosophy.md" }, { text: "Modes", items: [ @@ -124,6 +125,7 @@ export default defineConfig({ { text: "@cap.js/solver", link: "/guide/solver.md" }, ], }, + { text: "Benchmark", link: "/guide/benchmark.md" }, { text: "Demo", link: "https://cap-starter.glitch.me/" }, ], diff --git a/docs/guide/benchmark.md b/docs/guide/benchmark.md new file mode 100644 index 0000000..5b18085 --- /dev/null +++ b/docs/guide/benchmark.md @@ -0,0 +1,80 @@ +# Benchmark + +Coming soon! + + \ No newline at end of file diff --git a/docs/guide/philosophy.md b/docs/guide/philosophy.md new file mode 100644 index 0000000..14e9286 --- /dev/null +++ b/docs/guide/philosophy.md @@ -0,0 +1,15 @@ +# Philosophy + +Most CAPTCHA systems today are built around surveillance — tracking users, fingerprinting browsers, and collecting data in exchange for access. Cap rejects that model. + +Cap is designed around a few core ideas: + +- **Privacy by default** — no trackers, no third-party requests, no hidden profiling. +- **Simplicity over complexity** — no image labeling, no click-the-fire-hydrant puzzles. +- **Speed matters** — fast to render, fast to solve, fast to validate. +- **User-first** — designed to be unintrusive and accessible, with invisible and floating modes. +- **Self-hostable, not centralized** — you control the infra, tokens, and behavior. + +By using proof-of-work instead of user behavior analysis, Cap shifts the burden from identity to computation. That means anyone can prove they’re human — no cookies, no accounts, no friction. + +Cap is what a CAPTCHA should’ve been all along: **simple, honest, and yours.** \ No newline at end of file diff --git a/docs/guide/widget.md b/docs/guide/widget.md index f6b3fb6..cc487ec 100644 --- a/docs/guide/widget.md +++ b/docs/guide/widget.md @@ -59,3 +59,13 @@ The following custom events are supported: - `error`: Triggered when an error occurs. - `reset`: Triggered when the widget is reset. - `progress`: Triggered when the there's a progress update while in verification. + +## Custom fetch +You can override the default fetch implementation by setting `window.CAP_CUSTOM_FETCH` to a custom function. This function will receive the URL and options as arguments and should return a promise that resolves to the response. + +```js +window.CAP_CUSTOM_FETCH = function (url, options) { + // Custom fetch implementation + return fetch(url, options); +}; +``` \ No newline at end of file diff --git a/widget/src/cap.compat.min.js b/widget/src/cap.compat.min.js index 9584f67..90d9377 100644 --- a/widget/src/cap.compat.min.js +++ b/widget/src/cap.compat.min.js @@ -1 +1 @@ -"use strict";function _classPrivateFieldLooseBase(e,t){if(!{}.hasOwnProperty.call(e,t))throw new TypeError("attempted to use private field on non-instance");return e}var id=0;function _classPrivateFieldLooseKey(e){return"__private_"+id+++"_"+e}!function(){let e;const t=function(e,t){return void 0===t&&(t=1e4),new Promise(((s,a)=>{const i=setTimeout((()=>{a(new Error("Initialize timeout"))}),t),r=()=>{e()?(clearTimeout(i),s()):setTimeout(r,500)};r()}))};var s=_classPrivateFieldLooseKey("workerUrl"),a=_classPrivateFieldLooseKey("resetTimer"),i=_classPrivateFieldLooseKey("workersCount"),r=_classPrivateFieldLooseKey("token"),o=_classPrivateFieldLooseKey("shadow"),n=_classPrivateFieldLooseKey("div"),c=_classPrivateFieldLooseKey("host"),l=_classPrivateFieldLooseKey("solving"),d=_classPrivateFieldLooseKey("eventHandlers");class h extends HTMLElement{static get observedAttributes(){return["onsolve","onprogress","onreset","onerror","workers"]}constructor(){super(),Object.defineProperty(this,s,{writable:!0,value:""}),Object.defineProperty(this,a,{writable:!0,value:null}),Object.defineProperty(this,i,{writable:!0,value:navigator.hardwareConcurrency||8}),Object.defineProperty(this,r,{writable:!0,value:null}),Object.defineProperty(this,o,{writable:!0,value:void 0}),Object.defineProperty(this,n,{writable:!0,value:void 0}),Object.defineProperty(this,c,{writable:!0,value:void 0}),Object.defineProperty(this,l,{writable:!0,value:!1}),Object.defineProperty(this,d,{writable:!0,value:void 0}),_classPrivateFieldLooseBase(this,d)[d]&&_classPrivateFieldLooseBase(this,d)[d].forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),_classPrivateFieldLooseBase(this,d)[d]=new Map,this.boundHandleProgress=this.handleProgress.bind(this),this.boundHandleSolve=this.handleSolve.bind(this),this.boundHandleError=this.handleError.bind(this),this.boundHandleReset=this.handleReset.bind(this)}async initialize(){_classPrivateFieldLooseBase(this,s)[s]&&URL.revokeObjectURL(_classPrivateFieldLooseBase(this,s)[s]);try{await t((()=>!!e)),_classPrivateFieldLooseBase(this,s)[s]=URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}catch(e){throw this.error("Failed to initialize worker"),e}}attributeChangedCallback(e,t,s){if(e.startsWith("on")){const t=e.slice(2),a=_classPrivateFieldLooseBase(this,d)[d].get(e);if(a&&this.removeEventListener(t,a),s){const s=t=>{const s=this.getAttribute(e);"function"==typeof window[s]&&window[s].call(this,t)};_classPrivateFieldLooseBase(this,d)[d].set(e,s),this.addEventListener(t,s)}}}async connectedCallback(){_classPrivateFieldLooseBase(this,c)[c]=this,_classPrivateFieldLooseBase(this,o)[o]=this.attachShadow({mode:"open"}),_classPrivateFieldLooseBase(this,n)[n]=document.createElement("div"),this.createUI(),this.addEventListeners(),await this.initialize(),_classPrivateFieldLooseBase(this,n)[n].removeAttribute("disabled");const e=this.getAttribute("data-cap-worker-count");this.setWorkersCount(parseInt(e)?parseInt(e,10):navigator.hardwareConcurrency||8),_classPrivateFieldLooseBase(this,c)[c].innerHTML=''}async solve(){if(!_classPrivateFieldLooseBase(this,l)[l])try{_classPrivateFieldLooseBase(this,l)[l]=!0,this.updateUI("verifying","Verifying...",!0),await t((()=>!!_classPrivateFieldLooseBase(this,s)[s])),this.dispatchEvent("progress",{progress:0});try{const e=this.getAttribute("data-cap-api-endpoint");if(!e)throw new Error("Missing API endpoint");const{challenge:t,token:s}=await(await fetch(`${e}challenge`,{method:"POST"})).json(),i=await this.solveChallenges(t),o=await(await fetch(`${e}redeem`,{method:"POST",body:JSON.stringify({token:s,solutions:i}),headers:{"Content-Type":"application/json"}})).json();if(this.dispatchEvent("progress",{progress:100}),!o.success)throw new Error("Invalid solution");this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value=o.token),this.dispatchEvent("solve",{token:o.token}),_classPrivateFieldLooseBase(this,r)[r]=o.token,_classPrivateFieldLooseBase(this,a)[a]&&clearTimeout(_classPrivateFieldLooseBase(this,a)[a]);const n=new Date(o.expires).getTime()-Date.now();return n>0&&n<864e5?_classPrivateFieldLooseBase(this,a)[a]=setTimeout((()=>this.reset()),n):this.error("Invalid expiration time"),{success:!0,token:_classPrivateFieldLooseBase(this,r)[r]}}catch(e){throw this.error(e.message),e}}finally{_classPrivateFieldLooseBase(this,l)[l]=!1}}async solveChallenges(e){const t=e.length;let a=0;const r=Array(_classPrivateFieldLooseBase(this,i)[i]).fill(null).map((()=>new Worker(_classPrivateFieldLooseBase(this,s)[s]))),o=(e,i)=>{let[o,n]=e;return new Promise(((e,c)=>{const l=r[i],d=setTimeout((()=>{l.terminate(),r[i]=new Worker(_classPrivateFieldLooseBase(this,s)[s]),c(new Error("Worker timeout"))}),3e4);l.onmessage=s=>{let{data:i}=s;i.found&&(clearTimeout(d),a++,this.dispatchEvent("progress",{progress:Math.round(a/t*100)}),e([o,n,i.nonce]))},l.onerror=e=>{clearTimeout(d),this.error(`Error in worker: ${e}`),c(e)},l.postMessage({salt:o,target:n})}))},n=[];try{for(let t=0;to(e,t))));n.push(...a)}}finally{r.forEach((e=>e.terminate()))}return n}setWorkersCount(e){const t=parseInt(e,10),s=Math.min(navigator.hardwareConcurrency||8,16);_classPrivateFieldLooseBase(this,i)[i]=!isNaN(t)&&t>0&&t<=s?t:navigator.hardwareConcurrency||8}createUI(){_classPrivateFieldLooseBase(this,n)[n].classList.add("captcha"),_classPrivateFieldLooseBase(this,n)[n].setAttribute("role","button"),_classPrivateFieldLooseBase(this,n)[n].setAttribute("tabindex","0"),_classPrivateFieldLooseBase(this,n)[n].setAttribute("disabled","true"),_classPrivateFieldLooseBase(this,n)[n].innerHTML='

I\'m a human

Secured by Cap',_classPrivateFieldLooseBase(this,o)[o].innerHTML='',_classPrivateFieldLooseBase(this,o)[o].appendChild(_classPrivateFieldLooseBase(this,n)[n])}addEventListeners(){_classPrivateFieldLooseBase(this,n)[n].querySelector("a").addEventListener("click",(e=>{e.stopPropagation(),e.preventDefault(),window.open("https://capjs.js.org","_blank")})),_classPrivateFieldLooseBase(this,n)[n].addEventListener("click",(()=>{_classPrivateFieldLooseBase(this,n)[n].hasAttribute("disabled")||this.solve()})),_classPrivateFieldLooseBase(this,n)[n].addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||_classPrivateFieldLooseBase(this,n)[n].hasAttribute("disabled")||(e.preventDefault(),this.solve())})),this.addEventListener("progress",this.boundHandleProgress),this.addEventListener("solve",this.boundHandleSolve),this.addEventListener("error",this.boundHandleError),this.addEventListener("reset",this.boundHandleReset)}updateUI(e,t,s){void 0===s&&(s=!1),_classPrivateFieldLooseBase(this,n)[n].setAttribute("data-state",e),_classPrivateFieldLooseBase(this,n)[n].querySelector("p").innerText=t,s?_classPrivateFieldLooseBase(this,n)[n].setAttribute("disabled","true"):_classPrivateFieldLooseBase(this,n)[n].removeAttribute("disabled")}handleProgress(e){const t=_classPrivateFieldLooseBase(this,n)[n].querySelector("p");t&&(_classPrivateFieldLooseBase(this,n)[n].querySelector(".checkbox").style.setProperty("--progress",`${e.detail.progress}%`),t.innerText=`Verifying... ${e.detail.progress}%`),this.executeAttributeCode("onprogress",e)}handleSolve(e){this.updateUI("done","You're a human",!0),this.executeAttributeCode("onsolve",e)}handleError(e){this.updateUI("error","Error. Try again."),this.executeAttributeCode("onerror",e)}handleReset(e){this.updateUI("","I'm a human"),this.executeAttributeCode("onreset",e)}executeAttributeCode(e,t){const s=this.getAttribute(e);if(!s)return;new Function("event",s).call(this,t)}error(e){void 0===e&&(e="Unknown error"),console.error("[Cap] Error:",e),this.dispatchEvent("error",{isCap:!0,message:e})}dispatchEvent(e,t){void 0===t&&(t={});const s=new CustomEvent(e,{bubbles:!0,composed:!0,detail:t});super.dispatchEvent(s)}reset(){_classPrivateFieldLooseBase(this,a)[a]&&(clearTimeout(_classPrivateFieldLooseBase(this,a)[a]),_classPrivateFieldLooseBase(this,a)[a]=null),this.dispatchEvent("reset"),_classPrivateFieldLooseBase(this,r)[r]=null,this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value="")}get token(){return _classPrivateFieldLooseBase(this,r)[r]}disconnectedCallback(){this.removeEventListener("progress",this.boundHandleProgress),this.removeEventListener("solve",this.boundHandleSolve),this.removeEventListener("error",this.boundHandleError),this.removeEventListener("reset",this.boundHandleReset),_classPrivateFieldLooseBase(this,d)[d].forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),_classPrivateFieldLooseBase(this,d)[d].clear(),_classPrivateFieldLooseBase(this,o)[o]&&(_classPrivateFieldLooseBase(this,o)[o].innerHTML=""),this.reset(),this.cleanup()}cleanup(){_classPrivateFieldLooseBase(this,a)[a]&&(clearTimeout(_classPrivateFieldLooseBase(this,a)[a]),_classPrivateFieldLooseBase(this,a)[a]=null),_classPrivateFieldLooseBase(this,s)[s]&&(URL.revokeObjectURL(_classPrivateFieldLooseBase(this,s)[s]),_classPrivateFieldLooseBase(this,s)[s]="")}}class p{constructor(e,t){void 0===e&&(e={});let s=t||document.createElement("cap-widget");if(Object.entries(e).forEach((e=>{let[t,a]=e;s.setAttribute(t,a)})),!e.apiEndpoint)throw s.remove(),new Error("Missing API endpoint");s.setAttribute("data-cap-api-endpoint",e.apiEndpoint),this.widget=s,this.solve=this.widget.solve.bind(this.widget),this.reset=this.widget.reset.bind(this.widget),this.addEventListener=this.widget.addEventListener.bind(this.widget),Object.defineProperty(this,"token",{get:()=>s.getToken(),configurable:!0,enumerable:!0}),t||(s.style.display="none",document.documentElement.appendChild(s))}}const v=new CSSStyleSheet;v.replaceSync('html{--cap-font:system,-apple-system,"BlinkMacSystemFont",".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande","Ubuntu","arial",sans-serif;--cap-color:#212121;--cap-background:#fdfdfd;--cap-border-color:#dddddd8f;--cap-border-radius:14px;--cap-checkbox-border:1px solid #aaaaaad1;--cap-checkbox-border-radius:6px;--cap-checkbox-background:#fafafa91;--cap-widget-width:240px;--cap-widget-padding:14px;--cap-checkbox-size:24px;--cap-checkbox-margin:2px;--cap-transition-duration:0.2s;--cap-gap:15px;--cap-opacity-hover:0.8;--cap-hover-filter:brightness(97%);--cap-active-scale:0.98;--cap-credits-font-size:12px;--cap-spinner-color:black;--cap-spinner-background-color:#eee;--cap-error-cross:url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'96\' height=\'96\' viewBox=\'0 0 24 24\'%3E%3Cpath fill=\'%23f55b50\' d=\'M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8\'/%3E%3C/svg%3E");--cap-checkmark:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cstyle%3E%40keyframes%20anim%7B0%25%7Bstroke-dashoffset%3A23.21320343017578px%7Dto%7Bstroke-dashoffset%3A0%7D%7D%3C%2Fstyle%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%2300a67d%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20stroke-width%3D%222%22%20d%3D%22m5%2012%205%205L20%207%22%20style%3D%22stroke-dashoffset%3A0%3Bstroke-dasharray%3A23.21320343017578px%3Banimation%3Aanim%20.5s%20ease%22%2F%3E%3C%2Fsvg%3E");--cap-spinner-thickness:5px;}'),document.adoptedStyleSheets.push(v);const u=function(){let e;self.onmessage=async t=>{let{data:{salt:s,target:a}}=t,i=0;const r=5e4;let o=0;const n=new TextEncoder;if("object"!=typeof WebAssembly||"function"!=typeof WebAssembly.instantiate){console.log("[cap] WASM not enabled, falling back to crypto.subtle\nThis is significanty slower than the WASM implementation");const e=new Uint8Array(a.length/2);for(let t=0;t{const i=setTimeout((()=>{a(new Error("Initialize timeout"))}),t),r=()=>{e()?(clearTimeout(i),s()):setTimeout(r,500)};r()}))};var a=_classPrivateFieldLooseKey("workerUrl"),i=_classPrivateFieldLooseKey("resetTimer"),r=_classPrivateFieldLooseKey("workersCount"),o=_classPrivateFieldLooseKey("token"),n=_classPrivateFieldLooseKey("shadow"),c=_classPrivateFieldLooseKey("div"),l=_classPrivateFieldLooseKey("host"),d=_classPrivateFieldLooseKey("solving"),h=_classPrivateFieldLooseKey("eventHandlers");class p extends HTMLElement{static get observedAttributes(){return["onsolve","onprogress","onreset","onerror","workers"]}constructor(){super(),Object.defineProperty(this,a,{writable:!0,value:""}),Object.defineProperty(this,i,{writable:!0,value:null}),Object.defineProperty(this,r,{writable:!0,value:navigator.hardwareConcurrency||8}),Object.defineProperty(this,o,{writable:!0,value:null}),Object.defineProperty(this,n,{writable:!0,value:void 0}),Object.defineProperty(this,c,{writable:!0,value:void 0}),Object.defineProperty(this,l,{writable:!0,value:void 0}),Object.defineProperty(this,d,{writable:!0,value:!1}),Object.defineProperty(this,h,{writable:!0,value:void 0}),_classPrivateFieldLooseBase(this,h)[h]&&_classPrivateFieldLooseBase(this,h)[h].forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),_classPrivateFieldLooseBase(this,h)[h]=new Map,this.boundHandleProgress=this.handleProgress.bind(this),this.boundHandleSolve=this.handleSolve.bind(this),this.boundHandleError=this.handleError.bind(this),this.boundHandleReset=this.handleReset.bind(this)}async initialize(){_classPrivateFieldLooseBase(this,a)[a]&&URL.revokeObjectURL(_classPrivateFieldLooseBase(this,a)[a]);try{await s((()=>!!e)),_classPrivateFieldLooseBase(this,a)[a]=URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}catch(e){throw this.error("Failed to initialize worker"),e}}attributeChangedCallback(e,t,s){if(e.startsWith("on")){const t=e.slice(2),a=_classPrivateFieldLooseBase(this,h)[h].get(e);if(a&&this.removeEventListener(t,a),s){const s=t=>{const s=this.getAttribute(e);"function"==typeof window[s]&&window[s].call(this,t)};_classPrivateFieldLooseBase(this,h)[h].set(e,s),this.addEventListener(t,s)}}}async connectedCallback(){_classPrivateFieldLooseBase(this,l)[l]=this,_classPrivateFieldLooseBase(this,n)[n]=this.attachShadow({mode:"open"}),_classPrivateFieldLooseBase(this,c)[c]=document.createElement("div"),this.createUI(),this.addEventListeners(),await this.initialize(),_classPrivateFieldLooseBase(this,c)[c].removeAttribute("disabled");const e=this.getAttribute("data-cap-worker-count");this.setWorkersCount(parseInt(e)?parseInt(e,10):navigator.hardwareConcurrency||8),_classPrivateFieldLooseBase(this,l)[l].innerHTML=''}async solve(){if(!_classPrivateFieldLooseBase(this,d)[d])try{_classPrivateFieldLooseBase(this,d)[d]=!0,this.updateUI("verifying","Verifying...",!0),await s((()=>!!_classPrivateFieldLooseBase(this,a)[a])),this.dispatchEvent("progress",{progress:0});try{const e=this.getAttribute("data-cap-api-endpoint");if(!e)throw new Error("Missing API endpoint");const{challenge:s,token:a}=await(await t(`${e}challenge`,{method:"POST"})).json(),r=await this.solveChallenges(s),n=await(await t(`${e}redeem`,{method:"POST",body:JSON.stringify({token:a,solutions:r}),headers:{"Content-Type":"application/json"}})).json();if(this.dispatchEvent("progress",{progress:100}),!n.success)throw new Error("Invalid solution");this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value=n.token),this.dispatchEvent("solve",{token:n.token}),_classPrivateFieldLooseBase(this,o)[o]=n.token,_classPrivateFieldLooseBase(this,i)[i]&&clearTimeout(_classPrivateFieldLooseBase(this,i)[i]);const c=new Date(n.expires).getTime()-Date.now();return c>0&&c<864e5?_classPrivateFieldLooseBase(this,i)[i]=setTimeout((()=>this.reset()),c):this.error("Invalid expiration time"),{success:!0,token:_classPrivateFieldLooseBase(this,o)[o]}}catch(e){throw this.error(e.message),e}}finally{_classPrivateFieldLooseBase(this,d)[d]=!1}}async solveChallenges(e){const t=e.length;let s=0;const i=Array(_classPrivateFieldLooseBase(this,r)[r]).fill(null).map((()=>new Worker(_classPrivateFieldLooseBase(this,a)[a]))),o=(e,r)=>{let[o,n]=e;return new Promise(((e,c)=>{const l=i[r],d=setTimeout((()=>{l.terminate(),i[r]=new Worker(_classPrivateFieldLooseBase(this,a)[a]),c(new Error("Worker timeout"))}),3e4);l.onmessage=a=>{let{data:i}=a;i.found&&(clearTimeout(d),s++,this.dispatchEvent("progress",{progress:Math.round(s/t*100)}),e([o,n,i.nonce]))},l.onerror=e=>{clearTimeout(d),this.error(`Error in worker: ${e}`),c(e)},l.postMessage({salt:o,target:n})}))},n=[];try{for(let t=0;to(e,t))));n.push(...a)}}finally{i.forEach((e=>e.terminate()))}return n}setWorkersCount(e){const t=parseInt(e,10),s=Math.min(navigator.hardwareConcurrency||8,16);_classPrivateFieldLooseBase(this,r)[r]=!isNaN(t)&&t>0&&t<=s?t:navigator.hardwareConcurrency||8}createUI(){_classPrivateFieldLooseBase(this,c)[c].classList.add("captcha"),_classPrivateFieldLooseBase(this,c)[c].setAttribute("role","button"),_classPrivateFieldLooseBase(this,c)[c].setAttribute("tabindex","0"),_classPrivateFieldLooseBase(this,c)[c].setAttribute("disabled","true"),_classPrivateFieldLooseBase(this,c)[c].innerHTML='

I\'m a human

Secured by Cap',_classPrivateFieldLooseBase(this,n)[n].innerHTML='',_classPrivateFieldLooseBase(this,n)[n].appendChild(_classPrivateFieldLooseBase(this,c)[c])}addEventListeners(){_classPrivateFieldLooseBase(this,c)[c].querySelector("a").addEventListener("click",(e=>{e.stopPropagation(),e.preventDefault(),window.open("https://capjs.js.org","_blank")})),_classPrivateFieldLooseBase(this,c)[c].addEventListener("click",(()=>{_classPrivateFieldLooseBase(this,c)[c].hasAttribute("disabled")||this.solve()})),_classPrivateFieldLooseBase(this,c)[c].addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||_classPrivateFieldLooseBase(this,c)[c].hasAttribute("disabled")||(e.preventDefault(),this.solve())})),this.addEventListener("progress",this.boundHandleProgress),this.addEventListener("solve",this.boundHandleSolve),this.addEventListener("error",this.boundHandleError),this.addEventListener("reset",this.boundHandleReset)}updateUI(e,t,s){void 0===s&&(s=!1),_classPrivateFieldLooseBase(this,c)[c].setAttribute("data-state",e),_classPrivateFieldLooseBase(this,c)[c].querySelector("p").innerText=t,s?_classPrivateFieldLooseBase(this,c)[c].setAttribute("disabled","true"):_classPrivateFieldLooseBase(this,c)[c].removeAttribute("disabled")}handleProgress(e){const t=_classPrivateFieldLooseBase(this,c)[c].querySelector("p");t&&(_classPrivateFieldLooseBase(this,c)[c].querySelector(".checkbox").style.setProperty("--progress",`${e.detail.progress}%`),t.innerText=`Verifying... ${e.detail.progress}%`),this.executeAttributeCode("onprogress",e)}handleSolve(e){this.updateUI("done","You're a human",!0),this.executeAttributeCode("onsolve",e)}handleError(e){this.updateUI("error","Error. Try again."),this.executeAttributeCode("onerror",e)}handleReset(e){this.updateUI("","I'm a human"),this.executeAttributeCode("onreset",e)}executeAttributeCode(e,t){const s=this.getAttribute(e);if(!s)return;new Function("event",s).call(this,t)}error(e){void 0===e&&(e="Unknown error"),console.error("[Cap] Error:",e),this.dispatchEvent("error",{isCap:!0,message:e})}dispatchEvent(e,t){void 0===t&&(t={});const s=new CustomEvent(e,{bubbles:!0,composed:!0,detail:t});super.dispatchEvent(s)}reset(){_classPrivateFieldLooseBase(this,i)[i]&&(clearTimeout(_classPrivateFieldLooseBase(this,i)[i]),_classPrivateFieldLooseBase(this,i)[i]=null),this.dispatchEvent("reset"),_classPrivateFieldLooseBase(this,o)[o]=null,this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value="")}get token(){return _classPrivateFieldLooseBase(this,o)[o]}disconnectedCallback(){this.removeEventListener("progress",this.boundHandleProgress),this.removeEventListener("solve",this.boundHandleSolve),this.removeEventListener("error",this.boundHandleError),this.removeEventListener("reset",this.boundHandleReset),_classPrivateFieldLooseBase(this,h)[h].forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),_classPrivateFieldLooseBase(this,h)[h].clear(),_classPrivateFieldLooseBase(this,n)[n]&&(_classPrivateFieldLooseBase(this,n)[n].innerHTML=""),this.reset(),this.cleanup()}cleanup(){_classPrivateFieldLooseBase(this,i)[i]&&(clearTimeout(_classPrivateFieldLooseBase(this,i)[i]),_classPrivateFieldLooseBase(this,i)[i]=null),_classPrivateFieldLooseBase(this,a)[a]&&(URL.revokeObjectURL(_classPrivateFieldLooseBase(this,a)[a]),_classPrivateFieldLooseBase(this,a)[a]="")}}class v{constructor(e,t){void 0===e&&(e={});let s=t||document.createElement("cap-widget");if(Object.entries(e).forEach((e=>{let[t,a]=e;s.setAttribute(t,a)})),!e.apiEndpoint)throw s.remove(),new Error("Missing API endpoint");s.setAttribute("data-cap-api-endpoint",e.apiEndpoint),this.widget=s,this.solve=this.widget.solve.bind(this.widget),this.reset=this.widget.reset.bind(this.widget),this.addEventListener=this.widget.addEventListener.bind(this.widget),Object.defineProperty(this,"token",{get:()=>s.getToken(),configurable:!0,enumerable:!0}),t||(s.style.display="none",document.documentElement.appendChild(s))}}const u=new CSSStyleSheet;u.replaceSync('html{--cap-font:system,-apple-system,"BlinkMacSystemFont",".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande","Ubuntu","arial",sans-serif;--cap-color:#212121;--cap-background:#fdfdfd;--cap-border-color:#dddddd8f;--cap-border-radius:14px;--cap-checkbox-border:1px solid #aaaaaad1;--cap-checkbox-border-radius:6px;--cap-checkbox-background:#fafafa91;--cap-widget-width:240px;--cap-widget-padding:14px;--cap-checkbox-size:24px;--cap-checkbox-margin:2px;--cap-transition-duration:0.2s;--cap-gap:15px;--cap-opacity-hover:0.8;--cap-hover-filter:brightness(97%);--cap-active-scale:0.98;--cap-credits-font-size:12px;--cap-spinner-color:black;--cap-spinner-background-color:#eee;--cap-error-cross:url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'96\' height=\'96\' viewBox=\'0 0 24 24\'%3E%3Cpath fill=\'%23f55b50\' d=\'M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8\'/%3E%3C/svg%3E");--cap-checkmark:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cstyle%3E%40keyframes%20anim%7B0%25%7Bstroke-dashoffset%3A23.21320343017578px%7Dto%7Bstroke-dashoffset%3A0%7D%7D%3C%2Fstyle%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%2300a67d%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20stroke-width%3D%222%22%20d%3D%22m5%2012%205%205L20%207%22%20style%3D%22stroke-dashoffset%3A0%3Bstroke-dasharray%3A23.21320343017578px%3Banimation%3Aanim%20.5s%20ease%22%2F%3E%3C%2Fsvg%3E");--cap-spinner-thickness:5px;}'),document.adoptedStyleSheets.push(u);const b=function(){let e;self.onmessage=async t=>{let{data:{salt:s,target:a}}=t,i=0;const r=5e4;let o=0;const n=new TextEncoder;if("object"!=typeof WebAssembly||"function"!=typeof WebAssembly.instantiate){console.log("[cap] WASM not enabled, falling back to crypto.subtle\nThis is significanty slower than the WASM implementation");const e=new Uint8Array(a.length/2);for(let t=0;tnew Promise(((r,s)=>{const i=setTimeout((()=>{s(new Error("Initialize timeout"))}),t),a=()=>{e()?(clearTimeout(i),r()):setTimeout(a,500)};a()}));class r extends HTMLElement{#e="";#t=null;#r=navigator.hardwareConcurrency||8;#s=null;#i;#a;#n;#o=!1;#c;static get observedAttributes(){return["onsolve","onprogress","onreset","onerror","workers"]}constructor(){super(),this.#c&&this.#c.forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),this.#c=new Map,this.boundHandleProgress=this.handleProgress.bind(this),this.boundHandleSolve=this.handleSolve.bind(this),this.boundHandleError=this.handleError.bind(this),this.boundHandleReset=this.handleReset.bind(this)}async initialize(){this.#e&&URL.revokeObjectURL(this.#e);try{await t((()=>!!e)),this.#e=URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}catch(e){throw this.error("Failed to initialize worker"),e}}attributeChangedCallback(e,t,r){if(e.startsWith("on")){const t=e.slice(2),s=this.#c.get(e);if(s&&this.removeEventListener(t,s),r){const r=t=>{const r=this.getAttribute(e);"function"==typeof window[r]&&window[r].call(this,t)};this.#c.set(e,r),this.addEventListener(t,r)}}}async connectedCallback(){this.#n=this,this.#i=this.attachShadow({mode:"open"}),this.#a=document.createElement("div"),this.createUI(),this.addEventListeners(),await this.initialize(),this.#a.removeAttribute("disabled");const e=this.getAttribute("data-cap-worker-count");this.setWorkersCount(parseInt(e)?parseInt(e,10):navigator.hardwareConcurrency||8),this.#n.innerHTML=''}async solve(){if(!this.#o)try{this.#o=!0,this.updateUI("verifying","Verifying...",!0),await t((()=>!!this.#e)),this.dispatchEvent("progress",{progress:0});try{const e=this.getAttribute("data-cap-api-endpoint");if(!e)throw new Error("Missing API endpoint");const{challenge:t,token:r}=await(await fetch(`${e}challenge`,{method:"POST"})).json(),s=await this.solveChallenges(t),i=await(await fetch(`${e}redeem`,{method:"POST",body:JSON.stringify({token:r,solutions:s}),headers:{"Content-Type":"application/json"}})).json();if(this.dispatchEvent("progress",{progress:100}),!i.success)throw new Error("Invalid solution");this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value=i.token),this.dispatchEvent("solve",{token:i.token}),this.#s=i.token,this.#t&&clearTimeout(this.#t);const a=new Date(i.expires).getTime()-Date.now();return a>0&&a<864e5?this.#t=setTimeout((()=>this.reset()),a):this.error("Invalid expiration time"),{success:!0,token:this.#s}}catch(e){throw this.error(e.message),e}}finally{this.#o=!1}}async solveChallenges(e){const t=e.length;let r=0;const s=Array(this.#r).fill(null).map((()=>new Worker(this.#e))),i=([e,i],a)=>new Promise(((n,o)=>{const c=s[a],d=setTimeout((()=>{c.terminate(),s[a]=new Worker(this.#e),o(new Error("Worker timeout"))}),3e4);c.onmessage=({data:s})=>{s.found&&(clearTimeout(d),r++,this.dispatchEvent("progress",{progress:Math.round(r/t*100)}),n([e,i,s.nonce]))},c.onerror=e=>{clearTimeout(d),this.error(`Error in worker: ${e}`),o(e)},c.postMessage({salt:e,target:i})})),a=[];try{for(let t=0;ti(e,t))));a.push(...s)}}finally{s.forEach((e=>e.terminate()))}return a}setWorkersCount(e){const t=parseInt(e,10),r=Math.min(navigator.hardwareConcurrency||8,16);this.#r=!isNaN(t)&&t>0&&t<=r?t:navigator.hardwareConcurrency||8}createUI(){this.#a.classList.add("captcha"),this.#a.setAttribute("role","button"),this.#a.setAttribute("tabindex","0"),this.#a.setAttribute("disabled","true"),this.#a.innerHTML='

I\'m a human

Secured by Cap',this.#i.innerHTML='',this.#i.appendChild(this.#a)}addEventListeners(){this.#a.querySelector("a").addEventListener("click",(e=>{e.stopPropagation(),e.preventDefault(),window.open("https://capjs.js.org","_blank")})),this.#a.addEventListener("click",(()=>{this.#a.hasAttribute("disabled")||this.solve()})),this.#a.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||this.#a.hasAttribute("disabled")||(e.preventDefault(),this.solve())})),this.addEventListener("progress",this.boundHandleProgress),this.addEventListener("solve",this.boundHandleSolve),this.addEventListener("error",this.boundHandleError),this.addEventListener("reset",this.boundHandleReset)}updateUI(e,t,r=!1){this.#a.setAttribute("data-state",e),this.#a.querySelector("p").innerText=t,r?this.#a.setAttribute("disabled","true"):this.#a.removeAttribute("disabled")}handleProgress(e){const t=this.#a.querySelector("p");t&&(this.#a.querySelector(".checkbox").style.setProperty("--progress",`${e.detail.progress}%`),t.innerText=`Verifying... ${e.detail.progress}%`),this.executeAttributeCode("onprogress",e)}handleSolve(e){this.updateUI("done","You're a human",!0),this.executeAttributeCode("onsolve",e)}handleError(e){this.updateUI("error","Error. Try again."),this.executeAttributeCode("onerror",e)}handleReset(e){this.updateUI("","I'm a human"),this.executeAttributeCode("onreset",e)}executeAttributeCode(e,t){const r=this.getAttribute(e);if(!r)return;new Function("event",r).call(this,t)}error(e="Unknown error"){console.error("[Cap] Error:",e),this.dispatchEvent("error",{isCap:!0,message:e})}dispatchEvent(e,t={}){const r=new CustomEvent(e,{bubbles:!0,composed:!0,detail:t});super.dispatchEvent(r)}reset(){this.#t&&(clearTimeout(this.#t),this.#t=null),this.dispatchEvent("reset"),this.#s=null,this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value="")}get token(){return this.#s}disconnectedCallback(){this.removeEventListener("progress",this.boundHandleProgress),this.removeEventListener("solve",this.boundHandleSolve),this.removeEventListener("error",this.boundHandleError),this.removeEventListener("reset",this.boundHandleReset),this.#c.forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),this.#c.clear(),this.#i&&(this.#i.innerHTML=""),this.reset(),this.cleanup()}cleanup(){this.#t&&(clearTimeout(this.#t),this.#t=null),this.#e&&(URL.revokeObjectURL(this.#e),this.#e="")}}class s{constructor(e={},t){let r=t||document.createElement("cap-widget");if(Object.entries(e).forEach((([e,t])=>{r.setAttribute(e,t)})),!e.apiEndpoint)throw r.remove(),new Error("Missing API endpoint");r.setAttribute("data-cap-api-endpoint",e.apiEndpoint),this.widget=r,this.solve=this.widget.solve.bind(this.widget),this.reset=this.widget.reset.bind(this.widget),this.addEventListener=this.widget.addEventListener.bind(this.widget),Object.defineProperty(this,"token",{get:()=>r.getToken(),configurable:!0,enumerable:!0}),t||(r.style.display="none",document.documentElement.appendChild(r))}}const i=new CSSStyleSheet;i.replaceSync('html{--cap-font:system,-apple-system,"BlinkMacSystemFont",".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande","Ubuntu","arial",sans-serif;--cap-color:#212121;--cap-background:#fdfdfd;--cap-border-color:#dddddd8f;--cap-border-radius:14px;--cap-checkbox-border:1px solid #aaaaaad1;--cap-checkbox-border-radius:6px;--cap-checkbox-background:#fafafa91;--cap-widget-width:240px;--cap-widget-padding:14px;--cap-checkbox-size:24px;--cap-checkbox-margin:2px;--cap-transition-duration:0.2s;--cap-gap:15px;--cap-opacity-hover:0.8;--cap-hover-filter:brightness(97%);--cap-active-scale:0.98;--cap-credits-font-size:12px;--cap-spinner-color:black;--cap-spinner-background-color:#eee;--cap-error-cross:url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'96\' height=\'96\' viewBox=\'0 0 24 24\'%3E%3Cpath fill=\'%23f55b50\' d=\'M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8\'/%3E%3C/svg%3E");--cap-checkmark:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cstyle%3E%40keyframes%20anim%7B0%25%7Bstroke-dashoffset%3A23.21320343017578px%7Dto%7Bstroke-dashoffset%3A0%7D%7D%3C%2Fstyle%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%2300a67d%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20stroke-width%3D%222%22%20d%3D%22m5%2012%205%205L20%207%22%20style%3D%22stroke-dashoffset%3A0%3Bstroke-dasharray%3A23.21320343017578px%3Banimation%3Aanim%20.5s%20ease%22%2F%3E%3C%2Fsvg%3E");--cap-spinner-thickness:5px;}'),document.adoptedStyleSheets.push(i);const a=function(){let e;self.onmessage=async({data:{salt:t,target:r}})=>{let s=0;const i=5e4;let a=0;const n=new TextEncoder;if("object"!=typeof WebAssembly||"function"!=typeof WebAssembly.instantiate){console.log("[cap] WASM not enabled, falling back to crypto.subtle\nThis is significanty slower than the WASM implementation");const e=new Uint8Array(r.length/2);for(let t=0;tnew Promise(((r,s)=>{const i=setTimeout((()=>{s(new Error("Initialize timeout"))}),t),a=()=>{e()?(clearTimeout(i),r()):setTimeout(a,500)};a()}));class s extends HTMLElement{#e="";#t=null;#r=navigator.hardwareConcurrency||8;#s=null;#i;#a;#n;#o=!1;#c;static get observedAttributes(){return["onsolve","onprogress","onreset","onerror","workers"]}constructor(){super(),this.#c&&this.#c.forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),this.#c=new Map,this.boundHandleProgress=this.handleProgress.bind(this),this.boundHandleSolve=this.handleSolve.bind(this),this.boundHandleError=this.handleError.bind(this),this.boundHandleReset=this.handleReset.bind(this)}async initialize(){this.#e&&URL.revokeObjectURL(this.#e);try{await r((()=>!!e)),this.#e=URL.createObjectURL(new Blob([e],{type:"application/javascript"}))}catch(e){throw this.error("Failed to initialize worker"),e}}attributeChangedCallback(e,t,r){if(e.startsWith("on")){const t=e.slice(2),s=this.#c.get(e);if(s&&this.removeEventListener(t,s),r){const r=t=>{const r=this.getAttribute(e);"function"==typeof window[r]&&window[r].call(this,t)};this.#c.set(e,r),this.addEventListener(t,r)}}}async connectedCallback(){this.#n=this,this.#i=this.attachShadow({mode:"open"}),this.#a=document.createElement("div"),this.createUI(),this.addEventListeners(),await this.initialize(),this.#a.removeAttribute("disabled");const e=this.getAttribute("data-cap-worker-count");this.setWorkersCount(parseInt(e)?parseInt(e,10):navigator.hardwareConcurrency||8),this.#n.innerHTML=''}async solve(){if(!this.#o)try{this.#o=!0,this.updateUI("verifying","Verifying...",!0),await r((()=>!!this.#e)),this.dispatchEvent("progress",{progress:0});try{const e=this.getAttribute("data-cap-api-endpoint");if(!e)throw new Error("Missing API endpoint");const{challenge:r,token:s}=await(await t(`${e}challenge`,{method:"POST"})).json(),i=await this.solveChallenges(r),a=await(await t(`${e}redeem`,{method:"POST",body:JSON.stringify({token:s,solutions:i}),headers:{"Content-Type":"application/json"}})).json();if(this.dispatchEvent("progress",{progress:100}),!a.success)throw new Error("Invalid solution");this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value=a.token),this.dispatchEvent("solve",{token:a.token}),this.#s=a.token,this.#t&&clearTimeout(this.#t);const n=new Date(a.expires).getTime()-Date.now();return n>0&&n<864e5?this.#t=setTimeout((()=>this.reset()),n):this.error("Invalid expiration time"),{success:!0,token:this.#s}}catch(e){throw this.error(e.message),e}}finally{this.#o=!1}}async solveChallenges(e){const t=e.length;let r=0;const s=Array(this.#r).fill(null).map((()=>new Worker(this.#e))),i=([e,i],a)=>new Promise(((n,o)=>{const c=s[a],d=setTimeout((()=>{c.terminate(),s[a]=new Worker(this.#e),o(new Error("Worker timeout"))}),3e4);c.onmessage=({data:s})=>{s.found&&(clearTimeout(d),r++,this.dispatchEvent("progress",{progress:Math.round(r/t*100)}),n([e,i,s.nonce]))},c.onerror=e=>{clearTimeout(d),this.error(`Error in worker: ${e}`),o(e)},c.postMessage({salt:e,target:i})})),a=[];try{for(let t=0;ti(e,t))));a.push(...s)}}finally{s.forEach((e=>e.terminate()))}return a}setWorkersCount(e){const t=parseInt(e,10),r=Math.min(navigator.hardwareConcurrency||8,16);this.#r=!isNaN(t)&&t>0&&t<=r?t:navigator.hardwareConcurrency||8}createUI(){this.#a.classList.add("captcha"),this.#a.setAttribute("role","button"),this.#a.setAttribute("tabindex","0"),this.#a.setAttribute("disabled","true"),this.#a.innerHTML='

I\'m a human

Secured by Cap',this.#i.innerHTML='',this.#i.appendChild(this.#a)}addEventListeners(){this.#a.querySelector("a").addEventListener("click",(e=>{e.stopPropagation(),e.preventDefault(),window.open("https://capjs.js.org","_blank")})),this.#a.addEventListener("click",(()=>{this.#a.hasAttribute("disabled")||this.solve()})),this.#a.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||this.#a.hasAttribute("disabled")||(e.preventDefault(),this.solve())})),this.addEventListener("progress",this.boundHandleProgress),this.addEventListener("solve",this.boundHandleSolve),this.addEventListener("error",this.boundHandleError),this.addEventListener("reset",this.boundHandleReset)}updateUI(e,t,r=!1){this.#a.setAttribute("data-state",e),this.#a.querySelector("p").innerText=t,r?this.#a.setAttribute("disabled","true"):this.#a.removeAttribute("disabled")}handleProgress(e){const t=this.#a.querySelector("p");t&&(this.#a.querySelector(".checkbox").style.setProperty("--progress",`${e.detail.progress}%`),t.innerText=`Verifying... ${e.detail.progress}%`),this.executeAttributeCode("onprogress",e)}handleSolve(e){this.updateUI("done","You're a human",!0),this.executeAttributeCode("onsolve",e)}handleError(e){this.updateUI("error","Error. Try again."),this.executeAttributeCode("onerror",e)}handleReset(e){this.updateUI("","I'm a human"),this.executeAttributeCode("onreset",e)}executeAttributeCode(e,t){const r=this.getAttribute(e);if(!r)return;new Function("event",r).call(this,t)}error(e="Unknown error"){console.error("[Cap] Error:",e),this.dispatchEvent("error",{isCap:!0,message:e})}dispatchEvent(e,t={}){const r=new CustomEvent(e,{bubbles:!0,composed:!0,detail:t});super.dispatchEvent(r)}reset(){this.#t&&(clearTimeout(this.#t),this.#t=null),this.dispatchEvent("reset"),this.#s=null,this.querySelector("input[name='cap-token']")&&(this.querySelector("input[name='cap-token']").value="")}get token(){return this.#s}disconnectedCallback(){this.removeEventListener("progress",this.boundHandleProgress),this.removeEventListener("solve",this.boundHandleSolve),this.removeEventListener("error",this.boundHandleError),this.removeEventListener("reset",this.boundHandleReset),this.#c.forEach(((e,t)=>{this.removeEventListener(t.slice(2),e)})),this.#c.clear(),this.#i&&(this.#i.innerHTML=""),this.reset(),this.cleanup()}cleanup(){this.#t&&(clearTimeout(this.#t),this.#t=null),this.#e&&(URL.revokeObjectURL(this.#e),this.#e="")}}class i{constructor(e={},t){let r=t||document.createElement("cap-widget");if(Object.entries(e).forEach((([e,t])=>{r.setAttribute(e,t)})),!e.apiEndpoint)throw r.remove(),new Error("Missing API endpoint");r.setAttribute("data-cap-api-endpoint",e.apiEndpoint),this.widget=r,this.solve=this.widget.solve.bind(this.widget),this.reset=this.widget.reset.bind(this.widget),this.addEventListener=this.widget.addEventListener.bind(this.widget),Object.defineProperty(this,"token",{get:()=>r.getToken(),configurable:!0,enumerable:!0}),t||(r.style.display="none",document.documentElement.appendChild(r))}}const a=new CSSStyleSheet;a.replaceSync('html{--cap-font:system,-apple-system,"BlinkMacSystemFont",".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande","Ubuntu","arial",sans-serif;--cap-color:#212121;--cap-background:#fdfdfd;--cap-border-color:#dddddd8f;--cap-border-radius:14px;--cap-checkbox-border:1px solid #aaaaaad1;--cap-checkbox-border-radius:6px;--cap-checkbox-background:#fafafa91;--cap-widget-width:240px;--cap-widget-padding:14px;--cap-checkbox-size:24px;--cap-checkbox-margin:2px;--cap-transition-duration:0.2s;--cap-gap:15px;--cap-opacity-hover:0.8;--cap-hover-filter:brightness(97%);--cap-active-scale:0.98;--cap-credits-font-size:12px;--cap-spinner-color:black;--cap-spinner-background-color:#eee;--cap-error-cross:url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'96\' height=\'96\' viewBox=\'0 0 24 24\'%3E%3Cpath fill=\'%23f55b50\' d=\'M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8\'/%3E%3C/svg%3E");--cap-checkmark:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cstyle%3E%40keyframes%20anim%7B0%25%7Bstroke-dashoffset%3A23.21320343017578px%7Dto%7Bstroke-dashoffset%3A0%7D%7D%3C%2Fstyle%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%2300a67d%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20stroke-width%3D%222%22%20d%3D%22m5%2012%205%205L20%207%22%20style%3D%22stroke-dashoffset%3A0%3Bstroke-dasharray%3A23.21320343017578px%3Banimation%3Aanim%20.5s%20ease%22%2F%3E%3C%2Fsvg%3E");--cap-spinner-thickness:5px;}'),document.adoptedStyleSheets.push(a);const n=function(){let e;self.onmessage=async({data:{salt:t,target:r}})=>{let s=0;const i=5e4;let a=0;const n=new TextEncoder;if("object"!=typeof WebAssembly||"function"!=typeof WebAssembly.instantiate){console.log("[cap] WASM not enabled, falling back to crypto.subtle\nThis is significanty slower than the WASM implementation");const e=new Uint8Array(r.length/2);for(let t=0;t { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { @@ -124,14 +131,14 @@ if (!apiEndpoint) throw new Error("Missing API endpoint"); const { challenge, token } = await ( - await fetch(`${apiEndpoint}challenge`, { + await capFetch(`${apiEndpoint}challenge`, { method: "POST", }) ).json(); const solutions = await this.solveChallenges(challenge); const resp = await ( - await fetch(`${apiEndpoint}redeem`, { + await capFetch(`${apiEndpoint}redeem`, { method: "POST", body: JSON.stringify({ token, solutions }), headers: { "Content-Type": "application/json" }, @@ -527,7 +534,7 @@ setTimeout(async function () { workerScript = (await ( - await fetch( + await capFetch( "https://cdn.jsdelivr.net/npm/@cap.js/widget/wasm-hashes.min.js" ) ).text()) +