@ztimson/momentum 1.5.7 → 1.5.9

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
@@ -239,30 +239,37 @@
239
239
  if (type == "function") return target.toString() == values.toString();
240
240
  return target == values;
241
241
  }
242
- function isEqual(a, b, seen = /* @__PURE__ */ new WeakMap()) {
243
- if (a === b) return true;
244
- if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
245
- if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
246
- if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
247
- if (Number.isNaN(a) && Number.isNaN(b)) return true;
248
- if (typeof a === "function" && typeof b === "function") return a.toString() === b.toString();
249
- return false;
250
- }
251
- if (seen.has(a)) return seen.get(a) === b;
252
- seen.set(a, b);
253
- const isArrayA = Array.isArray(a);
254
- const isArrayB = Array.isArray(b);
255
- if (isArrayA && isArrayB) {
256
- if (a.length !== b.length) return false;
257
- for (let i = 0; i < a.length; i++) if (!isEqual(a[i], b[i], seen)) return false;
242
+ function isEqual(a, b, compare) {
243
+ const eq = (a2, b2, compare2, seen, path) => {
244
+ if (Array.isArray(compare2)) {
245
+ if (compare2.some((p) => new RegExp(`^${p.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^.]*")}(\\.|$)`).test(path))) return true;
246
+ } else if (typeof compare2 === "function") {
247
+ const r = compare2(path, a2, b2);
248
+ if (r !== void 0) return r;
249
+ }
250
+ if (a2 === b2) return true;
251
+ if (a2 instanceof Date && b2 instanceof Date) return a2.getTime() === b2.getTime();
252
+ if (a2 instanceof RegExp && b2 instanceof RegExp) return a2.source === b2.source && a2.flags === b2.flags;
253
+ if (typeof a2 !== "object" || a2 === null || typeof b2 !== "object" || b2 === null) {
254
+ if (Number.isNaN(a2) && Number.isNaN(b2)) return true;
255
+ if (typeof a2 === "function" && typeof b2 === "function") return a2.toString() === b2.toString();
256
+ return false;
257
+ }
258
+ if (seen.has(a2)) return seen.get(a2) === b2;
259
+ seen.set(a2, b2);
260
+ const isArrayA = Array.isArray(a2), isArrayB = Array.isArray(b2);
261
+ if (isArrayA && isArrayB) {
262
+ if (a2.length !== b2.length) return false;
263
+ for (let i = 0; i < a2.length; i++) if (!eq(a2[i], b2[i], compare2, seen, path ? `${path}.${i}` : `${i}`)) return false;
264
+ return true;
265
+ }
266
+ if (isArrayA !== isArrayB) return false;
267
+ const keysA = Object.keys(a2), keysB = Object.keys(b2);
268
+ if (keysA.length !== keysB.length) return false;
269
+ for (const key of keysA) if (!Object.prototype.hasOwnProperty.call(b2, key) || !eq(a2[key], b2[key], compare2, seen, path ? `${path}.${key}` : key)) return false;
258
270
  return true;
259
- }
260
- if (isArrayA !== isArrayB) return false;
261
- const keysA = Object.keys(a);
262
- const keysB = Object.keys(b);
263
- if (keysA.length !== keysB.length) return false;
264
- for (const key of keysA) if (!Object.prototype.hasOwnProperty.call(b, key) || !isEqual(a[key], b[key], seen)) return false;
265
- return true;
271
+ };
272
+ return eq(a, b, compare, /* @__PURE__ */ new WeakMap(), "");
266
273
  }
267
274
  var ASet = class ASet extends Array {
268
275
  /** Number of elements in set */
@@ -1137,34 +1144,88 @@
1137
1144
  };
