1"use strict"; 2!(function () { 3 let e; 4 const t = function () { 5 return window?.CAP_CUSTOM_FETCH 6 ? window.CAP_CUSTOM_FETCH(...arguments) 7 : fetch(...arguments); 8 }, 9 r = (e, t = 1e4) => 10 new Promise((r, s) => { 11 const i = setTimeout(() => { 12 s(new Error("Initialize timeout")); 13 }, t), 14 a = () => { 15 e() ? (clearTimeout(i), r()) : setTimeout(a, 500); 16 }; 17 a(); 18 }); 19 class s extends HTMLElement { 20 #e = ""; 21 #t = null; 22 #r = navigator.hardwareConcurrency || 8; 23 #s = null; 24 #i; 25 #a; 26 #n; 27 #o = !1; 28 #c; 29 static get observedAttributes() { 30 return ["onsolve", "onprogress", "onreset", "onerror", "workers"]; 31 } 32 constructor() { 33 super(), 34 this.#c && 35 this.#c.forEach((e, t) => { 36 this.removeEventListener(t.slice(2), e); 37 }), 38 (this.#c = new Map()), 39 (this.boundHandleProgress = this.handleProgress.bind(this)), 40 (this.boundHandleSolve = this.handleSolve.bind(this)), 41 (this.boundHandleError = this.handleError.bind(this)), 42 (this.boundHandleReset = this.handleReset.bind(this)); 43 } 44 async initialize() { 45 this.#e && URL.revokeObjectURL(this.#e);
46 try { 47 await r(() => !!e), 48 (this.#e = URL.createObjectURL( 49 new Blob([e], { type: "application/javascript" }), 50 )); 51 } catch (e) { 52 throw (this.error("Failed to initialize worker"), e); 53 } 54 } 55 attributeChangedCallback(e, t, r) { 56 if (e.startsWith("on")) { 57 const t = e.slice(2), 58 s = this.#c.get(e); 59 if ((s && this.removeEventListener(t, s), r)) { 60 const r = (t) => { 61 const r = this.getAttribute(e); 62 "function" == typeof window[r] && window[r].call(this, t); 63 }; 64 this.#c.set(e, r), this.addEventListener(t, r); 65 } 66 } 67 } 68 async connectedCallback() { 69 (this.#n = this), 70 (this.#i = this.attachShadow({ mode: "open" })), 71 (this.#a = document.createElement("div")), 72 this.createUI(), 73 this.addEventListeners(), 74 await this.initialize(), 75 this.#a.removeAttribute("disabled"); 76 const e = this.getAttribute("data-cap-worker-count"); 77 this.setWorkersCount( 78 parseInt(e) ? parseInt(e, 10) : navigator.hardwareConcurrency || 8, 79 ), 80 (this.#n.innerHTML = '<input type="hidden" name="cap-token">'); 81 } 82 async solve() { 83 if (!this.#o) 84 try { 85 (this.#o = !0), 86 this.updateUI("verifying", "Verifying...", !0), 87 await r(() => !!this.#e), 88 this.dispatchEvent("progress", { progress: 0 }); 89 try { 90 const e = this.getAttribute("data-cap-api-endpoint"); 91 if (!e) throw new Error("Missing API endpoint"); 92 const { challenge: r, token: s } = await ( 93 await t(`${e}challenge`, { method: "POST" }) 94 ).json(), 95 i = await this.solveChallenges(r), 96 a = await ( 97 await t(`${e}redeem`, { 98 method: "POST", 99 body: JSON.stringify({ token: s, solutions: i }), 100 headers: { "Content-Type": "application/json" }, 101 }) 102 ).json(); 103 if ((this.dispatchEvent("progress", { progress: 100 }), !a.success)) 104 throw new Error("Invalid solution"); 105 this.querySelector("input[name='cap-token']") && 106 (this.querySelector("input[name='cap-token']").value = a.token), 107 this.dispatchEvent("solve", { token: a.token }), 108 (this.#s = a.token), 109 this.#t && clearTimeout(this.#t); 110 const n = new Date(a.expires).getTime() - Date.now(); 111 return ( 112 n > 0 && n < 864e5 113 ? (this.#t = setTimeout(() => this.reset(), n)) 114 : this.error("Invalid expiration time"), 115 { success: !0, token: this.#s } 116 ); 117 } catch (e) { 118 throw (this.error(e.message), e); 119 } 120 } finally { 121 this.#o = !1; 122 } 123 } 124 async solveChallenges(e) { 125 const t = e.length; 126 let r = 0; 127 const s = Array(this.#r) 128 .fill(null) 129 .map(() => new Worker(this.#e)), 130 i = ([e, i], a) => 131 new Promise((n, o) => { 132 const c = s[a], 133 d = setTimeout(() => { 134 c.terminate(), 135 (s[a] = new Worker(this.#e)), 136 o(new Error("Worker timeout")); 137 }, 3e4); 138 (c.onmessage = ({ data: s }) => { 139 s.found && 140 (clearTimeout(d), 141 r++, 142 this.dispatchEvent("progress", { 143 progress: Math.round((r / t) * 100), 144 }), 145 n([e, i, s.nonce])); 146 }), 147 (c.onerror = (e) => { 148 clearTimeout(d), this.error(`Error in worker: ${e}`), o(e); 149 }), 150 c.postMessage({ salt: e, target: i }); 151 }), 152 a = [];
153 try { 154 for (let t = 0; t < e.length; t += this.#r) { 155 const r = e.slice(t, Math.min(t + this.#r, e.length)), 156 s = await Promise.all(r.map((e, t) => i(e, t))); 157 a.push(...s); 158 } 159 } finally { 160 s.forEach((e) => e.terminate()); 161 } 162 return a; 163 } 164 setWorkersCount(e) { 165 const t = parseInt(e, 10), 166 r = Math.min(navigator.hardwareConcurrency || 8, 16); 167 this.#r = 168 !isNaN(t) && t > 0 && t <= r ? t : navigator.hardwareConcurrency || 8; 169 } 170 createUI() { 171 this.#a.classList.add("captcha"), 172 this.#a.setAttribute("role", "button"), 173 this.#a.setAttribute("tabindex", "0"), 174 this.#a.setAttribute("disabled", "true"), 175 (this.#a.innerHTML = 176 '<div class="checkbox"></div><p>I\'m a human</p><a href="https://capjs.js.org/" class="credits" target="_blank" rel="follow noopener"><span>Secured by </span>Cap</a>'), 177 (this.#i.innerHTML = 178 '<style>.captcha{background-color:var(--cap-background);border:1px solid var(--cap-border-color);border-radius:var(--cap-border-radius);width:var(--cap-widget-width);display:flex;align-items:center;padding:var(--cap-widget-padding);gap:var(--cap-gap);cursor:pointer;transition:filter var(--cap-transition-duration),transform var(--cap-transition-duration);position:relative;-webkit-tap-highlight-color:rgba(255,255,255,0);overflow:hidden;color:var(--cap-color)}.captcha:hover{filter:var(--cap-hover-filter)}.captcha:not([disabled]):active{transform:scale(var(--cap-active-scale))}.checkbox{width:var(--cap-checkbox-size);height:var(--cap-checkbox-size);border:var(--cap-checkbox-border);border-radius:var(--cap-checkbox-border-radius);background-color:var(--cap-checkbox-background);transition:opacity var(--cap-transition-duration);margin-top:var(--cap-checkbox-margin);margin-bottom:var(--cap-checkbox-margin)}.captcha *{font-family:var(--cap-font)}.captcha p{margin:0;font-weight:500;font-size:15px;user-select:none;transition:opacity var(--cap-transition-duration)}.captcha[data-state=verifying] .checkbox{background: none;display:flex;align-items:center;justify-content:center;transform: scale(1.1);border: none;border-radius: 50%;background: conic-gradient(var(--cap-spinner-color) 0%, var(--cap-spinner-color) var(--progress, 0%), var(--cap-spinner-background-color) var(--progress, 0%), var(--cap-spinner-background-color) 100%);position: relative;}.captcha[data-state=verifying] .checkbox::after {content: "";background-color: var(--cap-background);width: calc(100% - var(--cap-spinner-thickness));height: calc(100% - var(--cap-spinner-thickness));border-radius: 50%;margin:calc(var(--cap-spinner-thickness) / 2)}.captcha[data-state=done] .checkbox{border:1px solid transparent;background-image:var(--cap-checkmark);background-size:cover}.captcha[data-state=error] .checkbox{border:1px solid transparent;background-image:var(--cap-error-cross);background-size:cover}.captcha[disabled]{\ncursor:not-allowed}.captcha[disabled][data-state=verifying]{cursor:progress}.captcha[disabled][data-state=done]{cursor:default}.captcha .credits{position:absolute;bottom:10px;right:10px;font-size:var(--cap-credits-font-size);color:var(--cap-color);opacity:var(--cap-opacity-hover)}.captcha .credits span{display:none;text-decoration:underline}.captcha .credits:hover span{display:inline-block}</style>'), 179 this.#i.appendChild(this.#a); 180 } 181 addEventListeners() { 182 this.#a.querySelector("a").addEventListener("click", (e) => { 183 e.stopPropagation(), 184 e.preventDefault(), 185 window.open("https://capjs.js.org", "_blank"); 186 }), 187 this.#a.addEventListener("click", () => { 188 this.#a.hasAttribute("disabled") || this.solve(); 189 }), 190 this.#a.addEventListener("keydown", (e) => { 191 ("Enter" !== e.key && " " !== e.key) || 192 this.#a.hasAttribute("disabled") || 193 (e.preventDefault(), this.solve()); 194 }), 195 this.addEventListener("progress", this.boundHandleProgress), 196 this.addEventListener("solve", this.boundHandleSolve), 197 this.addEventListener("error", this.boundHandleError), 198 this.addEventListener("reset", this.boundHandleReset); 199 } 200 updateUI(e, t, r = !1) { 201 this.#a.setAttribute("data-state", e), 202 (this.#a.querySelector("p").innerText = t), 203 r 204 ? this.#a.setAttribute("disabled", "true") 205 : this.#a.removeAttribute("disabled"); 206 } 207 handleProgress(e) { 208 const t = this.#a.querySelector("p"); 209 t && 210 (this.#a 211 .querySelector(".checkbox") 212 .style.setProperty("--progress", `${e.detail.progress}%`), 213 (t.innerText = `Verifying... ${e.detail.progress}%`)), 214 this.executeAttributeCode("onprogress", e); 215 } 216 handleSolve(e) { 217 this.updateUI("done", "You're a human", !0), 218 this.executeAttributeCode("onsolve", e); 219 } 220 handleError(e) { 221 this.updateUI("error", "Error. Try again."), 222 this.executeAttributeCode("onerror", e); 223 } 224 handleReset(e) { 225 this.updateUI("", "I'm a human"), this.executeAttributeCode("onreset", e); 226 } 227 executeAttributeCode(e, t) { 228 const r = this.getAttribute(e); 229 if (!r) return; 230 new Function("event", r).call(this, t); 231 } 232 error(e = "Unknown error") { 233 console.error("[Cap] Error:", e), 234 this.dispatchEvent("error", { isCap: !0, message: e }); 235 } 236 dispatchEvent(e, t = {}) { 237 const r = new CustomEvent(e, { bubbles: !0, composed: !0, detail: t }); 238 super.dispatchEvent(r); 239 } 240 reset() { 241 this.#t && (clearTimeout(this.#t), (this.#t = null)), 242 this.dispatchEvent("reset"), 243 (this.#s = null),
244 this.querySelector("input[name='cap-token']") && 245 (this.querySelector("input[name='cap-token']").value = ""); 246 } 247 get token() { 248 return this.#s; 249 } 250 disconnectedCallback() { 251 this.removeEventListener("progress", this.boundHandleProgress), 252 this.removeEventListener("solve", this.boundHandleSolve), 253 this.removeEventListener("error", this.boundHandleError), 254 this.removeEventListener("reset", this.boundHandleReset), 255 this.#c.forEach((e, t) => { 256 this.removeEventListener(t.slice(2), e); 257 }), 258 this.#c.clear(), 259 this.#i && (this.#i.innerHTML = ""), 260 this.reset(), 261 this.cleanup(); 262 } 263 cleanup() { 264 this.#t && (clearTimeout(this.#t), (this.#t = null)), 265 this.#e && (URL.revokeObjectURL(this.#e), (this.#e = "")); 266 } 267 } 268 class i { 269 constructor(e = {}, t) { 270 let r = t || document.createElement("cap-widget"); 271 if ( 272 (Object.entries(e).forEach(([e, t]) => { 273 r.setAttribute(e, t); 274 }), 275 !e.apiEndpoint) 276 ) 277 throw (r.remove(), new Error("Missing API endpoint")); 278 r.setAttribute("data-cap-api-endpoint", e.apiEndpoint), 279 (this.widget = r), 280 (this.solve = this.widget.solve.bind(this.widget)), 281 (this.reset = this.widget.reset.bind(this.widget)), 282 (this.addEventListener = this.widget.addEventListener.bind( 283 this.widget, 284 )), 285 Object.defineProperty(this, "token", { 286 get: () => r.getToken(), 287 configurable: !0, 288 enumerable: !0, 289 }), 290 t || 291 ((r.style.display = "none"), document.documentElement.appendChild(r)); 292 } 293 } 294 const a = new CSSStyleSheet(); 295 a.replaceSync( 296 '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%3
296E%3C%2Fsvg%3E");--cap-spinner-thickness:5px;}', 297 ), 298 document.adoptedStyleSheets.push(a); 299 const n = function () { 300 let e; 301 self.onmessage = async ({ data: { salt: t, target: r } }) => { 302 let s = 0; 303 const i = 5e4; 304 let a = 0; 305 const n = new TextEncoder(); 306 if ( 307 "object" != typeof WebAssembly || 308 "function" != typeof WebAssembly.instantiate 309 ) { 310 console.log( 311 "[cap] WASM not enabled, falling back to crypto.subtle\nThis is significanty slower than the WASM implementation", 312 ); 313 const e = new Uint8Array(r.length / 2); 314 for (let t = 0; t < e.length; t++) 315 e[t] = parseInt(r.substring(2 * t, 2 * t + 2), 16); 316 const o = e.length; 317 for (;;) 318 try { 319 for (let r = 0; r < i; r++) { 320 const r = t + s, 321 i = n.encode(r), 322 a = await crypto.subtle.digest("SHA-256", i), 323 c = new Uint8Array(a, 0, o); 324 let d = !0; 325 for (let t = 0; t < o; t++) 326 if (c[t] !== e[t]) { 327 d = !1; 328 break; 329 } 330 if (d) return void self.postMessage({ nonce: s, found: !0 }); 331 s++; 332 } 333 a += i; 334 } catch (e) { 335 return ( 336 console.error("[cap] fallback worker error", e), 337 void self.postMessage({ found: !1, error: e.message }) 338 ); 339 } 340 } 341 e || (e = await hashwasm.createSHA256()); 342 const o = new Uint8Array(128); 343 for (;;) 344 try { 345 for (let a = 0; a < i; a++) { 346 const i = t + s.toString(), 347 a = n.encode(i); 348 o.set(a), e.init(), e.update(o.subarray(0, a.length)); 349 if (e.digest("hex").startsWith(r)) 350 return void self.postMessage({ nonce: s, found: !0 }); 351 s++; 352 } 353 a += i; 354 } catch (e) { 355 return void self.postMessage({ found: !1, error: e.message }); 356 } 357 }; 358 }; 359 setTimeout(async function () { 360 e = 361 (await ( 362 await t( 363 "https://cdn.jsdelivr.net/npm/@cap.js/widget/wasm-hashes.min.js", 364 ) 365 ).text()) + 366 n 367 .toString() 368 .replace(/^function\s*\([^\)]*\)\s*{|\}$/g, "") 369 .trim(); 370 }, 1), 371 (window.Cap = i), 372 customElements.get("cap-widget") 373 ? console.warn( 374 "The cap-widget element has already been defined. Skipping re-defining it.", 375 ) 376 : customElements.define("cap-widget", s), 377 "object" == typeof exports && "undefined" != typeof module 378 ? (module.exports = i) 379 : "function" == typeof define && 380 define.amd && 381 define([], function () { 382 return i; 383 }), 384 "undefined" != typeof exports && (exports.default = i); 385})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.