@amatiscorp/disguard 1.0.0 → 1.2.0

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.
Files changed (68) hide show
  1. package/README.md +223 -3
  2. package/dist/AntiSpam.d.ts +22 -5
  3. package/dist/AntiSpam.d.ts.map +1 -1
  4. package/dist/AntiSpam.js +154 -21
  5. package/dist/AntiSpam.js.map +1 -1
  6. package/dist/defaults.d.ts.map +1 -1
  7. package/dist/defaults.js +65 -2
  8. package/dist/defaults.js.map +1 -1
  9. package/dist/detectors/accounts.d.ts +3 -0
  10. package/dist/detectors/accounts.d.ts.map +1 -0
  11. package/dist/detectors/accounts.js +37 -0
  12. package/dist/detectors/accounts.js.map +1 -0
  13. package/dist/detectors/duplicates.d.ts.map +1 -1
  14. package/dist/detectors/duplicates.js +5 -1
  15. package/dist/detectors/duplicates.js.map +1 -1
  16. package/dist/detectors/files.d.ts +4 -0
  17. package/dist/detectors/files.d.ts.map +1 -0
  18. package/dist/detectors/files.js +42 -0
  19. package/dist/detectors/files.js.map +1 -0
  20. package/dist/detectors/flood.d.ts.map +1 -1
  21. package/dist/detectors/flood.js +7 -1
  22. package/dist/detectors/flood.js.map +1 -1
  23. package/dist/detectors/images.d.ts +1 -0
  24. package/dist/detectors/images.d.ts.map +1 -1
  25. package/dist/detectors/images.js +19 -3
  26. package/dist/detectors/images.js.map +1 -1
  27. package/dist/detectors/length.d.ts +3 -0
  28. package/dist/detectors/length.d.ts.map +1 -0
  29. package/dist/detectors/length.js +23 -0
  30. package/dist/detectors/length.js.map +1 -0
  31. package/dist/detectors/links.d.ts +2 -0
  32. package/dist/detectors/links.d.ts.map +1 -1
  33. package/dist/detectors/links.js +29 -5
  34. package/dist/detectors/links.js.map +1 -1
  35. package/dist/detectors/mentions.d.ts.map +1 -1
  36. package/dist/detectors/mentions.js +19 -0
  37. package/dist/detectors/mentions.js.map +1 -1
  38. package/dist/detectors/newlines.d.ts +3 -0
  39. package/dist/detectors/newlines.d.ts.map +1 -0
  40. package/dist/detectors/newlines.js +25 -0
  41. package/dist/detectors/newlines.js.map +1 -0
  42. package/dist/detectors/zalgo.d.ts +3 -0
  43. package/dist/detectors/zalgo.d.ts.map +1 -0
  44. package/dist/detectors/zalgo.js +25 -0
  45. package/dist/detectors/zalgo.js.map +1 -0
  46. package/dist/enforcement.d.ts +1 -0
  47. package/dist/enforcement.d.ts.map +1 -1
  48. package/dist/enforcement.js +30 -9
  49. package/dist/enforcement.js.map +1 -1
  50. package/dist/index.d.ts +5 -2
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +11 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/locale.d.ts +14 -0
  55. package/dist/locale.d.ts.map +1 -0
  56. package/dist/locale.js +35 -0
  57. package/dist/locale.js.map +1 -0
  58. package/dist/store/MemoryStore.d.ts +2 -0
  59. package/dist/store/MemoryStore.d.ts.map +1 -1
  60. package/dist/store/MemoryStore.js +14 -2
  61. package/dist/store/MemoryStore.js.map +1 -1
  62. package/dist/types.d.ts +82 -13
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/utils/normalize.d.ts +2 -0
  65. package/dist/utils/normalize.d.ts.map +1 -1
  66. package/dist/utils/normalize.js +8 -0
  67. package/dist/utils/normalize.js.map +1 -1
  68. package/package.json +1 -1