1138
1145
  var PromiseProgress = class PromiseProgress extends Promise {
1139
1146
  listeners = [];
1140
- _progress = 0;
1147
+ _meta = {
1148
+ start: Date.now(),
1149
+ end: null,
1150
+ elapsed: 0,
1151
+ speed: 0,
1152
+ progress: 0,
1153
+ size: 0,
1154
+ total: 0,
1155
+ eta: null
1156
+ };
1157
+ get meta() {
1158
+ return this._meta;
1159
+ }
1160
+ get start() {
1161
+ return this._meta.start;
1162
+ }
1163
+ get end() {
1164
+ return this._meta.end;
1165
+ }
1166
+ get elapsed() {
1167
+ return this._meta.elapsed;
1168
+ }
1169
+ get speed() {
1170
+ return this._meta.speed;
1171
+ }
1141
1172
  get progress() {
1142
- return this._progress;
1173
+ return this._meta.progress;
1143
1174
  }
1144
- set progress(p) {
1145
- if (p == this._progress) return;
1146
- this._progress = p;
1147
- this.listeners.forEach((l) => l(p));
1175
+ get size() {
1176
+ return this._meta.size;
1177
+ }
1178
+ get total() {
1179
+ return this._meta.total;
1180
+ }
1181
+ get eta() {
1182
+ return this._meta.eta;
1183
+ }
1184
+ update(size, total) {
1185
+ const elapsed = (Date.now() - this._meta.start) / 1e3;
1186
+ const speed = elapsed ? size / elapsed : 0;
1187
+ const progress = total ? size / total : this._meta.progress;
1188
+ this._meta = {
1189
+ ...this._meta,
1190
+ size,
1191
+ total,
1192
+ progress,
1193
+ elapsed,
1194
+ speed,
1195
+ eta: speed && total ? (total - size) / speed : null
1196
+ };
1197
+ (this.listeners ||= []).forEach((l) => l(this._meta));
1148
1198
  }
1149
1199
  constructor(executor) {
1150
- super((resolve, reject) => executor((value) => resolve(value), (reason) => reject(reason), (progress) => this.progress = progress));
1200
+ super((resolve, reject) => executor((value) => {
1201
+ this._meta = {
1202
+ ...this._meta,
1203
+ end: Date.now()
1204
+ };
1205
+ resolve(value);
1206
+ }, (reason) => {
1207
+ this._meta = {
1208
+ ...this._meta,
1209
+ end: Date.now()
1210
+ };
1211
+ reject(reason);
1212
+ }, (size, total) => this.update(size, total ?? this._meta.total)));
1151
1213
  }
1152
1214
  static from(promise) {
1153
1215
  if (promise instanceof PromiseProgress) return promise;
1154
- return new PromiseProgress((res, rej) => promise.then((...args) => res(...args)).catch((...args) => rej(...args)));
1216
+ return new PromiseProgress((res, rej) => promise.then(res).catch(rej));
1155
1217
  }
1156
1218
  from(promise) {
1157
1219
  const newPromise = PromiseProgress.from(promise);
1158
- this.onProgress((p) => newPromise.progress = p);
1220
+ this.onProgress((m) => newPromise.update(m.size, m.total));
1159
1221
  return newPromise;
1160
1222
  }
1161
1223
  onProgress(callback) {
1162
- this.listeners.push(callback);
1224
+ (this.listeners ||= []).push(callback);
1163
1225
  return this;
1164
1226
  }
1165
1227
  then(res, rej) {
1166
- const resp = super.then(res, rej);
1167
- return this.from(resp);
1228
+ return this.from(super.then(res, rej));
1168
1229
  }
1169
1230
  catch(rej) {
1170
1231
  return this.from(super.catch(rej));
@@ -1213,7 +1274,7 @@
1213
1274
  const formData2 = new FormData();
1214
1275
  options.files.forEach((f) => formData2.append("files", f));
1215
1276
  xhr.withCredentials = !!options.withCredentials;
1216
- xhr.upload.addEventListener("progress", (event) => event.lengthComputable ? prog(event.loaded / event.total) : null);
1277
+ xhr.upload.addEventListener("progress", (event) => event.lengthComputable ? prog(event.loaded, event.total) : null);
1217
1278
  xhr.addEventListener("loadend", () => res(JSONAttemptParse(xhr.responseText)));
1218
1279
  xhr.addEventListener("error", () => rej(JSONAttemptParse(xhr.responseText)));
1219
1280
  xhr.addEventListener("timeout", () => rej({ error: "Request timed out" }));
@@ -2251,6 +2312,182 @@
2251
2312
  }
2252
2313
  };
2253
2314
  //#endregion
2315
+ //#region src/captcha.ts
2316
+ var Captcha = class {
2317
+ start = Date.now();
2318
+ events = {
2319
+ mouse: [],
2320
+ keys: [],
2321
+ clicks: [],
2322
+ scroll: [],
2323
+ focus: []
2324
+ };
2325
+ lastMouse = null;
2326
+ velocities = [];
2327
+ _score = .5;
2328
+ onScoreChange;
2329
+ set score(v) {
2330
+ const next = +Math.max(0, Math.min(1, Number.isFinite(v) ? v : .5)).toFixed(2);
2331
+ if (next == this._score) return;
2332
+ this._score = next;
2333
+ this.onScoreChange?.(next);
2334
+ }
2335
+ get score() {
2336
+ return this._score;
2337
+ }
2338
+ get verdict() {
2339
+ if (this.score >= .45 && this.score <= .55) return "unknown";
2340
+ if (this.score > .5) return "human";
2341
+ return "bot";
2342
+ }
2343
+ constructor(onScoreChange) {
2344
+ this.onScoreChange = onScoreChange;
2345
+ if (typeof window === "undefined" || !document) {
2346
+ this._score = 0;
2347
+ return;
2348
+ }
2349
+ document.addEventListener("pointermove", (e) => {
2350
+ const now = Date.now();
2351
+ const curr = {
2352
+ x: e.clientX,
2353
+ y: e.clientY,
2354
+ t: now
2355
+ };
2356
+ this.events.mouse.push(curr);
2357
+ if (this.lastMouse) {
2358
+ const dt = now - this.lastMouse.t;
2359
+ const dx = curr.x - this.lastMouse.x;
2360
+ const dy = curr.y - this.lastMouse.y;
2361
+ const dist = Math.sqrt(dx * dx + dy * dy);
2362
+ if (dt > 0 && dt < 1e3) this.velocities.push(dist / dt);
2363
+ }
2364
+ this.lastMouse = curr;
2365
+ if (this.events.mouse.length > 80) this.events.mouse.shift();
2366
+ if (this.velocities.length > 40) this.velocities.shift();
2367
+ }, { passive: true });
2368
+ document.addEventListener("keydown", () => {
2369
+ this.events.keys.push(Date.now());
2370
+ if (this.events.keys.length > 30) this.events.keys.shift();
2371
+ this.update();
2372
+ });
2373
+ document.addEventListener("pointerdown", (e) => {
2374
+ this.events.clicks.push({
2375
+ x: e.clientX,
2376
+ y: e.clientY,
2377
+ t: Date.now()
2378
+ });
2379
+ if (this.events.clicks.length > 20) this.events.clicks.shift();
2380
+ this.update();
2381
+ }, { passive: true });
2382
+ window.addEventListener("scroll", () => {
2383
+ this.events.scroll.push({
2384
+ x: window.scrollX,
2385
+ y: window.scrollY,
2386
+ t: Date.now()
2387
+ });
2388
+ if (this.events.scroll.length > 20) this.events.scroll.shift();
2389
+ }, { passive: true });
2390
+ document.addEventListener("visibilitychange", () => {
2391
+ this.events.focus.push({
2392
+ visible: document.visibilityState == "visible",
2393
+ t: Date.now()
2394
+ });
2395
+ if (this.events.focus.length > 20) this.events.focus.shift();
2396
+ this.update();
2397
+ });
2398
+ window.addEventListener("focus", () => {
2399
+ this.events.focus.push({
2400
+ visible: true,
2401
+ t: Date.now()
2402
+ });
2403
+ this.update();
2404
+ });
2405
+ window.addEventListener("blur", () => {
2406
+ this.events.focus.push({
2407
+ visible: false,
2408
+ t: Date.now()
2409
+ });
2410
+ this.update();
2411
+ });
2412
+ setInterval(() => this.update(), 2e3);
2413
+ }
2414
+ update() {
2415
+ if (navigator?.webdriver) {
2416
+ this._score = 0;
2417
+ this.onScoreChange?.(0);
2418
+ return;
2419
+ }
2420
+ let delta = 0;
2421
+ const elapsed = (Date.now() - this.start) / 1e3;
2422
+ delta += elapsed > 30 ? .08 : elapsed > 10 ? .04 : elapsed > 3 ? .01 : -.05;
2423
+ if (this.events.mouse.length >= 6) {
2424
+ const recent = this.events.mouse.slice(-30);
2425
+ const buckets = new Array(8).fill(0);
2426
+ for (let i = 1; i < recent.length; i++) {
2427
+ const dx = recent[i].x - recent[i - 1].x;
2428
+ const dy = recent[i].y - recent[i - 1].y;
2429
+ if (dx == 0 && dy == 0) continue;
2430
+ let angle = Math.atan2(dy, dx);
2431
+ if (angle < 0) angle += Math.PI * 2;
2432
+ buckets[Math.min(7, Math.floor(angle / (Math.PI * 2) * 8))]++;
2433
+ }
2434
+ const total = buckets.reduce((a, b) => a + b, 0);
2435
+ if (total >= 4) {
2436
+ let entropy = 0;
2437
+ for (const count of buckets) {
2438
+ if (!count) continue;
2439
+ const p = count / total;
2440
+ entropy -= p * Math.log2(p);
2441
+ }
2442
+ entropy /= Math.log2(8);
2443
+ if (entropy > .65) delta += .12;
2444
+ else if (entropy > .4) delta += .05;
2445
+ else delta -= .07;
2446
+ }
2447
+ } else if (this.events.mouse.length == 0) delta -= .01;
2448
+ if (this.velocities.length >= 5) {
2449
+ const avg = this.velocities.reduce((a, b) => a + b, 0) / this.velocities.length;
2450
+ const variance = this.velocities.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / this.velocities.length;
2451
+ const cv = avg > 0 ? Math.sqrt(variance) / avg : 0;
2452
+ if (cv > .45) delta += .1;
2453
+ else if (cv > .18) delta += .04;
2454
+ else if (avg > 0) delta -= .08;
2455
+ }
2456
+ if (this.events.clicks.length > 0) {
2457
+ const lastClick = this.events.clicks.at(-1);
2458
+ const mouseBeforeClick = this.events.mouse.some((m) => m.t < lastClick.t && lastClick.t - m.t < 2e3);
2459
+ delta += mouseBeforeClick ? .06 : -.08;
2460
+ const suspiciousClicks = this.events.clicks.filter((c) => Number.isInteger(c.x) && Number.isInteger(c.y) && c.x % 10 == 0 && c.y % 10 == 0).length;
2461
+ if (this.events.clicks.length >= 4 && suspiciousClicks / this.events.clicks.length > .5) delta -= .06;
2462
+ }
2463
+ if (this.events.keys.length >= 4) {
2464
+ const intervals = [];
2465
+ for (let i = 1; i < this.events.keys.length; i++) intervals.push(this.events.keys[i] - this.events.keys[i - 1]);
2466
+ const avg = intervals.reduce((a, b) => a + b, 0) / intervals.length;
2467
+ const stdDev = Math.sqrt(intervals.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / intervals.length);
2468
+ if (avg < 20) delta -= .15;
2469
+ else if (stdDev < 5) delta -= .1;
2470
+ else if (avg < 50) delta -= .04;
2471
+ else if (avg < 1e3 && stdDev > 20) delta += .08;
2472
+ }
2473
+ if (this.events.scroll.length >= 4) {
2474
+ let directionChanges = 0;
2475
+ let previousDirection = 0;
2476
+ for (let i = 1; i < this.events.scroll.length; i++) {
2477
+ const direction = Math.sign(this.events.scroll[i].y - this.events.scroll[i - 1].y);
2478
+ if (direction && previousDirection && direction != previousDirection) directionChanges++;
2479
+ if (direction) previousDirection = direction;
2480
+ }
2481
+ if (directionChanges >= 2) delta += .04;
2482
+ }
2483
+ if (this.events.focus.length >= 2) {
2484
+ const visible = this.events.focus.filter((x) => x.visible).length;
2485
+ delta += visible / this.events.focus.length > .4 ? .02 : -.02;
2486
+ }
2487
+ this.score = this.score + delta * .25;
2488
+ }
2489
+ };
2490
+ //#endregion
2254
2491
  //#region src/dialog.ts
2255
2492
  var dialogCount = 0;
2256
2493
  var closed = 0;
@@ -2463,6 +2700,16 @@
2463
2700
  var Analytics = class extends AssetController {
2464
2701
  momentum;
2465
2702
  lastPage;
2703
+ captcha = new Captcha((score) => this.updateCaptcha(score));
2704
+ captchaSecret;
2705
+ captchaSequence = 0;
2706
+ captchaUpdate;
2707
+ get captchaScore() {
2708
+ return this.captcha.score;
2709
+ }
2710
+ get actorType() {
2711
+ return this.captcha.verdict;
2712
+ }
2466
2713
  _ready;
2467
2714
  ready = new Promise((res) => this._ready = res);
2468
2715
  _performance = {
@@ -2541,6 +2788,9 @@
2541
2788
  this._id = "";
2542
2789
  this._consent = void 0;
2543
2790
  this._new = true;
2791
+ this.captchaSecret = void 0;
2792
+ this.captchaSequence = 0;
2793
+ delete this.momentum.api.headers["X-Captcha"];
2544
2794
  });
2545
2795
  this.momentum.auth.on("login:c", async () => {
2546
2796
  if (this.consent) await this.init();
@@ -2617,7 +2867,7 @@
2617
2867
  async init() {
2618
2868
  if (!this.momentum.opts.analytics) return;
2619
2869
  const performance = await this.performance;
2620
- this.id = await this.momentum.api.request({
2870
+ const response = await this.momentum.api.request({
2621
2871
  url: `api/analytics`,
2622
2872
  body: [
2623
2873
  navigator?.language,
@@ -2635,6 +2885,10 @@
2635
2885
  performance.total
2636
2886
  ]
2637
2887
  });
2888
+ this.id = response.id;
2889
+ this.captchaSecret = response.captchaSecret;
2890
+ this.captchaSequence = response.captchaSequence;
2891
+ await this.updateCaptcha(this.captcha.score, true);
2638
2892
  if (this._ready) {
2639
2893
  this._ready();
2640
2894
  this._ready = null;
@@ -2644,6 +2898,25 @@
2644
2898
  window.addEventListener("beforeunload", () => this.page("CLOSED"));
2645
2899
  return this.id;
2646
2900
  }
2901
+ updateCaptcha(score, initial = false) {
2902
+ if (!this.captchaSecret || !this.id || !globalThis.crypto?.subtle) return Promise.resolve();
2903
+ const update = this.captchaUpdate?.catch(() => {}) || Promise.resolve();
2904
+ this.captchaUpdate = update.then(() => this.attestCaptcha(score, initial)).catch(() => {});
2905
+ return this.captchaUpdate;
2906
+ }
2907
+ async attestCaptcha(score, initial) {
2908
+ if (!this.captchaSecret || !this.id) return;
2909
+ if (!initial) this.captchaSequence++;
2910
+ const canonical = Math.max(0, Math.min(1, Number.isFinite(score) ? score : .5)).toFixed(2);
2911
+ const payload = `${canonical}:${this.captchaSequence}`;
2912
+ const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(this.captchaSecret), {
2913
+ name: "HMAC",
2914
+ hash: "SHA-256"
2915
+ }, false, ["sign"]);
2916
+ const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(payload));
2917
+ const proof = btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2918
+ this.momentum.api.headers["X-Captcha"] = `${canonical},${this.captchaSequence},${proof}`;
2919
+ }
2647
2920
  async consentPrompt(content) {
2648
2921
  const settings = await this.momentum.settings.map();
2649
2922
  const { close, dialog, result } = createDialog(`
@@ -3017,19 +3290,29 @@
3017
3290
  loginRedirect(host = location.origin) {
3018
3291
  return new Promise((res, rej) => {
3019
3292
  let listener, win;
3293
+ const loginOrigin = new URL(this.momentum.opts.loginUrl, location.href).origin;
3294
+ const hostOrigin = new URL(host, location.href).origin;
3020
3295
  window.addEventListener("message", listener = async (event) => {
3296
+ if (event.origin !== loginOrigin || event?.data?.sender !== loginOrigin) return;
3021
3297
  const data = event?.data || {};
3022
- if (event.origin != origin || data.sender != origin) return;
3023
- if (!data.token) return rej("Unknown response from login");
3298
+ if (!data.token) {
3299
+ window.removeEventListener("message", listener);
3300
+ return rej(/* @__PURE__ */ new Error("Unknown response from login"));
3301
+ }
3024
3302
  window.removeEventListener("message", listener);
3025
- await this.readSession(data.token, true);
3026
- win.close();
3027
- res(data.token);
3303
+ try {
3304
+ await this.readSession(data.token, true);
3305
+ win?.close();
3306
+ res(data.token);
3307
+ } catch (err) {
3308
+ win?.close();
3309
+ rej(err);
3310
+ }
3028
3311
  });
3029
- win = window.open(`${this.momentum.opts.loginUrl}?redirect=postmessage&host=${encodeURI(host)}`, "_blank");
3312
+ win = window.open(`${this.momentum.opts.loginUrl}?redirect=postmessage&host=${encodeURIComponent(hostOrigin)}`, "_blank");
3030
3313
  if (!win) {
3031
3314
  window.removeEventListener("message", listener);
3032
- return rej("Unable to open login");
3315
+ return rej(/* @__PURE__ */ new Error("Unable to open login"));
3033
3316
  }
3034
3317
  });
3035
3318
  }
@@ -3155,174 +3438,20 @@
3155
3438
  }
3156
3439
  };
3157
3440
  //#endregion
3158
- //#region src/captcha.ts
3159
- var Captcha = class {
3160
- start = Date.now();
3161
- events = {
3162
- mouse: [],
3163
- keys: [],
3164
- clicks: []
3165
- };
3166
- lastMouse = null;
3167
- velocities = [];
3168
- _score = .5;
3169
- set score(v) {
3170
- this._score = v;
3171
- }
3172
- get score() {
3173
- return this._score;
3174
- }
3175
- get verdict() {
3176
- if (this.score == .5) return "unknown";
3177
- if (this.score > .5) return "human";
3178
- return "bot";
3179
- }
3180
- constructor() {
3181
- if (typeof window === "undefined" || !window.innerWidth || !this.validUserAgent()) {
3182
- this.score = 0;
3183
- return;
3184
- }
3185
- document.addEventListener("mousemove", (e) => {
3186
- const now = Date.now();
3187
- const curr = {
3188
- x: e.clientX,
3189
- y: e.clientY,
3190
- t: now
3191
- };
3192
- this.events.mouse.push(curr);
3193
- if (this.lastMouse) {
3194
- const dt = now - this.lastMouse.t;
3195
- const dx = curr.x - this.lastMouse.x;
3196
- const dy = curr.y - this.lastMouse.y;
3197
- const dist = Math.sqrt(dx * dx + dy * dy);
3198
- if (dt > 0) this.velocities.push(dist / dt);
3199
- }
3200
- this.lastMouse = curr;
3201
- if (this.events.mouse.length > 50) this.events.mouse.shift();
3202
- if (this.velocities.length > 30) this.velocities.shift();
3203
- });
3204
- document.addEventListener("keydown", (e) => {
3205
- this.events.keys.push(Date.now());
3206
- if (this.events.keys.length > 20) this.events.keys.shift();
3207
- });
3208
- document.addEventListener("click", (e) => {
3209
- this.events.clicks.push({
3210
- x: e.clientX,
3211
- y: e.clientY,
3212
- t: Date.now()
3213
- });
3214
- if (this.events.clicks.length > 15) this.events.clicks.shift();
3215
- });
3216
- setInterval(() => this.update(), 1e3);
3217
- }
3218
- validUserAgent() {
3219
- if (!navigator?.userAgent) return false;
3220
- const ua = navigator.userAgent.toLowerCase();
3221
- if ([
3222
- "bot",
3223
- "crawler",
3224
- "spider",
3225
- "scraper",
3226
- "headless",
3227
- "phantom",
3228
- "selenium",
3229
- "webdriver",
3230
- "puppeteer",
3231
- "playwright",
3232
- "cypress",
3233
- "automation"
3234
- ].some((pattern) => ua.includes(pattern))) return false;
3235
- if (![
3236
- "chrome",
3237
- "firefox",
3238
- "safari",
3239
- "edge",
3240
- "opera"
3241
- ].some((browser) => ua.includes(browser))) return false;
3242
- if (![
3243
- "windows",
3244
- "mac",
3245
- "linux",
3246
- "android",
3247
- "ios"
3248
- ].some((os) => ua.includes(os))) return false;
3249
- return ua.length > 20 && ua.length < 1e3;
3250
- }
3251
- update() {
3252
- if (navigator.webdriver) {
3253
- this.score = 0;
3254
- return;
3255
- }
3256
- let delta = 0;
3257
- const elapsed = (Date.now() - this.start) / 1e3;
3258
- delta += elapsed > 30 ? .08 : elapsed > 10 ? .04 : elapsed > 3 ? .01 : -.05;
3259
- if (this.events.mouse.length >= 5) {
3260
- const recent = this.events.mouse.slice(-20);
3261
- let changes = 0;
3262
- let maxStraightRun = 0;
3263
- let currentRun = 0;
3264
- for (let i = 2; i < recent.length; i++) {
3265
- const a1 = Math.atan2(recent[i - 1].y - recent[i - 2].y, recent[i - 1].x - recent[i - 2].x);
3266
- const a2 = Math.atan2(recent[i].y - recent[i - 1].y, recent[i].x - recent[i - 1].x);
3267
- if (Math.abs(a1 - a2) > .3) {
3268
- changes++;
3269
- currentRun = 0;
3270
- } else {
3271
- currentRun++;
3272
- maxStraightRun = Math.max(maxStraightRun, currentRun);
3273
- }
3274
- }
3275
- const entropy = changes / (recent.length - 2);
3276
- if (entropy > .4) delta += .12;
3277
- else if (entropy > .2) delta += .05;
3278
- else delta -= .08;
3279
- if (maxStraightRun > 8) delta -= .1;
3280
- } else if (this.events.mouse.length === 0) delta -= .03;
3281
- if (this.velocities.length >= 5) {
3282
- const avg = this.velocities.reduce((a, b) => a + b, 0) / this.velocities.length;
3283
- const variance = this.velocities.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / this.velocities.length;
3284
- const cv = avg > 0 ? Math.sqrt(variance) / avg : 0;
3285
- if (cv > .4) delta += .1;
3286
- else if (cv > .15) delta += .04;
3287
- else if (avg > 0) delta -= .1;
3288
- }
3289
- if (this.events.clicks.length > 0) {
3290
- const lastClick = this.events.clicks[this.events.clicks.length - 1];
3291
- const mouseBeforeClick = this.events.mouse.some((m) => m.t < lastClick.t && lastClick.t - m.t < 2e3);
3292
- delta += mouseBeforeClick ? .08 : -.12;
3293
- if (this.events.clicks.filter((c) => Number.isInteger(c.x) && Number.isInteger(c.y) && c.x % 10 === 0 && c.y % 10 === 0).length / this.events.clicks.length > .5) delta -= .08;
3294
- }
3295
- if (this.events.keys.length >= 3) {
3296
- const intervals = [];
3297
- for (let i = 1; i < this.events.keys.length; i++) intervals.push(this.events.keys[i] - this.events.keys[i - 1]);
3298
- const avg = intervals.reduce((a, b) => a + b, 0) / intervals.length;
3299
- const stdDev = Math.sqrt(intervals.reduce((a, b) => a + Math.pow(b - avg, 2), 0) / intervals.length);
3300
- if (avg < 20) delta -= .15;
3301
- else if (stdDev < 5) delta -= .12;
3302
- else if (avg < 50) delta -= .05;
3303
- else if (avg < 1e3 && stdDev > 20) delta += .1;
3304
- }
3305
- const raw = this.score + delta;
3306
- this.score = this.score * .75 + raw * .25;
3307
- this.score = Math.max(.05, Math.min(.95, this.score));
3308
- }
3309
- };
3310
- //#endregion
3311
3441
  //#region src/client.ts
3312
3442
  /** Handle device settings */
3313
3443
  var Client = class Client extends PathEventEmitter {
3314
3444
  momentum;
3315
- captcha = new Captcha();
3316
3445
  installTimeout;
3317
3446
  nativePwaPrompt;
3318
3447
  pendingInstall = null;
3319
3448
  speed;
3320
3449
  updating = false;
3321
3450
  get actorType() {
3322
- return this.captcha.verdict;
3451
+ return this.momentum.analytics.actorType;
3323
3452
  }
3324
3453
  get captchaScore() {
3325
- return this.captcha.score;
3454
+ return this.momentum.analytics.captchaScore;
3326
3455
  }
3327
3456
  /** Check for updates */
3328
3457
  updateReady = new Promise((res) => {
@@ -4841,7 +4970,7 @@ ${Object.entries(t).map(([name, value]) => `--theme-${kebabCase(name)}: ${value}
4841
4970
  headers: this.momentum.api.headers,
4842
4971
  files: f
4843
4972
  }).onProgress((p) => {
4844
- prog(p);
4973
+ prog(p.progress);
4845
4974
  }).then((resp) => {
4846
4975
  this.emit(PES`${this.module}/${path}:c`, resp);
4847
4976
  res(resp);
@@ -5019,7 +5148,7 @@ ${Object.entries(t).map(([name, value]) => `--theme-${kebabCase(name)}: ${value}
5019
5148
  };
5020
5149
  //#endregion
5021
5150
  //#region package.json
5022
- var version = "1.5.7";
5151
+ var version = "1.5.9";
5023
5152
  //#endregion
5024
5153
  //#region src/webRtc.ts
5025
5154
  var WebRtc = class extends PathEventEmitter {