@botsigged/sdk 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{a as y,b as U,d as v}from"./hash-q46pgar4.js";function T(Q){return typeof Q==="object"&&Q!==null&&"code"in Q&&Q.code==="LIMIT_EXCEEDED"}var q={endpoint:"wss://api.botsigged.com/socket/websocket",debug:!1,sendInterval:2000,maxBufferSize:1000,mouseSampleRate:0.5,autoStart:!0,actionThreshold:70,action:"none",minAlertLevel:"high",botScoreThresholds:{medium:40,high:70,critical:90},hashVerification:{enabled:!1,preferWasm:!0},challenge:{enabled:!1,minLevel:"high",chunkSize:1e4,difficulty:{medium:12,high:16,critical:20},ui:{enabled:!0,message:"Verifying you're human...",successMessage:"Verified!",backgroundColor:"rgba(0, 0, 0, 0.7)",textColor:"#ffffff",spinnerColor:"#3b82f6",zIndex:999999}},formProtection:{mode:"auto",minTimeBeforeSubmit:500,maxHoldTime:3000,showLoadingUI:!0,loadingMessage:"Please wait..."},fallbackMode:"degraded"},F={action:"challenge",challenge:{difficulty:{suspicious:14,bot:18},timeout_ms:30000},form_protection_mode:"holdUntilReady"};function h(Q){let X=Q.action??q.action,Y=X==="challenge"||Q.challenge?.enabled;return{apiKey:Q.apiKey,accountId:Q.accountId,endpoint:Q.endpoint??q.endpoint,debug:Q.debug??q.debug,sendInterval:Q.sendInterval??q.sendInterval,maxBufferSize:Q.maxBufferSize??q.maxBufferSize,mouseSampleRate:Q.mouseSampleRate??q.mouseSampleRate,autoStart:Q.autoStart??q.autoStart,actionThreshold:Q.actionThreshold??q.actionThreshold,action:X,minAlertLevel:Q.minAlertLevel??q.minAlertLevel,botScoreThresholds:{...q.botScoreThresholds,...Q.botScoreThresholds},hashVerification:{...q.hashVerification,...Q.hashVerification},challenge:{enabled:Y,minLevel:Q.challenge?.minLevel??q.challenge.minLevel,chunkSize:Q.challenge?.chunkSize??q.challenge.chunkSize,difficulty:{...q.challenge.difficulty,...Q.challenge?.difficulty},ui:{...q.challenge.ui,...Q.challenge?.ui},onChallengeStart:Q.challenge?.onChallengeStart,onChallengeComplete:Q.challenge?.onChallengeComplete,onChallengeProgress:Q.challenge?.onChallengeProgress},formProtection:{mode:Q.formProtection?.mode??q.formProtection.mode,minTimeBeforeSubmit:Q.formProtection?.minTimeBeforeSubmit??q.formProtection.minTimeBeforeSubmit,maxHoldTime:Q.formProtection?.maxHoldTime??q.formProtection.maxHoldTime,showLoadingUI:Q.formProtection?.showLoadingUI??q.formProtection.showLoadingUI,loadingMessage:Q.formProtection?.loadingMessage??q.formProtection.loadingMessage,onHold:Q.formProtection?.onHold,onRelease:Q.formProtection?.onRelease,onBlock:Q.formProtection?.onBlock},fallbackMode:Q.fallbackMode??q.fallbackMode,cookie:Q.cookie,headers:Q.headers,formInject:Q.formInject,onScoreUpdate:Q.onScoreUpdate,onConnectionChange:Q.onConnectionChange,onError:Q.onError,onUsageLimitExceeded:Q.onUsageLimitExceeded,onHighBotScore:Q.onHighBotScore,onServerConfig:Q.onServerConfig,onServerAction:Q.onServerAction}}class k{events=[];startTime=0;sampleRate;maxBufferSize;isListening=!1;boundHandleMouseMove;boundHandleMouseDown;boundHandleMouseUp;boundHandleClick;constructor(Q={}){this.sampleRate=Q.sampleRate??0.5,this.maxBufferSize=Q.maxBufferSize??500,this.boundHandleMouseMove=this.handleMouseMove.bind(this),this.boundHandleMouseDown=this.handleMouseDown.bind(this),this.boundHandleMouseUp=this.handleMouseUp.bind(this),this.boundHandleClick=this.handleClick.bind(this)}start(){if(this.isListening)return;this.startTime=Date.now(),document.addEventListener("mousemove",this.boundHandleMouseMove,{passive:!0}),document.addEventListener("mousedown",this.boundHandleMouseDown,{passive:!0}),document.addEventListener("mouseup",this.boundHandleMouseUp,{passive:!0}),document.addEventListener("click",this.boundHandleClick,{passive:!0}),this.isListening=!0}stop(){if(!this.isListening)return;document.removeEventListener("mousemove",this.boundHandleMouseMove),document.removeEventListener("mousedown",this.boundHandleMouseDown),document.removeEventListener("mouseup",this.boundHandleMouseUp),document.removeEventListener("click",this.boundHandleClick),this.isListening=!1}addEvent(Q){if(this.events.push(Q),this.events.length>this.maxBufferSize)this.events.shift()}handleMouseMove(Q){if(Math.random()>this.sampleRate)return;this.addEvent({type:"move",x:Q.clientX,y:Q.clientY,t:Date.now()})}handleMouseDown(Q){this.addEvent({type:"down",x:Q.clientX,y:Q.clientY,t:Date.now(),button:Q.button})}handleMouseUp(Q){this.addEvent({type:"up",x:Q.clientX,y:Q.clientY,t:Date.now(),button:Q.button})}handleClick(Q){let X=Q.target,Y,Z;if(X&&X.getBoundingClientRect){let $=X.getBoundingClientRect();Y={top:$.top,left:$.left,width:$.width,height:$.height},Z=X.tagName?.toLowerCase()}this.addEvent({type:"click",x:Q.clientX,y:Q.clientY,t:Date.now(),button:Q.button,targetRect:Y,targetTag:Z})}getSignal(){return{events:[...this.events],start_time:this.startTime}}flush(){this.events=[]}getBufferSize(){return this.events.length}reset(){this.events=[],this.startTime=Date.now()}}class x{events=[];startTime=0;maxBufferSize;isListening=!1;boundHandleScroll;constructor(Q={}){this.maxBufferSize=Q.maxBufferSize??200,this.boundHandleScroll=this.handleScroll.bind(this)}start(){if(this.isListening)return;this.startTime=Date.now(),window.addEventListener("scroll",this.boundHandleScroll,{passive:!0}),this.isListening=!0}stop(){if(!this.isListening)return;window.removeEventListener("scroll",this.boundHandleScroll),this.isListening=!1}handleScroll(){if(this.events.push({y:window.scrollY,t:Date.now()}),this.events.length>this.maxBufferSize)this.events.shift()}getSignal(){return{events:[...this.events],start_time:this.startTime}}flush(){this.events=[]}getBufferSize(){return this.events.length}reset(){this.events=[],this.startTime=Date.now()}}class w{static instance=null;timings={signalRoundtrips:[]};pendingSignals=new Map;constructor(){this.timings.scriptStart=performance.now()}static getInstance(){if(!w.instance)w.instance=new w;return w.instance}static reset(){w.instance=null}markScriptStart(){this.timings.scriptStart=performance.now()}markConstructorStart(){this.timings.constructorStart=performance.now()}markConstructorEnd(){this.timings.constructorEnd=performance.now()}markStartCalled(){this.timings.startCalled=performance.now()}markSdkReady(){this.timings.sdkReady=performance.now()}markFingerprintStart(){this.timings.fingerprintStart=performance.now()}markFingerprintEnd(){this.timings.fingerprintEnd=performance.now()}markWsConnectStart(){this.timings.wsConnectStart=performance.now()}markWsConnectEnd(){this.timings.wsConnectEnd=performance.now()}markChannelJoinStart(){this.timings.channelJoinStart=performance.now()}markChannelJoinEnd(){this.timings.channelJoinEnd=performance.now()}markInitialScoreReceived(){this.timings.initialScoreReceived=performance.now()}markFormCollectorStart(){this.timings.formCollectorStart=performance.now()}markFormCollectorReady(){this.timings.formCollectorReady=performance.now()}markFirstFormInteraction(){if(!this.timings.firstFormInteraction){if(this.timings.firstFormInteraction=performance.now(),this.timings.sdkReady)this.timings.timeToFirstInteraction=this.timings.firstFormInteraction-this.timings.sdkReady}}markFirstSubmitAttempt(Q){if(!this.timings.firstSubmitAttempt)this.timings.firstSubmitAttempt=performance.now(),this.timings.hadScoreBeforeSubmit=Q}markSignalSent(Q){this.pendingSignals.set(Q,performance.now())}markSignalResponseReceived(Q){let X=this.pendingSignals.get(Q);if(X!==void 0){let Y=performance.now(),Z={sentAt:X,receivedAt:Y,roundtripMs:Y-X,seq:Q};this.timings.signalRoundtrips?.push(Z),this.pendingSignals.delete(Q)}}getTimings(){return{...this.timings}}getSummary(){let Q=this.timings,X=Q.signalRoundtrips||[],Y=0,Z=1/0,$=0;if(X.length>0)Y=X.reduce((G,g)=>G+g.roundtripMs,0)/X.length,Z=Math.min(...X.map((G)=>G.roundtripMs)),$=Math.max(...X.map((G)=>G.roundtripMs));let J=(Q.sdkReady??0)-(Q.scriptStart??0),z=(Q.fingerprintEnd??0)-(Q.fingerprintStart??0),W=(Q.wsConnectEnd??0)-(Q.wsConnectStart??0),B=(Q.channelJoinEnd??0)-(Q.channelJoinStart??0),V=(Q.initialScoreReceived??0)-(Q.startCalled??0),R=(Q.initialScoreReceived??0)-(Q.scriptStart??0);return{totalStartupMs:Math.round(J),fingerprintMs:Math.round(z),wsConnectionMs:Math.round(W),channelJoinMs:Math.round(B),timeToFirstScoreMs:Math.round(V),avgSignalRoundtripMs:Math.round(Y),minSignalRoundtripMs:Z===1/0?0:Math.round(Z),maxSignalRoundtripMs:Math.round($),vulnerabilityWindowMs:Math.round(R),protectedBeforeSubmit:Q.hadScoreBeforeSubmit??!1}}logSummary(){let Q=this.getSummary(),X=this.timings;if(X.firstFormInteraction);if(X.firstSubmitAttempt);if(Q.vulnerabilityWindowMs>0);}getReport(){return{timings:this.timings,summary:this.getSummary(),userAgent:navigator.userAgent,timestamp:Date.now()}}}var K=w.getInstance();function N(){return w.getInstance()}function l(){return K.getSummary()}function f(){K.logSummary()}var j="__bs_ghost_value";class C{keyEvents=[];focusEvents=[];pasteEvents=[];inputEvents=[];submitCount=0;startTime=0;maxKeyEvents;maxFocusEvents;maxInputEvents;isListening=!1;valueSetterHooked=!1;onSubmit;originalInputDescriptor;originalTextareaDescriptor;lastKeyWasTab=!1;currentField=null;emailDomains=new Set;boundHandleFocusIn;boundHandleFocusOut;boundHandleKeyDown;boundHandleKeyUp;boundHandlePaste;boundHandleSubmit;boundHandleClick;boundHandleInput;boundHandleGhostValue;constructor(Q={}){this.maxKeyEvents=Q.maxKeyEvents??500,this.maxFocusEvents=Q.maxFocusEvents??100,this.maxInputEvents=Q.maxInputEvents??200,this.onSubmit=Q.onSubmit,this.boundHandleFocusIn=this.handleFocusIn.bind(this),this.boundHandleFocusOut=this.handleFocusOut.bind(this),this.boundHandleKeyDown=this.handleKeyDown.bind(this),this.boundHandleKeyUp=this.handleKeyUp.bind(this),this.boundHandlePaste=this.handlePaste.bind(this),this.boundHandleSubmit=this.handleSubmit.bind(this),this.boundHandleClick=this.handleClick.bind(this),this.boundHandleInput=this.handleInput.bind(this),this.boundHandleGhostValue=this.handleGhostValue.bind(this)}start(){if(this.isListening)return;this.startTime=Date.now(),document.addEventListener("focusin",this.boundHandleFocusIn,{passive:!0,capture:!0}),document.addEventListener("focusout",this.boundHandleFocusOut,{passive:!0,capture:!0}),document.addEventListener("keydown",this.boundHandleKeyDown,{passive:!0}),document.addEventListener("keyup",this.boundHandleKeyUp,{passive:!0}),document.addEventListener("paste",this.boundHandlePaste,{passive:!0}),document.addEventListener("submit",this.boundHandleSubmit,{passive:!0}),document.addEventListener("click",this.boundHandleClick,{passive:!0}),document.addEventListener("input",this.boundHandleInput,{passive:!0}),document.addEventListener(j,this.boundHandleGhostValue,{passive:!0}),this.hookValueSetters(),this.isListening=!0}stop(){if(!this.isListening)return;document.removeEventListener("focusin",this.boundHandleFocusIn,{capture:!0}),document.removeEventListener("focusout",this.boundHandleFocusOut,{capture:!0}),document.removeEventListener("keydown",this.boundHandleKeyDown),document.removeEventListener("keyup",this.boundHandleKeyUp),document.removeEventListener("paste",this.boundHandlePaste),document.removeEventListener("submit",this.boundHandleSubmit),document.removeEventListener("click",this.boundHandleClick),document.removeEventListener("input",this.boundHandleInput),document.removeEventListener(j,this.boundHandleGhostValue),this.unhookValueSetters(),this.isListening=!1}isFormInput(Q){if(!Q||!(Q instanceof HTMLElement))return!1;let X=Q.tagName.toLowerCase();if(X==="textarea"||X==="select")return!0;if(X==="input"){let Y=Q.type.toLowerCase();return!["submit","button","reset","hidden","image"].includes(Y)}return!1}isEmailField(Q){let X=Q.type?.toLowerCase()||"",Y=(Q.name||"").toLowerCase(),Z=(Q.id||"").toLowerCase();return X==="email"||Y.includes("email")||Y.includes("e-mail")||Z.includes("email")||Z.includes("e-mail")}extractEmailDomain(Q){if(!Q||typeof Q!=="string")return null;let X=Q.trim();if(!X)return null;let Y=X.match(/@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/);return Y?Y[1].toLowerCase():null}getFieldId(Q){return Q.id||Q.getAttribute("name")||`field-${Q.tagName.toLowerCase()}`}handleFocusIn(Q){if(!this.isFormInput(Q.target))return;N().markFirstFormInteraction();let X=this.getFieldId(Q.target),Y="direct";if(this.lastKeyWasTab)Y="tab";if(this.focusEvents.push({type:"focus",field:X,t:Date.now(),method:Y}),this.focusEvents.length>this.maxFocusEvents)this.focusEvents.shift();this.currentField=X,this.lastKeyWasTab=!1}handleFocusOut(Q){if(!this.isFormInput(Q.target))return;let X=Q.target,Y=this.getFieldId(X);if(this.focusEvents.push({type:"blur",field:Y,t:Date.now()}),this.focusEvents.length>this.maxFocusEvents)this.focusEvents.shift();if(X instanceof HTMLInputElement&&this.isEmailField(X)){let Z=this.extractEmailDomain(X.value);if(Z)this.emailDomains.add(Z)}this.currentField=null}handleClick(Q){if(!this.isFormInput(Q.target))return;let X=this.focusEvents[this.focusEvents.length-1];if(X&&X.type==="focus"&&Date.now()-X.t<50)X.method="click"}handleKeyDown(Q){if(Q.key==="Tab"){this.lastKeyWasTab=!0;return}if(!this.isFormInput(Q.target))return;let X="key";if(Q.key==="Backspace")X="backspace";else if(Q.key==="Delete")X="delete";else if(Q.key==="Enter")X="enter";else if(Q.key==="Tab")X="tab";else if(Q.key.length===1)X="char";else if(Q.key.startsWith("Arrow"))X="arrow";if(this.keyEvents.push({type:"down",code:X,t:Date.now(),field:this.currentField||void 0}),this.keyEvents.length>this.maxKeyEvents)this.keyEvents.shift()}handleKeyUp(Q){if(!this.isFormInput(Q.target))return;let X="key";if(Q.key==="Backspace")X="backspace";else if(Q.key==="Delete")X="delete";else if(Q.key.length===1)X="char";if(this.keyEvents.push({type:"up",code:X,t:Date.now(),field:this.currentField||void 0}),this.keyEvents.length>this.maxKeyEvents)this.keyEvents.shift()}handleInput(Q){if(!this.isFormInput(Q.target))return;let X=Q.target,Z=Q.inputType||"unknown",$=X.value?.length??0;if(this.inputEvents.push({field:this.getFieldId(X),t:Date.now(),inputType:Z,valueLength:$}),this.inputEvents.length>this.maxInputEvents)this.inputEvents.shift()}handlePaste(Q){if(!this.isFormInput(Q.target))return;let X=Q.clipboardData?.getData("text")||"";this.pasteEvents.push({field:this.getFieldId(Q.target),t:Date.now(),length:X.length})}handleSubmit(Q){this.submitCount++;let X=Q.target;if(X&&X.elements)for(let Y=0;Y<X.elements.length;Y++){let Z=X.elements[Y];if(Z instanceof HTMLInputElement&&this.isEmailField(Z)){let $=this.extractEmailDomain(Z.value);if($)this.emailDomains.add($)}}this.onSubmit?.()}getSignal(){return{keys:[...this.keyEvents],focus:[...this.focusEvents],pastes:[...this.pasteEvents],inputs:[...this.inputEvents],submits:this.submitCount,start_time:this.startTime,email_domains:this.emailDomains.size>0?Array.from(this.emailDomains):void 0}}flush(){this.keyEvents=[],this.focusEvents=[],this.pasteEvents=[],this.inputEvents=[]}getBufferSize(){return this.keyEvents.length+this.focusEvents.length+this.pasteEvents.length+this.inputEvents.length}reset(){this.keyEvents=[],this.focusEvents=[],this.pasteEvents=[],this.inputEvents=[],this.submitCount=0,this.startTime=Date.now(),this.lastKeyWasTab=!1,this.currentField=null,this.emailDomains.clear()}hookValueSetters(){if(this.valueSetterHooked)return;if(this.originalInputDescriptor=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value"),this.originalInputDescriptor){let Q=this.originalInputDescriptor.set,X=this.originalInputDescriptor.get;Object.defineProperty(HTMLInputElement.prototype,"value",{configurable:!0,enumerable:!0,get(){return X?.call(this)},set(Y){let Z=X?.call(this)??"";Q?.call(this,Y);let $=Y??"";if($!==Z)this.dispatchEvent(new CustomEvent(j,{bubbles:!0,detail:{valueLength:$.length,wasEmpty:Z.length===0}}))}})}if(this.originalTextareaDescriptor=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,"value"),this.originalTextareaDescriptor){let Q=this.originalTextareaDescriptor.set,X=this.originalTextareaDescriptor.get;Object.defineProperty(HTMLTextAreaElement.prototype,"value",{configurable:!0,enumerable:!0,get(){return X?.call(this)},set(Y){let Z=X?.call(this)??"";Q?.call(this,Y);let $=Y??"";if($!==Z)this.dispatchEvent(new CustomEvent(j,{bubbles:!0,detail:{valueLength:$.length,wasEmpty:Z.length===0}}))}})}this.valueSetterHooked=!0}unhookValueSetters(){if(!this.valueSetterHooked)return;if(this.originalInputDescriptor)Object.defineProperty(HTMLInputElement.prototype,"value",this.originalInputDescriptor);if(this.originalTextareaDescriptor)Object.defineProperty(HTMLTextAreaElement.prototype,"value",this.originalTextareaDescriptor);this.valueSetterHooked=!1}handleGhostValue(Q){let X=Q.target;if(!this.isFormInput(X))return;let Z=Q.detail?.valueLength??0;if(this.inputEvents.push({field:this.getFieldId(X),t:Date.now(),inputType:"programmatic",valueLength:Z}),this.inputEvents.length>this.maxInputEvents)this.inputEvents.shift()}}class L{cachedSignal=null;collect(){if(this.cachedSignal)return this.cachedSignal;let Q=navigator,X=window;return this.cachedSignal={user_agent:navigator.userAgent,platform:navigator.platform,language:navigator.language,languages:[...navigator.languages||[]],hardware_concurrency:navigator.hardwareConcurrency??null,device_memory:Q.deviceMemory??null,max_touch_points:navigator.maxTouchPoints??0,screen_width:screen.width,screen_height:screen.height,screen_avail_width:screen.availWidth,screen_avail_height:screen.availHeight,color_depth:screen.colorDepth,pixel_ratio:window.devicePixelRatio??1,...this.getWebGLInfo(),plugins_count:navigator.plugins?.length??0,mime_types_count:navigator.mimeTypes?.length??0,timezone:this.getTimezone(),timezone_offset:new Date().getTimezoneOffset(),has_webdriver:Q.webdriver===!0,has_chrome_runtime:!!X.chrome?.runtime,has_chrome_app:!!X.chrome?.app,has_notification_api:"Notification"in window,has_permissions_api:"permissions"in navigator,outer_dimensions:{width:window.outerWidth,height:window.outerHeight},inner_dimensions:{width:window.innerWidth,height:window.innerHeight},notification_permission:this.getNotificationPermission()},this.cachedSignal}getWebGLInfo(){try{let Q=document.createElement("canvas"),X=Q.getContext("webgl")||Q.getContext("experimental-webgl");if(!X||!(X instanceof WebGLRenderingContext))return{webgl_vendor:null,webgl_renderer:null};let Y=X.getExtension("WEBGL_debug_renderer_info");if(!Y)return{webgl_vendor:null,webgl_renderer:null};return{webgl_vendor:X.getParameter(Y.UNMASKED_VENDOR_WEBGL),webgl_renderer:X.getParameter(Y.UNMASKED_RENDERER_WEBGL)}}catch{return{webgl_vendor:null,webgl_renderer:null}}}getTimezone(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return null}}getNotificationPermission(){if("Notification"in window)return Notification.permission;return null}getSignal(){return this.collect()}reset(){this.cachedSignal=null}}class b{cachedFingerprint=null;async generate(){if(this.cachedFingerprint)return this.cachedFingerprint;let[Q,X,Y,Z,$]=await Promise.all([this.getCanvasHash(),this.getWebGLData(),this.getAudioHash(),this.getFontData(),this.getScreenHash()]),J={hash:"",canvas_hash:Q,webgl_hash:X.hash,audio_hash:Y,font_hash:Z.hash,screen_hash:$,webgl_vendor:X.vendor,webgl_renderer:X.renderer,timezone:this.getTimezone(),language:this.getLanguage(),platform:this.getPlatform(),font_count:Z.count};return J.hash=await this.generateMainHash(J),this.cachedFingerprint=J,J}getFingerprint(){return this.cachedFingerprint}reset(){this.cachedFingerprint=null}async getCanvasHash(){try{let Q=document.createElement("canvas");Q.width=200,Q.height=50;let X=Q.getContext("2d");if(!X)return null;X.textBaseline="top",X.font="14px 'Arial'",X.fillStyle="#f60",X.fillRect(125,1,62,20),X.fillStyle="#069",X.fillText("BotSigged,\uD83C\uDFA8",2,15),X.fillStyle="rgba(102, 204, 0, 0.7)",X.fillText("BotSigged,\uD83C\uDFA8",4,17);let Y=Q.toDataURL();return this.hashString(Y)}catch{return null}}async getWebGLData(){try{let Q=document.createElement("canvas"),X=Q.getContext("webgl")||Q.getContext("experimental-webgl");if(!X||!(X instanceof WebGLRenderingContext))return{hash:null,vendor:null,renderer:null};let Y=[],Z=[X.ALIASED_LINE_WIDTH_RANGE,X.ALIASED_POINT_SIZE_RANGE,X.ALPHA_BITS,X.BLUE_BITS,X.DEPTH_BITS,X.GREEN_BITS,X.MAX_COMBINED_TEXTURE_IMAGE_UNITS,X.MAX_CUBE_MAP_TEXTURE_SIZE,X.MAX_FRAGMENT_UNIFORM_VECTORS,X.MAX_RENDERBUFFER_SIZE,X.MAX_TEXTURE_IMAGE_UNITS,X.MAX_TEXTURE_SIZE,X.MAX_VARYING_VECTORS,X.MAX_VERTEX_ATTRIBS,X.MAX_VERTEX_TEXTURE_IMAGE_UNITS,X.MAX_VERTEX_UNIFORM_VECTORS,X.MAX_VIEWPORT_DIMS,X.RED_BITS,X.RENDERER,X.SHADING_LANGUAGE_VERSION,X.STENCIL_BITS,X.VENDOR,X.VERSION];for(let V of Z)try{let R=X.getParameter(V);Y.push(String(R))}catch{Y.push("")}let $=X.getSupportedExtensions();if($)Y.push($.sort().join(","));let J=null,z=null,W=X.getExtension("WEBGL_debug_renderer_info");if(W)J=X.getParameter(W.UNMASKED_VENDOR_WEBGL),z=X.getParameter(W.UNMASKED_RENDERER_WEBGL);return{hash:this.hashString(Y.join("|")),vendor:J,renderer:z}}catch{return{hash:null,vendor:null,renderer:null}}}async getAudioHash(){try{let Q=window.OfflineAudioContext||window.webkitOfflineAudioContext;if(!Q)return null;let X=new Q(1,4500,44100),Y=X.createOscillator(),Z=X.createDynamicsCompressor();Y.type="triangle",Y.frequency.setValueAtTime(1e4,X.currentTime),Z.threshold.setValueAtTime(-50,X.currentTime),Z.knee.setValueAtTime(40,X.currentTime),Z.ratio.setValueAtTime(12,X.currentTime),Z.attack.setValueAtTime(0,X.currentTime),Z.release.setValueAtTime(0.25,X.currentTime),Y.connect(Z),Z.connect(X.destination),Y.start(0);let J=(await X.startRendering()).getChannelData(0),z=[];for(let W=0;W<J.length;W+=100)z.push(J[W]);return this.hashString(z.join(","))}catch{return null}}async getFontData(){let Q=["Arial","Arial Black","Arial Narrow","Calibri","Cambria","Cambria Math","Comic Sans MS","Consolas","Courier","Courier New","Georgia","Helvetica","Impact","Lucida Console","Lucida Sans Unicode","Microsoft Sans Serif","MS Gothic","MS PGothic","MS Sans Serif","MS Serif","Palatino Linotype","Segoe Print","Segoe Script","Segoe UI","Symbol","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana","Wingdings"],X=["monospace","sans-serif","serif"],Y="mmmmmmmmmmlli",Z="72px",$=document.createElement("span");$.style.position="absolute",$.style.left="-9999px",$.style.fontSize="72px",$.style.lineHeight="normal",$.innerHTML="mmmmmmmmmmlli",document.body.appendChild($);let J={};for(let B of X)$.style.fontFamily=B,J[B]=$.offsetWidth;let z=[];for(let B of Q){let V=!1;for(let R of X)if($.style.fontFamily=`'${B}', ${R}`,$.offsetWidth!==J[R]){V=!0;break}if(V)z.push(B)}return document.body.removeChild($),{hash:this.hashString(z.join(",")),count:z.length}}async getScreenHash(){let Q=[String(screen.width),String(screen.height),String(screen.availWidth),String(screen.availHeight),String(screen.colorDepth),String(screen.pixelDepth),String(window.devicePixelRatio||1)];return this.hashString(Q.join("|"))}getTimezone(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return null}}getLanguage(){return navigator.language||null}getPlatform(){return navigator.platform||null}generateMainHash(Q){let X=[Q.canvas_hash||"",Q.webgl_hash||"",Q.audio_hash||"",Q.font_hash||"",Q.screen_hash||"",Q.timezone||"",Q.language||"",Q.platform||""];return this.hashString(X.join("|"))}hashString(Q){return v(Q)}}class A{ws=null;endpoint;apiKey;heartbeatInterval;reconnectAttempts;reconnectDelay;debug;state="disconnected";channelState="closed";refCounter=0;joinRef=null;heartbeatTimer=null;reconnectTimer=null;reconnectCount=0;pendingReplies=new Map;onConnectionChange;onError;channelCallbacks={};topic=null;constructor(Q){this.endpoint=Q.endpoint,this.apiKey=Q.apiKey,this.heartbeatInterval=Q.heartbeatInterval??30000,this.reconnectAttempts=Q.reconnectAttempts??10,this.reconnectDelay=Q.reconnectDelay??((X)=>Math.min(1000*Math.pow(2,X),30000)),this.debug=Q.debug??!1,this.onConnectionChange=Q.onConnectionChange,this.onError=Q.onError}connect(){return new Promise((Q,X)=>{if(this.ws&&this.state==="connected"){Q();return}this.setState("connecting");let Y=this.buildUrl();this.log("Connecting to",Y);try{this.ws=new WebSocket(Y),this.ws.onopen=()=>{this.log("WebSocket connected"),this.setState("connected"),this.reconnectCount=0,this.startHeartbeat(),Q()},this.ws.onclose=(Z)=>{this.log("WebSocket closed",Z.code,Z.reason),this.handleClose()},this.ws.onerror=(Z)=>{this.log("WebSocket error",Z);let $=Error("WebSocket connection error");this.handleError($),X($)},this.ws.onmessage=(Z)=>{this.handleMessage(Z.data)}}catch(Z){let $=Z instanceof Error?Z:Error(String(Z));this.handleError($),X($)}})}disconnect(){if(this.stopHeartbeat(),this.stopReconnect(),this.ws)this.ws.close(1000,"Client disconnect"),this.ws=null;this.setState("disconnected"),this.setChannelState("closed")}joinChannel(Q,X,Y,Z,$={},J){return this.channelCallbacks=$,this.topic=`detection:${Q}`,new Promise((z,W)=>{if(this.state!=="connected"){W(Error("WebSocket not connected"));return}this.setChannelState("joining"),this.joinRef=this.makeRef();let B={session_id:Q,api_key:this.apiKey,fingerprint:X,session:Y,browser:Z};if(J)B.account_id=J;this.push("phx_join",B,this.joinRef).then((V)=>{this.log("Channel joined",V),this.setChannelState("joined"),this.channelCallbacks.onJoin?.(),z(V)}).catch((V)=>{this.log("Channel join failed",V),this.setChannelState("error"),this.channelCallbacks.onError?.(V),W(V)})})}leaveChannel(){return new Promise((Q,X)=>{if(this.channelState!=="joined"){Q();return}this.setChannelState("leaving"),this.push("phx_leave",{}).then(()=>{this.log("Channel left"),this.setChannelState("closed"),this.joinRef=null,this.topic=null,this.channelCallbacks.onLeave?.(),Q()}).catch((Y)=>{this.setChannelState("error"),X(Y)})})}sendSignal(Q){if(this.channelState!=="joined")return Promise.reject(Error("Channel not joined"));return this.push("signal",Q)}sendFormStatus(Q){if(this.channelState!=="joined")return Promise.reject(Error("Channel not joined"));return this.push("form_status",{status:Q})}sendEvent(Q,X){if(this.channelState!=="joined")return Promise.reject(Error("Channel not joined"));return this.push(Q,X)}getState(){return this.state}getChannelState(){return this.channelState}isReady(){return this.state==="connected"&&this.channelState==="joined"}buildUrl(){let Q=new URL(this.endpoint);return Q.searchParams.set("vsn","2.0.0"),Q.searchParams.set("api_key",this.apiKey),Q.toString()}makeRef(){return this.refCounter++,String(this.refCounter)}push(Q,X,Y){return new Promise((Z,$)=>{if(!this.ws||this.ws.readyState!==WebSocket.OPEN){$(Error("WebSocket not open"));return}if(!this.topic){$(Error("Channel topic not set"));return}let J=Y??this.makeRef(),z=[this.joinRef,J,this.topic,Q,X],W=setTimeout(()=>{this.pendingReplies.delete(J),$(Error(`Timeout waiting for reply to ${Q}`))},1e4);this.pendingReplies.set(J,{resolve:Z,reject:$,timeout:W}),this.log("Sending",Q,X),this.ws.send(JSON.stringify(z))})}handleMessage(Q){try{let[X,Y,Z,$,J]=JSON.parse(Q);if(this.log("Received",$,J),$==="phx_reply"&&Y){let z=this.pendingReplies.get(Y);if(z){clearTimeout(z.timeout),this.pendingReplies.delete(Y);let W=J;if(W.status==="ok")z.resolve(W.response??{});else if(W.response&&typeof W.response==="object"&&"code"in W.response)z.reject(W.response);else{let B=this.buildErrorMessage(W.status,W.response);z.reject(Error(B))}}return}if($==="phx_error"){let z=Error("Channel error");this.setChannelState("error"),this.channelCallbacks.onError?.(z);return}if($==="phx_close"){this.setChannelState("closed"),this.channelCallbacks.onLeave?.();return}if($==="score_update"){this.channelCallbacks.onScoreUpdate?.(J);return}if($==="action"){this.channelCallbacks.onAction?.(J);return}this.channelCallbacks.onMessage?.($,J)}catch(X){this.log("Error parsing message",X)}}handleClose(){this.stopHeartbeat(),this.setState("disconnected"),this.setChannelState("closed");for(let[Q,X]of this.pendingReplies)clearTimeout(X.timeout),X.reject(Error("Connection closed"));this.pendingReplies.clear(),this.scheduleReconnect()}handleError(Q){this.setState("error"),this.onError?.(Q)}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{if(this.ws&&this.ws.readyState===WebSocket.OPEN){let Q=[null,this.makeRef(),"phoenix","heartbeat",{}];if(this.ws.send(JSON.stringify(Q)),this.channelState==="joined")this.push("heartbeat",{}).then((X)=>{if(X.bot_score!==void 0)this.channelCallbacks.onScoreUpdate?.({bot_score:X.bot_score,classification:X.classification,triggered_rules:[],event_count:0})}).catch(()=>{})}},this.heartbeatInterval)}stopHeartbeat(){if(this.heartbeatTimer)clearInterval(this.heartbeatTimer),this.heartbeatTimer=null}scheduleReconnect(){if(this.reconnectCount>=this.reconnectAttempts){this.log("Max reconnect attempts reached");return}let Q=this.reconnectDelay(this.reconnectCount);this.reconnectCount++,this.log(`Scheduling reconnect attempt ${this.reconnectCount} in ${Q}ms`),this.reconnectTimer=setTimeout(()=>{this.connect().catch((X)=>{this.log("Reconnect failed",X)})},Q)}stopReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;this.reconnectCount=0}setState(Q){if(this.state!==Q)this.state=Q,this.onConnectionChange?.(Q)}setChannelState(Q){this.channelState=Q}buildErrorMessage(Q,X){if(X){if(typeof X.reason==="string")return`Channel error: ${X.reason}`;if(Object.keys(X).length>0)return`Channel error (${Q??"error"}): ${JSON.stringify(X)}`}return Q??"Unknown error"}log(...Q){if(this.debug);}}class D{config;isReady=!1;hasScore=!1;hasFormScore=!1;currentScore=null;pendingSubmissions=[];pendingRequests=[];protectedForms=new Set;releasingForms=new Set;loadingOverlay=null;formObserver=null;startTime;originalFetch=null;originalXHROpen=null;originalXHRSend=null;constructor(Q={}){if(this.startTime=performance.now(),this.config={mode:Q.mode??"none",minTimeBeforeSubmit:Q.minTimeBeforeSubmit??500,maxHoldTime:Q.maxHoldTime??5000,showLoadingUI:Q.showLoadingUI??!0,loadingMessage:Q.loadingMessage??"Please wait...",onHold:Q.onHold,onRelease:Q.onRelease,onBlock:Q.onBlock,flushAndWaitForScore:Q.flushAndWaitForScore},this.config.mode!=="none")this.setup()}setup(){if(this.config.mode==="auto")this.interceptFetch(),this.interceptXHR();let Q=()=>{document.querySelectorAll("form").forEach((X)=>{this.protectForm(X)}),this.formObserver=new MutationObserver((X)=>{X.forEach((Y)=>{Y.addedNodes.forEach((Z)=>{if(Z instanceof HTMLFormElement)this.protectForm(Z);if(Z instanceof HTMLElement)Z.querySelectorAll("form").forEach(($)=>{this.protectForm($)})})})}),this.formObserver.observe(document.body,{childList:!0,subtree:!0})};if(document.body)Q();else document.addEventListener("DOMContentLoaded",Q,{once:!0})}isFormLikeRequest(Q,X){if((X?.method?.toUpperCase()||"GET")!=="POST")return!1;try{if((typeof Q==="string"?new URL(Q,window.location.origin):Q instanceof URL?Q:new URL(Q.url)).origin!==window.location.origin)return!1}catch{return!1}let Z=X?.headers instanceof Headers?X.headers.get("content-type"):typeof X?.headers==="object"&&X.headers!==null?X.headers["content-type"]||X.headers["Content-Type"]:null;if(Z){let $=Z.toLowerCase();if($.includes("application/x-www-form-urlencoded")||$.includes("multipart/form-data")||$.includes("application/json"))return!0;return!1}if(X?.body)return!0;return!1}interceptFetch(){this.originalFetch=window.fetch.bind(window);let Q=this;window.fetch=async function(X,Y){if(!Q.isFormLikeRequest(X,Y))return Q.originalFetch(X,Y);if(Q.hasScore)return Q.originalFetch(X,Y);return new Promise((Z,$)=>{let J={resolve:Z,reject:$,execute:()=>Q.originalFetch(X,Y),timestamp:performance.now()};if(Q.pendingRequests.push(J),Q.config.showLoadingUI&&Q.pendingRequests.length===1)Q.showLoading(document.createElement("form"));if(setTimeout(()=>{if(Q.pendingRequests.includes(J))Q.releaseRequest(J)},Q.config.maxHoldTime),Q.hasScore)Q.releaseRequest(J)})}}interceptXHR(){this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send;let Q=this;XMLHttpRequest.prototype.open=function(X,Y,Z=!0,$,J){let z=this;return z._bsMethod=X.toUpperCase(),z._bsUrl=Y.toString(),Q.originalXHROpen.call(this,X,Y,Z,$,J)},XMLHttpRequest.prototype.send=function(X){let Y=this,Z=Y._bsMethod||"GET",$=Y._bsUrl||"";if(Z!=="POST")return Q.originalXHRSend.call(this,X);try{if(new URL($,window.location.origin).origin!==window.location.origin)return Q.originalXHRSend.call(this,X)}catch{return Q.originalXHRSend.call(this,X)}if(Q.hasScore)return Q.originalXHRSend.call(this,X);let J=performance.now(),z=()=>{if(Q.hasScore){if(Q.config.showLoadingUI)Q.hideLoading();Q.originalXHRSend.call(Y,X)}else if(performance.now()-J>=Q.config.maxHoldTime){if(Q.config.showLoadingUI)Q.hideLoading();Q.originalXHRSend.call(Y,X)}else setTimeout(z,50)};if(Q.config.showLoadingUI)Q.showLoading(document.createElement("form"));z()}}releaseRequest(Q){let X=this.pendingRequests.indexOf(Q);if(X===-1)return;if(this.pendingRequests.splice(X,1),this.pendingRequests.length===0&&this.config.showLoadingUI)this.hideLoading();Q.execute().then(Q.resolve).catch(Q.reject)}protectForm(Q){if(this.protectedForms.has(Q))return;this.protectedForms.add(Q),Q.addEventListener("submit",(X)=>this.handleSubmit(X,Q),{capture:!0})}handleSubmit(Q,X){if(this.releasingForms.has(X)){this.releasingForms.delete(X);return}let Z=performance.now()-this.startTime;switch(N().markFirstSubmitAttempt(this.hasScore),this.config.mode){case"holdUntilReady":if(!this.hasScore)Q.preventDefault(),Q.stopPropagation(),this.holdSubmission(X,Q);break;case"holdUntilFormScored":Q.preventDefault(),Q.stopPropagation(),this.holdAndScoreSubmission(X,Q);break;case"blockInstant":if(Z<this.config.minTimeBeforeSubmit)Q.preventDefault(),Q.stopPropagation(),this.config.onBlock?.(X,"instant_submission");break;case"challengeFirst":if(!this.hasScore)Q.preventDefault(),Q.stopPropagation(),this.holdSubmission(X,Q);break;case"none":default:break}}holdSubmission(Q,X){if(this.config.onHold?.(Q),this.config.showLoadingUI)this.showLoading(Q);let Y={form:Q,event:X,timestamp:performance.now(),resolver:()=>{},rejecter:()=>{}},Z=new Promise(($,J)=>{Y.resolver=$,Y.rejecter=J});if(this.pendingSubmissions.push(Y),setTimeout(()=>{if(this.pendingSubmissions.includes(Y))this.releaseSubmission(Y,!1)},this.config.maxHoldTime),this.hasScore)this.releaseSubmission(Y,!1);Z.catch(()=>{})}async holdAndScoreSubmission(Q,X){if(this.config.onHold?.(Q),this.config.showLoadingUI)this.showLoading(Q);let Y=performance.now();try{if(!this.config.flushAndWaitForScore){this.submitForm(Q);return}let Z=this.config.flushAndWaitForScore(),$=new Promise((W)=>{setTimeout(()=>W(null),this.config.maxHoldTime)}),J=await Promise.race([Z,$]),z=performance.now()-Y;if(J===null);else this.currentScore=J,this.hasFormScore=!0;if(this.config.showLoadingUI)this.hideLoading();this.config.onRelease?.(Q,!1),this.submitForm(Q)}catch(Z){if(this.config.showLoadingUI)this.hideLoading();this.config.onRelease?.(Q,!1),this.submitForm(Q)}}submitForm(Q){if(this.releasingForms.add(Q),Q.requestSubmit)Q.requestSubmit();else Q.submit()}releaseSubmission(Q,X){let Y=this.pendingSubmissions.indexOf(Q);if(Y===-1)return;if(this.pendingSubmissions.splice(Y,1),this.config.showLoadingUI)this.hideLoading();if(this.config.onRelease?.(Q.form,X),!X)if(Q.resolver(),Q.form.requestSubmit)Q.form.requestSubmit();else Q.form.submit();else Q.rejecter("blocked")}showLoading(Q){if(this.loadingOverlay)return;this.loadingOverlay=document.createElement("div"),this.loadingOverlay.innerHTML=`
1
+ import{a as y,b as U,d as v}from"./hash-q46pgar4.js";function T(Q){return typeof Q==="object"&&Q!==null&&"code"in Q&&Q.code==="LIMIT_EXCEEDED"}var q={endpoint:"wss://botsigged.com/sdk/websocket",debug:!1,sendInterval:2000,maxBufferSize:1000,mouseSampleRate:0.5,autoStart:!0,actionThreshold:70,action:"none",minAlertLevel:"high",botScoreThresholds:{medium:40,high:70,critical:90},hashVerification:{enabled:!1,preferWasm:!0},challenge:{enabled:!1,minLevel:"high",chunkSize:1e4,difficulty:{medium:12,high:16,critical:20},ui:{enabled:!0,message:"Verifying you're human...",successMessage:"Verified!",backgroundColor:"rgba(0, 0, 0, 0.7)",textColor:"#ffffff",spinnerColor:"#3b82f6",zIndex:999999}},formProtection:{mode:"auto",minTimeBeforeSubmit:500,maxHoldTime:3000,showLoadingUI:!0,loadingMessage:"Please wait..."},fallbackMode:"degraded"},F={action:"challenge",challenge:{difficulty:{suspicious:14,bot:18},timeout_ms:30000},form_protection_mode:"holdUntilReady"};function h(Q){let X=Q.action??q.action,Y=X==="challenge"||Q.challenge?.enabled;return{apiKey:Q.apiKey,accountId:Q.accountId,endpoint:Q.endpoint??q.endpoint,debug:Q.debug??q.debug,sendInterval:Q.sendInterval??q.sendInterval,maxBufferSize:Q.maxBufferSize??q.maxBufferSize,mouseSampleRate:Q.mouseSampleRate??q.mouseSampleRate,autoStart:Q.autoStart??q.autoStart,actionThreshold:Q.actionThreshold??q.actionThreshold,action:X,minAlertLevel:Q.minAlertLevel??q.minAlertLevel,botScoreThresholds:{...q.botScoreThresholds,...Q.botScoreThresholds},hashVerification:{...q.hashVerification,...Q.hashVerification},challenge:{enabled:Y,minLevel:Q.challenge?.minLevel??q.challenge.minLevel,chunkSize:Q.challenge?.chunkSize??q.challenge.chunkSize,difficulty:{...q.challenge.difficulty,...Q.challenge?.difficulty},ui:{...q.challenge.ui,...Q.challenge?.ui},onChallengeStart:Q.challenge?.onChallengeStart,onChallengeComplete:Q.challenge?.onChallengeComplete,onChallengeProgress:Q.challenge?.onChallengeProgress},formProtection:{mode:Q.formProtection?.mode??q.formProtection.mode,minTimeBeforeSubmit:Q.formProtection?.minTimeBeforeSubmit??q.formProtection.minTimeBeforeSubmit,maxHoldTime:Q.formProtection?.maxHoldTime??q.formProtection.maxHoldTime,showLoadingUI:Q.formProtection?.showLoadingUI??q.formProtection.showLoadingUI,loadingMessage:Q.formProtection?.loadingMessage??q.formProtection.loadingMessage,onHold:Q.formProtection?.onHold,onRelease:Q.formProtection?.onRelease,onBlock:Q.formProtection?.onBlock},fallbackMode:Q.fallbackMode??q.fallbackMode,cookie:Q.cookie,headers:Q.headers,formInject:Q.formInject,onScoreUpdate:Q.onScoreUpdate,onConnectionChange:Q.onConnectionChange,onError:Q.onError,onUsageLimitExceeded:Q.onUsageLimitExceeded,onHighBotScore:Q.onHighBotScore,onServerConfig:Q.onServerConfig,onServerAction:Q.onServerAction}}class k{events=[];startTime=0;sampleRate;maxBufferSize;isListening=!1;boundHandleMouseMove;boundHandleMouseDown;boundHandleMouseUp;boundHandleClick;constructor(Q={}){this.sampleRate=Q.sampleRate??0.5,this.maxBufferSize=Q.maxBufferSize??500,this.boundHandleMouseMove=this.handleMouseMove.bind(this),this.boundHandleMouseDown=this.handleMouseDown.bind(this),this.boundHandleMouseUp=this.handleMouseUp.bind(this),this.boundHandleClick=this.handleClick.bind(this)}start(){if(this.isListening)return;this.startTime=Date.now(),document.addEventListener("mousemove",this.boundHandleMouseMove,{passive:!0}),document.addEventListener("mousedown",this.boundHandleMouseDown,{passive:!0}),document.addEventListener("mouseup",this.boundHandleMouseUp,{passive:!0}),document.addEventListener("click",this.boundHandleClick,{passive:!0}),this.isListening=!0}stop(){if(!this.isListening)return;document.removeEventListener("mousemove",this.boundHandleMouseMove),document.removeEventListener("mousedown",this.boundHandleMouseDown),document.removeEventListener("mouseup",this.boundHandleMouseUp),document.removeEventListener("click",this.boundHandleClick),this.isListening=!1}addEvent(Q){if(this.events.push(Q),this.events.length>this.maxBufferSize)this.events.shift()}handleMouseMove(Q){if(Math.random()>this.sampleRate)return;this.addEvent({type:"move",x:Q.clientX,y:Q.clientY,t:Date.now()})}handleMouseDown(Q){this.addEvent({type:"down",x:Q.clientX,y:Q.clientY,t:Date.now(),button:Q.button})}handleMouseUp(Q){this.addEvent({type:"up",x:Q.clientX,y:Q.clientY,t:Date.now(),button:Q.button})}handleClick(Q){let X=Q.target,Y,Z;if(X&&X.getBoundingClientRect){let $=X.getBoundingClientRect();Y={top:$.top,left:$.left,width:$.width,height:$.height},Z=X.tagName?.toLowerCase()}this.addEvent({type:"click",x:Q.clientX,y:Q.clientY,t:Date.now(),button:Q.button,targetRect:Y,targetTag:Z})}getSignal(){return{events:[...this.events],start_time:this.startTime}}flush(){this.events=[]}getBufferSize(){return this.events.length}reset(){this.events=[],this.startTime=Date.now()}}class x{events=[];startTime=0;maxBufferSize;isListening=!1;boundHandleScroll;constructor(Q={}){this.maxBufferSize=Q.maxBufferSize??200,this.boundHandleScroll=this.handleScroll.bind(this)}start(){if(this.isListening)return;this.startTime=Date.now(),window.addEventListener("scroll",this.boundHandleScroll,{passive:!0}),this.isListening=!0}stop(){if(!this.isListening)return;window.removeEventListener("scroll",this.boundHandleScroll),this.isListening=!1}handleScroll(){if(this.events.push({y:window.scrollY,t:Date.now()}),this.events.length>this.maxBufferSize)this.events.shift()}getSignal(){return{events:[...this.events],start_time:this.startTime}}flush(){this.events=[]}getBufferSize(){return this.events.length}reset(){this.events=[],this.startTime=Date.now()}}class w{static instance=null;timings={signalRoundtrips:[]};pendingSignals=new Map;constructor(){this.timings.scriptStart=performance.now()}static getInstance(){if(!w.instance)w.instance=new w;return w.instance}static reset(){w.instance=null}markScriptStart(){this.timings.scriptStart=performance.now()}markConstructorStart(){this.timings.constructorStart=performance.now()}markConstructorEnd(){this.timings.constructorEnd=performance.now()}markStartCalled(){this.timings.startCalled=performance.now()}markSdkReady(){this.timings.sdkReady=performance.now()}markFingerprintStart(){this.timings.fingerprintStart=performance.now()}markFingerprintEnd(){this.timings.fingerprintEnd=performance.now()}markWsConnectStart(){this.timings.wsConnectStart=performance.now()}markWsConnectEnd(){this.timings.wsConnectEnd=performance.now()}markChannelJoinStart(){this.timings.channelJoinStart=performance.now()}markChannelJoinEnd(){this.timings.channelJoinEnd=performance.now()}markInitialScoreReceived(){this.timings.initialScoreReceived=performance.now()}markFormCollectorStart(){this.timings.formCollectorStart=performance.now()}markFormCollectorReady(){this.timings.formCollectorReady=performance.now()}markFirstFormInteraction(){if(!this.timings.firstFormInteraction){if(this.timings.firstFormInteraction=performance.now(),this.timings.sdkReady)this.timings.timeToFirstInteraction=this.timings.firstFormInteraction-this.timings.sdkReady}}markFirstSubmitAttempt(Q){if(!this.timings.firstSubmitAttempt)this.timings.firstSubmitAttempt=performance.now(),this.timings.hadScoreBeforeSubmit=Q}markSignalSent(Q){this.pendingSignals.set(Q,performance.now())}markSignalResponseReceived(Q){let X=this.pendingSignals.get(Q);if(X!==void 0){let Y=performance.now(),Z={sentAt:X,receivedAt:Y,roundtripMs:Y-X,seq:Q};this.timings.signalRoundtrips?.push(Z),this.pendingSignals.delete(Q)}}getTimings(){return{...this.timings}}getSummary(){let Q=this.timings,X=Q.signalRoundtrips||[],Y=0,Z=1/0,$=0;if(X.length>0)Y=X.reduce((G,g)=>G+g.roundtripMs,0)/X.length,Z=Math.min(...X.map((G)=>G.roundtripMs)),$=Math.max(...X.map((G)=>G.roundtripMs));let J=(Q.sdkReady??0)-(Q.scriptStart??0),z=(Q.fingerprintEnd??0)-(Q.fingerprintStart??0),W=(Q.wsConnectEnd??0)-(Q.wsConnectStart??0),B=(Q.channelJoinEnd??0)-(Q.channelJoinStart??0),V=(Q.initialScoreReceived??0)-(Q.startCalled??0),R=(Q.initialScoreReceived??0)-(Q.scriptStart??0);return{totalStartupMs:Math.round(J),fingerprintMs:Math.round(z),wsConnectionMs:Math.round(W),channelJoinMs:Math.round(B),timeToFirstScoreMs:Math.round(V),avgSignalRoundtripMs:Math.round(Y),minSignalRoundtripMs:Z===1/0?0:Math.round(Z),maxSignalRoundtripMs:Math.round($),vulnerabilityWindowMs:Math.round(R),protectedBeforeSubmit:Q.hadScoreBeforeSubmit??!1}}logSummary(){let Q=this.getSummary(),X=this.timings;if(X.firstFormInteraction);if(X.firstSubmitAttempt);if(Q.vulnerabilityWindowMs>0);}getReport(){return{timings:this.timings,summary:this.getSummary(),userAgent:navigator.userAgent,timestamp:Date.now()}}}var K=w.getInstance();function N(){return w.getInstance()}function l(){return K.getSummary()}function f(){K.logSummary()}var j="__bs_ghost_value";class C{keyEvents=[];focusEvents=[];pasteEvents=[];inputEvents=[];submitCount=0;startTime=0;maxKeyEvents;maxFocusEvents;maxInputEvents;isListening=!1;valueSetterHooked=!1;onSubmit;originalInputDescriptor;originalTextareaDescriptor;lastKeyWasTab=!1;currentField=null;emailDomains=new Set;boundHandleFocusIn;boundHandleFocusOut;boundHandleKeyDown;boundHandleKeyUp;boundHandlePaste;boundHandleSubmit;boundHandleClick;boundHandleInput;boundHandleGhostValue;constructor(Q={}){this.maxKeyEvents=Q.maxKeyEvents??500,this.maxFocusEvents=Q.maxFocusEvents??100,this.maxInputEvents=Q.maxInputEvents??200,this.onSubmit=Q.onSubmit,this.boundHandleFocusIn=this.handleFocusIn.bind(this),this.boundHandleFocusOut=this.handleFocusOut.bind(this),this.boundHandleKeyDown=this.handleKeyDown.bind(this),this.boundHandleKeyUp=this.handleKeyUp.bind(this),this.boundHandlePaste=this.handlePaste.bind(this),this.boundHandleSubmit=this.handleSubmit.bind(this),this.boundHandleClick=this.handleClick.bind(this),this.boundHandleInput=this.handleInput.bind(this),this.boundHandleGhostValue=this.handleGhostValue.bind(this)}start(){if(this.isListening)return;this.startTime=Date.now(),document.addEventListener("focusin",this.boundHandleFocusIn,{passive:!0,capture:!0}),document.addEventListener("focusout",this.boundHandleFocusOut,{passive:!0,capture:!0}),document.addEventListener("keydown",this.boundHandleKeyDown,{passive:!0}),document.addEventListener("keyup",this.boundHandleKeyUp,{passive:!0}),document.addEventListener("paste",this.boundHandlePaste,{passive:!0}),document.addEventListener("submit",this.boundHandleSubmit,{passive:!0}),document.addEventListener("click",this.boundHandleClick,{passive:!0}),document.addEventListener("input",this.boundHandleInput,{passive:!0}),document.addEventListener(j,this.boundHandleGhostValue,{passive:!0}),this.hookValueSetters(),this.isListening=!0}stop(){if(!this.isListening)return;document.removeEventListener("focusin",this.boundHandleFocusIn,{capture:!0}),document.removeEventListener("focusout",this.boundHandleFocusOut,{capture:!0}),document.removeEventListener("keydown",this.boundHandleKeyDown),document.removeEventListener("keyup",this.boundHandleKeyUp),document.removeEventListener("paste",this.boundHandlePaste),document.removeEventListener("submit",this.boundHandleSubmit),document.removeEventListener("click",this.boundHandleClick),document.removeEventListener("input",this.boundHandleInput),document.removeEventListener(j,this.boundHandleGhostValue),this.unhookValueSetters(),this.isListening=!1}isFormInput(Q){if(!Q||!(Q instanceof HTMLElement))return!1;let X=Q.tagName.toLowerCase();if(X==="textarea"||X==="select")return!0;if(X==="input"){let Y=Q.type.toLowerCase();return!["submit","button","reset","hidden","image"].includes(Y)}return!1}isEmailField(Q){let X=Q.type?.toLowerCase()||"",Y=(Q.name||"").toLowerCase(),Z=(Q.id||"").toLowerCase();return X==="email"||Y.includes("email")||Y.includes("e-mail")||Z.includes("email")||Z.includes("e-mail")}extractEmailDomain(Q){if(!Q||typeof Q!=="string")return null;let X=Q.trim();if(!X)return null;let Y=X.match(/@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/);return Y?Y[1].toLowerCase():null}getFieldId(Q){return Q.id||Q.getAttribute("name")||`field-${Q.tagName.toLowerCase()}`}handleFocusIn(Q){if(!this.isFormInput(Q.target))return;N().markFirstFormInteraction();let X=this.getFieldId(Q.target),Y="direct";if(this.lastKeyWasTab)Y="tab";if(this.focusEvents.push({type:"focus",field:X,t:Date.now(),method:Y}),this.focusEvents.length>this.maxFocusEvents)this.focusEvents.shift();this.currentField=X,this.lastKeyWasTab=!1}handleFocusOut(Q){if(!this.isFormInput(Q.target))return;let X=Q.target,Y=this.getFieldId(X);if(this.focusEvents.push({type:"blur",field:Y,t:Date.now()}),this.focusEvents.length>this.maxFocusEvents)this.focusEvents.shift();if(X instanceof HTMLInputElement&&this.isEmailField(X)){let Z=this.extractEmailDomain(X.value);if(Z)this.emailDomains.add(Z)}this.currentField=null}handleClick(Q){if(!this.isFormInput(Q.target))return;let X=this.focusEvents[this.focusEvents.length-1];if(X&&X.type==="focus"&&Date.now()-X.t<50)X.method="click"}handleKeyDown(Q){if(Q.key==="Tab"){this.lastKeyWasTab=!0;return}if(!this.isFormInput(Q.target))return;let X="key";if(Q.key==="Backspace")X="backspace";else if(Q.key==="Delete")X="delete";else if(Q.key==="Enter")X="enter";else if(Q.key==="Tab")X="tab";else if(Q.key.length===1)X="char";else if(Q.key.startsWith("Arrow"))X="arrow";if(this.keyEvents.push({type:"down",code:X,t:Date.now(),field:this.currentField||void 0}),this.keyEvents.length>this.maxKeyEvents)this.keyEvents.shift()}handleKeyUp(Q){if(!this.isFormInput(Q.target))return;let X="key";if(Q.key==="Backspace")X="backspace";else if(Q.key==="Delete")X="delete";else if(Q.key.length===1)X="char";if(this.keyEvents.push({type:"up",code:X,t:Date.now(),field:this.currentField||void 0}),this.keyEvents.length>this.maxKeyEvents)this.keyEvents.shift()}handleInput(Q){if(!this.isFormInput(Q.target))return;let X=Q.target,Z=Q.inputType||"unknown",$=X.value?.length??0;if(this.inputEvents.push({field:this.getFieldId(X),t:Date.now(),inputType:Z,valueLength:$}),this.inputEvents.length>this.maxInputEvents)this.inputEvents.shift()}handlePaste(Q){if(!this.isFormInput(Q.target))return;let X=Q.clipboardData?.getData("text")||"";this.pasteEvents.push({field:this.getFieldId(Q.target),t:Date.now(),length:X.length})}handleSubmit(Q){this.submitCount++;let X=Q.target;if(X&&X.elements)for(let Y=0;Y<X.elements.length;Y++){let Z=X.elements[Y];if(Z instanceof HTMLInputElement&&this.isEmailField(Z)){let $=this.extractEmailDomain(Z.value);if($)this.emailDomains.add($)}}this.onSubmit?.()}getSignal(){return{keys:[...this.keyEvents],focus:[...this.focusEvents],pastes:[...this.pasteEvents],inputs:[...this.inputEvents],submits:this.submitCount,start_time:this.startTime,email_domains:this.emailDomains.size>0?Array.from(this.emailDomains):void 0}}flush(){this.keyEvents=[],this.focusEvents=[],this.pasteEvents=[],this.inputEvents=[]}getBufferSize(){return this.keyEvents.length+this.focusEvents.length+this.pasteEvents.length+this.inputEvents.length}reset(){this.keyEvents=[],this.focusEvents=[],this.pasteEvents=[],this.inputEvents=[],this.submitCount=0,this.startTime=Date.now(),this.lastKeyWasTab=!1,this.currentField=null,this.emailDomains.clear()}hookValueSetters(){if(this.valueSetterHooked)return;if(this.originalInputDescriptor=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value"),this.originalInputDescriptor){let Q=this.originalInputDescriptor.set,X=this.originalInputDescriptor.get;Object.defineProperty(HTMLInputElement.prototype,"value",{configurable:!0,enumerable:!0,get(){return X?.call(this)},set(Y){let Z=X?.call(this)??"";Q?.call(this,Y);let $=Y??"";if($!==Z)this.dispatchEvent(new CustomEvent(j,{bubbles:!0,detail:{valueLength:$.length,wasEmpty:Z.length===0}}))}})}if(this.originalTextareaDescriptor=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,"value"),this.originalTextareaDescriptor){let Q=this.originalTextareaDescriptor.set,X=this.originalTextareaDescriptor.get;Object.defineProperty(HTMLTextAreaElement.prototype,"value",{configurable:!0,enumerable:!0,get(){return X?.call(this)},set(Y){let Z=X?.call(this)??"";Q?.call(this,Y);let $=Y??"";if($!==Z)this.dispatchEvent(new CustomEvent(j,{bubbles:!0,detail:{valueLength:$.length,wasEmpty:Z.length===0}}))}})}this.valueSetterHooked=!0}unhookValueSetters(){if(!this.valueSetterHooked)return;if(this.originalInputDescriptor)Object.defineProperty(HTMLInputElement.prototype,"value",this.originalInputDescriptor);if(this.originalTextareaDescriptor)Object.defineProperty(HTMLTextAreaElement.prototype,"value",this.originalTextareaDescriptor);this.valueSetterHooked=!1}handleGhostValue(Q){let X=Q.target;if(!this.isFormInput(X))return;let Z=Q.detail?.valueLength??0;if(this.inputEvents.push({field:this.getFieldId(X),t:Date.now(),inputType:"programmatic",valueLength:Z}),this.inputEvents.length>this.maxInputEvents)this.inputEvents.shift()}}class L{cachedSignal=null;collect(){if(this.cachedSignal)return this.cachedSignal;let Q=navigator,X=window;return this.cachedSignal={user_agent:navigator.userAgent,platform:navigator.platform,language:navigator.language,languages:[...navigator.languages||[]],hardware_concurrency:navigator.hardwareConcurrency??null,device_memory:Q.deviceMemory??null,max_touch_points:navigator.maxTouchPoints??0,screen_width:screen.width,screen_height:screen.height,screen_avail_width:screen.availWidth,screen_avail_height:screen.availHeight,color_depth:screen.colorDepth,pixel_ratio:window.devicePixelRatio??1,...this.getWebGLInfo(),plugins_count:navigator.plugins?.length??0,mime_types_count:navigator.mimeTypes?.length??0,timezone:this.getTimezone(),timezone_offset:new Date().getTimezoneOffset(),has_webdriver:Q.webdriver===!0,has_chrome_runtime:!!X.chrome?.runtime,has_chrome_app:!!X.chrome?.app,has_notification_api:"Notification"in window,has_permissions_api:"permissions"in navigator,outer_dimensions:{width:window.outerWidth,height:window.outerHeight},inner_dimensions:{width:window.innerWidth,height:window.innerHeight},notification_permission:this.getNotificationPermission()},this.cachedSignal}getWebGLInfo(){try{let Q=document.createElement("canvas"),X=Q.getContext("webgl")||Q.getContext("experimental-webgl");if(!X||!(X instanceof WebGLRenderingContext))return{webgl_vendor:null,webgl_renderer:null};let Y=X.getExtension("WEBGL_debug_renderer_info");if(!Y)return{webgl_vendor:null,webgl_renderer:null};return{webgl_vendor:X.getParameter(Y.UNMASKED_VENDOR_WEBGL),webgl_renderer:X.getParameter(Y.UNMASKED_RENDERER_WEBGL)}}catch{return{webgl_vendor:null,webgl_renderer:null}}}getTimezone(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return null}}getNotificationPermission(){if("Notification"in window)return Notification.permission;return null}getSignal(){return this.collect()}reset(){this.cachedSignal=null}}class b{cachedFingerprint=null;async generate(){if(this.cachedFingerprint)return this.cachedFingerprint;let[Q,X,Y,Z,$]=await Promise.all([this.getCanvasHash(),this.getWebGLData(),this.getAudioHash(),this.getFontData(),this.getScreenHash()]),J={hash:"",canvas_hash:Q,webgl_hash:X.hash,audio_hash:Y,font_hash:Z.hash,screen_hash:$,webgl_vendor:X.vendor,webgl_renderer:X.renderer,timezone:this.getTimezone(),language:this.getLanguage(),platform:this.getPlatform(),font_count:Z.count};return J.hash=await this.generateMainHash(J),this.cachedFingerprint=J,J}getFingerprint(){return this.cachedFingerprint}reset(){this.cachedFingerprint=null}async getCanvasHash(){try{let Q=document.createElement("canvas");Q.width=200,Q.height=50;let X=Q.getContext("2d");if(!X)return null;X.textBaseline="top",X.font="14px 'Arial'",X.fillStyle="#f60",X.fillRect(125,1,62,20),X.fillStyle="#069",X.fillText("BotSigged,\uD83C\uDFA8",2,15),X.fillStyle="rgba(102, 204, 0, 0.7)",X.fillText("BotSigged,\uD83C\uDFA8",4,17);let Y=Q.toDataURL();return this.hashString(Y)}catch{return null}}async getWebGLData(){try{let Q=document.createElement("canvas"),X=Q.getContext("webgl")||Q.getContext("experimental-webgl");if(!X||!(X instanceof WebGLRenderingContext))return{hash:null,vendor:null,renderer:null};let Y=[],Z=[X.ALIASED_LINE_WIDTH_RANGE,X.ALIASED_POINT_SIZE_RANGE,X.ALPHA_BITS,X.BLUE_BITS,X.DEPTH_BITS,X.GREEN_BITS,X.MAX_COMBINED_TEXTURE_IMAGE_UNITS,X.MAX_CUBE_MAP_TEXTURE_SIZE,X.MAX_FRAGMENT_UNIFORM_VECTORS,X.MAX_RENDERBUFFER_SIZE,X.MAX_TEXTURE_IMAGE_UNITS,X.MAX_TEXTURE_SIZE,X.MAX_VARYING_VECTORS,X.MAX_VERTEX_ATTRIBS,X.MAX_VERTEX_TEXTURE_IMAGE_UNITS,X.MAX_VERTEX_UNIFORM_VECTORS,X.MAX_VIEWPORT_DIMS,X.RED_BITS,X.RENDERER,X.SHADING_LANGUAGE_VERSION,X.STENCIL_BITS,X.VENDOR,X.VERSION];for(let V of Z)try{let R=X.getParameter(V);Y.push(String(R))}catch{Y.push("")}let $=X.getSupportedExtensions();if($)Y.push($.sort().join(","));let J=null,z=null,W=X.getExtension("WEBGL_debug_renderer_info");if(W)J=X.getParameter(W.UNMASKED_VENDOR_WEBGL),z=X.getParameter(W.UNMASKED_RENDERER_WEBGL);return{hash:this.hashString(Y.join("|")),vendor:J,renderer:z}}catch{return{hash:null,vendor:null,renderer:null}}}async getAudioHash(){try{let Q=window.OfflineAudioContext||window.webkitOfflineAudioContext;if(!Q)return null;let X=new Q(1,4500,44100),Y=X.createOscillator(),Z=X.createDynamicsCompressor();Y.type="triangle",Y.frequency.setValueAtTime(1e4,X.currentTime),Z.threshold.setValueAtTime(-50,X.currentTime),Z.knee.setValueAtTime(40,X.currentTime),Z.ratio.setValueAtTime(12,X.currentTime),Z.attack.setValueAtTime(0,X.currentTime),Z.release.setValueAtTime(0.25,X.currentTime),Y.connect(Z),Z.connect(X.destination),Y.start(0);let J=(await X.startRendering()).getChannelData(0),z=[];for(let W=0;W<J.length;W+=100)z.push(J[W]);return this.hashString(z.join(","))}catch{return null}}async getFontData(){let Q=["Arial","Arial Black","Arial Narrow","Calibri","Cambria","Cambria Math","Comic Sans MS","Consolas","Courier","Courier New","Georgia","Helvetica","Impact","Lucida Console","Lucida Sans Unicode","Microsoft Sans Serif","MS Gothic","MS PGothic","MS Sans Serif","MS Serif","Palatino Linotype","Segoe Print","Segoe Script","Segoe UI","Symbol","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana","Wingdings"],X=["monospace","sans-serif","serif"],Y="mmmmmmmmmmlli",Z="72px",$=document.createElement("span");$.style.position="absolute",$.style.left="-9999px",$.style.fontSize="72px",$.style.lineHeight="normal",$.innerHTML="mmmmmmmmmmlli",document.body.appendChild($);let J={};for(let B of X)$.style.fontFamily=B,J[B]=$.offsetWidth;let z=[];for(let B of Q){let V=!1;for(let R of X)if($.style.fontFamily=`'${B}', ${R}`,$.offsetWidth!==J[R]){V=!0;break}if(V)z.push(B)}return document.body.removeChild($),{hash:this.hashString(z.join(",")),count:z.length}}async getScreenHash(){let Q=[String(screen.width),String(screen.height),String(screen.availWidth),String(screen.availHeight),String(screen.colorDepth),String(screen.pixelDepth),String(window.devicePixelRatio||1)];return this.hashString(Q.join("|"))}getTimezone(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{return null}}getLanguage(){return navigator.language||null}getPlatform(){return navigator.platform||null}generateMainHash(Q){let X=[Q.canvas_hash||"",Q.webgl_hash||"",Q.audio_hash||"",Q.font_hash||"",Q.screen_hash||"",Q.timezone||"",Q.language||"",Q.platform||""];return this.hashString(X.join("|"))}hashString(Q){return v(Q)}}class A{ws=null;endpoint;apiKey;heartbeatInterval;reconnectAttempts;reconnectDelay;debug;state="disconnected";channelState="closed";refCounter=0;joinRef=null;heartbeatTimer=null;reconnectTimer=null;reconnectCount=0;pendingReplies=new Map;onConnectionChange;onError;channelCallbacks={};topic=null;constructor(Q){this.endpoint=Q.endpoint,this.apiKey=Q.apiKey,this.heartbeatInterval=Q.heartbeatInterval??30000,this.reconnectAttempts=Q.reconnectAttempts??10,this.reconnectDelay=Q.reconnectDelay??((X)=>Math.min(1000*Math.pow(2,X),30000)),this.debug=Q.debug??!1,this.onConnectionChange=Q.onConnectionChange,this.onError=Q.onError}connect(){return new Promise((Q,X)=>{if(this.ws&&this.state==="connected"){Q();return}this.setState("connecting");let Y=this.buildUrl();this.log("Connecting to",Y);try{this.ws=new WebSocket(Y),this.ws.onopen=()=>{this.log("WebSocket connected"),this.setState("connected"),this.reconnectCount=0,this.startHeartbeat(),Q()},this.ws.onclose=(Z)=>{this.log("WebSocket closed",Z.code,Z.reason),this.handleClose()},this.ws.onerror=(Z)=>{this.log("WebSocket error",Z);let $=Error("WebSocket connection error");this.handleError($),X($)},this.ws.onmessage=(Z)=>{this.handleMessage(Z.data)}}catch(Z){let $=Z instanceof Error?Z:Error(String(Z));this.handleError($),X($)}})}disconnect(){if(this.stopHeartbeat(),this.stopReconnect(),this.ws)this.ws.close(1000,"Client disconnect"),this.ws=null;this.setState("disconnected"),this.setChannelState("closed")}joinChannel(Q,X,Y,Z,$={},J){return this.channelCallbacks=$,this.topic=`detection:${Q}`,new Promise((z,W)=>{if(this.state!=="connected"){W(Error("WebSocket not connected"));return}this.setChannelState("joining"),this.joinRef=this.makeRef();let B={session_id:Q,api_key:this.apiKey,fingerprint:X,session:Y,browser:Z};if(J)B.account_id=J;this.push("phx_join",B,this.joinRef).then((V)=>{this.log("Channel joined",V),this.setChannelState("joined"),this.channelCallbacks.onJoin?.(),z(V)}).catch((V)=>{this.log("Channel join failed",V),this.setChannelState("error"),this.channelCallbacks.onError?.(V),W(V)})})}leaveChannel(){return new Promise((Q,X)=>{if(this.channelState!=="joined"){Q();return}this.setChannelState("leaving"),this.push("phx_leave",{}).then(()=>{this.log("Channel left"),this.setChannelState("closed"),this.joinRef=null,this.topic=null,this.channelCallbacks.onLeave?.(),Q()}).catch((Y)=>{this.setChannelState("error"),X(Y)})})}sendSignal(Q){if(this.channelState!=="joined")return Promise.reject(Error("Channel not joined"));return this.push("signal",Q)}sendFormStatus(Q){if(this.channelState!=="joined")return Promise.reject(Error("Channel not joined"));return this.push("form_status",{status:Q})}sendEvent(Q,X){if(this.channelState!=="joined")return Promise.reject(Error("Channel not joined"));return this.push(Q,X)}getState(){return this.state}getChannelState(){return this.channelState}isReady(){return this.state==="connected"&&this.channelState==="joined"}buildUrl(){let Q=new URL(this.endpoint);return Q.searchParams.set("vsn","2.0.0"),Q.searchParams.set("api_key",this.apiKey),Q.toString()}makeRef(){return this.refCounter++,String(this.refCounter)}push(Q,X,Y){return new Promise((Z,$)=>{if(!this.ws||this.ws.readyState!==WebSocket.OPEN){$(Error("WebSocket not open"));return}if(!this.topic){$(Error("Channel topic not set"));return}let J=Y??this.makeRef(),z=[this.joinRef,J,this.topic,Q,X],W=setTimeout(()=>{this.pendingReplies.delete(J),$(Error(`Timeout waiting for reply to ${Q}`))},1e4);this.pendingReplies.set(J,{resolve:Z,reject:$,timeout:W}),this.log("Sending",Q,X),this.ws.send(JSON.stringify(z))})}handleMessage(Q){try{let[X,Y,Z,$,J]=JSON.parse(Q);if(this.log("Received",$,J),$==="phx_reply"&&Y){let z=this.pendingReplies.get(Y);if(z){clearTimeout(z.timeout),this.pendingReplies.delete(Y);let W=J;if(W.status==="ok")z.resolve(W.response??{});else if(W.response&&typeof W.response==="object"&&"code"in W.response)z.reject(W.response);else{let B=this.buildErrorMessage(W.status,W.response);z.reject(Error(B))}}return}if($==="phx_error"){let z=Error("Channel error");this.setChannelState("error"),this.channelCallbacks.onError?.(z);return}if($==="phx_close"){this.setChannelState("closed"),this.channelCallbacks.onLeave?.();return}if($==="score_update"){this.channelCallbacks.onScoreUpdate?.(J);return}if($==="action"){this.channelCallbacks.onAction?.(J);return}this.channelCallbacks.onMessage?.($,J)}catch(X){this.log("Error parsing message",X)}}handleClose(){this.stopHeartbeat(),this.setState("disconnected"),this.setChannelState("closed");for(let[Q,X]of this.pendingReplies)clearTimeout(X.timeout),X.reject(Error("Connection closed"));this.pendingReplies.clear(),this.scheduleReconnect()}handleError(Q){this.setState("error"),this.onError?.(Q)}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{if(this.ws&&this.ws.readyState===WebSocket.OPEN){let Q=[null,this.makeRef(),"phoenix","heartbeat",{}];if(this.ws.send(JSON.stringify(Q)),this.channelState==="joined")this.push("heartbeat",{}).then((X)=>{if(X.bot_score!==void 0)this.channelCallbacks.onScoreUpdate?.({bot_score:X.bot_score,classification:X.classification,triggered_rules:[],event_count:0})}).catch(()=>{})}},this.heartbeatInterval)}stopHeartbeat(){if(this.heartbeatTimer)clearInterval(this.heartbeatTimer),this.heartbeatTimer=null}scheduleReconnect(){if(this.reconnectCount>=this.reconnectAttempts){this.log("Max reconnect attempts reached");return}let Q=this.reconnectDelay(this.reconnectCount);this.reconnectCount++,this.log(`Scheduling reconnect attempt ${this.reconnectCount} in ${Q}ms`),this.reconnectTimer=setTimeout(()=>{this.connect().catch((X)=>{this.log("Reconnect failed",X)})},Q)}stopReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;this.reconnectCount=0}setState(Q){if(this.state!==Q)this.state=Q,this.onConnectionChange?.(Q)}setChannelState(Q){this.channelState=Q}buildErrorMessage(Q,X){if(X){if(typeof X.reason==="string")return`Channel error: ${X.reason}`;if(Object.keys(X).length>0)return`Channel error (${Q??"error"}): ${JSON.stringify(X)}`}return Q??"Unknown error"}log(...Q){if(this.debug);}}class D{config;isReady=!1;hasScore=!1;hasFormScore=!1;currentScore=null;pendingSubmissions=[];pendingRequests=[];protectedForms=new Set;releasingForms=new Set;loadingOverlay=null;formObserver=null;startTime;originalFetch=null;originalXHROpen=null;originalXHRSend=null;constructor(Q={}){if(this.startTime=performance.now(),this.config={mode:Q.mode??"none",minTimeBeforeSubmit:Q.minTimeBeforeSubmit??500,maxHoldTime:Q.maxHoldTime??5000,showLoadingUI:Q.showLoadingUI??!0,loadingMessage:Q.loadingMessage??"Please wait...",onHold:Q.onHold,onRelease:Q.onRelease,onBlock:Q.onBlock,flushAndWaitForScore:Q.flushAndWaitForScore},this.config.mode!=="none")this.setup()}setup(){if(this.config.mode==="auto")this.interceptFetch(),this.interceptXHR();let Q=()=>{document.querySelectorAll("form").forEach((X)=>{this.protectForm(X)}),this.formObserver=new MutationObserver((X)=>{X.forEach((Y)=>{Y.addedNodes.forEach((Z)=>{if(Z instanceof HTMLFormElement)this.protectForm(Z);if(Z instanceof HTMLElement)Z.querySelectorAll("form").forEach(($)=>{this.protectForm($)})})})}),this.formObserver.observe(document.body,{childList:!0,subtree:!0})};if(document.body)Q();else document.addEventListener("DOMContentLoaded",Q,{once:!0})}isFormLikeRequest(Q,X){if((X?.method?.toUpperCase()||"GET")!=="POST")return!1;try{if((typeof Q==="string"?new URL(Q,window.location.origin):Q instanceof URL?Q:new URL(Q.url)).origin!==window.location.origin)return!1}catch{return!1}let Z=X?.headers instanceof Headers?X.headers.get("content-type"):typeof X?.headers==="object"&&X.headers!==null?X.headers["content-type"]||X.headers["Content-Type"]:null;if(Z){let $=Z.toLowerCase();if($.includes("application/x-www-form-urlencoded")||$.includes("multipart/form-data")||$.includes("application/json"))return!0;return!1}if(X?.body)return!0;return!1}interceptFetch(){this.originalFetch=window.fetch.bind(window);let Q=this;window.fetch=async function(X,Y){if(!Q.isFormLikeRequest(X,Y))return Q.originalFetch(X,Y);if(Q.hasScore)return Q.originalFetch(X,Y);return new Promise((Z,$)=>{let J={resolve:Z,reject:$,execute:()=>Q.originalFetch(X,Y),timestamp:performance.now()};if(Q.pendingRequests.push(J),Q.config.showLoadingUI&&Q.pendingRequests.length===1)Q.showLoading(document.createElement("form"));if(setTimeout(()=>{if(Q.pendingRequests.includes(J))Q.releaseRequest(J)},Q.config.maxHoldTime),Q.hasScore)Q.releaseRequest(J)})}}interceptXHR(){this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send;let Q=this;XMLHttpRequest.prototype.open=function(X,Y,Z=!0,$,J){let z=this;return z._bsMethod=X.toUpperCase(),z._bsUrl=Y.toString(),Q.originalXHROpen.call(this,X,Y,Z,$,J)},XMLHttpRequest.prototype.send=function(X){let Y=this,Z=Y._bsMethod||"GET",$=Y._bsUrl||"";if(Z!=="POST")return Q.originalXHRSend.call(this,X);try{if(new URL($,window.location.origin).origin!==window.location.origin)return Q.originalXHRSend.call(this,X)}catch{return Q.originalXHRSend.call(this,X)}if(Q.hasScore)return Q.originalXHRSend.call(this,X);let J=performance.now(),z=()=>{if(Q.hasScore){if(Q.config.showLoadingUI)Q.hideLoading();Q.originalXHRSend.call(Y,X)}else if(performance.now()-J>=Q.config.maxHoldTime){if(Q.config.showLoadingUI)Q.hideLoading();Q.originalXHRSend.call(Y,X)}else setTimeout(z,50)};if(Q.config.showLoadingUI)Q.showLoading(document.createElement("form"));z()}}releaseRequest(Q){let X=this.pendingRequests.indexOf(Q);if(X===-1)return;if(this.pendingRequests.splice(X,1),this.pendingRequests.length===0&&this.config.showLoadingUI)this.hideLoading();Q.execute().then(Q.resolve).catch(Q.reject)}protectForm(Q){if(this.protectedForms.has(Q))return;this.protectedForms.add(Q),Q.addEventListener("submit",(X)=>this.handleSubmit(X,Q),{capture:!0})}handleSubmit(Q,X){if(this.releasingForms.has(X)){this.releasingForms.delete(X);return}let Z=performance.now()-this.startTime;switch(N().markFirstSubmitAttempt(this.hasScore),this.config.mode){case"holdUntilReady":if(!this.hasScore)Q.preventDefault(),Q.stopPropagation(),this.holdSubmission(X,Q);break;case"holdUntilFormScored":Q.preventDefault(),Q.stopPropagation(),this.holdAndScoreSubmission(X,Q);break;case"blockInstant":if(Z<this.config.minTimeBeforeSubmit)Q.preventDefault(),Q.stopPropagation(),this.config.onBlock?.(X,"instant_submission");break;case"challengeFirst":if(!this.hasScore)Q.preventDefault(),Q.stopPropagation(),this.holdSubmission(X,Q);break;case"none":default:break}}holdSubmission(Q,X){if(this.config.onHold?.(Q),this.config.showLoadingUI)this.showLoading(Q);let Y={form:Q,event:X,timestamp:performance.now(),resolver:()=>{},rejecter:()=>{}},Z=new Promise(($,J)=>{Y.resolver=$,Y.rejecter=J});if(this.pendingSubmissions.push(Y),setTimeout(()=>{if(this.pendingSubmissions.includes(Y))this.releaseSubmission(Y,!1)},this.config.maxHoldTime),this.hasScore)this.releaseSubmission(Y,!1);Z.catch(()=>{})}async holdAndScoreSubmission(Q,X){if(this.config.onHold?.(Q),this.config.showLoadingUI)this.showLoading(Q);let Y=performance.now();try{if(!this.config.flushAndWaitForScore){this.submitForm(Q);return}let Z=this.config.flushAndWaitForScore(),$=new Promise((W)=>{setTimeout(()=>W(null),this.config.maxHoldTime)}),J=await Promise.race([Z,$]),z=performance.now()-Y;if(J===null);else this.currentScore=J,this.hasFormScore=!0;if(this.config.showLoadingUI)this.hideLoading();this.config.onRelease?.(Q,!1),this.submitForm(Q)}catch(Z){if(this.config.showLoadingUI)this.hideLoading();this.config.onRelease?.(Q,!1),this.submitForm(Q)}}submitForm(Q){if(this.releasingForms.add(Q),Q.requestSubmit)Q.requestSubmit();else Q.submit()}releaseSubmission(Q,X){let Y=this.pendingSubmissions.indexOf(Q);if(Y===-1)return;if(this.pendingSubmissions.splice(Y,1),this.config.showLoadingUI)this.hideLoading();if(this.config.onRelease?.(Q.form,X),!X)if(Q.resolver(),Q.form.requestSubmit)Q.form.requestSubmit();else Q.form.submit();else Q.rejecter("blocked")}showLoading(Q){if(this.loadingOverlay)return;this.loadingOverlay=document.createElement("div"),this.loadingOverlay.innerHTML=`
2
2
  <div style="
3
3
  position: fixed;
4
4
  top: 0;
@@ -37,6 +37,6 @@ import{a as y,b as U,d as v}from"./hash-q46pgar4.js";function T(Q){return typeof
37
37
  to { transform: rotate(360deg); }
38
38
  }
39
39
  </style>
40
- `,document.body.appendChild(this.loadingOverlay)}hideLoading(){if(this.loadingOverlay)this.loadingOverlay.remove(),this.loadingOverlay=null}notifyReady(Q){this.isReady=!0,this.hasScore=!0,this.currentScore=Q,[...this.pendingSubmissions].forEach((Z)=>{this.releaseSubmission(Z,!1)}),[...this.pendingRequests].forEach((Z)=>{this.releaseRequest(Z)}),this.hideLoading()}blockAllPending(Q){[...this.pendingSubmissions].forEach((Y)=>{this.config.onBlock?.(Y.form,Q),this.releaseSubmission(Y,!0)})}getStatus(){return{mode:this.config.mode,isReady:this.isReady,hasScore:this.hasScore,pendingCount:this.pendingSubmissions.length,protectedFormCount:this.protectedForms.size}}waitUntilReady(){if(this.hasScore)return Promise.resolve({score:this.currentScore,timedOut:!1});return new Promise((Q)=>{let X=performance.now(),Y=()=>{if(this.hasScore){Q({score:this.currentScore,timedOut:!1});return}if(performance.now()-X>=this.config.maxHoldTime){Q({score:null,timedOut:!0});return}setTimeout(Y,50)};Y()})}withProtection(Q){return async(...X)=>{let Y=performance.now()-this.startTime;if(N().markFirstSubmitAttempt(this.hasScore),this.config.mode==="blockInstant"&&Y<this.config.minTimeBeforeSubmit)throw this.config.onBlock?.(document.createElement("form"),"instant_submission"),Error("Submission blocked: too fast");if(this.config.mode==="holdUntilReady"&&!this.hasScore){if(this.config.showLoadingUI)this.showLoading(document.createElement("form"));let{timedOut:Z}=await this.waitUntilReady();if(this.config.showLoadingUI)this.hideLoading()}return Q(...X)}}protectedFetch(){return this.withProtection(async(Q,X)=>{return fetch(Q,X)})}setMode(Q){if(this.config.mode=Q,Q==="none")[...this.pendingSubmissions].forEach((Y)=>this.releaseSubmission(Y,!1))}setMaxHoldTime(Q){this.config.maxHoldTime=Q}canSubmit(){let Q=performance.now()-this.startTime;if(this.config.mode==="blockInstant"&&Q<this.config.minTimeBeforeSubmit)return{allowed:!1,reason:"too_fast",score:this.currentScore};if(this.config.mode==="holdUntilReady"&&!this.hasScore)return{allowed:!1,reason:"waiting_for_score",score:null};return{allowed:!0,score:this.currentScore}}destroy(){if(this.formObserver)this.formObserver.disconnect(),this.formObserver=null;if(this.originalFetch)window.fetch=this.originalFetch,this.originalFetch=null;if(this.originalXHROpen)XMLHttpRequest.prototype.open=this.originalXHROpen,this.originalXHROpen=null;if(this.originalXHRSend)XMLHttpRequest.prototype.send=this.originalXHRSend,this.originalXHRSend=null;this.hideLoading(),this.pendingSubmissions=[],this.pendingRequests=[],this.protectedForms.clear()}}var u={suspicious:40,bot:70},H={name:"_bsid",riskName:"_bsrisk",path:"/",sameSite:"Strict"};function d(Q){if(!Q)return null;if(Q===!0)return{...H};return{...H,...Q}}function a(Q){if(Q>=u.bot)return"bot";if(Q>=u.suspicious)return"suspicious";return"human"}class M{config;sessionIdGetter;sessionCookieSet=!1;currentRiskTier=null;constructor(Q,X){this.config={...H,...Q},this.sessionIdGetter=X}buildCookieString(Q,X){let Y=this.config.path||H.path,Z=this.config.sameSite||H.sameSite,$=this.config.secure??location.protocol==="https:",J=[`${encodeURIComponent(Q)}=${encodeURIComponent(X)}`,`Path=${Y}`,`SameSite=${Z}`];if($||Z==="None")J.push("Secure");return J.join("; ")}deleteCookie(Q){let X=this.config.path||H.path;document.cookie=`${encodeURIComponent(Q)}=; Path=${X}; Max-Age=0`}setSessionCookie(){if(this.sessionCookieSet)return;let Q=this.sessionIdGetter();if(!Q)return;let X=this.config.name||H.name;document.cookie=this.buildCookieString(X,Q),this.sessionCookieSet=!0}updateRiskTier(Q){let X=a(Q);if(X===this.currentRiskTier)return!1;let Y=this.config.riskName||H.riskName;document.cookie=this.buildCookieString(Y,X);let Z=this.currentRiskTier;return this.currentRiskTier=X,!0}removeCookies(){let Q=this.config.name||H.name,X=this.config.riskName||H.riskName;if(this.sessionCookieSet)this.deleteCookie(Q),this.sessionCookieSet=!1;if(this.currentRiskTier!==null)this.deleteCookie(X),this.currentRiskTier=null}setCookie(){this.setSessionCookie()}removeCookie(){this.removeCookies()}isSessionCookieSet(){return this.sessionCookieSet}getCurrentRiskTier(){return this.currentRiskTier}getSessionCookieName(){return this.config.name||H.name}getRiskCookieName(){return this.config.riskName||H.riskName}}var P={name:"X-BotSigged-ID"};function m(Q){if(!Q)return null;if(Q===!0)return{...P};return{...P,...Q}}class E{config;sessionIdGetter;started=!1;originalFetch=null;originalXHROpen=null;originalXHRSend=null;originalXHRSetRequestHeader=null;xhrInjectionMap=new WeakMap;constructor(Q,X){this.config={...P,...Q},this.sessionIdGetter=X}start(){if(this.started)return;this.started=!0,this.patchFetch(),this.patchXHR()}stop(){if(!this.started)return;if(this.originalFetch)window.fetch=this.originalFetch,this.originalFetch=null;if(this.originalXHROpen)XMLHttpRequest.prototype.open=this.originalXHROpen,this.originalXHROpen=null;if(this.originalXHRSend)XMLHttpRequest.prototype.send=this.originalXHRSend,this.originalXHRSend=null;if(this.originalXHRSetRequestHeader)XMLHttpRequest.prototype.setRequestHeader=this.originalXHRSetRequestHeader,this.originalXHRSetRequestHeader=null;this.started=!1}isSameOrigin(Q){try{let X;if(Q instanceof Request)X=new URL(Q.url,window.location.origin);else if(Q instanceof URL)X=Q;else X=new URL(Q,window.location.origin);return X.origin===window.location.origin}catch{return!0}}patchFetch(){this.originalFetch=window.fetch.bind(window);let Q=this,X=this.config.name||P.name;window.fetch=function(Y,Z){if(!Q.isSameOrigin(Y))return Q.originalFetch(Y,Z);let $=Q.sessionIdGetter();if(!$)return Q.originalFetch(Y,Z);let J=new Headers(Z?.headers);if(!J.has(X))J.set(X,$);return Q.originalFetch(Y,{...Z,headers:J})}}patchXHR(){this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send,this.originalXHRSetRequestHeader=XMLHttpRequest.prototype.setRequestHeader;let Q=this,X=this.config.name||P.name;XMLHttpRequest.prototype.open=function(Y,Z,$=!0,J,z){let W=Q.isSameOrigin(Z);return Q.xhrInjectionMap.set(this,W),Q.originalXHROpen.call(this,Y,Z,$,J,z)},XMLHttpRequest.prototype.send=function(Y){if(Q.xhrInjectionMap.get(this)){let Z=Q.sessionIdGetter();if(Z)try{Q.originalXHRSetRequestHeader.call(this,X,Z)}catch{}}return Q.originalXHRSend.call(this,Y)}}getHeaderName(){return this.config.name||P.name}isStarted(){return this.started}}var _={selector:"form",inputName:"_bsid"};function p(Q){if(!Q)return null;if(Q===!0)return{..._};return{..._,...Q}}class I{config;sessionIdGetter;observer=null;started=!1;constructor(Q,X){this.config={..._,...Q},this.sessionIdGetter=X}start(){if(this.started)return;this.started=!0;let Q=()=>{this.setupExistingForms(),this.setupObserver()};if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",Q,{once:!0});else Q()}stop(){if(!this.started)return;if(this.observer)this.observer.disconnect(),this.observer=null;let Q=this.config.selector||_.selector,X=this.config.inputName||_.inputName;document.querySelectorAll(`${Q}[data-bs-inject-setup]`).forEach((Y)=>{if(Y instanceof HTMLFormElement)Y.removeEventListener("submit",this.handleSubmit,{capture:!0});Y.removeAttribute("data-bs-inject-setup");let Z=Y.querySelector(`input[name="${X}"][data-bs-injected]`);if(Z)Z.remove()}),this.started=!1}setupExistingForms(){let Q=this.config.selector||_.selector;document.querySelectorAll(Q).forEach((X)=>{if(X instanceof HTMLFormElement)this.setupForm(X)})}setupObserver(){if(!document.body)return;let Q=this.config.selector||_.selector;this.observer=new MutationObserver((X)=>{X.forEach((Y)=>{Y.addedNodes.forEach((Z)=>{if(Z instanceof HTMLFormElement&&Z.matches(Q))this.setupForm(Z);if(Z instanceof HTMLElement)Z.querySelectorAll(Q).forEach(($)=>{if($ instanceof HTMLFormElement)this.setupForm($)})})})}),this.observer.observe(document.body,{childList:!0,subtree:!0})}setupForm(Q){if(Q.hasAttribute("data-bs-inject-setup"))return;Q.setAttribute("data-bs-inject-setup","true"),Q.addEventListener("submit",this.handleSubmit,{capture:!0})}handleSubmit=(Q)=>{let X=Q.currentTarget;this.injectInput(X)};injectInput(Q){let X=this.config.inputName||_.inputName,Y=Q.querySelector(`input[name="${X}"]`);if(Y){if(Y.hasAttribute("data-bs-injected"))Y.value=this.sessionIdGetter();return}let Z=document.createElement("input");Z.type="hidden",Z.name=X,Z.value=this.sessionIdGetter(),Z.setAttribute("data-bs-injected","true"),Q.appendChild(Z)}getConfig(){return{...this.config}}isStarted(){return this.started}}async function kQ(){return await import("./hash-q46pgar4.js")}class S{config;mouseCollector;scrollCollector;formCollector;browserCollector;fingerprintGenerator;socket=null;sessionId;sequenceNumber=0;isRunning=!1;sendTimer=null;fingerprint=null;browserSignal=null;lastScore=null;hasSentInitial=!1;boundBeforeUnload=null;boundVisibilityChange=null;hashModule=null;formBlocked=!1;formObserver=null;highScoreTriggeredLevels=new Set;challengeManager=null;challengeManagerPromise=null;formProtectionManager=null;formSubmissionStatus="no_submission";cookieManager=null;headerInjector=null;formInjector=null;serverConfig=null;connectionState="disconnected";reconnectTimer=null;readyPromise;readyResolver=null;constructor(Q){if(K.markConstructorStart(),!Q.apiKey)throw Error("BotSigged: apiKey is required");if(this.config=h(Q),this.sessionId=this.generateSessionId(),this.readyPromise=new Promise(($)=>{this.readyResolver=$}),this.mouseCollector=new k({sampleRate:this.config.mouseSampleRate,maxBufferSize:this.config.maxBufferSize}),this.scrollCollector=new x({maxBufferSize:Math.floor(this.config.maxBufferSize/3)}),this.formCollector=new C({maxKeyEvents:this.config.maxBufferSize,onSubmit:()=>this.handleFormSubmit()}),this.browserCollector=new L,this.fingerprintGenerator=new b,this.config.hashVerification.enabled)this.initializeHashModule();if(this.config.action==="challenge"||this.config.challenge.enabled)this.challengeManagerPromise=this.initializeChallengeManager();if(this.config.formProtection.mode!=="none")this.formProtectionManager=new D({mode:this.config.formProtection.mode,minTimeBeforeSubmit:this.config.formProtection.minTimeBeforeSubmit,maxHoldTime:this.config.formProtection.maxHoldTime,showLoadingUI:this.config.formProtection.showLoadingUI,loadingMessage:this.config.formProtection.loadingMessage,onHold:($)=>{this.updateFormStatus("challenged"),this.config.formProtection.onHold?.($)},onRelease:($,J)=>{if(!J)this.updateFormStatus("completed");this.config.formProtection.onRelease?.($,J)},onBlock:($,J)=>{this.updateFormStatus("blocked"),this.config.formProtection.onBlock?.($,J)},flushAndWaitForScore:()=>this.sendSignalAndGetScore()}),this.log("Form protection enabled:",this.config.formProtection.mode);else this.log("Form protection disabled (mode='none')");let X=d(this.config.cookie);if(X)this.cookieManager=new M(X,()=>this.sessionId),this.log("Cookie manager enabled:",X.name);let Y=m(this.config.headers);if(Y)this.headerInjector=new E(Y,()=>this.sessionId),this.headerInjector.start(),this.log("Header injector enabled:",Y.name);let Z=p(this.config.formInject);if(Z)this.formInjector=new I(Z,()=>this.sessionId),this.formInjector.start(),this.log("Form injector enabled:",Z.inputName);if(this.config.autoStart)if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",()=>this.start());else this.start();K.markConstructorEnd(),this.log("Constructor completed in",(K.getTimings().constructorEnd??0)-(K.getTimings().constructorStart??0),"ms")}async initializeHashModule(){try{let{initHashModule:Q}=await import("./hash-q46pgar4.js");this.hashModule=await Q({preferWasm:this.config.hashVerification.preferWasm,onWasmLoaded:()=>{this.log("WASM hash module loaded"),this.config.hashVerification.onWasmLoaded?.()},onFallback:(X)=>{this.log("Using JS hash fallback:",X),this.config.hashVerification.onWasmFallback?.(X)}})}catch(Q){this.log("Failed to initialize hash module",Q)}}async initializeChallengeManager(){try{let{ChallengeManager:Q}=await import("./challenge-8yg1wp51.js");this.challengeManager=new Q(this.config.challenge,this.config.debug),this.log("Challenge manager loaded")}catch(Q){this.log("Failed to initialize challenge manager",Q)}}async start(){if(this.isRunning){this.log("Already running");return}K.markStartCalled(),this.log("Starting BotSigged SDK"),this.isRunning=!0,this.connectionState="connecting";try{this.browserSignal=this.browserCollector.collect(),K.markFormCollectorStart(),this.mouseCollector.start(),this.scrollCollector.start(),this.formCollector.start(),K.markFormCollectorReady(),this.log("Collectors started in",(K.getTimings().formCollectorReady??0)-(K.getTimings().formCollectorStart??0),"ms"),K.markFingerprintStart(),K.markWsConnectStart();let[Q]=await Promise.all([this.fingerprintGenerator.generate(),this.connectWithRetry()]);this.fingerprint=Q,K.markFingerprintEnd(),this.log("Fingerprint generated in",(K.getTimings().fingerprintEnd??0)-(K.getTimings().fingerprintStart??0),"ms"),await this.joinChannel(),this.connectionState="connected",this.readyResolver?.(),K.markSdkReady(),this.startSendInterval(),this.registerBeforeUnload();let X=K.getSummary();if(this.log("SDK started successfully"),this.log("Total startup time:",X.totalStartupMs,"ms"),this.log("Time to first score:",X.timeToFirstScoreMs,"ms"),this.log("Vulnerability window:",X.vulnerabilityWindowMs,"ms"),this.config.debug)K.logSummary()}catch(Q){let X=Q instanceof Error?Q:Error(String(Q));this.log("Failed to start",X),this.handleConnectionFailure(X)}}async stop(){if(!this.isRunning)return;if(this.log("Stopping BotSigged SDK"),this.formProtectionManager)this.formProtectionManager.destroy(),this.formProtectionManager=null;if(this.cookieManager)this.cookieManager.removeCookies(),this.cookieManager=null;if(this.headerInjector)this.headerInjector.stop(),this.headerInjector=null;if(this.formInjector)this.formInjector.stop(),this.formInjector=null;if(this.formObserver)this.formObserver.disconnect(),this.formObserver=null;this.unregisterBeforeUnload(),this.mouseCollector.stop(),this.scrollCollector.stop(),this.formCollector.stop(),this.stopSendInterval(),await this.sendSignal(),await this.disconnect(),this.isRunning=!1,this.log("SDK stopped")}async sendSignal(){if(!this.socket?.isReady()){this.log("Cannot send signal: not connected");return}let Q=this.buildPayload(),X=Q.seq;this.log("Sending signal seq:",X),K.markSignalSent(X);try{let Y=await this.socket.sendSignal(Q);K.markSignalResponseReceived(X);let Z=K.getTimings().signalRoundtrips||[],$=Z[Z.length-1];if($)this.log("Signal roundtrip:",$.roundtripMs,"ms");if(Y.bot_score!==void 0){let J={bot_score:Y.bot_score,classification:Y.classification||"unknown",triggered_rules:Y.triggered_rules||[]};this.lastScore=J,this.config.onScoreUpdate?.(J),this.handleScoreUpdate(J)}this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush(),this.hasSentInitial=!0}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));this.log("Failed to send signal",Z),this.config.onError?.(Z)}}async sendSignalAndGetScore(){if(!this.socket?.isReady())return this.log("Cannot send signal: not connected"),null;let Q=this.buildPayload(),X=Q.seq;this.log("Sending signal for form scoring, seq:",X);try{let Y=await this.socket.sendSignal(Q);if(Y.bot_score!==void 0){let Z={bot_score:Y.bot_score,classification:Y.classification||"unknown",triggered_rules:Y.triggered_rules||[]};return this.lastScore=Z,this.config.onScoreUpdate?.(Z),this.handleScoreUpdate(Z),this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush(),this.hasSentInitial=!0,Z.bot_score}return this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush(),this.hasSentInitial=!0,null}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));return this.log("Failed to send signal for form scoring",Z),this.config.onError?.(Z),null}}getSessionId(){return this.sessionId}getFingerprint(){return this.fingerprint}getFormSubmissionStatus(){return this.formSubmissionStatus}getLastScore(){return this.lastScore}isConnected(){return this.socket?.isReady()??!1}whenReady(){if(this.connectionState==="connected")return Promise.resolve();return this.readyPromise}getConnectionState(){return this.connectionState}getServerConfig(){return this.serverConfig}async identify(Q){let{accountId:X}=Q;if(!X||typeof X!=="string")throw Error("BotSigged: accountId is required and must be a string");if(X.length>255)throw Error("BotSigged: accountId must be 255 characters or less");this.log("Identifying account:",X),await this.whenReady();try{let Y=await this.socket.sendEvent("identify",{account_id:X,timestamp:Date.now()});if(Y.identified)this.log("Account identified successfully");else throw Error(Y.reason?.toString()||"Failed to identify account")}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));throw this.log("Failed to identify account:",Z),this.config.onError?.(Z),Z}}isDegraded(){return this.connectionState==="degraded"||this.connectionState==="failed"}getCurrentSignals(){return{mouse:this.mouseCollector.getSignal(),scroll:this.scrollCollector.getSignal(),form:this.formCollector.getSignal(),browser:this.browserSignal}}getBufferSizes(){return{mouse:this.mouseCollector.getBufferSize(),scroll:this.scrollCollector.getBufferSize(),form:this.formCollector.getBufferSize()}}resetSignals(){this.mouseCollector.reset(),this.scrollCollector.reset(),this.formCollector.reset(),this.browserCollector.reset(),this.sequenceNumber=0,this.hasSentInitial=!1}async connectSocket(){this.socket=new A({endpoint:this.config.endpoint,apiKey:this.config.apiKey,debug:this.config.debug,onConnectionChange:(Q)=>{this.config.onConnectionChange?.(Q==="connected")},onError:(Q)=>{this.config.onError?.(Q)}}),await this.socket.connect(),K.markWsConnectEnd(),this.log("WebSocket connected in",(K.getTimings().wsConnectEnd??0)-(K.getTimings().wsConnectStart??0),"ms")}async connectWithRetry(){let X=[1000,2000,4000];for(let Y=0;Y<3;Y++)try{await this.connectSocket();return}catch(Z){if(this.log(`Connection attempt ${Y+1} failed:`,Z),Y<2)await this.sleep(X[Y]);else throw Z}}sleep(Q){return new Promise((X)=>setTimeout(X,Q))}handleConnectionFailure(Q){this.connectionState="failed";let X=this.config.fallbackMode||"degraded";switch(this.log("Connection failed, applying fallback mode:",X),X){case"open":if(this.connectionState="degraded",this.formProtectionManager)this.formProtectionManager.setMode("none"),this.formProtectionManager.notifyReady(0);break;case"closed":this.blockFormsUntilConnected(),this.scheduleReconnect();break;case"cached":let Y=this.loadCachedConfig();if(Y)this.applyServerConfig(Y),this.connectionState="degraded";else this.applyFallbackConfig();this.scheduleReconnect();break;case"degraded":default:this.applyFallbackConfig(),this.connectionState="degraded",this.scheduleReconnect();break}this.config.onError?.(Q),this.config.onConnectionChange?.(!1)}applyFallbackConfig(){if(this.log("Applying fallback config"),this.serverConfig=F,this.formProtectionManager&&this.serverConfig.form_protection_mode)this.formProtectionManager.setMode(this.serverConfig.form_protection_mode);this.config.onServerConfig?.(this.serverConfig,"fallback")}blockFormsUntilConnected(){if(this.formProtectionManager)this.formProtectionManager.setMode("holdUntilReady"),this.formProtectionManager.setMaxHoldTime(30000)}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer);this.reconnectTimer=setTimeout(()=>{this.attemptReconnect()},5000)}async attemptReconnect(){this.log("Attempting reconnection..."),this.connectionState="connecting";try{if(await this.connectWithRetry(),!this.fingerprint)this.fingerprint=await this.fingerprintGenerator.generate();if(await this.joinChannel(),this.connectionState="connected",this.readyResolver?.(),this.log("Reconnection successful"),!this.sendTimer)this.startSendInterval()}catch(Q){this.log("Reconnection failed:",Q),this.connectionState="failed"}}cacheServerConfig(Q){try{localStorage.setItem(`botsigged_config_${this.config.apiKey}`,JSON.stringify({config:Q,timestamp:Date.now()}))}catch{}}loadCachedConfig(){try{let Q=localStorage.getItem(`botsigged_config_${this.config.apiKey}`);if(!Q)return null;let{config:X,timestamp:Y}=JSON.parse(Q);if(Date.now()-Y>86400000)return localStorage.removeItem(`botsigged_config_${this.config.apiKey}`),null;return X}catch{return null}}applyServerConfig(Q){if(this.log("Applying server config:",Q),this.serverConfig=Q,this.formProtectionManager&&Q.form_protection_mode)this.formProtectionManager.setMode(Q.form_protection_mode);if(Q.action&&Q.action!=="none")this.applyServerAction(Q.action,Q.challenge);this.cacheServerConfig(Q),this.config.onServerConfig?.(Q,"server")}async applyServerAction(Q,X){switch(this.log("Applying server action:",Q),Q){case"block":if(!this.formBlocked)this.blockForms();break;case"challenge":if(!this.challengeManager&&!this.challengeManagerPromise)this.log("Lazily loading challenge manager for server-requested challenge"),this.challengeManagerPromise=this.initializeChallengeManager();if(this.challengeManagerPromise)await this.challengeManagerPromise;if(this.challengeManager){let Y=X?.difficulty?.bot??16,Z=Y>=18?"critical":Y>=16?"high":"medium";this.challengeManager.blockFormsUntilSolved(Z)}else this.log("Challenge requested but challenge manager failed to load");break;case"flag":this.log("Session flagged by server");break;case"none":default:break}}handleServerAction(Q){this.log("Received server action:",Q),this.config.onServerAction?.(Q);let X=Q.challenge?{difficulty:{suspicious:Q.challenge.difficulty,bot:Q.challenge.difficulty},timeout_ms:Q.challenge.timeout_ms}:void 0;this.applyServerAction(Q.type,X)}async joinChannel(){if(!this.socket)throw Error("WebSocket not initialized");K.markChannelJoinStart();let Q;try{Q=await this.socket.joinChannel(this.sessionId,this.fingerprint,this.getSessionData(),this.browserSignal,{onScoreUpdate:(X)=>{this.lastScore=X,this.config.onScoreUpdate?.(X),this.handleScoreUpdate(X)},onError:(X)=>{this.config.onError?.(X)},onAction:(X)=>{this.handleServerAction(X)}},this.config.accountId)}catch(X){if(T(X)){if(this.log("Usage limit exceeded:",X),this.config.onUsageLimitExceeded)this.config.onUsageLimitExceeded(X);else this.config.onError?.(Error(`Usage limit exceeded: ${X.current_usage}/${X.limit} verifications (${X.plan_name} plan). Please upgrade your plan.`));return}throw X}if(K.markChannelJoinEnd(),this.log("Channel joined in",(K.getTimings().channelJoinEnd??0)-(K.getTimings().channelJoinStart??0),"ms"),Q.config){let X=Q.config;this.applyServerConfig(X)}if(Q.initial_score!==void 0){K.markInitialScoreReceived();let X={bot_score:Q.initial_score,classification:Q.classification||"unknown",triggered_rules:Q.triggered_rules||[]};if(this.lastScore=X,this.config.onScoreUpdate?.(X),this.handleScoreUpdate(X),this.formProtectionManager)this.formProtectionManager.notifyReady(X.bot_score);if(this.cookieManager)this.cookieManager.setCookie();this.log("Initial score received:",X.bot_score,"in",(K.getTimings().initialScoreReceived??0)-(K.getTimings().startCalled??0),"ms from start")}}handleScoreUpdate(Q){if(this.cookieManager)this.cookieManager.updateRiskTier(Q.bot_score);let X=this.getBotScoreLevel(Q.bot_score),Y=Q.bot_score>=this.config.actionThreshold;if(this.shouldTriggerAlert(X)){let Z={score:Q.bot_score,level:X,scoreUpdate:Q,sessionId:this.sessionId,fingerprintHash:this.fingerprint?.hash};if(Y&&!this.highScoreTriggeredLevels.has(X))this.executeAction(Z);this.config.onHighBotScore?.(Z),this.highScoreTriggeredLevels.add(X)}}getBotScoreLevel(Q){let X=this.config.botScoreThresholds;if(Q>=X.critical)return"critical";if(Q>=X.high)return"high";if(Q>=X.medium)return"medium";return"low"}shouldTriggerAlert(Q){if(this.highScoreTriggeredLevels.has(Q))return!1;let X=["low","medium","high","critical"],Y=this.config.minAlertLevel,Z=X.indexOf(Q),$=X.indexOf(Y);return Z>=$}async executeAction(Q){let X=this.config.action;switch(this.log(`Executing action '${X}' for score ${Q.score}`),X){case"challenge":if(this.challengeManagerPromise)await this.challengeManagerPromise;if(this.challengeManager)this.challengeManager.blockFormsUntilSolved(Q.level);break;case"block":if(!this.formBlocked)this.blockForms();break;case"none":default:break}}blockForms(){if(this.formBlocked)return;this.formBlocked=!0,document.querySelectorAll("form").forEach((Q)=>{Q.addEventListener("submit",this.blockFormSubmit,!0)}),this.formObserver=new MutationObserver((Q)=>{Q.forEach((X)=>{X.addedNodes.forEach((Y)=>{if(Y instanceof HTMLFormElement)Y.addEventListener("submit",this.blockFormSubmit,!0);if(Y instanceof HTMLElement)Y.querySelectorAll("form").forEach((Z)=>{Z.addEventListener("submit",this.blockFormSubmit,!0)})})})}),this.formObserver.observe(document.body,{childList:!0,subtree:!0}),this.log("Forms blocked due to high bot score")}blockFormSubmit=(Q)=>{Q.preventDefault(),Q.stopPropagation(),this.log("Form submission blocked due to high bot score");return};isFormsBlocked(){return this.formBlocked}unblockForms(){if(!this.formBlocked)return;if(this.formObserver)this.formObserver.disconnect(),this.formObserver=null;document.querySelectorAll("form").forEach((Q)=>{Q.removeEventListener("submit",this.blockFormSubmit,!0)}),this.formBlocked=!1,this.log("Forms unblocked")}getHashModule(){return this.hashModule}createSignature(Q){let X=this.config.hashVerification.secret;if(!X)return this.log("Cannot create signature: no secret configured"),null;return createSignature(Q,X)}verifySignature(Q,X){let Y=this.config.hashVerification.secret;if(!Y)return this.log("Cannot verify signature: no secret configured"),!1;return verifySignature(Q,X,Y)}isChallengeSolving(){return this.challengeManager?.isSolving()??!1}isChallengeSolved(){return this.challengeManager?.isSolved()??!1}getPerformanceSummary(){return K.getSummary()}logPerformance(){K.logSummary()}getPerformanceReport(){return K.getReport()}async waitUntilReady(){if(this.lastScore)return{score:this.lastScore.bot_score,timedOut:!1};if(this.formProtectionManager)return this.formProtectionManager.waitUntilReady();return new Promise((Q)=>{let X=performance.now(),Y=5000,Z=()=>{if(this.lastScore){Q({score:this.lastScore.bot_score,timedOut:!1});return}if(performance.now()-X>=5000){Q({score:null,timedOut:!0});return}setTimeout(Z,50)};Z()})}withProtection(Q,X={}){let Y=X.blockThreshold??this.config.actionThreshold;return async(...Z)=>{let{score:$,timedOut:J}=await this.waitUntilReady();if(K.markFirstSubmitAttempt($!==null),$!==null&&$>=Y)throw this.log(`Blocking submission: score ${$} >= threshold ${Y}`),Error(`Submission blocked: bot score ${$} exceeds threshold`);if(J)this.log("Warning: submitting without detection score (timed out)");return Q(...Z)}}protectedFetch(Q={}){return this.withProtection(async(X,Y)=>{return fetch(X,Y)},Q)}canSubmit(){if(!this.lastScore)return{allowed:!1,reason:"waiting_for_score",score:null};if(this.lastScore.bot_score>=this.config.actionThreshold)return{allowed:!1,reason:"high_bot_score",score:this.lastScore.bot_score};return{allowed:!0,score:this.lastScore.bot_score}}async triggerChallenge(Q="high"){if(this.challengeManagerPromise)await this.challengeManagerPromise;if(!this.challengeManager){this.log("Challenge not enabled");return}this.challengeManager.blockFormsUntilSolved(Q)}async disconnect(){if(this.socket)await this.socket.leaveChannel(),this.socket.disconnect(),this.socket=null}startSendInterval(){this.stopSendInterval(),this.sendTimer=setInterval(()=>{this.sendSignal()},this.config.sendInterval)}stopSendInterval(){if(this.sendTimer)clearInterval(this.sendTimer),this.sendTimer=null}registerBeforeUnload(){this.boundBeforeUnload=()=>{this.handleBeforeUnload()},this.boundVisibilityChange=()=>{if(document.visibilityState==="hidden")this.handleBeforeUnload()},window.addEventListener("beforeunload",this.boundBeforeUnload),document.addEventListener("visibilitychange",this.boundVisibilityChange)}unregisterBeforeUnload(){if(this.boundBeforeUnload)window.removeEventListener("beforeunload",this.boundBeforeUnload),this.boundBeforeUnload=null;if(this.boundVisibilityChange)document.removeEventListener("visibilitychange",this.boundVisibilityChange),this.boundVisibilityChange=null}handleBeforeUnload(){if(!this.isRunning||!this.socket)return;try{let Q=this.buildPayload();if(this.socket.isReady())this.socket.sendSignal(Q).catch(()=>{})}catch{}}handleFormSubmit(){if(!this.isRunning)return;if(K.markFirstSubmitAttempt(this.lastScore!==null),this.log("Form submitted, flushing signals via beacon"),this.log("Had score before submit:",this.lastScore!==null),this.updateFormStatus("completed"),!this.sessionId){this.log("No session ID yet, cannot send beacon");return}let Q=this.buildPayload();if(!this.sendViaBeacon(Q))this.sendSignal().catch((Y)=>{this.log("Failed to flush signals on form submit",Y)});else this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush()}sendViaBeacon(Q){if(!navigator.sendBeacon)return this.log("sendBeacon not available"),!1;try{let X=new URL(this.config.endpoint),Y=`${X.protocol==="wss:"?"https:":"http:"}//${X.host}/api/signal`,Z=JSON.stringify({session_id:this.sessionId,api_key:this.config.apiKey,payload:Q,form_status:this.formSubmissionStatus}),$=new Blob([Z],{type:"application/json"}),J=navigator.sendBeacon(Y,$);return this.log("Beacon sent:",J),J}catch(X){return this.log("Beacon send failed:",X),!1}}buildPayload(){this.sequenceNumber++;let Q={session_id:this.sessionId,seq:this.sequenceNumber,mouse:this.mouseCollector.getSignal(),scroll:this.scrollCollector.getSignal(),form:this.formCollector.getSignal(),timestamp:Date.now()};if(!this.hasSentInitial)Q.session=this.getSessionData(),Q.fingerprint=this.fingerprint,Q.browser=this.browserSignal;return Q}getSessionData(){let Q=new URL(window.location.href),X={};Q.searchParams.forEach((Z,$)=>{X[$]=Z});let Y=null;if(document.referrer)try{Y=new URL(document.referrer).hostname}catch{}return{url_path:Q.pathname,url_params:X,referrer_url:document.referrer||null,referrer_domain:Y,user_agent:navigator.userAgent}}generateSessionId(){if(crypto.randomUUID)return crypto.randomUUID();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(Q)=>{let X=Math.random()*16|0;return(Q==="x"?X:X&3|8).toString(16)})}updateFormStatus(Q){if(this.formSubmissionStatus==="blocked"||this.formSubmissionStatus==="completed"){this.log(`Form status already terminal (${this.formSubmissionStatus}), ignoring ${Q}`);return}if(this.formSubmissionStatus==="challenged"&&Q!=="completed"){this.log(`Form status is challenged, can only become completed, ignoring ${Q}`);return}if(this.formSubmissionStatus=Q,this.log(`Form status updated to: ${Q}`),this.socket?.isReady())this.socket.sendFormStatus(Q).catch((X)=>{this.log("Failed to send form status:",X)})}log(...Q){if(this.config.debug);}}var O=null;function xQ(Q){if(O)return O;return O=new S(Q),O}function CQ(){return O}async function LQ(){if(O)await O.stop(),O=null}var AQ=S;export{f as logPerformanceSummary,kQ as loadHashModule,T as isUsageLimitError,xQ as init,l as getPerformanceSummary,N as getPerformanceMetrics,CQ as getInstance,LQ as destroy,AQ as default,q as DEFAULT_CONFIG,S as BotSigged};
40
+ `,document.body.appendChild(this.loadingOverlay)}hideLoading(){if(this.loadingOverlay)this.loadingOverlay.remove(),this.loadingOverlay=null}notifyReady(Q){this.isReady=!0,this.hasScore=!0,this.currentScore=Q,[...this.pendingSubmissions].forEach((Z)=>{this.releaseSubmission(Z,!1)}),[...this.pendingRequests].forEach((Z)=>{this.releaseRequest(Z)}),this.hideLoading()}blockAllPending(Q){[...this.pendingSubmissions].forEach((Y)=>{this.config.onBlock?.(Y.form,Q),this.releaseSubmission(Y,!0)})}getStatus(){return{mode:this.config.mode,isReady:this.isReady,hasScore:this.hasScore,pendingCount:this.pendingSubmissions.length,protectedFormCount:this.protectedForms.size}}waitUntilReady(){if(this.hasScore)return Promise.resolve({score:this.currentScore,timedOut:!1});return new Promise((Q)=>{let X=performance.now(),Y=()=>{if(this.hasScore){Q({score:this.currentScore,timedOut:!1});return}if(performance.now()-X>=this.config.maxHoldTime){Q({score:null,timedOut:!0});return}setTimeout(Y,50)};Y()})}withProtection(Q){return async(...X)=>{let Y=performance.now()-this.startTime;if(N().markFirstSubmitAttempt(this.hasScore),this.config.mode==="blockInstant"&&Y<this.config.minTimeBeforeSubmit)throw this.config.onBlock?.(document.createElement("form"),"instant_submission"),Error("Submission blocked: too fast");if(this.config.mode==="holdUntilReady"&&!this.hasScore){if(this.config.showLoadingUI)this.showLoading(document.createElement("form"));let{timedOut:Z}=await this.waitUntilReady();if(this.config.showLoadingUI)this.hideLoading()}return Q(...X)}}protectedFetch(){return this.withProtection(async(Q,X)=>{return fetch(Q,X)})}setMode(Q){if(this.config.mode=Q,Q==="none")[...this.pendingSubmissions].forEach((Y)=>this.releaseSubmission(Y,!1))}setMaxHoldTime(Q){this.config.maxHoldTime=Q}canSubmit(){let Q=performance.now()-this.startTime;if(this.config.mode==="blockInstant"&&Q<this.config.minTimeBeforeSubmit)return{allowed:!1,reason:"too_fast",score:this.currentScore};if(this.config.mode==="holdUntilReady"&&!this.hasScore)return{allowed:!1,reason:"waiting_for_score",score:null};return{allowed:!0,score:this.currentScore}}destroy(){if(this.formObserver)this.formObserver.disconnect(),this.formObserver=null;if(this.originalFetch)window.fetch=this.originalFetch,this.originalFetch=null;if(this.originalXHROpen)XMLHttpRequest.prototype.open=this.originalXHROpen,this.originalXHROpen=null;if(this.originalXHRSend)XMLHttpRequest.prototype.send=this.originalXHRSend,this.originalXHRSend=null;this.hideLoading(),this.pendingSubmissions=[],this.pendingRequests=[],this.protectedForms.clear()}}var u={suspicious:40,bot:70},H={name:"_bsid",riskName:"_bsrisk",path:"/",sameSite:"Strict"};function d(Q){if(!Q)return null;if(Q===!0)return{...H};return{...H,...Q}}function a(Q){if(Q>=u.bot)return"bot";if(Q>=u.suspicious)return"suspicious";return"human"}class M{config;sessionIdGetter;sessionCookieSet=!1;currentRiskTier=null;constructor(Q,X){this.config={...H,...Q},this.sessionIdGetter=X}buildCookieString(Q,X){let Y=this.config.path||H.path,Z=this.config.sameSite||H.sameSite,$=this.config.secure??location.protocol==="https:",J=[`${encodeURIComponent(Q)}=${encodeURIComponent(X)}`,`Path=${Y}`,`SameSite=${Z}`];if($||Z==="None")J.push("Secure");return J.join("; ")}deleteCookie(Q){let X=this.config.path||H.path;document.cookie=`${encodeURIComponent(Q)}=; Path=${X}; Max-Age=0`}setSessionCookie(){if(this.sessionCookieSet)return;let Q=this.sessionIdGetter();if(!Q)return;let X=this.config.name||H.name;document.cookie=this.buildCookieString(X,Q),this.sessionCookieSet=!0}updateRiskTier(Q){let X=a(Q);if(X===this.currentRiskTier)return!1;let Y=this.config.riskName||H.riskName;document.cookie=this.buildCookieString(Y,X);let Z=this.currentRiskTier;return this.currentRiskTier=X,!0}removeCookies(){let Q=this.config.name||H.name,X=this.config.riskName||H.riskName;if(this.sessionCookieSet)this.deleteCookie(Q),this.sessionCookieSet=!1;if(this.currentRiskTier!==null)this.deleteCookie(X),this.currentRiskTier=null}setCookie(){this.setSessionCookie()}removeCookie(){this.removeCookies()}isSessionCookieSet(){return this.sessionCookieSet}getCurrentRiskTier(){return this.currentRiskTier}getSessionCookieName(){return this.config.name||H.name}getRiskCookieName(){return this.config.riskName||H.riskName}}var P={name:"X-BotSigged-ID"};function m(Q){if(!Q)return null;if(Q===!0)return{...P};return{...P,...Q}}class E{config;sessionIdGetter;started=!1;originalFetch=null;originalXHROpen=null;originalXHRSend=null;originalXHRSetRequestHeader=null;xhrInjectionMap=new WeakMap;constructor(Q,X){this.config={...P,...Q},this.sessionIdGetter=X}start(){if(this.started)return;this.started=!0,this.patchFetch(),this.patchXHR()}stop(){if(!this.started)return;if(this.originalFetch)window.fetch=this.originalFetch,this.originalFetch=null;if(this.originalXHROpen)XMLHttpRequest.prototype.open=this.originalXHROpen,this.originalXHROpen=null;if(this.originalXHRSend)XMLHttpRequest.prototype.send=this.originalXHRSend,this.originalXHRSend=null;if(this.originalXHRSetRequestHeader)XMLHttpRequest.prototype.setRequestHeader=this.originalXHRSetRequestHeader,this.originalXHRSetRequestHeader=null;this.started=!1}isSameOrigin(Q){try{let X;if(Q instanceof Request)X=new URL(Q.url,window.location.origin);else if(Q instanceof URL)X=Q;else X=new URL(Q,window.location.origin);return X.origin===window.location.origin}catch{return!0}}patchFetch(){this.originalFetch=window.fetch.bind(window);let Q=this,X=this.config.name||P.name;window.fetch=function(Y,Z){if(!Q.isSameOrigin(Y))return Q.originalFetch(Y,Z);let $=Q.sessionIdGetter();if(!$)return Q.originalFetch(Y,Z);let J=new Headers(Z?.headers);if(!J.has(X))J.set(X,$);return Q.originalFetch(Y,{...Z,headers:J})}}patchXHR(){this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send,this.originalXHRSetRequestHeader=XMLHttpRequest.prototype.setRequestHeader;let Q=this,X=this.config.name||P.name;XMLHttpRequest.prototype.open=function(Y,Z,$=!0,J,z){let W=Q.isSameOrigin(Z);return Q.xhrInjectionMap.set(this,W),Q.originalXHROpen.call(this,Y,Z,$,J,z)},XMLHttpRequest.prototype.send=function(Y){if(Q.xhrInjectionMap.get(this)){let Z=Q.sessionIdGetter();if(Z)try{Q.originalXHRSetRequestHeader.call(this,X,Z)}catch{}}return Q.originalXHRSend.call(this,Y)}}getHeaderName(){return this.config.name||P.name}isStarted(){return this.started}}var _={selector:"form",inputName:"_bsid"};function p(Q){if(!Q)return null;if(Q===!0)return{..._};return{..._,...Q}}class I{config;sessionIdGetter;observer=null;started=!1;constructor(Q,X){this.config={..._,...Q},this.sessionIdGetter=X}start(){if(this.started)return;this.started=!0;let Q=()=>{this.setupExistingForms(),this.setupObserver()};if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",Q,{once:!0});else Q()}stop(){if(!this.started)return;if(this.observer)this.observer.disconnect(),this.observer=null;let Q=this.config.selector||_.selector,X=this.config.inputName||_.inputName;document.querySelectorAll(`${Q}[data-bs-inject-setup]`).forEach((Y)=>{if(Y instanceof HTMLFormElement)Y.removeEventListener("submit",this.handleSubmit,{capture:!0});Y.removeAttribute("data-bs-inject-setup");let Z=Y.querySelector(`input[name="${X}"][data-bs-injected]`);if(Z)Z.remove()}),this.started=!1}setupExistingForms(){let Q=this.config.selector||_.selector;document.querySelectorAll(Q).forEach((X)=>{if(X instanceof HTMLFormElement)this.setupForm(X)})}setupObserver(){if(!document.body)return;let Q=this.config.selector||_.selector;this.observer=new MutationObserver((X)=>{X.forEach((Y)=>{Y.addedNodes.forEach((Z)=>{if(Z instanceof HTMLFormElement&&Z.matches(Q))this.setupForm(Z);if(Z instanceof HTMLElement)Z.querySelectorAll(Q).forEach(($)=>{if($ instanceof HTMLFormElement)this.setupForm($)})})})}),this.observer.observe(document.body,{childList:!0,subtree:!0})}setupForm(Q){if(Q.hasAttribute("data-bs-inject-setup"))return;Q.setAttribute("data-bs-inject-setup","true"),Q.addEventListener("submit",this.handleSubmit,{capture:!0})}handleSubmit=(Q)=>{let X=Q.currentTarget;this.injectInput(X)};injectInput(Q){let X=this.config.inputName||_.inputName,Y=Q.querySelector(`input[name="${X}"]`);if(Y){if(Y.hasAttribute("data-bs-injected"))Y.value=this.sessionIdGetter();return}let Z=document.createElement("input");Z.type="hidden",Z.name=X,Z.value=this.sessionIdGetter(),Z.setAttribute("data-bs-injected","true"),Q.appendChild(Z)}getConfig(){return{...this.config}}isStarted(){return this.started}}async function kQ(){return await import("./hash-q46pgar4.js")}class S{config;mouseCollector;scrollCollector;formCollector;browserCollector;fingerprintGenerator;socket=null;sessionId;sequenceNumber=0;isRunning=!1;sendTimer=null;fingerprint=null;browserSignal=null;lastScore=null;hasSentInitial=!1;boundBeforeUnload=null;boundVisibilityChange=null;hashModule=null;formBlocked=!1;formObserver=null;highScoreTriggeredLevels=new Set;challengeManager=null;challengeManagerPromise=null;formProtectionManager=null;formSubmissionStatus="no_submission";cookieManager=null;headerInjector=null;formInjector=null;serverConfig=null;connectionState="disconnected";reconnectTimer=null;readyPromise;readyResolver=null;constructor(Q){if(K.markConstructorStart(),!Q.apiKey)throw Error("BotSigged: apiKey is required");if(this.config=h(Q),this.sessionId=this.generateSessionId(),this.readyPromise=new Promise(($)=>{this.readyResolver=$}),this.mouseCollector=new k({sampleRate:this.config.mouseSampleRate,maxBufferSize:this.config.maxBufferSize}),this.scrollCollector=new x({maxBufferSize:Math.floor(this.config.maxBufferSize/3)}),this.formCollector=new C({maxKeyEvents:this.config.maxBufferSize,onSubmit:()=>this.handleFormSubmit()}),this.browserCollector=new L,this.fingerprintGenerator=new b,this.config.hashVerification.enabled)this.initializeHashModule();if(this.config.action==="challenge"||this.config.challenge.enabled)this.challengeManagerPromise=this.initializeChallengeManager();if(this.config.formProtection.mode!=="none")this.formProtectionManager=new D({mode:this.config.formProtection.mode,minTimeBeforeSubmit:this.config.formProtection.minTimeBeforeSubmit,maxHoldTime:this.config.formProtection.maxHoldTime,showLoadingUI:this.config.formProtection.showLoadingUI,loadingMessage:this.config.formProtection.loadingMessage,onHold:($)=>{this.updateFormStatus("challenged"),this.config.formProtection.onHold?.($)},onRelease:($,J)=>{if(!J)this.updateFormStatus("completed");this.config.formProtection.onRelease?.($,J)},onBlock:($,J)=>{this.updateFormStatus("blocked"),this.config.formProtection.onBlock?.($,J)},flushAndWaitForScore:()=>this.sendSignalAndGetScore()}),this.log("Form protection enabled:",this.config.formProtection.mode);else this.log("Form protection disabled (mode='none')");let X=d(this.config.cookie);if(X)this.cookieManager=new M(X,()=>this.sessionId),this.log("Cookie manager enabled:",X.name);let Y=m(this.config.headers);if(Y)this.headerInjector=new E(Y,()=>this.sessionId),this.headerInjector.start(),this.log("Header injector enabled:",Y.name);let Z=p(this.config.formInject);if(Z)this.formInjector=new I(Z,()=>this.sessionId),this.formInjector.start(),this.log("Form injector enabled:",Z.inputName);if(this.config.autoStart)if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",()=>this.start());else this.start();K.markConstructorEnd(),this.log("Constructor completed in",(K.getTimings().constructorEnd??0)-(K.getTimings().constructorStart??0),"ms")}async initializeHashModule(){try{let{initHashModule:Q}=await import("./hash-q46pgar4.js");this.hashModule=await Q({preferWasm:this.config.hashVerification.preferWasm,onWasmLoaded:()=>{this.log("WASM hash module loaded"),this.config.hashVerification.onWasmLoaded?.()},onFallback:(X)=>{this.log("Using JS hash fallback:",X),this.config.hashVerification.onWasmFallback?.(X)}})}catch(Q){this.log("Failed to initialize hash module",Q)}}async initializeChallengeManager(){try{let{ChallengeManager:Q}=await import("./challenge-8yg1wp51.js");this.challengeManager=new Q(this.config.challenge,this.config.debug),this.log("Challenge manager loaded")}catch(Q){this.log("Failed to initialize challenge manager",Q)}}async start(){if(this.isRunning){this.log("Already running");return}K.markStartCalled(),this.log("Starting BotSigged SDK"),this.isRunning=!0,this.connectionState="connecting";try{this.browserSignal=this.browserCollector.collect(),K.markFormCollectorStart(),this.mouseCollector.start(),this.scrollCollector.start(),this.formCollector.start(),K.markFormCollectorReady(),this.log("Collectors started in",(K.getTimings().formCollectorReady??0)-(K.getTimings().formCollectorStart??0),"ms"),K.markFingerprintStart(),K.markWsConnectStart();let[Q]=await Promise.all([this.fingerprintGenerator.generate(),this.connectWithRetry()]);this.fingerprint=Q,K.markFingerprintEnd(),this.log("Fingerprint generated in",(K.getTimings().fingerprintEnd??0)-(K.getTimings().fingerprintStart??0),"ms"),await this.joinChannel(),this.connectionState="connected",this.readyResolver?.(),K.markSdkReady(),this.startSendInterval(),this.registerBeforeUnload();let X=K.getSummary();if(this.log("SDK started successfully"),this.log("Total startup time:",X.totalStartupMs,"ms"),this.log("Time to first score:",X.timeToFirstScoreMs,"ms"),this.log("Vulnerability window:",X.vulnerabilityWindowMs,"ms"),this.config.debug)K.logSummary()}catch(Q){let X=Q instanceof Error?Q:Error(String(Q));this.log("Failed to start",X),this.handleConnectionFailure(X)}}async stop(){if(!this.isRunning)return;if(this.log("Stopping BotSigged SDK"),this.formProtectionManager)this.formProtectionManager.destroy(),this.formProtectionManager=null;if(this.cookieManager)this.cookieManager.removeCookies(),this.cookieManager=null;if(this.headerInjector)this.headerInjector.stop(),this.headerInjector=null;if(this.formInjector)this.formInjector.stop(),this.formInjector=null;if(this.formObserver)this.formObserver.disconnect(),this.formObserver=null;this.unregisterBeforeUnload(),this.mouseCollector.stop(),this.scrollCollector.stop(),this.formCollector.stop(),this.stopSendInterval(),await this.sendSignal(),await this.disconnect(),this.isRunning=!1,this.log("SDK stopped")}async sendSignal(){if(!this.socket?.isReady()){this.log("Cannot send signal: not connected");return}let Q=this.buildPayload(),X=Q.seq;this.log("Sending signal seq:",X),K.markSignalSent(X);try{let Y=await this.socket.sendSignal(Q);K.markSignalResponseReceived(X);let Z=K.getTimings().signalRoundtrips||[],$=Z[Z.length-1];if($)this.log("Signal roundtrip:",$.roundtripMs,"ms");if(Y.bot_score!==void 0){let J={bot_score:Y.bot_score,classification:Y.classification||"unknown",triggered_rules:Y.triggered_rules||[]};this.lastScore=J,this.config.onScoreUpdate?.(J),this.handleScoreUpdate(J)}this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush(),this.hasSentInitial=!0}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));this.log("Failed to send signal",Z),this.config.onError?.(Z)}}async sendSignalAndGetScore(){if(!this.socket?.isReady())return this.log("Cannot send signal: not connected"),null;let Q=this.buildPayload(),X=Q.seq;this.log("Sending signal for form scoring, seq:",X);try{let Y=await this.socket.sendSignal(Q);if(Y.bot_score!==void 0){let Z={bot_score:Y.bot_score,classification:Y.classification||"unknown",triggered_rules:Y.triggered_rules||[]};return this.lastScore=Z,this.config.onScoreUpdate?.(Z),this.handleScoreUpdate(Z),this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush(),this.hasSentInitial=!0,Z.bot_score}return this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush(),this.hasSentInitial=!0,null}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));return this.log("Failed to send signal for form scoring",Z),this.config.onError?.(Z),null}}getSessionId(){return this.sessionId}getFingerprint(){return this.fingerprint}getFormSubmissionStatus(){return this.formSubmissionStatus}getLastScore(){return this.lastScore}isConnected(){return this.socket?.isReady()??!1}whenReady(){if(this.connectionState==="connected")return Promise.resolve();return this.readyPromise}getConnectionState(){return this.connectionState}getServerConfig(){return this.serverConfig}async identify(Q){let{accountId:X}=Q;if(!X||typeof X!=="string")throw Error("BotSigged: accountId is required and must be a string");if(X.length>255)throw Error("BotSigged: accountId must be 255 characters or less");this.log("Identifying account:",X),await this.whenReady();try{let Y=await this.socket.sendEvent("identify",{account_id:X,timestamp:Date.now()});if(Y.identified)this.log("Account identified successfully");else throw Error(Y.reason?.toString()||"Failed to identify account")}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));throw this.log("Failed to identify account:",Z),this.config.onError?.(Z),Z}}isDegraded(){return this.connectionState==="degraded"||this.connectionState==="failed"}getCurrentSignals(){return{mouse:this.mouseCollector.getSignal(),scroll:this.scrollCollector.getSignal(),form:this.formCollector.getSignal(),browser:this.browserSignal}}getBufferSizes(){return{mouse:this.mouseCollector.getBufferSize(),scroll:this.scrollCollector.getBufferSize(),form:this.formCollector.getBufferSize()}}resetSignals(){this.mouseCollector.reset(),this.scrollCollector.reset(),this.formCollector.reset(),this.browserCollector.reset(),this.sequenceNumber=0,this.hasSentInitial=!1}async connectSocket(){this.socket=new A({endpoint:this.config.endpoint,apiKey:this.config.apiKey,debug:this.config.debug,onConnectionChange:(Q)=>{this.config.onConnectionChange?.(Q==="connected")},onError:(Q)=>{this.config.onError?.(Q)}}),await this.socket.connect(),K.markWsConnectEnd(),this.log("WebSocket connected in",(K.getTimings().wsConnectEnd??0)-(K.getTimings().wsConnectStart??0),"ms")}async connectWithRetry(){let X=[1000,2000,4000];for(let Y=0;Y<3;Y++)try{await this.connectSocket();return}catch(Z){if(this.log(`Connection attempt ${Y+1} failed:`,Z),Y<2)await this.sleep(X[Y]);else throw Z}}sleep(Q){return new Promise((X)=>setTimeout(X,Q))}handleConnectionFailure(Q){this.connectionState="failed";let X=this.config.fallbackMode||"degraded";switch(this.log("Connection failed, applying fallback mode:",X),X){case"open":if(this.connectionState="degraded",this.formProtectionManager)this.formProtectionManager.setMode("none"),this.formProtectionManager.notifyReady(0);break;case"closed":this.blockFormsUntilConnected(),this.scheduleReconnect();break;case"cached":let Y=this.loadCachedConfig();if(Y)this.applyServerConfig(Y),this.connectionState="degraded";else this.applyFallbackConfig();this.scheduleReconnect();break;case"degraded":default:this.applyFallbackConfig(),this.connectionState="degraded",this.scheduleReconnect();break}this.config.onError?.(Q),this.config.onConnectionChange?.(!1)}applyFallbackConfig(){if(this.log("Applying fallback config"),this.serverConfig=F,this.formProtectionManager&&this.serverConfig.form_protection_mode)this.formProtectionManager.setMode(this.serverConfig.form_protection_mode);this.config.onServerConfig?.(this.serverConfig,"fallback")}blockFormsUntilConnected(){if(this.formProtectionManager)this.formProtectionManager.setMode("holdUntilReady"),this.formProtectionManager.setMaxHoldTime(30000)}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer);this.reconnectTimer=setTimeout(()=>{this.attemptReconnect()},5000)}async attemptReconnect(){this.log("Attempting reconnection..."),this.connectionState="connecting";try{if(await this.connectWithRetry(),!this.fingerprint)this.fingerprint=await this.fingerprintGenerator.generate();if(await this.joinChannel(),this.connectionState="connected",this.readyResolver?.(),this.log("Reconnection successful"),!this.sendTimer)this.startSendInterval()}catch(Q){this.log("Reconnection failed:",Q),this.connectionState="failed"}}cacheServerConfig(Q){try{localStorage.setItem(`botsigged_config_${this.config.apiKey}`,JSON.stringify({config:Q,timestamp:Date.now()}))}catch{}}loadCachedConfig(){try{let Q=localStorage.getItem(`botsigged_config_${this.config.apiKey}`);if(!Q)return null;let{config:X,timestamp:Y}=JSON.parse(Q);if(Date.now()-Y>86400000)return localStorage.removeItem(`botsigged_config_${this.config.apiKey}`),null;return X}catch{return null}}applyServerConfig(Q){if(this.log("Applying server config:",Q),this.serverConfig=Q,this.formProtectionManager&&Q.form_protection_mode)this.formProtectionManager.setMode(Q.form_protection_mode);if(Q.action&&Q.action!=="none")this.applyServerAction(Q.action,Q.challenge);this.cacheServerConfig(Q),this.config.onServerConfig?.(Q,"server")}async applyServerAction(Q,X){switch(this.log("Applying server action:",Q),Q){case"block":if(this.updateFormStatus("blocked"),!this.formBlocked)this.blockForms();break;case"challenge":if(this.updateFormStatus("challenged"),!this.challengeManager&&!this.challengeManagerPromise)this.log("Lazily loading challenge manager for server-requested challenge"),this.challengeManagerPromise=this.initializeChallengeManager();if(this.challengeManagerPromise)await this.challengeManagerPromise;if(this.challengeManager){let Y=X?.difficulty?.bot??16,Z=Y>=18?"critical":Y>=16?"high":"medium";this.challengeManager.blockFormsUntilSolved(Z)}else this.log("Challenge requested but challenge manager failed to load");break;case"flag":this.updateFormStatus("flagged"),this.log("Session flagged by server");break;case"none":default:break}}handleServerAction(Q){this.log("Received server action:",Q),this.config.onServerAction?.(Q);let X=Q.challenge?{difficulty:{suspicious:Q.challenge.difficulty,bot:Q.challenge.difficulty},timeout_ms:Q.challenge.timeout_ms}:void 0;this.applyServerAction(Q.type,X)}async joinChannel(){if(!this.socket)throw Error("WebSocket not initialized");K.markChannelJoinStart();let Q;try{Q=await this.socket.joinChannel(this.sessionId,this.fingerprint,this.getSessionData(),this.browserSignal,{onScoreUpdate:(X)=>{this.lastScore=X,this.config.onScoreUpdate?.(X),this.handleScoreUpdate(X)},onError:(X)=>{this.config.onError?.(X)},onAction:(X)=>{this.handleServerAction(X)}},this.config.accountId)}catch(X){if(T(X)){if(this.log("Usage limit exceeded:",X),this.config.onUsageLimitExceeded)this.config.onUsageLimitExceeded(X);else this.config.onError?.(Error(`Usage limit exceeded: ${X.current_usage}/${X.limit} verifications (${X.plan_name} plan). Please upgrade your plan.`));return}throw X}if(K.markChannelJoinEnd(),this.log("Channel joined in",(K.getTimings().channelJoinEnd??0)-(K.getTimings().channelJoinStart??0),"ms"),Q.config){let X=Q.config;this.applyServerConfig(X)}if(Q.initial_score!==void 0){K.markInitialScoreReceived();let X={bot_score:Q.initial_score,classification:Q.classification||"unknown",triggered_rules:Q.triggered_rules||[]};if(this.lastScore=X,this.config.onScoreUpdate?.(X),this.handleScoreUpdate(X),this.formProtectionManager)this.formProtectionManager.notifyReady(X.bot_score);if(this.cookieManager)this.cookieManager.setCookie();this.log("Initial score received:",X.bot_score,"in",(K.getTimings().initialScoreReceived??0)-(K.getTimings().startCalled??0),"ms from start")}}handleScoreUpdate(Q){if(this.cookieManager)this.cookieManager.updateRiskTier(Q.bot_score);let X=this.getBotScoreLevel(Q.bot_score),Y=Q.bot_score>=this.config.actionThreshold;if(this.shouldTriggerAlert(X)){let Z={score:Q.bot_score,level:X,scoreUpdate:Q,sessionId:this.sessionId,fingerprintHash:this.fingerprint?.hash};if(Y&&!this.highScoreTriggeredLevels.has(X))this.executeAction(Z);this.config.onHighBotScore?.(Z),this.highScoreTriggeredLevels.add(X)}}getBotScoreLevel(Q){let X=this.config.botScoreThresholds;if(Q>=X.critical)return"critical";if(Q>=X.high)return"high";if(Q>=X.medium)return"medium";return"low"}shouldTriggerAlert(Q){if(this.highScoreTriggeredLevels.has(Q))return!1;let X=["low","medium","high","critical"],Y=this.config.minAlertLevel,Z=X.indexOf(Q),$=X.indexOf(Y);return Z>=$}async executeAction(Q){let X=this.config.action;switch(this.log(`Executing action '${X}' for score ${Q.score}`),X){case"challenge":if(this.challengeManagerPromise)await this.challengeManagerPromise;if(this.challengeManager)this.challengeManager.blockFormsUntilSolved(Q.level);break;case"block":if(!this.formBlocked)this.blockForms();break;case"none":default:break}}blockForms(){if(this.formBlocked)return;this.formBlocked=!0,document.querySelectorAll("form").forEach((Q)=>{Q.addEventListener("submit",this.blockFormSubmit,!0)}),this.formObserver=new MutationObserver((Q)=>{Q.forEach((X)=>{X.addedNodes.forEach((Y)=>{if(Y instanceof HTMLFormElement)Y.addEventListener("submit",this.blockFormSubmit,!0);if(Y instanceof HTMLElement)Y.querySelectorAll("form").forEach((Z)=>{Z.addEventListener("submit",this.blockFormSubmit,!0)})})})}),this.formObserver.observe(document.body,{childList:!0,subtree:!0}),this.log("Forms blocked due to high bot score")}blockFormSubmit=(Q)=>{Q.preventDefault(),Q.stopPropagation(),this.log("Form submission blocked due to high bot score");return};isFormsBlocked(){return this.formBlocked}unblockForms(){if(!this.formBlocked)return;if(this.formObserver)this.formObserver.disconnect(),this.formObserver=null;document.querySelectorAll("form").forEach((Q)=>{Q.removeEventListener("submit",this.blockFormSubmit,!0)}),this.formBlocked=!1,this.log("Forms unblocked")}getHashModule(){return this.hashModule}createSignature(Q){let X=this.config.hashVerification.secret;if(!X)return this.log("Cannot create signature: no secret configured"),null;return createSignature(Q,X)}verifySignature(Q,X){let Y=this.config.hashVerification.secret;if(!Y)return this.log("Cannot verify signature: no secret configured"),!1;return verifySignature(Q,X,Y)}isChallengeSolving(){return this.challengeManager?.isSolving()??!1}isChallengeSolved(){return this.challengeManager?.isSolved()??!1}getPerformanceSummary(){return K.getSummary()}logPerformance(){K.logSummary()}getPerformanceReport(){return K.getReport()}async waitUntilReady(){if(this.lastScore)return{score:this.lastScore.bot_score,timedOut:!1};if(this.formProtectionManager)return this.formProtectionManager.waitUntilReady();return new Promise((Q)=>{let X=performance.now(),Y=5000,Z=()=>{if(this.lastScore){Q({score:this.lastScore.bot_score,timedOut:!1});return}if(performance.now()-X>=5000){Q({score:null,timedOut:!0});return}setTimeout(Z,50)};Z()})}withProtection(Q,X={}){let Y=X.blockThreshold??this.config.actionThreshold;return async(...Z)=>{let{score:$,timedOut:J}=await this.waitUntilReady();if(K.markFirstSubmitAttempt($!==null),$!==null&&$>=Y)throw this.log(`Blocking submission: score ${$} >= threshold ${Y}`),Error(`Submission blocked: bot score ${$} exceeds threshold`);if(J)this.log("Warning: submitting without detection score (timed out)");return Q(...Z)}}protectedFetch(Q={}){return this.withProtection(async(X,Y)=>{return fetch(X,Y)},Q)}canSubmit(){if(!this.lastScore)return{allowed:!1,reason:"waiting_for_score",score:null};if(this.lastScore.bot_score>=this.config.actionThreshold)return{allowed:!1,reason:"high_bot_score",score:this.lastScore.bot_score};return{allowed:!0,score:this.lastScore.bot_score}}async triggerChallenge(Q="high"){if(this.challengeManagerPromise)await this.challengeManagerPromise;if(!this.challengeManager){this.log("Challenge not enabled");return}this.challengeManager.blockFormsUntilSolved(Q)}async disconnect(){if(this.socket)await this.socket.leaveChannel(),this.socket.disconnect(),this.socket=null}startSendInterval(){this.stopSendInterval(),this.sendTimer=setInterval(()=>{this.sendSignal()},this.config.sendInterval)}stopSendInterval(){if(this.sendTimer)clearInterval(this.sendTimer),this.sendTimer=null}registerBeforeUnload(){this.boundBeforeUnload=()=>{this.handleBeforeUnload()},this.boundVisibilityChange=()=>{if(document.visibilityState==="hidden")this.handleBeforeUnload()},window.addEventListener("beforeunload",this.boundBeforeUnload),document.addEventListener("visibilitychange",this.boundVisibilityChange)}unregisterBeforeUnload(){if(this.boundBeforeUnload)window.removeEventListener("beforeunload",this.boundBeforeUnload),this.boundBeforeUnload=null;if(this.boundVisibilityChange)document.removeEventListener("visibilitychange",this.boundVisibilityChange),this.boundVisibilityChange=null}handleBeforeUnload(){if(!this.isRunning||!this.socket)return;try{let Q=this.buildPayload();if(this.socket.isReady())this.socket.sendSignal(Q).catch(()=>{})}catch{}}handleFormSubmit(){if(!this.isRunning)return;if(K.markFirstSubmitAttempt(this.lastScore!==null),this.log("Form submitted, flushing signals via beacon"),this.log("Had score before submit:",this.lastScore!==null),this.updateFormStatus("completed"),!this.sessionId){this.log("No session ID yet, cannot send beacon");return}let Q=this.buildPayload();if(!this.sendViaBeacon(Q))this.sendSignal().catch((Y)=>{this.log("Failed to flush signals on form submit",Y)});else this.mouseCollector.flush(),this.scrollCollector.flush(),this.formCollector.flush()}sendViaBeacon(Q){if(!navigator.sendBeacon)return this.log("sendBeacon not available"),!1;try{let X=new URL(this.config.endpoint),Y=`${X.protocol==="wss:"?"https:":"http:"}//${X.host}/api/signal`,Z=JSON.stringify({session_id:this.sessionId,api_key:this.config.apiKey,payload:Q,form_status:this.formSubmissionStatus}),$=new Blob([Z],{type:"application/json"}),J=navigator.sendBeacon(Y,$);return this.log("Beacon sent:",J),J}catch(X){return this.log("Beacon send failed:",X),!1}}buildPayload(){this.sequenceNumber++;let Q={session_id:this.sessionId,seq:this.sequenceNumber,mouse:this.mouseCollector.getSignal(),scroll:this.scrollCollector.getSignal(),form:this.formCollector.getSignal(),timestamp:Date.now()};if(!this.hasSentInitial)Q.session=this.getSessionData(),Q.fingerprint=this.fingerprint,Q.browser=this.browserSignal;return Q}getSessionData(){let Q=new URL(window.location.href),X={};Q.searchParams.forEach((Z,$)=>{X[$]=Z});let Y=null;if(document.referrer)try{Y=new URL(document.referrer).hostname}catch{}return{url_path:Q.pathname,url_params:X,referrer_url:document.referrer||null,referrer_domain:Y,user_agent:navigator.userAgent}}generateSessionId(){if(crypto.randomUUID)return crypto.randomUUID();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(Q)=>{let X=Math.random()*16|0;return(Q==="x"?X:X&3|8).toString(16)})}updateFormStatus(Q){if(this.formSubmissionStatus==="challenged"||this.formSubmissionStatus==="flagged"||this.formSubmissionStatus==="blocked"||this.formSubmissionStatus==="completed"){this.log(`Form status already terminal (${this.formSubmissionStatus}), ignoring ${Q}`);return}if(this.formSubmissionStatus=Q,this.log(`Form status updated to: ${Q}`),this.socket?.isReady())this.socket.sendFormStatus(Q).catch((X)=>{this.log("Failed to send form status:",X)})}log(...Q){if(this.config.debug);}}var O=null;function xQ(Q){if(O)return O;return O=new S(Q),O}function CQ(){return O}async function LQ(){if(O)await O.stop(),O=null}var AQ=S;export{f as logPerformanceSummary,kQ as loadHashModule,T as isUsageLimitError,xQ as init,l as getPerformanceSummary,N as getPerformanceMetrics,CQ as getInstance,LQ as destroy,AQ as default,q as DEFAULT_CONFIG,S as BotSigged};
41
41
 
42
- //# debugId=7176A7404A75914864756E2164756E21
42
+ //# debugId=1DB83A96804B237464756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botsigged/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "BotSigged SDK - Real-time bot detection via WebSocket",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",