package/README.md CHANGED
@@ -21,8 +21,92 @@ Detects flood, repeated text, phishing / unwanted links, duplicate images, menti
21
21
 
22
22
  # English
23
23
 
24
+ ## What's new in 1.2.0
25
+
26
+ More knobs, per-channel rules, and bilingual user-facing text.
27
+
28
+ | Option | What it does |
29
+ | --- | --- |
30
+ | `locale` | `"en"` or `"es"` for warn + log labels. Empty `warnMessage` uses the locale template. |
31
+ | `ignorePermissions` | Skip members with those Discord permission names (`ManageMessages`, …). |
32
+ | `setChannelConfig(guildId, channelId, patch)` | Rules for one channel (on top of guild + global). |
33
+ | `channelOverrides` | Same thing in static config: `{ "CHANNEL_ID": { flood: { maxMessages: 10 } } }`. |
34
+ | `disabledDetectors` | Turn off detectors by name without touching each block. |
35
+ | `detectorOrder` | Custom detector run order. |
36
+ | `flood.sameChannelOnly` / `duplicates.sameChannelOnly` | Count only the current channel. |
37
+ | `links.maxLinks` / `links.scanEmbeds` | Cap URLs per message; toggle embed scanning. |
38
+ | `images.skipContentTypes` / `images.maxAttachments` | Ignore GIFs, limit images per message. |
39
+ | `mentions.maxRepeatsOfSame` | Same user pinged over and over in one message. |
40
+ | `accounts` | Flag brand-new accounts (`minAgeDays`) or default avatars. Off by default. |
41
+ | `length` | Flag walls of text. Off by default. |
42
+ | `punishment.timeout.scale` | `"none"` \| `"linear"` \| `"exponential"` with `maxDurationMs`. |
43
+ | `punishment.warnAsEmbed` | Warning as an embed. |
44
+
45
+ ```js
46
+ const antispam = new AntiSpam(client, {
47
+ preset: "balanced",
48
+ locale: "es",
49
+ ignorePermissions: ["ManageMessages", "ModerateMembers"],
50
+ flood: { sameChannelOnly: true },
51
+ links: { maxLinks: 3, scanEmbeds: true },
52
+ accounts: { enabled: true, minAgeDays: 2 },
53
+ punishment: {
54
+ warnAsEmbed: true,
55
+ timeout: { enabled: true, durationMs: 60_000, scale: "linear", maxDurationMs: 10 * 60_000 },
56
+ },
57
+ disabledDetectors: ["caps"],
58
+ channelOverrides: {
59
+ "MEMES_CHANNEL_ID": { images: { maxRepeats: 8 }, emojis: { maxEmojis: 30 } },
60
+ },
61
+ });
62
+
63
+ antispam.setChannelConfig(guildId, channelId, { flood: { maxMessages: 12 } });
64
+ ```
65
+
66
+ ## What's new in 1.1.0
67
+
68
+ - **Punishment cooldown** — after a strike, Disguard waits `punishment.cooldownMs` (8s by default) before warning / timeout / kick / ban again. Extra spam in that window is deleted quietly. This stops the “4 timeouts in one flood” you saw in 1.0.0.
69
+ - **Per-guild config** — `setGuildConfig(guildId, patch)`, `getGuildConfig`, `clearGuildConfig`.
70
+ - **Custom detectors** — `antispam.use({ type, inspect })`.
71
+ - **Stats** — `getStats()` / `resetStats()`.
72
+ - **New detectors:** dangerous files (`.exe`, `.bat`, …), zalgo / stacked diacritics, newline walls.
73
+ - **Links in embeds** — phishing checks also read embed title, description, fields and footer.
74
+ - `isCoolingDown(guildId, userId)`.
75
+
76
+ ```js
77
+ antispam.setGuildConfig("123456789", {
78
+ flood: { maxMessages: 3 },
79
+ links: { blockInvites: true },
80
+ });
81
+
82
+ antispam.use({
83
+ type: "flood",
84
+ inspect({ message, snapshot }) {
85
+ if (message.content.includes("raid-now")) {
86
+ return {
87
+ type: "flood",
88
+ severity: "critical",
89
+ userId: message.author.id,
90
+ guildId: message.guild.id,
91
+ channelId: snapshot.channelId,
92
+ messageId: snapshot.id,
93
+ reason: "Custom raid keyword",
94
+ details: {},
95
+ recommendedActions: ["delete", "timeout"],
96
+ timestamp: snapshot.timestamp,
97
+ };
98
+ }
99
+ return null;
100
+ },
101
+ });
102
+
103
+ console.log(antispam.getStats());
104
+ ```
105
+
24
106
  ## Table of contents
