@redsocs/spam-warden 1.2.1 → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  (function() {
2
2
  /**
3
- * SpamWarden.js — Client-side spam detection engine
3
+ * SpamWarden.js — endpoint-side spam detection engine
4
4
  * Trained model from spam-labeler (Bernoulli NB)
5
5
  * Zero dependencies. Pure vanilla JS.
6
6
  */
@@ -15,9 +15,14 @@
15
15
  _version: modelData.version,
16
16
  _nFeatures: Object.keys(modelData.vocabulary).length,
17
17
  _absentLogProb: null,
18
- _filters: (filterData && Array.isArray(filterData)) ? filterData.map(codes => {
19
- return Array.isArray(codes) ? String.fromCharCode(...codes.map(c => c + 100)) : codes;
20
- }) : [],
18
+ _filters:
19
+ filterData && Array.isArray(filterData)
20
+ ? filterData.map((codes) => {
21
+ return Array.isArray(codes)
22
+ ? String.fromCharCode(...codes.map((c) => c + 100))
23
+ : codes;
24
+ })
25
+ : [],
21
26
  _checkFilter: function(item) {
22
27
  if (!this._filters || !Array.isArray(this._filters)) return false;
23
28
  const lowerItem = item.toLowerCase();
@@ -44,15 +49,21 @@
44
49
  * Configure the warden for secondary SIEM/SOC reporting.
45
50
  */
46
51
  configure: function(options) {
47
- if (options.endpoint !== undefined) this._config.endpoint = options.endpoint;
48
- if (options.siemEndpoint !== undefined) this._config.siemEndpoint = options.siemEndpoint;
49
- if (options.siteToken !== undefined) this._config.siteToken = options.siteToken;
50
- if (options.payloadLimit !== undefined) this._config.payloadLimit = parseInt(options.payloadLimit, 10) || 250;
52
+ if (options.endpoint !== undefined)
53
+ this._config.endpoint = options.endpoint;
54
+ if (options.siemEndpoint !== undefined)
55
+ this._config.siemEndpoint = options.siemEndpoint;
56
+ if (options.siteToken !== undefined)
57
+ this._config.siteToken = options.siteToken;
58
+ if (options.payloadLimit !== undefined)
59
+ this._config.payloadLimit = parseInt(options.payloadLimit, 10) || 250;
51
60
  this._config.autoReport = !!options.autoReport;
52
61
  this._config.reportSD = !!options.reportSD;
53
62
  this._config.isTrusted = !!options.isTrusted;
54
- if (typeof options.onSpam === "function") this._config.onSpam = options.onSpam;
55
- if (typeof options.customReporter === "function") this._config.customReporter = options.customReporter;
63
+ if (typeof options.onSpam === "function")
64
+ this._config.onSpam = options.onSpam;
65
+ if (typeof options.customReporter === "function")
66
+ this._config.customReporter = options.customReporter;
56
67
  },
57
68
 
58
69
  /**
@@ -76,12 +87,14 @@
76
87
  _bind: function(target) {
77
88
  // Note: With the new document-level capturer, explicit binding is now
78
89
  // primarily used to "register" forms that might not match the auto-discovery heuristic.
79
- const form = (typeof target === "string") ?
80
- (document.getElementById(target) || document.querySelector(`form[name="${target}"]`)) :
81
- target;
82
-
83
- if (form && !form.hasAttribute('data-sw-protected')) {
84
- form.setAttribute('data-sw-protected', 'true');
90
+ const form =
91
+ typeof target === "string"
92
+ ? document.getElementById(target) ||
93
+ document.querySelector(`form[name="${target}"]`)
94
+ : target;
95
+
96
+ if (form && !form.hasAttribute("data-sw-protected")) {
97
+ form.setAttribute("data-sw-protected", "true");
85
98
  }
86
99
  },
87
100
 
@@ -92,22 +105,30 @@
92
105
  this._setupGlobalProtections();
93
106
 
94
107
  const scan = () => {
95
- const forms = Array.from(document.querySelectorAll('form:not([data-sw-protected])'));
96
- forms.forEach(form => {
97
- const inputs = Array.from(form.querySelectorAll('input[type="text"], input:not([type]), textarea'))
98
- .filter(el => {
99
- if (el.type === 'hidden' || el.type === 'password') return false;
100
- return el.offsetWidth > 0 || el.offsetHeight > 0;
101
- });
102
-
108
+ const forms = Array.from(
109
+ document.querySelectorAll("form:not([data-sw-protected])"),
110
+ );
111
+ forms.forEach((form) => {
112
+ const inputs = Array.from(
113
+ form.querySelectorAll(
114
+ 'input[type="text"], input:not([type]), textarea',
115
+ ),
116
+ ).filter((el) => {
117
+ if (el.type === "hidden" || el.type === "password") return false;
118
+ return el.offsetWidth > 0 || el.offsetHeight > 0;
119
+ });
120
+
103
121
  if (inputs.length >= 2) {
104
122
  this._bind(form);
105
123
  }
106
124
  });
107
125
  };
108
126
 
109
- if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", scan); }
110
- else { scan(); }
127
+ if (document.readyState === "loading") {
128
+ document.addEventListener("DOMContentLoaded", scan);
129
+ } else {
130
+ scan();
131
+ }
111
132
  },
112
133
 
113
134
  /**
@@ -123,32 +144,46 @@
123
144
 
124
145
  // 1. Document-Level Capturing Interceptor
125
146
  // Catches submit events before they reach the form, even if cloned or replaced.
126
- document.addEventListener("submit", function(e) {
127
- const form = e.target;
128
- if (!form || form.tagName !== "FORM") return;
129
- if (!form.hasAttribute('data-sw-protected')) return;
130
-
131
- const inputs = Array.from(form.querySelectorAll('input[type="text"], input:not([type]), textarea'))
132
- .filter(el => el.type !== 'hidden' && el.type !== 'password');
133
-
134
- const combinedText = inputs
135
- .map(el => el.value)
136
- .filter(val => val.trim() !== '')
137
- .join('\n');
138
-
139
- const result = self.spamcheck(combinedText, { pasted: hasPasted });
140
- if (result.isSpam) {
141
- e.preventDefault();
142
- e.stopImmediatePropagation(); // Prevent other listeners from firing
143
- if (self._config.onSpam) { self._config.onSpam(result); }
144
- else { alert("Submission Blocked: Spam detected."); }
145
- }
146
- }, true); // TRUE = Capturing Phase
147
+ document.addEventListener(
148
+ "submit",
149
+ function(e) {
150
+ const form = e.target;
151
+ if (!form || form.tagName !== "FORM") return;
152
+ if (!form.hasAttribute("data-sw-protected")) return;
153
+
154
+ const inputs = Array.from(
155
+ form.querySelectorAll(
156
+ 'input[type="text"], input:not([type]), textarea',
157
+ ),
158
+ ).filter((el) => el.type !== "hidden" && el.type !== "password");
159
+
160
+ const combinedText = inputs
161
+ .map((el) => el.value)
162
+ .filter((val) => val.trim() !== "")
163
+ .join("\n");
164
+
165
+ const result = self.spamcheck(combinedText, { pasted: hasPasted });
166
+ if (result.isSpam) {
167
+ e.preventDefault();
168
+ e.stopImmediatePropagation(); // Prevent other listeners from firing
169
+ if (self._config.onSpam) {
170
+ self._config.onSpam(result);
171
+ } else {
172
+ alert("Submission Blocked: Spam detected.");
173
+ }
174
+ }
175
+ },
176
+ true,
177
+ ); // TRUE = Capturing Phase
147
178
 
148
179
  // Global paste tracker
149
- document.addEventListener("paste", function() {
150
- hasPasted = true;
151
- }, true);
180
+ document.addEventListener(
181
+ "paste",
182
+ function() {
183
+ hasPasted = true;
184
+ },
185
+ true,
186
+ );
152
187
 
153
188
  // 2. Prototype Monkey-Patching
154
189
  // Intercepts direct calls to document.forms[0].submit() which skip events.
@@ -156,22 +191,27 @@
156
191
  const originalSubmit = HTMLFormElement.prototype.submit;
157
192
  HTMLFormElement.prototype.submit = function() {
158
193
  const form = this;
159
- if (form.hasAttribute('data-sw-protected')) {
160
- const inputs = Array.from(form.querySelectorAll('input[type="text"], input:not([type]), textarea'))
161
- .filter(el => el.type !== 'hidden' && el.type !== 'password');
162
-
163
- const combinedText = inputs.map(el => el.value).join('\n');
194
+ if (form.hasAttribute("data-sw-protected")) {
195
+ const inputs = Array.from(
196
+ form.querySelectorAll(
197
+ 'input[type="text"], input:not([type]), textarea',
198
+ ),
199
+ ).filter((el) => el.type !== "hidden" && el.type !== "password");
200
+
201
+ const combinedText = inputs.map((el) => el.value).join("\n");
164
202
  const result = self.spamcheck(combinedText, { pasted: hasPasted });
165
203
 
166
204
  if (result.isSpam) {
167
205
  console.warn("[SpamWarden] Blocked programmatic submit() call.");
168
- if (self._config.onSpam) { self._config.onSpam(result); }
206
+ if (self._config.onSpam) {
207
+ self._config.onSpam(result);
208
+ }
169
209
  return;
170
210
  }
171
211
  }
172
212
  originalSubmit.call(form);
173
213
  };
174
- } catch (err) {}
214
+ } catch (err) { }
175
215
 
176
216
  // 3. MutationObserver (Anti-Tampering)
177
217
  // Watches for removal of protected forms or their input fields.
@@ -181,12 +221,19 @@
181
221
  if (m.removedNodes.length > 0) {
182
222
  for (const node of m.removedNodes) {
183
223
  if (node.nodeType !== 1) continue;
184
- if (node.tagName === 'FORM' && node.hasAttribute('data-sw-protected')) {
185
- console.error("[SpamWarden] Critical Error: Protected form was removed from DOM.");
224
+ if (
225
+ node.tagName === "FORM" &&
226
+ node.hasAttribute("data-sw-protected")
227
+ ) {
228
+ console.error(
229
+ "[SpamWarden] Critical Error: Protected form was removed from DOM.",
230
+ );
186
231
  }
187
- if (node.tagName === 'TEXTAREA' || node.tagName === 'INPUT') {
232
+ if (node.tagName === "TEXTAREA" || node.tagName === "INPUT") {
188
233
  // Check if the node belonged to a protected form
189
- console.warn("[SpamWarden] Warning: Input element removal detected.");
234
+ console.warn(
235
+ "[SpamWarden] Warning: Input element removal detected.",
236
+ );
190
237
  }
191
238
  }
192
239
  }
@@ -199,16 +246,22 @@
199
246
  // ── 2. SIEM Internal Reporting & Actor Extraction ────────────────
200
247
  _defang: function(str) {
201
248
  if (!str) return "";
202
- return str.replace(/https?:\/\//gi, "h_tt_p://").replace(/\./g, "[.]").replace(/@/g, "[at]");
249
+ return str
250
+ .replace(/https?:\/\//gi, "h_tt_p://")
251
+ .replace(/\./g, "[.]")
252
+ .replace(/@/g, "[at]");
203
253
  },
204
254
 
205
255
  _sanitizeData: function(text) {
206
256
  if (!text) return { text: "", sd: false };
207
257
  let sd = false;
208
-
209
- const cardRegex = /(?:^|\s|\b)(\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4})(?:\s|\b|$)/g;
210
- const emailRegex = /(?:^|\s|\b)([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})(?:\s|\b|$)/g;
211
- const phoneRegex = /(?:^|\s|\b)(0[-\s]?[2-9](?:[-\s]?\d){7,8})(?:\s|\b|$)/g;
258
+
259
+ const cardRegex =
260
+ /(?:^|\s|\b)(\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4})(?:\s|\b|$)/g;
261
+ const emailRegex =
262
+ /(?:^|\s|\b)([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})(?:\s|\b|$)/g;
263
+ const phoneRegex =
264
+ /(?:^|\s|\b)(0[-\s]?[2-9](?:[-\s]?\d){7,8})(?:\s|\b|$)/g;
212
265
 
213
266
  const t1 = text.replace(cardRegex, " [CARD_MASKED] ");
214
267
  if (t1 !== text) sd = true;
@@ -216,37 +269,54 @@
216
269
  if (t2 !== t1) sd = true;
217
270
  const t3 = t2.replace(phoneRegex, " [PHONE_MASKED] ");
218
271
  if (t3 !== t2) sd = true;
219
-
272
+
220
273
  return { text: t3.trim(), sd: sd };
221
274
  },
222
275
 
223
276
  _report: function(input, result, pastedFlag = false) {
224
- if (!this._config.autoReport || !this._config.siteToken || !this._config.isTrusted) return;
277
+ if (
278
+ !this._config.autoReport ||
279
+ !this._config.siteToken ||
280
+ !this._config.isTrusted
281
+ )
282
+ return;
225
283
 
226
284
  const actors = [];
227
285
  const lineMatches = input.match(/(?:^|\s)(@[A-Za-z0-9_]+)(?=\s|$)/g);
228
286
  if (lineMatches) {
229
- for (let i = 0; i < lineMatches.length; i++) {
230
- actors.push(this._defang(lineMatches[i].trim()));
231
- }
287
+ for (let i = 0; i < lineMatches.length; i++) {
288
+ actors.push(this._defang(lineMatches[i].trim()));
289
+ }
232
290
  }
233
291
 
234
292
  const urlRegex = /https?:\/\/[^\s"<>]+/g;
235
293
  const allLinks = input.match(urlRegex) || [];
236
- const permittedDomains = ['google.com', 'facebook.com', 'twitter.com', 'instagram.com', 'youtube.com', 'apple.com', 'microsoft.com'];
294
+ const permittedDomains = [
295
+ "google.com",
296
+ "facebook.com",
297
+ "twitter.com",
298
+ "instagram.com",
299
+ "youtube.com",
300
+ "apple.com",
301
+ "microsoft.com",
302
+ ];
237
303
 
238
304
  for (let i = 0; i < allLinks.length; i++) {
239
- const link = allLinks[i];
240
- const lowerLink = link.toLowerCase();
241
-
242
- if (lowerLink.match(/\.[a-z0-9-]+\.th\b/) || lowerLink.endsWith('.th')) continue;
305
+ const link = allLinks[i];
306
+ const lowerLink = link.toLowerCase();
243
307
 
244
- let isPermitted = false;
245
- for (let j = 0; j < permittedDomains.length; j++) {
246
- if (lowerLink.indexOf(permittedDomains[j]) !== -1) { isPermitted = true; break; }
308
+ if (lowerLink.match(/\.[a-z0-9-]+\.th\b/) || lowerLink.endsWith(".th"))
309
+ continue;
310
+
311
+ let isPermitted = false;
312
+ for (let j = 0; j < permittedDomains.length; j++) {
313
+ if (lowerLink.indexOf(permittedDomains[j]) !== -1) {
314
+ isPermitted = true;
315
+ break;
247
316
  }
248
- if (isPermitted) continue;
249
- actors.push(this._defang(link));
317
+ }
318
+ if (isPermitted) continue;
319
+ actors.push(this._defang(link));
250
320
  }
251
321
 
252
322
  const tagMatches = input.match(/([ก-๙]+[A-Za-z0-9]{2,})/g);
@@ -256,7 +326,7 @@
256
326
  if (brandMatches) actors.push(...brandMatches);
257
327
 
258
328
  const uid = actors.filter((v, i, a) => a.indexOf(v) === i);
259
-
329
+
260
330
  const sanitizedFull = this._sanitizeData(input);
261
331
 
262
332
  let sampleRaw = "";
@@ -273,35 +343,47 @@
273
343
  }
274
344
  }
275
345
  this._config.autoReport = origReport;
276
-
346
+
277
347
  if (!sampleRaw) sampleRaw = input;
278
348
 
279
349
  const sanitizedSample = this._sanitizeData(sampleRaw);
280
350
 
281
351
  const payload = {
282
- client: this._config.siteToken || null,
283
- url: typeof window !== "undefined" ? this._defang(window.location.href) : "node",
352
+ endpoint: this._config.siteToken || null,
353
+ url:
354
+ typeof window !== "undefined"
355
+ ? this._defang(window.location.href)
356
+ : "node",
284
357
  rule: result.reason || "ML",
285
358
  prob: Math.round(result.prob * 100),
286
- text: this._defang(sanitizedSample.text).substring(0, this._config.payloadLimit),
359
+ text: this._defang(sanitizedSample.text).substring(
360
+ 0,
361
+ this._config.payloadLimit,
362
+ ),
287
363
  uid: uid,
288
364
  sd: sanitizedFull.sd,
289
- paste: !!pastedFlag
365
+ paste: !!pastedFlag,
290
366
  };
291
367
 
292
368
  const destinations = [];
293
369
  if (this._config.endpoint) {
294
- if (Array.isArray(this._config.endpoint)) destinations.push(...this._config.endpoint);
370
+ if (Array.isArray(this._config.endpoint))
371
+ destinations.push(...this._config.endpoint);
295
372
  else destinations.push(this._config.endpoint);
296
373
  }
297
374
  if (this._config.siemEndpoint) {
298
- if (Array.isArray(this._config.siemEndpoint)) destinations.push(...this._config.siemEndpoint);
375
+ if (Array.isArray(this._config.siemEndpoint))
376
+ destinations.push(...this._config.siemEndpoint);
299
377
  else destinations.push(this._config.siemEndpoint);
300
378
  }
301
379
  for (let i = 0; i < destinations.length; i++) {
302
380
  this._send(destinations[i], payload);
303
381
  }
304
- if (this._config.customReporter) { try { this._config.customReporter(payload); } catch(e) {} }
382
+ if (this._config.customReporter) {
383
+ try {
384
+ this._config.customReporter(payload);
385
+ } catch (e) { }
386
+ }
305
387
  },
306
388
 
307
389
  _send: function(url, data) {
@@ -313,12 +395,19 @@
313
395
  }
314
396
  if (typeof navigator !== "undefined" && navigator.sendBeacon) {
315
397
  try {
316
- const blob = new Blob([JSON.stringify(data)], { type: "application/json" });
398
+ const blob = new Blob([JSON.stringify(data)], {
399
+ type: "application/json",
400
+ });
317
401
  if (navigator.sendBeacon(finalUrl, blob)) return;
318
- } catch (e) {}
402
+ } catch (e) { }
319
403
  }
320
404
  if (typeof fetch !== "undefined") {
321
- fetch(finalUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), keepalive: true }).catch(() => {});
405
+ fetch(finalUrl, {
406
+ method: "POST",
407
+ headers: { "Content-Type": "application/json" },
408
+ body: JSON.stringify(data),
409
+ keepalive: true,
410
+ }).catch(() => { });
322
411
  }
323
412
  },
324
413
 
@@ -328,16 +417,16 @@
328
417
  const nClasses = this._classes.length;
329
418
  this._baseScore = new Float64Array(nClasses);
330
419
  this._featureWeight = [];
331
-
420
+
332
421
  for (let c = 0; c < nClasses; c++) {
333
422
  this._featureWeight[c] = new Float64Array(this._nFeatures);
334
423
  let base = this._classLogPrior[c];
335
-
424
+
336
425
  for (let j = 0; j < this._nFeatures; j++) {
337
426
  const logP = this._featureLogProb[c][j];
338
427
  const p = Math.exp(logP);
339
428
  const logNotP = Math.log(Math.max(1.0 - p, 1e-300));
340
-
429
+
341
430
  base += logNotP;
342
431
  this._featureWeight[c][j] = logP - logNotP;
343
432
  }
@@ -348,17 +437,17 @@
348
437
  _transform: function(text) {
349
438
  const presentFeatures = new Set();
350
439
  const t = text.toLowerCase();
351
-
440
+
352
441
  // Split text into tokens by whitespace
353
442
  const tokens = t.split(/\s+/);
354
-
443
+
355
444
  for (let i = 0; i < tokens.length; i++) {
356
- let word = tokens[i].replace(/\s/g, '');
445
+ let word = tokens[i].replace(/\s/g, "");
357
446
  if (word.length === 0) continue;
358
447
 
359
448
  // Unigram (Exact word match)
360
- if (word in this._vocab) {
361
- presentFeatures.add(this._vocab[word]);
449
+ if (word in this._vocab) {
450
+ presentFeatures.add(this._vocab[word]);
362
451
  }
363
452
 
364
453
  // Noise Limiter: Prevent massive unbroken strings from diluting the ML score
@@ -367,62 +456,103 @@
367
456
  }
368
457
 
369
458
  const n = word.length;
370
-
459
+
371
460
  // Trigrams
372
461
  for (let j = 0; j <= n - 3; j++) {
373
462
  const trigram = word.substring(j, j + 3);
374
- if (trigram in this._vocab) { presentFeatures.add(this._vocab[trigram]); }
463
+ if (trigram in this._vocab) {
464
+ presentFeatures.add(this._vocab[trigram]);
465
+ }
375
466
  }
376
-
467
+
377
468
  // Quadgrams
378
469
  for (let j = 0; j <= n - 4; j++) {
379
470
  const quadgram = word.substring(j, j + 4);
380
- if (quadgram in this._vocab) { presentFeatures.add(this._vocab[quadgram]); }
471
+ if (quadgram in this._vocab) {
472
+ presentFeatures.add(this._vocab[quadgram]);
473
+ }
381
474
  }
382
475
  }
383
-
476
+
384
477
  return Array.from(presentFeatures);
385
478
  },
386
479
 
387
480
  lightcheck: function(input) {
388
- if (!input || typeof input !== "string") { return { isSpam: false, prob: 0, version: this._version, reason: "safe" }; }
389
-
481
+ if (!input || typeof input !== "string") {
482
+ return {
483
+ isSpam: false,
484
+ prob: 0,
485
+ version: this._version,
486
+ reason: "safe",
487
+ };
488
+ }
489
+
390
490
  // 1. Filter List (Domains) - Priority Check
391
491
  const tokens = input.toLowerCase().split(/[^\w\d\.@\-]+/);
392
492
  for (let i = 0; i < tokens.length; i++) {
393
493
  const t = tokens[i];
394
494
  if (t && this._checkFilter(t)) {
395
- return { isSpam: true, prob: 0.95, reason: "spam_link", version: this._version };
495
+ return {
496
+ isSpam: true,
497
+ prob: 0.95,
498
+ reason: "spam_link",
499
+ version: this._version,
500
+ };
396
501
  }
397
502
  }
398
503
 
399
504
  // 2. Currency Symbols
400
- const currencySymbols = ["$", "€", "£", "฿", "¥", "₹", "₽", "₿", "₮", "₩", "₱", "₫"];
505
+ const currencySymbols = [
506
+ "$",
507
+ "€",
508
+ "£",
509
+ "฿",
510
+ "¥",
511
+ "₹",
512
+ "₽",
513
+ "₿",
514
+ "₮",
515
+ "₩",
516
+ "₱",
517
+ "₫",
518
+ ];
401
519
  for (let i = 0; i < currencySymbols.length; i++) {
402
520
  if (input.indexOf(currencySymbols[i]) !== -1) {
403
- return { isSpam: true, prob: 1.0, reason: "currency_symbol", version: this._version };
521
+ return {
522
+ isSpam: true,
523
+ prob: 1.0,
524
+ reason: "currency_symbol",
525
+ version: this._version,
526
+ };
404
527
  }
405
528
  }
406
-
529
+
407
530
  return { isSpam: false, prob: 0, reason: "safe", version: this._version };
408
531
  },
409
532
 
410
533
  spamcheck: function(input, opts) {
411
- if (!input || typeof input !== "string") { return { isSpam: false, prob: 0, version: this._version }; }
412
-
413
- const pasted = (typeof opts === "object" && opts !== null) ? !!opts.pasted : !!opts;
534
+ if (!input || typeof input !== "string") {
535
+ return { isSpam: false, prob: 0, version: this._version };
536
+ }
537
+
538
+ const pasted =
539
+ typeof opts === "object" && opts !== null ? !!opts.pasted : !!opts;
414
540
 
415
541
  // Perform light check first (Fast Fail)
416
542
  const lightResult = this.lightcheck(input);
417
543
  if (lightResult.isSpam) {
418
544
  return this._finishCheck(input, lightResult, pasted);
419
545
  }
420
-
546
+
421
547
  // Bypass ML model for non-Thai text (if not caught by lightcheck rules)
422
548
  if (!/[\u0e00-\u0e7f]/.test(input)) {
423
- return this._finishCheck(input, { isSpam: false, prob: 0, version: this._version }, pasted);
549
+ return this._finishCheck(
550
+ input,
551
+ { isSpam: false, prob: 0, version: this._version },
552
+ pasted,
553
+ );
424
554
  }
425
-
555
+
426
556
  // Heavy ML processing (Present-Only Naive Bayes)
427
557
  this.init();
428
558
  const presentFeatures = this._transform(input);
@@ -436,7 +566,7 @@
436
566
  scores[c] = s;
437
567
  }
438
568
  // Apply calibrated threshold offset
439
- scores[1] -= (5.5 + 0.49 * presentFeatures.length);
569
+ scores[1] -= 5.5 + 0.49 * presentFeatures.length;
440
570
 
441
571
  const maxScore = Math.max(scores[0], scores[1]);
442
572
  const exp0 = Math.exp(scores[0] - maxScore);
@@ -448,41 +578,49 @@
448
578
  return this._finishCheck(input, result, pasted);
449
579
  },
450
580
 
451
-
452
581
  _finishCheck: function(input, result, pastedFlag = false) {
453
582
  const hasSD = this._sanitizeData(input).sd;
454
- if (this._config.autoReport && (result.isSpam || (this._config.reportSD && hasSD))) {
583
+ if (
584
+ this._config.autoReport &&
585
+ (result.isSpam || (this._config.reportSD && hasSD))
586
+ ) {
455
587
  this._report(input, result, pastedFlag);
456
588
  }
457
589
  return result;
458
590
  },
459
591
 
460
- isSpam: function(text) { return this.spamcheck(text).isSpam; },
461
- get version() { return this._version; },
592
+ isSpam: function(text) {
593
+ return this.spamcheck(text).isSpam;
594
+ },
595
+ get version() {
596
+ return this._version;
597
+ },
462
598
  };
463
599
 
464
600
  // ── 3. Active Defense: The Ghost Tarpit ───────────────────────────
465
-
466
- if (typeof window !== 'undefined') {
601
+
602
+ if (typeof window !== "undefined") {
467
603
  // The Real Engine: Bound via state validation hash to ensure execution integrity
468
- const REAL_KEY = "_sw_6c4a255d";
604
+ const REAL_KEY = "_sw_57cfab1e";
469
605
  window[REAL_KEY] = SpamWarden;
470
606
 
471
607
  // --- Developer Mode Bypass ---
472
608
  // Allows the live demo (docs/index.html) or authorized devs to test the full API.
473
609
  let isDevMode = false;
474
610
  try {
475
- const scripts = document.querySelectorAll('script');
611
+ const scripts = document.querySelectorAll("script");
476
612
  for (let i = 0; i < scripts.length; i++) {
477
- if (scripts[i].getAttribute('data-sw-dev') === 'true') {
613
+ if (scripts[i].getAttribute("data-sw-dev") === "true") {
478
614
  isDevMode = true;
479
615
  break;
480
616
  }
481
617
  }
482
- } catch(e) {}
618
+ } catch (e) { }
483
619
 
484
620
  if (isDevMode) {
485
- console.warn("[SpamWarden] ⚠️ DEV MODE ACTIVE: Tarpit disabled. Real engine exposed globally.");
621
+ console.warn(
622
+ "[SpamWarden] ⚠️ DEV MODE ACTIVE: Tarpit disabled. Real engine exposed globally.",
623
+ );
486
624
  window.spamwarden = SpamWarden;
487
625
  } else {
488
626
  // The Decoy: Filled with a "Poison Pill" to crash bots attempting bypasses
@@ -490,32 +628,34 @@
490
628
  version: SpamWarden.version,
491
629
  spamcheck: function() {
492
630
  console.log("[System] Initializing heuristic validation...");
493
-
631
+
494
632
  // The CPU Tarpit: Synchronous DOM thrashing and memory exhaustion
495
633
  let junkArray = [];
496
634
  let counter = 0;
497
-
635
+
498
636
  // This locks the main thread, spiking CPU to 100%
499
637
  while (true) {
500
638
  counter++;
501
639
  // Push garbage to memory to trigger heap exhaustion
502
- junkArray.push(new Array(10000).join('x'));
503
-
640
+ junkArray.push(new Array(10000).join("x"));
641
+
504
642
  // Thrash the browser's history API (heavily degrades performance in headless bots)
505
643
  try {
506
- history.pushState(0, 0, '/' + counter);
507
- } catch(e) {}
644
+ history.pushState(0, 0, "/" + counter);
645
+ } catch (e) { }
508
646
 
509
647
  // Cryptographic math to burn CPU cycles
510
648
  Math.sqrt(Math.random() * 9999999) * Math.sin(counter);
511
-
649
+
512
650
  // Anti-debugging: Break in the loop if DevTools are open
513
651
  if (counter % 1000 === 0) {
514
652
  debugger;
515
653
  }
516
654
  }
517
655
  },
518
- isSpam: function() { return this.spamcheck(); }
656
+ isSpam: function() {
657
+ return this.spamcheck();
658
+ },
519
659
  };
520
660
  }
521
661
  }
@@ -525,41 +665,43 @@
525
665
  if (typeof document !== "undefined" && document.currentScript) {
526
666
  const script = document.currentScript;
527
667
  const src = script.src;
528
-
668
+
529
669
  const queryStr = src.indexOf("?") !== -1 ? src.split("?")[1] : "";
530
670
  const params = new URLSearchParams(queryStr);
531
- const clientTokenRaw = params.get("client");
671
+ const endpointTokenRaw = params.get("endpoint");
532
672
 
533
- if (clientTokenRaw) {
673
+ if (endpointTokenRaw) {
534
674
  try {
535
- let base64Config = clientTokenRaw.replace(/ /g, "+");
675
+ let base64Config = endpointTokenRaw.replace(/ /g, "+");
536
676
  while (base64Config.length % 4 !== 0) base64Config += "=";
537
677
 
538
678
  const decodedString = atob(base64Config);
539
679
  const parts = decodedString.split("|");
540
-
680
+
541
681
  if (parts.length >= 2) {
542
682
  const sdFlag = parts[0];
543
683
  const siemEndpointRaw = parts[1] || null;
544
684
 
545
685
  if (siemEndpointRaw) {
546
- SpamWarden._config.siemEndpoint = siemEndpointRaw.indexOf(",") !== -1 ?
547
- siemEndpointRaw.split(",") :
548
- siemEndpointRaw;
686
+ SpamWarden._config.siemEndpoint =
687
+ siemEndpointRaw.indexOf(",") !== -1
688
+ ? siemEndpointRaw.split(",")
689
+ : siemEndpointRaw;
549
690
  }
550
691
 
551
- SpamWarden._config.siteToken = clientTokenRaw;
692
+ SpamWarden._config.siteToken = endpointTokenRaw;
552
693
  SpamWarden._config.reportSD = sdFlag === "1";
553
694
  SpamWarden._config.autoReport = true;
554
695
  SpamWarden._config.isTrusted = true;
555
696
 
556
697
  SpamWarden._autoBind();
557
698
  }
558
- } catch (e) { console.error("[SpamWarden] Configuration failure."); }
559
- }
560
- else if (script.hasAttribute("data-auto-protect")) {
699
+ } catch (e) {
700
+ console.error("[SpamWarden] Configuration failure.");
701
+ }
702
+ } else if (script.hasAttribute("data-auto-protect")) {
561
703
  const sdAttr = script.getAttribute("data-sd");
562
- SpamWarden._config.reportSD = sdAttr !== "0";
704
+ SpamWarden._config.reportSD = sdAttr !== "0";
563
705
  SpamWarden._config.autoReport = false;
564
706
  SpamWarden._config.isTrusted = true;
565
707
  SpamWarden._autoBind();
@@ -567,12 +709,14 @@
567
709
  }
568
710
 
569
711
  // Handle module exports safely
570
- if (typeof module !== 'undefined' && module.exports) { module.exports = SpamWarden; }
712
+ if (typeof module !== "undefined" && module.exports) {
713
+ module.exports = SpamWarden;
714
+ }
571
715
  })();
572
716
 
573
717
  if (typeof window !== 'undefined') {
574
718
 
575
- window['_sw_a1d28179'] = {
719
+ window['_sw_31a8780a'] = {
576
720
  _vocab: { decoy: 1, trap: 2 }, // Base signature
577
721
  _version: "v11.06",
578
722
  _nFeatures: 28106,
@@ -604,7 +748,7 @@ if (typeof window !== 'undefined') {
604
748
  }
605
749
  };
606
750
 
607
- window['_sw_0080296f'] = {
751
+ window['_sw_dafb19a2'] = {
608
752
  _vocab: { decoy: 1, trap: 2 }, // Base signature
609
753
  _version: "v11.06",
610
754
  _nFeatures: 28106,
@@ -636,7 +780,7 @@ if (typeof window !== 'undefined') {
636
780
  }
637
781
  };
638
782
 
639
- window['_sw_f0cb3821'] = {
783
+ window['_sw_a01f6d62'] = {
640
784
  _vocab: { decoy: 1, trap: 2 }, // Base signature
641
785
  _version: "v11.06",
642
786
  _nFeatures: 28106,
@@ -668,7 +812,7 @@ if (typeof window !== 'undefined') {
668
812
  }
669
813
  };
670
814
 
671
- window['_sw_5f20a05d'] = {
815
+ window['_sw_4c8d876b'] = {
672
816
  _vocab: { decoy: 1, trap: 2 }, // Base signature
673
817
  _version: "v11.06",
674
818
  _nFeatures: 28106,
@@ -700,7 +844,7 @@ if (typeof window !== 'undefined') {
700
844
  }
701
845
  };
702
846
 
703
- window['_sw_ef8658ec'] = {
847
+ window['_sw_094eac46'] = {
704
848
  _vocab: { decoy: 1, trap: 2 }, // Base signature
705
849
  _version: "v11.06",
706
850
  _nFeatures: 28106,
@@ -732,7 +876,7 @@ if (typeof window !== 'undefined') {
732
876
  }
733
877
  };
734
878
 
735
- window['_sw_4a2f5c4d'] = {
879
+ window['_sw_f2f438fb'] = {
736
880
  _vocab: { decoy: 1, trap: 2 }, // Base signature
737
881
  _version: "v11.06",
738
882
  _nFeatures: 28106,
@@ -764,7 +908,7 @@ if (typeof window !== 'undefined') {
764
908
  }
765
909
  };
766
910
 
767
- window['_sw_5672fd6a'] = {
911
+ window['_sw_0cc127ee'] = {
768
912
  _vocab: { decoy: 1, trap: 2 }, // Base signature
769
913
  _version: "v11.06",
770
914
  _nFeatures: 28106,
@@ -796,7 +940,7 @@ if (typeof window !== 'undefined') {
796
940
  }
797
941
  };
798
942
 
799
- window['_sw_a945224e'] = {
943
+ window['_sw_ab633c8a'] = {
800
944
  _vocab: { decoy: 1, trap: 2 }, // Base signature
801
945
  _version: "v11.06",
802
946
  _nFeatures: 28106,
@@ -828,7 +972,7 @@ if (typeof window !== 'undefined') {
828
972
  }
829
973
  };
830
974
 
831
- window['_sw_2446a3de'] = {
975
+ window['_sw_dbd1052e'] = {
832
976
  _vocab: { decoy: 1, trap: 2 }, // Base signature
833
977
  _version: "v11.06",
834
978
  _nFeatures: 28106,
@@ -860,7 +1004,7 @@ if (typeof window !== 'undefined') {
860
1004
  }
861
1005
  };
862
1006
 
863
- window['_sw_9de89758'] = {
1007
+ window['_sw_344f6f75'] = {
864
1008
  _vocab: { decoy: 1, trap: 2 }, // Base signature
865
1009
  _version: "v11.06",
866
1010
  _nFeatures: 28106,
@@ -892,7 +1036,7 @@ if (typeof window !== 'undefined') {
892
1036
  }
893
1037
  };
894
1038
 
895
- window['_sw_26d22992'] = {
1039
+ window['_sw_f9fac381'] = {
896
1040
  _vocab: { decoy: 1, trap: 2 }, // Base signature
897
1041
  _version: "v11.06",
898
1042
  _nFeatures: 28106,
@@ -924,7 +1068,7 @@ if (typeof window !== 'undefined') {
924
1068
  }
925
1069
  };
926
1070
 
927
- window['_sw_a27bd68b'] = {
1071
+ window['_sw_40c78f05'] = {
928
1072
  _vocab: { decoy: 1, trap: 2 }, // Base signature
929
1073
  _version: "v11.06",
930
1074
  _nFeatures: 28106,
@@ -956,7 +1100,7 @@ if (typeof window !== 'undefined') {
956
1100
  }
957
1101
  };
958
1102
 
959
- window['_sw_49425d3b'] = {
1103
+ window['_sw_20a2df22'] = {
960
1104
  _vocab: { decoy: 1, trap: 2 }, // Base signature
961
1105
  _version: "v11.06",
962
1106
  _nFeatures: 28106,
@@ -988,7 +1132,7 @@ if (typeof window !== 'undefined') {
988
1132
  }
989
1133
  };
990
1134
 
991
- window['_sw_db05b02e'] = {
1135
+ window['_sw_2f9814e1'] = {
992
1136
  _vocab: { decoy: 1, trap: 2 }, // Base signature
993
1137
  _version: "v11.06",
994
1138
  _nFeatures: 28106,
@@ -1020,7 +1164,7 @@ if (typeof window !== 'undefined') {
1020
1164
  }
1021
1165
  };
1022
1166
 
1023
- window['_sw_5185dd03'] = {
1167
+ window['_sw_7bc7d2e9'] = {
1024
1168
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1025
1169
  _version: "v11.06",
1026
1170
  _nFeatures: 28106,
@@ -1052,7 +1196,7 @@ if (typeof window !== 'undefined') {
1052
1196
  }
1053
1197
  };
1054
1198
 
1055
- window['_sw_eeac6984'] = {
1199
+ window['_sw_a4687cc6'] = {
1056
1200
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1057
1201
  _version: "v11.06",
1058
1202
  _nFeatures: 28106,
@@ -1084,7 +1228,7 @@ if (typeof window !== 'undefined') {
1084
1228
  }
1085
1229
  };
1086
1230
 
1087
- window['_sw_26d2e4ec'] = {
1231
+ window['_sw_f202e262'] = {
1088
1232
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1089
1233
  _version: "v11.06",
1090
1234
  _nFeatures: 28106,
@@ -1116,7 +1260,7 @@ if (typeof window !== 'undefined') {
1116
1260
  }
1117
1261
  };
1118
1262
 
1119
- window['_sw_af0592f4'] = {
1263
+ window['_sw_e5c77f3d'] = {
1120
1264
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1121
1265
  _version: "v11.06",
1122
1266
  _nFeatures: 28106,
@@ -1148,7 +1292,7 @@ if (typeof window !== 'undefined') {
1148
1292
  }
1149
1293
  };
1150
1294
 
1151
- window['_sw_864fe9a4'] = {
1295
+ window['_sw_d9d273c6'] = {
1152
1296
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1153
1297
  _version: "v11.06",
1154
1298
  _nFeatures: 28106,
@@ -1180,7 +1324,7 @@ if (typeof window !== 'undefined') {
1180
1324
  }
1181
1325
  };
1182
1326
 
1183
- window['_sw_eaecc9f8'] = {
1327
+ window['_sw_dda652e9'] = {
1184
1328
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1185
1329
  _version: "v11.06",
1186
1330
  _nFeatures: 28106,
@@ -1212,7 +1356,7 @@ if (typeof window !== 'undefined') {
1212
1356
  }
1213
1357
  };
1214
1358
 
1215
- window['_sw_bee172bb'] = {
1359
+ window['_sw_9b8473ce'] = {
1216
1360
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1217
1361
  _version: "v11.06",
1218
1362
  _nFeatures: 28106,
@@ -1244,7 +1388,7 @@ if (typeof window !== 'undefined') {
1244
1388
  }
1245
1389
  };
1246
1390
 
1247
- window['_sw_594e43e3'] = {
1391
+ window['_sw_f3b2ce6b'] = {
1248
1392
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1249
1393
  _version: "v11.06",
1250
1394
  _nFeatures: 28106,
@@ -1276,7 +1420,7 @@ if (typeof window !== 'undefined') {
1276
1420
  }
1277
1421
  };
1278
1422
 
1279
- window['_sw_564e1f43'] = {
1423
+ window['_sw_085d80ce'] = {
1280
1424
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1281
1425
  _version: "v11.06",
1282
1426
  _nFeatures: 28106,
@@ -1308,7 +1452,7 @@ if (typeof window !== 'undefined') {
1308
1452
  }
1309
1453
  };
1310
1454
 
1311
- window['_sw_65f33f31'] = {
1455
+ window['_sw_6537fd34'] = {
1312
1456
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1313
1457
  _version: "v11.06",
1314
1458
  _nFeatures: 28106,
@@ -1340,7 +1484,7 @@ if (typeof window !== 'undefined') {
1340
1484
  }
1341
1485
  };
1342
1486
 
1343
- window['_sw_60576197'] = {
1487
+ window['_sw_a69e2174'] = {
1344
1488
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1345
1489
  _version: "v11.06",
1346
1490
  _nFeatures: 28106,
@@ -1372,7 +1516,7 @@ if (typeof window !== 'undefined') {
1372
1516
  }
1373
1517
  };
1374
1518
 
1375
- window['_sw_5e706074'] = {
1519
+ window['_sw_030a07e9'] = {
1376
1520
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1377
1521
  _version: "v11.06",
1378
1522
  _nFeatures: 28106,
@@ -1404,7 +1548,7 @@ if (typeof window !== 'undefined') {
1404
1548
  }
1405
1549
  };
1406
1550
 
1407
- window['_sw_5c9f0295'] = {
1551
+ window['_sw_267b7519'] = {
1408
1552
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1409
1553
  _version: "v11.06",
1410
1554
  _nFeatures: 28106,
@@ -1436,7 +1580,7 @@ if (typeof window !== 'undefined') {
1436
1580
  }
1437
1581
  };
1438
1582
 
1439
- window['_sw_315dc4a6'] = {
1583
+ window['_sw_a026232f'] = {
1440
1584
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1441
1585
  _version: "v11.06",
1442
1586
  _nFeatures: 28106,
@@ -1468,7 +1612,7 @@ if (typeof window !== 'undefined') {
1468
1612
  }
1469
1613
  };
1470
1614
 
1471
- window['_sw_c2e79459'] = {
1615
+ window['_sw_93b32887'] = {
1472
1616
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1473
1617
  _version: "v11.06",
1474
1618
  _nFeatures: 28106,
@@ -1500,7 +1644,7 @@ if (typeof window !== 'undefined') {
1500
1644
  }
1501
1645
  };
1502
1646
 
1503
- window['_sw_2d10783c'] = {
1647
+ window['_sw_023bce0c'] = {
1504
1648
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1505
1649
  _version: "v11.06",
1506
1650
  _nFeatures: 28106,
@@ -1532,7 +1676,7 @@ if (typeof window !== 'undefined') {
1532
1676
  }
1533
1677
  };
1534
1678
 
1535
- window['_sw_e6749ff2'] = {
1679
+ window['_sw_895a395b'] = {
1536
1680
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1537
1681
  _version: "v11.06",
1538
1682
  _nFeatures: 28106,
@@ -1564,7 +1708,7 @@ if (typeof window !== 'undefined') {
1564
1708
  }
1565
1709
  };
1566
1710
 
1567
- window['_sw_be0b12d4'] = {
1711
+ window['_sw_3a1ad6f2'] = {
1568
1712
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1569
1713
  _version: "v11.06",
1570
1714
  _nFeatures: 28106,
@@ -1596,7 +1740,7 @@ if (typeof window !== 'undefined') {
1596
1740
  }
1597
1741
  };
1598
1742
 
1599
- window['_sw_71290039'] = {
1743
+ window['_sw_ae5db24e'] = {
1600
1744
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1601
1745
  _version: "v11.06",
1602
1746
  _nFeatures: 28106,
@@ -1628,7 +1772,7 @@ if (typeof window !== 'undefined') {
1628
1772
  }
1629
1773
  };
1630
1774
 
1631
- window['_sw_1c46d65d'] = {
1775
+ window['_sw_d522ab11'] = {
1632
1776
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1633
1777
  _version: "v11.06",
1634
1778
  _nFeatures: 28106,
@@ -1660,7 +1804,7 @@ if (typeof window !== 'undefined') {
1660
1804
  }
1661
1805
  };
1662
1806
 
1663
- window['_sw_8331d717'] = {
1807
+ window['_sw_b67edeb7'] = {
1664
1808
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1665
1809
  _version: "v11.06",
1666
1810
  _nFeatures: 28106,
@@ -1692,7 +1836,7 @@ if (typeof window !== 'undefined') {
1692
1836
  }
1693
1837
  };
1694
1838
 
1695
- window['_sw_42c3fdc5'] = {
1839
+ window['_sw_2218e922'] = {
1696
1840
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1697
1841
  _version: "v11.06",
1698
1842
  _nFeatures: 28106,
@@ -1724,7 +1868,7 @@ if (typeof window !== 'undefined') {
1724
1868
  }
1725
1869
  };
1726
1870
 
1727
- window['_sw_fbc9ba39'] = {
1871
+ window['_sw_8ed49fa1'] = {
1728
1872
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1729
1873
  _version: "v11.06",
1730
1874
  _nFeatures: 28106,
@@ -1756,7 +1900,7 @@ if (typeof window !== 'undefined') {
1756
1900
  }
1757
1901
  };
1758
1902
 
1759
- window['_sw_ed72dc77'] = {
1903
+ window['_sw_6df168f4'] = {
1760
1904
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1761
1905
  _version: "v11.06",
1762
1906
  _nFeatures: 28106,
@@ -1788,7 +1932,7 @@ if (typeof window !== 'undefined') {
1788
1932
  }
1789
1933
  };
1790
1934
 
1791
- window['_sw_29934231'] = {
1935
+ window['_sw_caeebc1a'] = {
1792
1936
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1793
1937
  _version: "v11.06",
1794
1938
  _nFeatures: 28106,
@@ -1820,7 +1964,7 @@ if (typeof window !== 'undefined') {
1820
1964
  }
1821
1965
  };
1822
1966
 
1823
- window['_sw_ea925aba'] = {
1967
+ window['_sw_fd6c687a'] = {
1824
1968
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1825
1969
  _version: "v11.06",
1826
1970
  _nFeatures: 28106,
@@ -1852,7 +1996,7 @@ if (typeof window !== 'undefined') {
1852
1996
  }
1853
1997
  };
1854
1998
 
1855
- window['_sw_2940c30a'] = {
1999
+ window['_sw_e31b19f0'] = {
1856
2000
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1857
2001
  _version: "v11.06",
1858
2002
  _nFeatures: 28106,
@@ -1884,7 +2028,7 @@ if (typeof window !== 'undefined') {
1884
2028
  }
1885
2029
  };
1886
2030
 
1887
- window['_sw_72059a86'] = {
2031
+ window['_sw_10844d4e'] = {
1888
2032
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1889
2033
  _version: "v11.06",
1890
2034
  _nFeatures: 28106,
@@ -1916,7 +2060,7 @@ if (typeof window !== 'undefined') {
1916
2060
  }
1917
2061
  };
1918
2062
 
1919
- window['_sw_18bbe18c'] = {
2063
+ window['_sw_da30ac09'] = {
1920
2064
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1921
2065
  _version: "v11.06",
1922
2066
  _nFeatures: 28106,
@@ -1948,7 +2092,7 @@ if (typeof window !== 'undefined') {
1948
2092
  }
1949
2093
  };
1950
2094
 
1951
- window['_sw_63e47a17'] = {
2095
+ window['_sw_6a27eb7f'] = {
1952
2096
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1953
2097
  _version: "v11.06",
1954
2098
  _nFeatures: 28106,
@@ -1980,7 +2124,7 @@ if (typeof window !== 'undefined') {
1980
2124
  }
1981
2125
  };
1982
2126
 
1983
- window['_sw_d36445a7'] = {
2127
+ window['_sw_f54aaaee'] = {
1984
2128
  _vocab: { decoy: 1, trap: 2 }, // Base signature
1985
2129
  _version: "v11.06",
1986
2130
  _nFeatures: 28106,
@@ -2012,7 +2156,7 @@ if (typeof window !== 'undefined') {
2012
2156
  }
2013
2157
  };
2014
2158
 
2015
- window['_sw_527c3739'] = {
2159
+ window['_sw_47cdd64e'] = {
2016
2160
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2017
2161
  _version: "v11.06",
2018
2162
  _nFeatures: 28106,
@@ -2044,7 +2188,7 @@ if (typeof window !== 'undefined') {
2044
2188
  }
2045
2189
  };
2046
2190
 
2047
- window['_sw_a836b7cb'] = {
2191
+ window['_sw_af3d1b15'] = {
2048
2192
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2049
2193
  _version: "v11.06",
2050
2194
  _nFeatures: 28106,
@@ -2076,7 +2220,7 @@ if (typeof window !== 'undefined') {
2076
2220
  }
2077
2221
  };
2078
2222
 
2079
- window['_sw_2f1073e5'] = {
2223
+ window['_sw_91bfc5fb'] = {
2080
2224
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2081
2225
  _version: "v11.06",
2082
2226
  _nFeatures: 28106,
@@ -2108,7 +2252,7 @@ if (typeof window !== 'undefined') {
2108
2252
  }
2109
2253
  };
2110
2254
 
2111
- window['_sw_dd1aba69'] = {
2255
+ window['_sw_269252a8'] = {
2112
2256
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2113
2257
  _version: "v11.06",
2114
2258
  _nFeatures: 28106,
@@ -2140,7 +2284,7 @@ if (typeof window !== 'undefined') {
2140
2284
  }
2141
2285
  };
2142
2286
 
2143
- window['_sw_d29dd701'] = {
2287
+ window['_sw_0db1fea6'] = {
2144
2288
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2145
2289
  _version: "v11.06",
2146
2290
  _nFeatures: 28106,
@@ -2172,7 +2316,7 @@ if (typeof window !== 'undefined') {
2172
2316
  }
2173
2317
  };
2174
2318
 
2175
- window['_sw_90895be3'] = {
2319
+ window['_sw_2db45ef4'] = {
2176
2320
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2177
2321
  _version: "v11.06",
2178
2322
  _nFeatures: 28106,
@@ -2204,7 +2348,7 @@ if (typeof window !== 'undefined') {
2204
2348
  }
2205
2349
  };
2206
2350
 
2207
- window['_sw_52679993'] = {
2351
+ window['_sw_59d112cf'] = {
2208
2352
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2209
2353
  _version: "v11.06",
2210
2354
  _nFeatures: 28106,
@@ -2236,7 +2380,7 @@ if (typeof window !== 'undefined') {
2236
2380
  }
2237
2381
  };
2238
2382
 
2239
- window['_sw_7a6c5353'] = {
2383
+ window['_sw_2d749858'] = {
2240
2384
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2241
2385
  _version: "v11.06",
2242
2386
  _nFeatures: 28106,
@@ -2268,7 +2412,7 @@ if (typeof window !== 'undefined') {
2268
2412
  }
2269
2413
  };
2270
2414
 
2271
- window['_sw_09d965a9'] = {
2415
+ window['_sw_3e7bbc14'] = {
2272
2416
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2273
2417
  _version: "v11.06",
2274
2418
  _nFeatures: 28106,
@@ -2300,7 +2444,7 @@ if (typeof window !== 'undefined') {
2300
2444
  }
2301
2445
  };
2302
2446
 
2303
- window['_sw_cc5359ae'] = {
2447
+ window['_sw_9fadcbd2'] = {
2304
2448
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2305
2449
  _version: "v11.06",
2306
2450
  _nFeatures: 28106,
@@ -2332,7 +2476,7 @@ if (typeof window !== 'undefined') {
2332
2476
  }
2333
2477
  };
2334
2478
 
2335
- window['_sw_7313d212'] = {
2479
+ window['_sw_fd6e26a1'] = {
2336
2480
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2337
2481
  _version: "v11.06",
2338
2482
  _nFeatures: 28106,
@@ -2364,7 +2508,7 @@ if (typeof window !== 'undefined') {
2364
2508
  }
2365
2509
  };
2366
2510
 
2367
- window['_sw_1013265d'] = {
2511
+ window['_sw_c17ce309'] = {
2368
2512
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2369
2513
  _version: "v11.06",
2370
2514
  _nFeatures: 28106,
@@ -2396,7 +2540,7 @@ if (typeof window !== 'undefined') {
2396
2540
  }
2397
2541
  };
2398
2542
 
2399
- window['_sw_5470f773'] = {
2543
+ window['_sw_1ef40e6c'] = {
2400
2544
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2401
2545
  _version: "v11.06",
2402
2546
  _nFeatures: 28106,
@@ -2428,7 +2572,7 @@ if (typeof window !== 'undefined') {
2428
2572
  }
2429
2573
  };
2430
2574
 
2431
- window['_sw_abf38b3d'] = {
2575
+ window['_sw_f371a182'] = {
2432
2576
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2433
2577
  _version: "v11.06",
2434
2578
  _nFeatures: 28106,
@@ -2460,7 +2604,7 @@ if (typeof window !== 'undefined') {
2460
2604
  }
2461
2605
  };
2462
2606
 
2463
- window['_sw_c0a67276'] = {
2607
+ window['_sw_b2a227a4'] = {
2464
2608
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2465
2609
  _version: "v11.06",
2466
2610
  _nFeatures: 28106,
@@ -2492,7 +2636,7 @@ if (typeof window !== 'undefined') {
2492
2636
  }
2493
2637
  };
2494
2638
 
2495
- window['_sw_dd9e3f4f'] = {
2639
+ window['_sw_e17fa488'] = {
2496
2640
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2497
2641
  _version: "v11.06",
2498
2642
  _nFeatures: 28106,
@@ -2524,7 +2668,7 @@ if (typeof window !== 'undefined') {
2524
2668
  }
2525
2669
  };
2526
2670
 
2527
- window['_sw_995b7c6f'] = {
2671
+ window['_sw_c02a750a'] = {
2528
2672
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2529
2673
  _version: "v11.06",
2530
2674
  _nFeatures: 28106,
@@ -2556,7 +2700,7 @@ if (typeof window !== 'undefined') {
2556
2700
  }
2557
2701
  };
2558
2702
 
2559
- window['_sw_1dc4cf2b'] = {
2703
+ window['_sw_693081c5'] = {
2560
2704
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2561
2705
  _version: "v11.06",
2562
2706
  _nFeatures: 28106,
@@ -2588,7 +2732,7 @@ if (typeof window !== 'undefined') {
2588
2732
  }
2589
2733
  };
2590
2734
 
2591
- window['_sw_6a486531'] = {
2735
+ window['_sw_9c6f4627'] = {
2592
2736
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2593
2737
  _version: "v11.06",
2594
2738
  _nFeatures: 28106,
@@ -2620,7 +2764,7 @@ if (typeof window !== 'undefined') {
2620
2764
  }
2621
2765
  };
2622
2766
 
2623
- window['_sw_53e7bf68'] = {
2767
+ window['_sw_b39e9846'] = {
2624
2768
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2625
2769
  _version: "v11.06",
2626
2770
  _nFeatures: 28106,
@@ -2652,7 +2796,7 @@ if (typeof window !== 'undefined') {
2652
2796
  }
2653
2797
  };
2654
2798
 
2655
- window['_sw_278af426'] = {
2799
+ window['_sw_b74f884a'] = {
2656
2800
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2657
2801
  _version: "v11.06",
2658
2802
  _nFeatures: 28106,
@@ -2684,7 +2828,7 @@ if (typeof window !== 'undefined') {
2684
2828
  }
2685
2829
  };
2686
2830
 
2687
- window['_sw_89c3406b'] = {
2831
+ window['_sw_83e6c0cf'] = {
2688
2832
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2689
2833
  _version: "v11.06",
2690
2834
  _nFeatures: 28106,
@@ -2716,7 +2860,7 @@ if (typeof window !== 'undefined') {
2716
2860
  }
2717
2861
  };
2718
2862
 
2719
- window['_sw_9e53f596'] = {
2863
+ window['_sw_8d3a48d4'] = {
2720
2864
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2721
2865
  _version: "v11.06",
2722
2866
  _nFeatures: 28106,
@@ -2748,7 +2892,7 @@ if (typeof window !== 'undefined') {
2748
2892
  }
2749
2893
  };
2750
2894
 
2751
- window['_sw_9658d71c'] = {
2895
+ window['_sw_590271de'] = {
2752
2896
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2753
2897
  _version: "v11.06",
2754
2898
  _nFeatures: 28106,
@@ -2780,7 +2924,7 @@ if (typeof window !== 'undefined') {
2780
2924
  }
2781
2925
  };
2782
2926
 
2783
- window['_sw_77a1e8e0'] = {
2927
+ window['_sw_f01e4f48'] = {
2784
2928
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2785
2929
  _version: "v11.06",
2786
2930
  _nFeatures: 28106,
@@ -2812,7 +2956,7 @@ if (typeof window !== 'undefined') {
2812
2956
  }
2813
2957
  };
2814
2958
 
2815
- window['_sw_acb97f2d'] = {
2959
+ window['_sw_01ff326a'] = {
2816
2960
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2817
2961
  _version: "v11.06",
2818
2962
  _nFeatures: 28106,
@@ -2844,7 +2988,7 @@ if (typeof window !== 'undefined') {
2844
2988
  }
2845
2989
  };
2846
2990
 
2847
- window['_sw_55bb0dbd'] = {
2991
+ window['_sw_b6169022'] = {
2848
2992
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2849
2993
  _version: "v11.06",
2850
2994
  _nFeatures: 28106,
@@ -2876,7 +3020,7 @@ if (typeof window !== 'undefined') {
2876
3020
  }
2877
3021
  };
2878
3022
 
2879
- window['_sw_54268c61'] = {
3023
+ window['_sw_5f961416'] = {
2880
3024
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2881
3025
  _version: "v11.06",
2882
3026
  _nFeatures: 28106,
@@ -2908,7 +3052,7 @@ if (typeof window !== 'undefined') {
2908
3052
  }
2909
3053
  };
2910
3054
 
2911
- window['_sw_2ff00b35'] = {
3055
+ window['_sw_239ce3e3'] = {
2912
3056
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2913
3057
  _version: "v11.06",
2914
3058
  _nFeatures: 28106,
@@ -2940,7 +3084,7 @@ if (typeof window !== 'undefined') {
2940
3084
  }
2941
3085
  };
2942
3086
 
2943
- window['_sw_ec409aed'] = {
3087
+ window['_sw_5f38bfbe'] = {
2944
3088
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2945
3089
  _version: "v11.06",
2946
3090
  _nFeatures: 28106,
@@ -2972,7 +3116,7 @@ if (typeof window !== 'undefined') {
2972
3116
  }
2973
3117
  };
2974
3118
 
2975
- window['_sw_c37e2cef'] = {
3119
+ window['_sw_cee9feed'] = {
2976
3120
  _vocab: { decoy: 1, trap: 2 }, // Base signature
2977
3121
  _version: "v11.06",
2978
3122
  _nFeatures: 28106,
@@ -3004,7 +3148,7 @@ if (typeof window !== 'undefined') {
3004
3148
  }
3005
3149
  };
3006
3150
 
3007
- window['_sw_ad4dce9b'] = {
3151
+ window['_sw_975ec724'] = {
3008
3152
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3009
3153
  _version: "v11.06",
3010
3154
  _nFeatures: 28106,
@@ -3036,7 +3180,7 @@ if (typeof window !== 'undefined') {
3036
3180
  }
3037
3181
  };
3038
3182
 
3039
- window['_sw_96a467a3'] = {
3183
+ window['_sw_9f6b5ede'] = {
3040
3184
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3041
3185
  _version: "v11.06",
3042
3186
  _nFeatures: 28106,
@@ -3068,7 +3212,7 @@ if (typeof window !== 'undefined') {
3068
3212
  }
3069
3213
  };
3070
3214
 
3071
- window['_sw_5591eaa1'] = {
3215
+ window['_sw_d64efcb5'] = {
3072
3216
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3073
3217
  _version: "v11.06",
3074
3218
  _nFeatures: 28106,
@@ -3100,7 +3244,7 @@ if (typeof window !== 'undefined') {
3100
3244
  }
3101
3245
  };
3102
3246
 
3103
- window['_sw_610db422'] = {
3247
+ window['_sw_c1a3b490'] = {
3104
3248
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3105
3249
  _version: "v11.06",
3106
3250
  _nFeatures: 28106,
@@ -3132,7 +3276,7 @@ if (typeof window !== 'undefined') {
3132
3276
  }
3133
3277
  };
3134
3278
 
3135
- window['_sw_91f9a36a'] = {
3279
+ window['_sw_f391d5c3'] = {
3136
3280
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3137
3281
  _version: "v11.06",
3138
3282
  _nFeatures: 28106,
@@ -3164,7 +3308,7 @@ if (typeof window !== 'undefined') {
3164
3308
  }
3165
3309
  };
3166
3310
 
3167
- window['_sw_9a701c99'] = {
3311
+ window['_sw_4b5ebe20'] = {
3168
3312
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3169
3313
  _version: "v11.06",
3170
3314
  _nFeatures: 28106,
@@ -3196,7 +3340,7 @@ if (typeof window !== 'undefined') {
3196
3340
  }
3197
3341
  };
3198
3342
 
3199
- window['_sw_eaacc5a4'] = {
3343
+ window['_sw_1fe8e9d4'] = {
3200
3344
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3201
3345
  _version: "v11.06",
3202
3346
  _nFeatures: 28106,
@@ -3228,7 +3372,7 @@ if (typeof window !== 'undefined') {
3228
3372
  }
3229
3373
  };
3230
3374
 
3231
- window['_sw_35c55010'] = {
3375
+ window['_sw_f8a6da1d'] = {
3232
3376
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3233
3377
  _version: "v11.06",
3234
3378
  _nFeatures: 28106,
@@ -3260,7 +3404,7 @@ if (typeof window !== 'undefined') {
3260
3404
  }
3261
3405
  };
3262
3406
 
3263
- window['_sw_9e803c49'] = {
3407
+ window['_sw_6676a2d0'] = {
3264
3408
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3265
3409
  _version: "v11.06",
3266
3410
  _nFeatures: 28106,
@@ -3292,7 +3436,7 @@ if (typeof window !== 'undefined') {
3292
3436
  }
3293
3437
  };
3294
3438
 
3295
- window['_sw_98170b48'] = {
3439
+ window['_sw_eefee361'] = {
3296
3440
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3297
3441
  _version: "v11.06",
3298
3442
  _nFeatures: 28106,
@@ -3324,7 +3468,7 @@ if (typeof window !== 'undefined') {
3324
3468
  }
3325
3469
  };
3326
3470
 
3327
- window['_sw_74ec3bf4'] = {
3471
+ window['_sw_2d489ccc'] = {
3328
3472
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3329
3473
  _version: "v11.06",
3330
3474
  _nFeatures: 28106,
@@ -3356,7 +3500,7 @@ if (typeof window !== 'undefined') {
3356
3500
  }
3357
3501
  };
3358
3502
 
3359
- window['_sw_5bc562d2'] = {
3503
+ window['_sw_9aba0dd3'] = {
3360
3504
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3361
3505
  _version: "v11.06",
3362
3506
  _nFeatures: 28106,
@@ -3388,7 +3532,7 @@ if (typeof window !== 'undefined') {
3388
3532
  }
3389
3533
  };
3390
3534
 
3391
- window['_sw_23090dc8'] = {
3535
+ window['_sw_f9f4771b'] = {
3392
3536
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3393
3537
  _version: "v11.06",
3394
3538
  _nFeatures: 28106,
@@ -3420,7 +3564,7 @@ if (typeof window !== 'undefined') {
3420
3564
  }
3421
3565
  };
3422
3566
 
3423
- window['_sw_fe870ae8'] = {
3567
+ window['_sw_87e6e93f'] = {
3424
3568
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3425
3569
  _version: "v11.06",
3426
3570
  _nFeatures: 28106,
@@ -3452,7 +3596,7 @@ if (typeof window !== 'undefined') {
3452
3596
  }
3453
3597
  };
3454
3598
 
3455
- window['_sw_c0cf3414'] = {
3599
+ window['_sw_f2b09c5f'] = {
3456
3600
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3457
3601
  _version: "v11.06",
3458
3602
  _nFeatures: 28106,
@@ -3484,7 +3628,7 @@ if (typeof window !== 'undefined') {
3484
3628
  }
3485
3629
  };
3486
3630
 
3487
- window['_sw_88e29f5c'] = {
3631
+ window['_sw_d108b2ca'] = {
3488
3632
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3489
3633
  _version: "v11.06",
3490
3634
  _nFeatures: 28106,
@@ -3516,7 +3660,7 @@ if (typeof window !== 'undefined') {
3516
3660
  }
3517
3661
  };
3518
3662
 
3519
- window['_sw_6eee44f7'] = {
3663
+ window['_sw_1ced21d6'] = {
3520
3664
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3521
3665
  _version: "v11.06",
3522
3666
  _nFeatures: 28106,
@@ -3548,7 +3692,7 @@ if (typeof window !== 'undefined') {
3548
3692
  }
3549
3693
  };
3550
3694
 
3551
- window['_sw_4214d3f4'] = {
3695
+ window['_sw_a0222071'] = {
3552
3696
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3553
3697
  _version: "v11.06",
3554
3698
  _nFeatures: 28106,
@@ -3580,7 +3724,7 @@ if (typeof window !== 'undefined') {
3580
3724
  }
3581
3725
  };
3582
3726
 
3583
- window['_sw_95306b6f'] = {
3727
+ window['_sw_581d3304'] = {
3584
3728
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3585
3729
  _version: "v11.06",
3586
3730
  _nFeatures: 28106,
@@ -3612,7 +3756,7 @@ if (typeof window !== 'undefined') {
3612
3756
  }
3613
3757
  };
3614
3758
 
3615
- window['_sw_a0e816cd'] = {
3759
+ window['_sw_13567d33'] = {
3616
3760
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3617
3761
  _version: "v11.06",
3618
3762
  _nFeatures: 28106,
@@ -3644,7 +3788,7 @@ if (typeof window !== 'undefined') {
3644
3788
  }
3645
3789
  };
3646
3790
 
3647
- window['_sw_d55b86db'] = {
3791
+ window['_sw_8ed75968'] = {
3648
3792
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3649
3793
  _version: "v11.06",
3650
3794
  _nFeatures: 28106,
@@ -3676,7 +3820,7 @@ if (typeof window !== 'undefined') {
3676
3820
  }
3677
3821
  };
3678
3822
 
3679
- window['_sw_3fecddc1'] = {
3823
+ window['_sw_4924c241'] = {
3680
3824
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3681
3825
  _version: "v11.06",
3682
3826
  _nFeatures: 28106,
@@ -3708,7 +3852,7 @@ if (typeof window !== 'undefined') {
3708
3852
  }
3709
3853
  };
3710
3854
 
3711
- window['_sw_3feeb214'] = {
3855
+ window['_sw_fde63cb6'] = {
3712
3856
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3713
3857
  _version: "v11.06",
3714
3858
  _nFeatures: 28106,
@@ -3740,7 +3884,7 @@ if (typeof window !== 'undefined') {
3740
3884
  }
3741
3885
  };
3742
3886
 
3743
- window['_sw_e354ef59'] = {
3887
+ window['_sw_16e9ba8e'] = {
3744
3888
  _vocab: { decoy: 1, trap: 2 }, // Base signature
3745
3889
  _version: "v11.06",
3746
3890
  _nFeatures: 28106,