25
107
 
108
+ - [What's new in 1.2.0](#whats-new-in-120)
109
+ - [What's new in 1.1.0](#whats-new-in-110)
26
110
  - [Features](#features)
27
111
  - [Requirements](#requirements)
28
112
  - [Install](#install)
@@ -51,6 +135,11 @@ Detects flood, repeated text, phishing / unwanted links, duplicate images, menti
51
135
  | **mention** | `@everyone`, `@here`, too many unique mentions |
52
136
  | **caps** | Messages that are mostly uppercase |
53
137
  | **emoji** | Too many emojis or stickers in one message |
138
+ | **file** | Dangerous attachments (`.exe`, `.bat`, `.dll`, `.msi`, …) |
139
+ | **zalgo** | Obfuscated / zalgo text (stacked combining marks) |
140
+ | **newline** | Message walls made of empty lines |
141
+ | **account** | Brand-new Discord accounts / default avatar (off by default) |
142
+ | **length** | Over-long messages (off by default) |
54
143
 
55
144
  Also included:
56
145
 
@@ -183,7 +272,7 @@ Enable **Message Content Intent** in the [Discord Developer Portal](https://disc
183
272
 
184
273
  1. Ignores bots, webhooks, the owner, administrators, and anything in your ignore lists.
185
274
  2. Keeps a short **in-memory** history per user and guild (no database).
186
- 3. Runs detectors in this order: flood → duplicates → links → images → mentions → caps → emojis. The first match wins.
275
+ 3. Runs detectors in this order: files → flood → duplicates → links → images → mentions → zalgo → newlines → caps → emojis. The first match wins.
187
276
  4. Adds one strike (with optional decay) and applies the configured punishment.
188
277
  5. Message edits only re-check **links** and **mentions**, so editing `hello` into a phishing URL is still caught without counting as flood.
189
278
 
@@ -233,6 +322,11 @@ Every option is optional. Missing fields fall back to the preset (or `balanced`
233
322
  | `ignoreAdministrators` | `boolean` | `true` | Skip members with Administrator. |
234
323
  | `checkEdits` | `boolean` | `true` | Re-scan edits for links and mentions. |
235
324
  | `cleanupIntervalMs` | `number` | `60000` | How often the memory store is pruned. |
325
+ | `locale` | `"en"` \| `"es"` | `"en"` | Language for warnings and log embeds. |
326
+ | `ignorePermissions` | `string[]` | `[]` | Permission names that bypass checks. |
327
+ | `disabledDetectors` | `DetectorType[]` | `[]` | Detectors to skip. |
328
+ | `detectorOrder` | `DetectorType[]` | `[]` | Custom order. Empty = default. |
329
+ | `channelOverrides` | `object` | `{}` | Per-channel patches keyed by channel id. |
236
330
 
237
331
  ### Ignore lists
238
332
 
@@ -373,6 +467,45 @@ emojis: {
373
467
  }
374
468
  ```
375
469
 
470
+ ### Accounts and length
471
+
472
+ ```js
473
+ accounts: {
474
+ enabled: false, // turn on to flag new users
475
+ minAgeDays: 3,
476
+ blockDefaultAvatar: false,
477
+ severity: "medium",
478
+ }
479
+
480
+ length: {
481
+ enabled: false,
482
+ maxCharacters: 1000,
483
+ severity: "low",
484
+ }
485
+ ```
486
+
487
+ ### Files, zalgo, newlines
488
+
489
+ ```js
490
+ files: {
491
+ enabled: true,
492
+ blockedExtensions: ["exe", "bat", "cmd", "com", "scr", "dll", "msi", "vbs", "ps1", "jar", "apk"],
493
+ severity: "critical",
494
+ }
495
+
496
+ zalgo: {
497
+ enabled: true,
498
+ maxCombining: 20,
499
+ severity: "medium",
500
+ }
501
+
502
+ newlines: {
503
+ enabled: true,
504
+ maxNewlines: 15,
505
+ severity: "low",
506
+ }
507
+ ```
508
+
376
509
  ### Punishment
377
510
 
378
511
  Kick and ban stay **disabled** on purpose. Turn them on only if you really want that.
@@ -389,7 +522,14 @@ punishment: {
389
522
  escalate: true,
390
523
  logChannelId: "CHANNEL_ID_OR_NULL",
391
524
  strikeDecayMs: 15 * 60_000, // strikes expire after 15 minutes
525
+ cooldownMs: 8_000, // no second timeout/warn during this window
526
+ deleteDuringCooldown: true, // still delete extra spam quietly
527
+ warnAsEmbed: false,
392
528
  }
529
+
530
+ // timeout.scale: "none" | "linear" (base * strikes) | "exponential" (base * 2^n)
531
+ // timeout.maxDurationMs caps the result (Discord max = 28 days)
532
+
393
533
  ```
394
534
 
395
535
  `warnMessage` placeholders: `{user}` `{reason}` `{type}` `{strikes}`.
@@ -460,6 +600,18 @@ antispam.setConfig({ flood: { maxMessages: 8 } }); // deep merge, other keys sta
460
600
 
461
601
  antispam.getStrikes(guildId, userId);
462
602
  antispam.resetUser(guildId, userId);
603
+ antispam.isCoolingDown(guildId, userId);
604
+
605
+ antispam.setGuildConfig(guildId, { flood: { maxMessages: 3 } });
606
+ antispam.getGuildConfig(guildId);
607
+ antispam.clearGuildConfig(guildId);
608
+ antispam.setChannelConfig(guildId, channelId, { images: { maxRepeats: 8 } });
609
+ antispam.getChannelConfig(guildId, channelId);
610
+ antispam.clearChannelConfig(guildId, channelId);
611
+
612
+ antispam.use(customDetector);
613
+ antispam.getStats();
614
+ antispam.resetStats();
463
615
 
464
616
  // Analyze only — no punishment, no callbacks
465
617
  const incident = await antispam.analyze(message);
@@ -591,6 +743,9 @@ Wait a few seconds between categories so flood does not eat the next test.
591
743
  | Mentions | `@everyone`, `@here`, or 7 different users |
592
744
  | Caps | `THIS IS A MESSAGE IN ALL CAPS` (16+ letters) |
593
745
  | Emojis | 13+ emojis, or 4 stickers |
746
+ | File | Upload a dummy `.exe` or `.bat` |
747
+ | Zalgo | Text with many stacked combining marks |
748
+ | Newlines | A message with more than 15 line breaks |
594
749
  | Edit | Send `hello`, then edit it to `Free Nitro https://bit.ly/test` |
595
750
 
596
751
  Watch the terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji`.
@@ -634,8 +789,58 @@ MIT
634
789
 
635
790
  # Español
636
791
 
792
+ ## Novedades de 1.2.0
793
+
794
+ Más opciones, reglas por canal y textos al usuario en inglés o español.
795
+
796
+ | Opción | Qué hace |
797
+ | --- | --- |
798
+ | `locale` | `"en"` o `"es"` para avisos y logs. Si `warnMessage` está vacío, usa la plantilla del idioma. |
799
+ | `ignorePermissions` | Ignora quien tenga esos permisos (`ManageMessages`, …). |
800
+ | `setChannelConfig` | Config de un canal (encima de guild + global). |
801
+ | `channelOverrides` | Lo mismo en la config estática. |
802
+ | `disabledDetectors` | Apaga detectores por nombre. |
803
+ | `detectorOrder` | Orden de ejecución. |
804
+ | `flood.sameChannelOnly` / `duplicates.sameChannelOnly` | Solo cuenta el canal actual. |
805
+ | `links.maxLinks` / `links.scanEmbeds` | Tope de URLs; escanear embeds. |
806
+ | `images.skipContentTypes` / `images.maxAttachments` | Ignorar gifs, limitar adjuntos. |
807
+ | `mentions.maxRepeatsOfSame` | El mismo ping repetido. |
808
+ | `accounts` | Cuentas nuevas (`minAgeDays`) o avatar por defecto. Apagado por defecto. |
809
+ | `length` | Mensajes kilométricos. Apagado por defecto. |
810
+ | `punishment.timeout.scale` | `"none"` \| `"linear"` \| `"exponential"`. |
811
+ | `punishment.warnAsEmbed` | Aviso en embed. |
812
+
813
+ ```js
814
+ new AntiSpam(client, {
815
+ locale: "es",
816
+ ignorePermissions: ["ManageMessages"],
817
+ flood: { sameChannelOnly: true },
818
+ links: { maxLinks: 3 },
819
+ accounts: { enabled: true, minAgeDays: 2 },
820
+ punishment: {
821
+ warnAsEmbed: true,
822
+ timeout: { durationMs: 60_000, scale: "linear", maxDurationMs: 600_000 },
823
+ },
824
+ channelOverrides: {
825
+ "ID_CANAL_MEMES": { emojis: { maxEmojis: 30 } },
826
+ },
827
+ });
828
+ ```
829
+
830
+ ## Novedades de 1.1.0
831
+
832
+ - **Cooldown de castigo** — tras un strike espera `punishment.cooldownMs` (8s por defecto) antes de volver a avisar o timeout. El spam extra de esa ventana se borra en silencio. Así no salen 4 timeouts en el mismo flood.
833
+ - **Config por servidor** — `setGuildConfig`, `getGuildConfig`, `clearGuildConfig`.
834
+ - **Detectores propios** — `antispam.use({ type, inspect })`.
835
+ - **Estadísticas** — `getStats()` / `resetStats()`.
836
+ - **Nuevos detectores:** archivos peligrosos, zalgo, paredes de saltos de línea.
837
+ - **Enlaces en embeds** — también se revisan título, descripción, fields y footer.
838
+ - `isCoolingDown(guildId, userId)`.
839
+
637
840
  ## Tabla de contenidos
638
841
 
842
+ - [Novedades de 1.2.0](#novedades-de-120)
843
+ - [Novedades de 1.1.0](#novedades-de-110)
639
844
  - [Qué es](#qué-es)
640
845
  - [Requisitos](#requisitos)
641
846
  - [Instalación](#instalación)
@@ -657,7 +862,7 @@ MIT
657
862
 
658
863
  **Disguard** es una librería antispam para bots de discord.js v14. No es un bot: la enchufas a tu `Client` y tú decides umbrales, listas y castigos.
659
864
 
660
- Detecta flood, texto repetido, phishing / enlaces no deseados, imágenes repetidas, spam de menciones, mayúsculas y emojis.
865
+ Detecta flood, texto repetido, phishing / enlaces no deseados (también en embeds), imágenes repetidas, spam de menciones, mayúsculas, emojis, archivos peligrosos, zalgo y paredes de líneas.
661
866
 
662
867
  ## Requisitos
663
868
 
@@ -878,6 +1083,14 @@ caps: { enabled: true, minLength: 16, maxPercent: 75, severity: "low" },
878
1083
  emojis: { enabled: true, maxEmojis: 12, maxStickers: 3, severity: "low" },
879
1084
  ```
880
1085
 
1086
+ ### Archivos, zalgo, saltos de línea
1087
+
1088
+ ```js
1089
+ files: { enabled: true, blockedExtensions: ["exe", "bat", "cmd", "dll", "msi"], severity: "critical" },
1090
+ zalgo: { enabled: true, maxCombining: 20, severity: "medium" },
1091
+ newlines: { enabled: true, maxNewlines: 15, severity: "low" },
1092
+ ```
1093
+
881
1094
  ### Castigos
882
1095
 
883
1096
  Kick y ban van **apagados**. Actívalos solo si lo tienes claro.
@@ -894,6 +1107,8 @@ punishment: {
894
1107
  escalate: true,
895
1108
  logChannelId: "ID_O_NULL",
896
1109
  strikeDecayMs: 15 * 60_000,
1110
+ cooldownMs: 8_000,
1111
+ deleteDuringCooldown: true,
897
1112
  }
898
1113
  ```
899
1114
 
@@ -927,6 +1142,8 @@ antispam.getConfig();
927
1142
  antispam.setConfig({ flood: { maxMessages: 8 } });
928
1143
  antispam.getStrikes(guildId, userId);
929
1144
  antispam.resetUser(guildId, userId);
1145
+ antispam.setGuildConfig(guildId, { flood: { maxMessages: 3 } });
1146
+ antispam.getStats();
930
1147
 
931
1148
  const incident = await antispam.analyze(message);
932
1149
  const editado = await antispam.analyze(message, { isEdit: true });
@@ -991,9 +1208,12 @@ Espera unos segundos entre categorías.
991
1208
  | Menciones | `@everyone`, `@here`, o 7 usuarios |
992
1209
  | Caps | `ESTO ES UN MENSAJE TODO EN MAYUSCULAS` |
993
1210
  | Emojis | Más de 12 emojis, o 4 stickers |
1211
+ | Archivo | Sube un `.exe` o `.bat` (aunque sea de mentira) |
1212
+ | Zalgo | Texto con muchos diacríticos apilados |
1213
+ | Líneas | Un mensaje con más de 15 enters |
994
1214
  | Edición | Manda `hola` y edítalo a `Free Nitro https://bit.ly/test` |
995
1215
 
996
- En la terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji`.
1216
+ En la terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji|file|zalgo|newline`.
997
1217
 
998
1218
  Al segundo strike el ejemplo mete timeout de 1 minuto. Los strikes caducan a los 15 minutos, o usa `resetUser`.
999
1219
 
@@ -1,34 +1,51 @@
1
1
  import { type Client, type Message } from "discord.js";
2
2
  import { MemoryStore } from "./store/MemoryStore";
3
- import type { AntiSpamOptions, DeepPartial, Incident, ResolvedConfig } from "./types";
3
+ import type { AntiSpamOptions, AntiSpamStats, DeepPartial, Detector, Incident, ResolvedConfig } from "./types";
4
4
  export declare class AntiSpam {
5
5
  readonly client: Client;
6
6
  readonly store: MemoryStore;
7
7
  private config;
8
8
  private readonly detectors;
9
9
  private readonly options;
10
+ private readonly guildConfigs;
11
+ private readonly channelConfigs;
12
+ private stats;
10
13
  private started;
11
14
  private cleanupTimer;
12
15
  private readonly onMessage;
13
16
  private readonly onEdit;
14
17
  constructor(client: Client, options?: AntiSpamOptions);
15
- /** Empieza a escuchar `messageCreate` (y `messageUpdate` si está activo). */
18
+ /** Starts listening to `messageCreate` (and `messageUpdate` if enabled). */
16
19
  start(): this;
17
- /** Deja de escuchar eventos. Llama esto al apagar el bot. */
20
+ /** Stops listening. Call this on shutdown. */
18
21
  stop(): this;
22
+ /** Adds a custom detector. It runs after the built-in ones. */
23
+ use(detector: Detector): this;
19
24
  getConfig(): ResolvedConfig;
20
25
  setConfig(patch: DeepPartial<ResolvedConfig>): ResolvedConfig;
26
+ /** Global defaults + this guild's overrides. */
27
+ getGuildConfig(guildId: string): ResolvedConfig;
28
+ setGuildConfig(guildId: string, patch: DeepPartial<ResolvedConfig>): ResolvedConfig;
29
+ clearGuildConfig(guildId: string): void;
30
+ getChannelConfig(guildId: string, channelId: string): ResolvedConfig;
31
+ setChannelConfig(guildId: string, channelId: string, patch: DeepPartial<ResolvedConfig>): ResolvedConfig;
32
+ clearChannelConfig(guildId: string, channelId: string): void;
21
33
  getStrikes(guildId: string, userId: string): number;
34
+ isCoolingDown(guildId: string, userId: string): boolean;
22
35
  resetUser(guildId: string, userId: string): void;
36
+ getStats(): AntiSpamStats;
37
+ resetStats(): void;
23
38
  /**
24
- * Analiza un mensaje sin aplicar castigos.
25
- * Útil para tests o para integrar tu propio sistema de sanciones.
39
+ * Analyzes a message without punishing.
40
+ * Useful for tests or your own sanction pipeline.
26
41
  */
27
42
  analyze(message: Message, options?: {
28
43
  isEdit?: boolean;
29
44
  }): Promise<Incident | null>;
30
45
  private handle;
31
46
  shouldIgnore(message: Message): boolean;
47
+ private configFor;
48
+ private orderedDetectors;
32
49
  private toSnapshot;
33
50
  private maxRetentionMs;
34
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AntiSpam.d.ts","sourceRoot":"","sources":["../src/AntiSpam.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAUpB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EAEX,QAAQ,EAER,cAAc,EACf,MAAM,SAAS,CAAC;AAGjB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,cAAqB;IAEnC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAA+B;IAEnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAExB;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGrB;gBAEU,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;IAgBzD,6EAA6E;IAC7E,KAAK,IAAI,IAAI;IAcb,6DAA6D;IAC7D,IAAI,IAAI,IAAI;IAYZ,SAAS,IAAI,cAAc;IAI3B,SAAS,CAAC,KAAK,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,cAAc;IAK7D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAInD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIhD;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;YAqC/E,MAAM;IAwBpB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IA4BvC,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,cAAc;CASvB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAElF"}
1
+ {"version":3,"file":"AntiSpam.d.ts","sourceRoot":"","sources":["../src/AntiSpam.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAepB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EACb,WAAW,EACX,QAAQ,EAER,QAAQ,EAER,cAAc,EACf,MAAM,SAAS,CAAC;AA8BjB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,cAAqB;IAEnC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkD;IAC/E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkD;IACjF,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAA+B;IAEnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAExB;IAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGrB;gBAEU,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;IAqBzD,4EAA4E;IAC5E,KAAK,IAAI,IAAI;IAcb,8CAA8C;IAC9C,IAAI,IAAI,IAAI;IAYZ,+DAA+D;IAC/D,GAAG,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAK7B,SAAS,IAAI,cAAc;IAI3B,SAAS,CAAC,KAAK,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,cAAc;IAK7D,gDAAgD;IAChD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;IAI/C,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,cAAc;IAMnF,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIvC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc;IAIpE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,cAAc,CAAC,GAAG,cAAc;IAOxG,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI5D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IASnD,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAKvD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIhD,QAAQ,IAAI,aAAa;IAIzB,UAAU,IAAI,IAAI;IAIlB;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;YA0C/E,MAAM;IAkDpB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAgCvC,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,cAAc;CAUvB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAElF"}