@amatiscorp/disguard 1.1.0 → 1.3.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.
- package/README.md +384 -22
- package/dist/AntiSpam.d.ts +15 -1
- package/dist/AntiSpam.d.ts.map +1 -1
- package/dist/AntiSpam.js +159 -12
- package/dist/AntiSpam.js.map +1 -1
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +79 -2
- package/dist/defaults.js.map +1 -1
- package/dist/detectors/accounts.d.ts +3 -0
- package/dist/detectors/accounts.d.ts.map +1 -0
- package/dist/detectors/accounts.js +50 -0
- package/dist/detectors/accounts.js.map +1 -0
- package/dist/detectors/duplicates.d.ts.map +1 -1
- package/dist/detectors/duplicates.js +5 -1
- package/dist/detectors/duplicates.js.map +1 -1
- package/dist/detectors/files.d.ts.map +1 -1
- package/dist/detectors/files.js +10 -0
- package/dist/detectors/files.js.map +1 -1
- package/dist/detectors/flood.d.ts.map +1 -1
- package/dist/detectors/flood.js +7 -1
- package/dist/detectors/flood.js.map +1 -1
- package/dist/detectors/ghost.d.ts +4 -0
- package/dist/detectors/ghost.d.ts.map +1 -0
- package/dist/detectors/ghost.js +34 -0
- package/dist/detectors/ghost.js.map +1 -0
- package/dist/detectors/hop.d.ts +3 -0
- package/dist/detectors/hop.d.ts.map +1 -0
- package/dist/detectors/hop.js +30 -0
- package/dist/detectors/hop.js.map +1 -0
- package/dist/detectors/images.d.ts +1 -0
- package/dist/detectors/images.d.ts.map +1 -1
- package/dist/detectors/images.js +19 -3
- package/dist/detectors/images.js.map +1 -1
- package/dist/detectors/length.d.ts +3 -0
- package/dist/detectors/length.d.ts.map +1 -0
- package/dist/detectors/length.js +23 -0
- package/dist/detectors/length.js.map +1 -0
- package/dist/detectors/links.d.ts.map +1 -1
- package/dist/detectors/links.js +15 -1
- package/dist/detectors/links.js.map +1 -1
- package/dist/detectors/mentions.d.ts.map +1 -1
- package/dist/detectors/mentions.js +19 -0
- package/dist/detectors/mentions.js.map +1 -1
- package/dist/detectors/punctuation.d.ts +3 -0
- package/dist/detectors/punctuation.d.ts.map +1 -0
- package/dist/detectors/punctuation.js +26 -0
- package/dist/detectors/punctuation.js.map +1 -0
- package/dist/detectors/spoilers.d.ts +3 -0
- package/dist/detectors/spoilers.d.ts.map +1 -0
- package/dist/detectors/spoilers.js +25 -0
- package/dist/detectors/spoilers.js.map +1 -0
- package/dist/detectors/words.d.ts +3 -0
- package/dist/detectors/words.d.ts.map +1 -0
- package/dist/detectors/words.js +56 -0
- package/dist/detectors/words.js.map +1 -0
- package/dist/enforcement.d.ts +1 -0
- package/dist/enforcement.d.ts.map +1 -1
- package/dist/enforcement.js +57 -9
- package/dist/enforcement.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +14 -0
- package/dist/locale.d.ts.map +1 -0
- package/dist/locale.js +35 -0
- package/dist/locale.js.map +1 -0
- package/dist/types.d.ts +103 -15
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# Disguard
|
|
2
2
|
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**Configurable antispam for discord.js v14**
|
|
6
|
+
|
|
7
|
+
Flood · phishing · channel hop · blocked words · ghost pings · TypeScript
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@amatiscorp/disguard)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://www.typescriptlang.org/)
|
|
12
|
+
|
|
13
|
+
[Install](#install) · [Quick start](#quick-start) · [API](#api) · [Español](#español)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
3
19
|
npm: [`@amatiscorp/disguard`](https://www.npmjs.com/package/@amatiscorp/disguard)
|
|
4
20
|
|
|
5
21
|
Configurable antispam for [discord.js](https://discord.js.org) v14 bots.
|
|
6
22
|
|
|
7
23
|
It is **not** a bot. You plug it into your existing `Client` and decide every threshold, allowlist, and punishment.
|
|
8
24
|
|
|
9
|
-
Detects flood,
|
|
25
|
+
Detects flood, channel hopping, blocked words, phishing / unwanted links, duplicate images, mention spam, ghost pings, excessive caps, and emoji spam.
|
|
10
26
|
|
|
11
27
|
> **Español:** librería antispam configurable para bots de discord.js. No es un bot. La documentación en español está más abajo: [Español](#español).
|
|
12
28
|
|
|
@@ -21,6 +37,100 @@ Detects flood, repeated text, phishing / unwanted links, duplicate images, menti
|
|
|
21
37
|
|
|
22
38
|
# English
|
|
23
39
|
|
|
40
|
+
## What's new in 1.3.0
|
|
41
|
+
|
|
42
|
+
More detectors, role overlays, mute-style role punishments, and extra ignore knobs. Everything is optional and falls back to the preset.
|
|
43
|
+
|
|
44
|
+
| Option | Default | What it does |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| `words` | **off**, empty list | Block a word list and/or regex. `ignoreCase` and `matchWholeWord` are both `true` by default. |
|
|
47
|
+
| `hop` | **on**, 5 channels / 8s | Same user posting across too many unique channels in a window (raid / hop). |
|
|
48
|
+
| `punctuation` | **on**, 10 | `aaaaaa` / `!!!!!!` runs longer than `maxRepeated`. |
|
|
49
|
+
| `spoilers` | **on**, 8 pairs | Too many `\|\|spoiler\|\|` pairs in one message. |
|
|
50
|
+
| `ghostPing` | **off** (`strict`: on) | Punish deleting a message that mentioned people (`messageDelete`). |
|
|
51
|
+
| `checkDeletes` | `true` | Listen for `messageDelete`. Set `false` if you do not want ghost-ping checks. |
|
|
52
|
+
| `ignored.prefixes` | `[]` | Skip messages that start with `!`, `/`, `.`, etc. |
|
|
53
|
+
| `ignoreThreads` | `false` | Skip thread messages. |
|
|
54
|
+
| `ignoreSystem` | `true` | Skip Discord system messages. |
|
|
55
|
+
| `roleOverrides` / `setRoleConfig` | `{}` | Per-role config overlay (before channel overrides). |
|
|
56
|
+
| `links.blockOauth` | `true` | Flag non-allowlisted URLs whose path looks like `/oauth`, `/authorize`, `/login`. Official `discord.com` stays allowed. |
|
|
57
|
+
| `files.maxBytes` | `0` | Max attachment size in bytes. `0` = unlimited. |
|
|
58
|
+
| `accounts.minGuildAgeDays` | `0` | Flag members who joined the guild too recently. `0` = off. |
|
|
59
|
+
| `punishment.addRoleIds` / `removeRoleIds` | `[]` | Add/remove roles on punish (mute role). Needs **Manage Roles**. |
|
|
60
|
+
| `punishment.minStrikesForRoles` | `1` | Minimum strikes before those role actions run. |
|
|
61
|
+
| `onCooldown` | — | Callback when extra spam is deleted quietly during the punishment cooldown. |
|
|
62
|
+
| `pause()` / `resume()` | — | Freeze enforcement without removing listeners. |
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
const antispam = new AntiSpam(client, {
|
|
66
|
+
preset: "balanced",
|
|
67
|
+
locale: "es",
|
|
68
|
+
ignored: { prefixes: ["!", "/", "."], roles: ["STAFF_ROLE_ID"] },
|
|
69
|
+
words: { enabled: true, list: ["raid-now"], regex: ["n[i1]tro\\s+free"] },
|
|
70
|
+
hop: { maxChannels: 4, windowMs: 6_000 },
|
|
71
|
+
ghostPing: { enabled: true, minMentions: 1, maxAgeMs: 15_000 },
|
|
72
|
+
links: { blockOauth: true },
|
|
73
|
+
files: { maxBytes: 8 * 1024 * 1024 },
|
|
74
|
+
roleOverrides: {
|
|
75
|
+
"VIP_ROLE_ID": { flood: { maxMessages: 10 } },
|
|
76
|
+
},
|
|
77
|
+
punishment: {
|
|
78
|
+
addRoleIds: ["MUTE_ROLE_ID"],
|
|
79
|
+
minStrikesForRoles: 2,
|
|
80
|
+
},
|
|
81
|
+
onCooldown(message) {
|
|
82
|
+
console.log("quiet delete", message.id);
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
antispam.setRoleConfig("VIP_ROLE_ID", { emojis: { maxEmojis: 40 } });
|
|
87
|
+
antispam.pause(); // raid over? antispam.resume();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Ghost pings need the message in cache (or `Partials.Message`) so `messageDelete` still has mentions. Kick/ban stay **off**. Role add/remove is opt-in via empty arrays.
|
|
91
|
+
|
|
92
|
+
## What's new in 1.2.0
|
|
93
|
+
|
|
94
|
+
More knobs, per-channel rules, and bilingual user-facing text.
|
|
95
|
+
|
|
96
|
+
| Option | What it does |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `locale` | `"en"` or `"es"` for warn + log labels. Empty `warnMessage` uses the locale template. |
|
|
99
|
+
| `ignorePermissions` | Skip members with those Discord permission names (`ManageMessages`, …). |
|
|
100
|
+
| `setChannelConfig(guildId, channelId, patch)` | Rules for one channel (on top of guild + global). |
|
|
101
|
+
| `channelOverrides` | Same thing in static config: `{ "CHANNEL_ID": { flood: { maxMessages: 10 } } }`. |
|
|
102
|
+
| `disabledDetectors` | Turn off detectors by name without touching each block. |
|
|
103
|
+
| `detectorOrder` | Custom detector run order. |
|
|
104
|
+
| `flood.sameChannelOnly` / `duplicates.sameChannelOnly` | Count only the current channel. |
|
|
105
|
+
| `links.maxLinks` / `links.scanEmbeds` | Cap URLs per message; toggle embed scanning. |
|
|
106
|
+
| `images.skipContentTypes` / `images.maxAttachments` | Ignore GIFs, limit images per message. |
|
|
107
|
+
| `mentions.maxRepeatsOfSame` | Same user pinged over and over in one message. |
|
|
108
|
+
| `accounts` | Flag brand-new accounts (`minAgeDays`) or default avatars. Off by default. |
|
|
109
|
+
| `length` | Flag walls of text. Off by default. |
|
|
110
|
+
| `punishment.timeout.scale` | `"none"` \| `"linear"` \| `"exponential"` with `maxDurationMs`. |
|
|
111
|
+
| `punishment.warnAsEmbed` | Warning as an embed. |
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
const antispam = new AntiSpam(client, {
|
|
115
|
+
preset: "balanced",
|
|
116
|
+
locale: "es",
|
|
117
|
+
ignorePermissions: ["ManageMessages", "ModerateMembers"],
|
|
118
|
+
flood: { sameChannelOnly: true },
|
|
119
|
+
links: { maxLinks: 3, scanEmbeds: true },
|
|
120
|
+
accounts: { enabled: true, minAgeDays: 2 },
|
|
121
|
+
punishment: {
|
|
122
|
+
warnAsEmbed: true,
|
|
123
|
+
timeout: { enabled: true, durationMs: 60_000, scale: "linear", maxDurationMs: 10 * 60_000 },
|
|
124
|
+
},
|
|
125
|
+
disabledDetectors: ["caps"],
|
|
126
|
+
channelOverrides: {
|
|
127
|
+
"MEMES_CHANNEL_ID": { images: { maxRepeats: 8 }, emojis: { maxEmojis: 30 } },
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
antispam.setChannelConfig(guildId, channelId, { flood: { maxMessages: 12 } });
|
|
132
|
+
```
|
|
133
|
+
|
|
24
134
|
## What's new in 1.1.0
|
|
25
135
|
|
|
26
136
|
- **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.
|
|
@@ -63,6 +173,8 @@ console.log(antispam.getStats());
|
|
|
63
173
|
|
|
64
174
|
## Table of contents
|
|
65
175
|
|
|
176
|
+
- [What's new in 1.3.0](#whats-new-in-130)
|
|
177
|
+
- [What's new in 1.2.0](#whats-new-in-120)
|
|
66
178
|
- [What's new in 1.1.0](#whats-new-in-110)
|
|
67
179
|
- [Features](#features)
|
|
68
180
|
- [Requirements](#requirements)
|
|
@@ -95,15 +207,23 @@ console.log(antispam.getStats());
|
|
|
95
207
|
| **file** | Dangerous attachments (`.exe`, `.bat`, `.dll`, `.msi`, …) |
|
|
96
208
|
| **zalgo** | Obfuscated / zalgo text (stacked combining marks) |
|
|
97
209
|
| **newline** | Message walls made of empty lines |
|
|
210
|
+
| **account** | Brand-new Discord accounts / default avatar / new guild members (off by default) |
|
|
211
|
+
| **length** | Over-long messages (off by default) |
|
|
212
|
+
| **word** | Custom blocked words and regex (off until you fill `list` / `regex`) |
|
|
213
|
+
| **hop** | Same user jumping across too many channels |
|
|
214
|
+
| **punctuation** | Long runs of the same character (`!!!!`, `aaaa`) |
|
|
215
|
+
| **spoiler** | Spoiler-tag walls |
|
|
216
|
+
| **ghost** | Deleted messages that mentioned users (off by default) |
|
|
98
217
|
|
|
99
218
|
Also included:
|
|
100
219
|
|
|
101
220
|
- Three presets: `lenient`, `balanced`, `strict`
|
|
102
|
-
- Ignore lists for users, roles, channels, categories, and
|
|
221
|
+
- Ignore lists for users, roles, channels, categories, guilds, and command prefixes
|
|
222
|
+
- Per-guild, per-channel, and per-role overlays
|
|
103
223
|
- Strike system with decay
|
|
104
|
-
- Optional delete / warn / timeout / kick / ban (kick and ban are **off** by default)
|
|
224
|
+
- Optional delete / warn / timeout / kick / ban / addRole / removeRole (kick and ban are **off** by default)
|
|
105
225
|
- `dryRun` to tune rules without punishing anyone
|
|
106
|
-
- Edit scanning (links and
|
|
226
|
+
- Edit scanning (links, mentions, and words)
|
|
107
227
|
- Zero extra runtime dependencies (peer: `discord.js`)
|
|
108
228
|
- In-memory store only — no database required
|
|
109
229
|
- Full TypeScript types
|
|
@@ -218,6 +338,7 @@ npm run dev
|
|
|
218
338
|
| Warn in the channel | **Send Messages** |
|
|
219
339
|
| Log embeds | **Embed Links** |
|
|
220
340
|
| Kick / ban (opt-in) | **Kick Members** / **Ban Members** |
|
|
341
|
+
| Mute / add / remove roles (opt-in) | **Manage Roles** |
|
|
221
342
|
|
|
222
343
|
The bot will not sanction the guild owner or anyone above it in the role hierarchy. Those actions are skipped and reported in `onAction`.
|
|
223
344
|
|
|
@@ -225,11 +346,12 @@ Enable **Message Content Intent** in the [Discord Developer Portal](https://disc
|
|
|
225
346
|
|
|
226
347
|
## How it works
|
|
227
348
|
|
|
228
|
-
1. Ignores bots, webhooks, the owner, administrators, and anything in your ignore lists.
|
|
349
|
+
1. Ignores bots, webhooks, system messages, the owner, administrators, command prefixes, and anything in your ignore lists.
|
|
229
350
|
2. Keeps a short **in-memory** history per user and guild (no database).
|
|
230
|
-
3. Runs detectors in this order: files → flood → duplicates → links → images → mentions → zalgo → newlines → caps → emojis. The first match wins.
|
|
351
|
+
3. Runs detectors in this order: files → words → flood → hop → duplicates → links → images → mentions → zalgo → newlines → punctuation → spoilers → accounts → length → caps → emojis. The first match wins.
|
|
231
352
|
4. Adds one strike (with optional decay) and applies the configured punishment.
|
|
232
|
-
5. Message edits
|
|
353
|
+
5. Message edits re-check **links**, **mentions**, and **words**, so editing `hello` into a phishing URL or a blocked word is still caught without counting as flood.
|
|
354
|
+
6. Deletes can trigger **ghost** pings if `ghostPing.enabled` is true.
|
|
233
355
|
|
|
234
356
|
Call `antispam.stop()` on shutdown, hot reload, or plugin unload.
|
|
235
357
|
|
|
@@ -259,6 +381,8 @@ new AntiSpam(client, {
|
|
|
259
381
|
| Mentions | 10 | 6 | 3 |
|
|
260
382
|
| Block invites | no | no | yes |
|
|
261
383
|
| Block shorteners | no | yes | yes |
|
|
384
|
+
| Channel hop | off | 5 / 8s | 3 / 6s |
|
|
385
|
+
| Ghost pings | off | off | on |
|
|
262
386
|
| Auto timeout | off | 60s from 2 strikes | 5 min from 1 strike |
|
|
263
387
|
|
|
264
388
|
## Full configuration
|
|
@@ -275,8 +399,17 @@ Every option is optional. Missing fields fall back to the preset (or `balanced`
|
|
|
275
399
|
| `ignoreWebhooks` | `boolean` | `true` | Skip webhooks. |
|
|
276
400
|
| `ignoreOwner` | `boolean` | `true` | Skip the guild owner. |
|
|
277
401
|
| `ignoreAdministrators` | `boolean` | `true` | Skip members with Administrator. |
|
|
278
|
-
| `checkEdits` | `boolean` | `true` | Re-scan edits for links and
|
|
402
|
+
| `checkEdits` | `boolean` | `true` | Re-scan edits for links, mentions, and words. |
|
|
403
|
+
| `checkDeletes` | `boolean` | `true` | Listen for `messageDelete` (ghost pings). |
|
|
404
|
+
| `ignoreThreads` | `boolean` | `false` | Skip messages in threads. |
|
|
405
|
+
| `ignoreSystem` | `boolean` | `true` | Skip Discord system messages. |
|
|
279
406
|
| `cleanupIntervalMs` | `number` | `60000` | How often the memory store is pruned. |
|
|
407
|
+
| `locale` | `"en"` \| `"es"` | `"en"` | Language for warnings and log embeds. |
|
|
408
|
+
| `ignorePermissions` | `string[]` | `[]` | Permission names that bypass checks. |
|
|
409
|
+
| `disabledDetectors` | `DetectorType[]` | `[]` | Detectors to skip. |
|
|
410
|
+
| `detectorOrder` | `DetectorType[]` | `[]` | Custom order. Empty = default. |
|
|
411
|
+
| `channelOverrides` | `object` | `{}` | Per-channel patches keyed by channel id. |
|
|
412
|
+
| `roleOverrides` | `object` | `{}` | Per-role patches keyed by role id. |
|
|
280
413
|
|
|
281
414
|
### Ignore lists
|
|
282
415
|
|
|
@@ -287,10 +420,11 @@ ignored: {
|
|
|
287
420
|
channels: ["789"],
|
|
288
421
|
categories: ["101"],
|
|
289
422
|
guilds: ["202"],
|
|
423
|
+
prefixes: ["!", "/", "."],
|
|
290
424
|
}
|
|
291
425
|
```
|
|
292
426
|
|
|
293
|
-
IDs are snowflakes as strings. A staff role in `ignored.roles` bypasses every detector.
|
|
427
|
+
IDs are snowflakes as strings. A staff role in `ignored.roles` bypasses every detector. `prefixes` skip command messages (`!help` is ignored if `"!"` is listed).
|
|
294
428
|
|
|
295
429
|
### Flood
|
|
296
430
|
|
|
@@ -337,6 +471,9 @@ links: {
|
|
|
337
471
|
suspiciousTlds: [], // e.g. ["tk", "gq"]
|
|
338
472
|
customPatterns: [], // regex against the whole message
|
|
339
473
|
extraPhishingKeywords: ["fake giveaway"],
|
|
474
|
+
maxLinks: 0,
|
|
475
|
+
scanEmbeds: true,
|
|
476
|
+
blockOauth: true,
|
|
340
477
|
severity: "high",
|
|
341
478
|
}
|
|
342
479
|
```
|
|
@@ -352,6 +489,7 @@ Built-in checks (each can be turned off):
|
|
|
352
489
|
- Scam phrases plus any link (`free nitro`, `steam gift`, `verifica tu cuenta`, …)
|
|
353
490
|
- Discord invite links if `blockInvites` is `true`
|
|
354
491
|
- Markdown-masked links: `[click](https://evil.test)`
|
|
492
|
+
- Login / OAuth-looking paths on non-allowlisted hosts if `blockOauth` is `true`
|
|
355
493
|
|
|
356
494
|
```js
|
|
357
495
|
// Block foreign server invites
|
|
@@ -417,12 +555,31 @@ emojis: {
|
|
|
417
555
|
}
|
|
418
556
|
```
|
|
419
557
|
|
|
558
|
+
### Accounts and length
|
|
559
|
+
|
|
560
|
+
```js
|
|
561
|
+
accounts: {
|
|
562
|
+
enabled: false, // turn on to flag new users
|
|
563
|
+
minAgeDays: 3,
|
|
564
|
+
blockDefaultAvatar: false,
|
|
565
|
+
minGuildAgeDays: 0, // 0 = off; e.g. 1 = joined this guild today
|
|
566
|
+
severity: "medium",
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
length: {
|
|
570
|
+
enabled: false,
|
|
571
|
+
maxCharacters: 1000,
|
|
572
|
+
severity: "low",
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
420
576
|
### Files, zalgo, newlines
|
|
421
577
|
|
|
422
578
|
```js
|
|
423
579
|
files: {
|
|
424
580
|
enabled: true,
|
|
425
581
|
blockedExtensions: ["exe", "bat", "cmd", "com", "scr", "dll", "msi", "vbs", "ps1", "jar", "apk"],
|
|
582
|
+
maxBytes: 0, // 0 = unlimited
|
|
426
583
|
severity: "critical",
|
|
427
584
|
}
|
|
428
585
|
|
|
@@ -439,6 +596,57 @@ newlines: {
|
|
|
439
596
|
}
|
|
440
597
|
```
|
|
441
598
|
|
|
599
|
+
### Words, channel hop, punctuation, spoilers
|
|
600
|
+
|
|
601
|
+
```js
|
|
602
|
+
words: {
|
|
603
|
+
enabled: false, // stays off until you add a list or regex
|
|
604
|
+
list: ["raid-now"],
|
|
605
|
+
regex: ["n[i1]tro\\s+free"],
|
|
606
|
+
ignoreCase: true,
|
|
607
|
+
matchWholeWord: true,
|
|
608
|
+
severity: "high",
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
hop: {
|
|
612
|
+
enabled: true,
|
|
613
|
+
maxChannels: 5, // 5th unique channel in the window triggers
|
|
614
|
+
windowMs: 8_000,
|
|
615
|
+
severity: "high",
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
punctuation: {
|
|
619
|
+
enabled: true,
|
|
620
|
+
maxRepeated: 10, // 11+ of the same character in a row
|
|
621
|
+
severity: "low",
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
spoilers: {
|
|
625
|
+
enabled: true,
|
|
626
|
+
maxSpoilers: 8,
|
|
627
|
+
severity: "low",
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
`lenient` turns hop and punctuation off. `strict` tightens hop to 3 channels / 6s.
|
|
632
|
+
|
|
633
|
+
### Ghost pings
|
|
634
|
+
|
|
635
|
+
Off in `balanced` / `lenient`. On in `strict`. Needs `checkDeletes: true` (default) and the deleted message in cache (`Partials.Message` in your Client).
|
|
636
|
+
|
|
637
|
+
```js
|
|
638
|
+
ghostPing: {
|
|
639
|
+
enabled: false,
|
|
640
|
+
minMentions: 1,
|
|
641
|
+
maxAgeMs: 15_000, // 0 = any age
|
|
642
|
+
severity: "high",
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
checkDeletes: true
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
Disable with `ghostPing: { enabled: false }` or `disabledDetectors: ["ghost"]`.
|
|
649
|
+
|
|
442
650
|
### Punishment
|
|
443
651
|
|
|
444
652
|
Kick and ban stay **disabled** on purpose. Turn them on only if you really want that.
|
|
@@ -457,12 +665,20 @@ punishment: {
|
|
|
457
665
|
strikeDecayMs: 15 * 60_000, // strikes expire after 15 minutes
|
|
458
666
|
cooldownMs: 8_000, // no second timeout/warn during this window
|
|
459
667
|
deleteDuringCooldown: true, // still delete extra spam quietly
|
|
668
|
+
warnAsEmbed: false,
|
|
669
|
+
addRoleIds: [], // e.g. ["MUTE_ROLE_ID"] — needs Manage Roles
|
|
670
|
+
removeRoleIds: [],
|
|
671
|
+
minStrikesForRoles: 1,
|
|
460
672
|
}
|
|
673
|
+
|
|
674
|
+
// timeout.scale: "none" | "linear" (base * strikes) | "exponential" (base * 2^n)
|
|
675
|
+
// timeout.maxDurationMs caps the result (Discord max = 28 days)
|
|
676
|
+
|
|
461
677
|
```
|
|
462
678
|
|
|
463
679
|
`warnMessage` placeholders: `{user}` `{reason}` `{type}` `{strikes}`.
|
|
464
680
|
|
|
465
|
-
With `escalate: true`, Disguard applies **one** hard action (timeout, or kick, or ban — whichever threshold you hit). Delete and warn can still run together.
|
|
681
|
+
With `escalate: true`, Disguard applies **one** hard action (timeout, or kick, or ban — whichever threshold you hit). Delete and warn can still run together. `addRole` / `removeRole` run if those ID lists are non-empty and strikes ≥ `minStrikesForRoles`.
|
|
466
682
|
|
|
467
683
|
If the bot lacks a permission, or the target is higher in the hierarchy, that action is skipped and listed in `result.skipped`.
|
|
468
684
|
|
|
@@ -480,6 +696,9 @@ new AntiSpam(client, {
|
|
|
480
696
|
onError(error, context) {
|
|
481
697
|
console.error("[disguard]", context, error);
|
|
482
698
|
},
|
|
699
|
+
onCooldown(message) {
|
|
700
|
+
// Extra spam during punishment.cooldownMs (already deleted if deleteDuringCooldown).
|
|
701
|
+
},
|
|
483
702
|
});
|
|
484
703
|
```
|
|
485
704
|
|
|
@@ -487,7 +706,9 @@ new AntiSpam(client, {
|
|
|
487
706
|
|
|
488
707
|
```ts
|
|
489
708
|
{
|
|
490
|
-
type: "flood" | "duplicate" | "link" | "image" | "mention" | "caps" | "emoji"
|
|
709
|
+
type: "flood" | "duplicate" | "link" | "image" | "mention" | "caps" | "emoji"
|
|
710
|
+
| "file" | "zalgo" | "newline" | "account" | "length"
|
|
711
|
+
| "word" | "hop" | "punctuation" | "spoiler" | "ghost",
|
|
491
712
|
severity: "low" | "medium" | "high" | "critical",
|
|
492
713
|
userId: string,
|
|
493
714
|
guildId: string,
|
|
@@ -495,7 +716,7 @@ new AntiSpam(client, {
|
|
|
495
716
|
messageId: string,
|
|
496
717
|
reason: string,
|
|
497
718
|
details: Record<string, unknown>,
|
|
498
|
-
recommendedActions: Array<"delete" | "warn" | "timeout" | "kick" | "ban">,
|
|
719
|
+
recommendedActions: Array<"delete" | "warn" | "timeout" | "kick" | "ban" | "addRole" | "removeRole">,
|
|
499
720
|
timestamp: number,
|
|
500
721
|
}
|
|
501
722
|
```
|
|
@@ -522,6 +743,9 @@ const antispam = new AntiSpam(client, options);
|
|
|
522
743
|
|
|
523
744
|
antispam.start();
|
|
524
745
|
antispam.stop();
|
|
746
|
+
antispam.pause();
|
|
747
|
+
antispam.resume();
|
|
748
|
+
antispam.isPaused();
|
|
525
749
|
|
|
526
750
|
const config = antispam.getConfig();
|
|
527
751
|
antispam.setConfig({ flood: { maxMessages: 8 } }); // deep merge, other keys stay
|
|
@@ -533,6 +757,11 @@ antispam.isCoolingDown(guildId, userId);
|
|
|
533
757
|
antispam.setGuildConfig(guildId, { flood: { maxMessages: 3 } });
|
|
534
758
|
antispam.getGuildConfig(guildId);
|
|
535
759
|
antispam.clearGuildConfig(guildId);
|
|
760
|
+
antispam.setChannelConfig(guildId, channelId, { images: { maxRepeats: 8 } });
|
|
761
|
+
antispam.getChannelConfig(guildId, channelId);
|
|
762
|
+
antispam.clearChannelConfig(guildId, channelId);
|
|
763
|
+
antispam.setRoleConfig(roleId, { flood: { maxMessages: 12 } });
|
|
764
|
+
antispam.clearRoleConfig(roleId);
|
|
536
765
|
|
|
537
766
|
antispam.use(customDetector);
|
|
538
767
|
antispam.getStats();
|
|
@@ -617,6 +846,18 @@ antispam.setConfig(resolveConfig("strict", { ignored: antispam.getConfig().ignor
|
|
|
617
846
|
images: { hashMode: "content", maxDownloadBytes: 1_000_000 }
|
|
618
847
|
```
|
|
619
848
|
|
|
849
|
+
**Mute role instead of timeout**
|
|
850
|
+
|
|
851
|
+
```js
|
|
852
|
+
punishment: {
|
|
853
|
+
timeout: { enabled: false, durationMs: 60_000, minStrikes: 99 },
|
|
854
|
+
addRoleIds: ["MUTE_ROLE_ID"],
|
|
855
|
+
minStrikesForRoles: 1,
|
|
856
|
+
}
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
The bot role must sit **above** the mute role. Needs **Manage Roles**.
|
|
860
|
+
|
|
620
861
|
**Reset a user after a false positive**
|
|
621
862
|
|
|
622
863
|
```js
|
|
@@ -671,9 +912,14 @@ Wait a few seconds between categories so flood does not eat the next test.
|
|
|
671
912
|
| File | Upload a dummy `.exe` or `.bat` |
|
|
672
913
|
| Zalgo | Text with many stacked combining marks |
|
|
673
914
|
| Newlines | A message with more than 15 line breaks |
|
|
915
|
+
| Channel hop | Same user posts in 5 different channels within 8 seconds |
|
|
916
|
+
| Punctuation | `aaaaaaaaaaa` or `!!!!!!!!!!!` |
|
|
917
|
+
| Spoilers | More than 8 `\|\|spoiler\|\|` pairs |
|
|
918
|
+
| Blocked word | Enable `words` first, then send a listed word |
|
|
919
|
+
| Ghost ping | Mention someone and delete the message within 15s (`ghostPing.enabled: true`) |
|
|
674
920
|
| Edit | Send `hello`, then edit it to `Free Nitro https://bit.ly/test` |
|
|
675
921
|
|
|
676
|
-
Watch the terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji`.
|
|
922
|
+
Watch the terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji|file|zalgo|newline|word|hop|punctuation|spoiler|ghost`.
|
|
677
923
|
|
|
678
924
|
The second strike applies a 1 minute timeout with the default example config. Strikes decay after 15 minutes, or call `resetUser`.
|
|
679
925
|
|
|
@@ -714,6 +960,83 @@ MIT
|
|
|
714
960
|
|
|
715
961
|
# Español
|
|
716
962
|
|
|
963
|
+
## Novedades de 1.3.0
|
|
964
|
+
|
|
965
|
+
Más detectores, overlays por rol, mute por rol y más ignores. Todo es opcional.
|
|
966
|
+
|
|
967
|
+
| Opción | Default | Qué hace |
|
|
968
|
+
| --- | --- | --- |
|
|
969
|
+
| `words` | **apagado**, lista vacía | Palabras y/o regex bloqueados. `ignoreCase` y `matchWholeWord` en `true`. |
|
|
970
|
+
| `hop` | **on**, 5 canales / 8s | El mismo usuario escribe en demasiados canales (raid / hop). |
|
|
971
|
+
| `punctuation` | **on**, 10 | Rachas de `aaaaaa` / `!!!!!!` más largas que `maxRepeated`. |
|
|
972
|
+
| `spoilers` | **on**, 8 pares | Demasiados `\|\|spoiler\|\|` en un mensaje. |
|
|
973
|
+
| `ghostPing` | **off** (`strict`: on) | Castiga borrar un mensaje que mencionaba gente. |
|
|
974
|
+
| `checkDeletes` | `true` | Escucha `messageDelete`. |
|
|
975
|
+
| `ignored.prefixes` | `[]` | Ignora mensajes que empiezan por `!`, `/`, `.`. |
|
|
976
|
+
| `ignoreThreads` | `false` | Ignora hilos. |
|
|
977
|
+
| `ignoreSystem` | `true` | Ignora mensajes de sistema. |
|
|
978
|
+
| `roleOverrides` / `setRoleConfig` | `{}` | Config por rol (antes de la de canal). |
|
|
979
|
+
| `links.blockOauth` | `true` | URLs de login/OAuth fuera de la allowList. `discord.com` sigue permitido. |
|
|
980
|
+
| `files.maxBytes` | `0` | Tamaño máximo de adjunto. `0` = sin límite. |
|
|
981
|
+
| `accounts.minGuildAgeDays` | `0` | Miembros demasiado nuevos en **este** servidor. `0` = off. |
|
|
982
|
+
| `punishment.addRoleIds` / `removeRoleIds` | `[]` | Añadir/quitar roles al castigar (mute). Hace falta **Manage Roles**. |
|
|
983
|
+
| `onCooldown` | — | Callback cuando el cooldown borra spam extra en silencio. |
|
|
984
|
+
| `pause()` / `resume()` | — | Congela el antispam sin quitar listeners. |
|
|
985
|
+
|
|
986
|
+
```js
|
|
987
|
+
const antispam = new AntiSpam(client, {
|
|
988
|
+
locale: "es",
|
|
989
|
+
ignored: { prefixes: ["!", "/", "."], roles: ["ID_STAFF"] },
|
|
990
|
+
words: { enabled: true, list: ["raid-now"] },
|
|
991
|
+
hop: { maxChannels: 4, windowMs: 6_000 },
|
|
992
|
+
ghostPing: { enabled: true, maxAgeMs: 15_000 },
|
|
993
|
+
punishment: { addRoleIds: ["ID_MUTE"], minStrikesForRoles: 2 },
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
antispam.setRoleConfig("ID_VIP", { flood: { maxMessages: 10 } });
|
|
997
|
+
antispam.pause();
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
Kick y ban siguen **apagados**. Ghost ping necesita el mensaje en caché (`Partials.Message`).
|
|
1001
|
+
|
|
1002
|
+
## Novedades de 1.2.0
|
|
1003
|
+
|
|
1004
|
+
Más opciones, reglas por canal y textos al usuario en inglés o español.
|
|
1005
|
+
|
|
1006
|
+
| Opción | Qué hace |
|
|
1007
|
+
| --- | --- |
|
|
1008
|
+
| `locale` | `"en"` o `"es"` para avisos y logs. Si `warnMessage` está vacío, usa la plantilla del idioma. |
|
|
1009
|
+
| `ignorePermissions` | Ignora quien tenga esos permisos (`ManageMessages`, …). |
|
|
1010
|
+
| `setChannelConfig` | Config de un canal (encima de guild + global). |
|
|
1011
|
+
| `channelOverrides` | Lo mismo en la config estática. |
|
|
1012
|
+
| `disabledDetectors` | Apaga detectores por nombre. |
|
|
1013
|
+
| `detectorOrder` | Orden de ejecución. |
|
|
1014
|
+
| `flood.sameChannelOnly` / `duplicates.sameChannelOnly` | Solo cuenta el canal actual. |
|
|
1015
|
+
| `links.maxLinks` / `links.scanEmbeds` | Tope de URLs; escanear embeds. |
|
|
1016
|
+
| `images.skipContentTypes` / `images.maxAttachments` | Ignorar gifs, limitar adjuntos. |
|
|
1017
|
+
| `mentions.maxRepeatsOfSame` | El mismo ping repetido. |
|
|
1018
|
+
| `accounts` | Cuentas nuevas (`minAgeDays`) o avatar por defecto. Apagado por defecto. |
|
|
1019
|
+
| `length` | Mensajes kilométricos. Apagado por defecto. |
|
|
1020
|
+
| `punishment.timeout.scale` | `"none"` \| `"linear"` \| `"exponential"`. |
|
|
1021
|
+
| `punishment.warnAsEmbed` | Aviso en embed. |
|
|
1022
|
+
|
|
1023
|
+
```js
|
|
1024
|
+
new AntiSpam(client, {
|
|
1025
|
+
locale: "es",
|
|
1026
|
+
ignorePermissions: ["ManageMessages"],
|
|
1027
|
+
flood: { sameChannelOnly: true },
|
|
1028
|
+
links: { maxLinks: 3 },
|
|
1029
|
+
accounts: { enabled: true, minAgeDays: 2 },
|
|
1030
|
+
punishment: {
|
|
1031
|
+
warnAsEmbed: true,
|
|
1032
|
+
timeout: { durationMs: 60_000, scale: "linear", maxDurationMs: 600_000 },
|
|
1033
|
+
},
|
|
1034
|
+
channelOverrides: {
|
|
1035
|
+
"ID_CANAL_MEMES": { emojis: { maxEmojis: 30 } },
|
|
1036
|
+
},
|
|
1037
|
+
});
|
|
1038
|
+
```
|
|
1039
|
+
|
|
717
1040
|
## Novedades de 1.1.0
|
|
718
1041
|
|
|
719
1042
|
- **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.
|
|
@@ -726,6 +1049,8 @@ MIT
|
|
|
726
1049
|
|
|
727
1050
|
## Tabla de contenidos
|
|
728
1051
|
|
|
1052
|
+
- [Novedades de 1.3.0](#novedades-de-130)
|
|
1053
|
+
- [Novedades de 1.2.0](#novedades-de-120)
|
|
729
1054
|
- [Novedades de 1.1.0](#novedades-de-110)
|
|
730
1055
|
- [Qué es](#qué-es)
|
|
731
1056
|
- [Requisitos](#requisitos)
|
|
@@ -748,7 +1073,7 @@ MIT
|
|
|
748
1073
|
|
|
749
1074
|
**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.
|
|
750
1075
|
|
|
751
|
-
Detecta flood,
|
|
1076
|
+
Detecta flood, salto de canales, palabras bloqueadas, phishing / enlaces no deseados (también en embeds), imágenes repetidas, spam de menciones, ghost pings, mayúsculas, emojis, archivos peligrosos, zalgo y paredes de líneas.
|
|
752
1077
|
|
|
753
1078
|
## Requisitos
|
|
754
1079
|
|
|
@@ -834,6 +1159,7 @@ npm run dev
|
|
|
834
1159
|
| Avisar en el canal | **Send Messages** |
|
|
835
1160
|
| Embed de logs | **Embed Links** |
|
|
836
1161
|
| Kick / ban (opt-in) | **Kick Members** / **Ban Members** |
|
|
1162
|
+
| Mute / add / remove roles (opt-in) | **Manage Roles** |
|
|
837
1163
|
|
|
838
1164
|
No puede sancionar al dueño del servidor ni a quien esté por encima del bot en la jerarquía.
|
|
839
1165
|
|
|
@@ -841,11 +1167,12 @@ Activa **Message Content Intent** en el [Portal de Discord](https://discord.com/
|
|
|
841
1167
|
|
|
842
1168
|
## Cómo funciona
|
|
843
1169
|
|
|
844
|
-
1. Ignora bots, webhooks, el dueño, administradores y tus listas de ignore.
|
|
1170
|
+
1. Ignora bots, webhooks, mensajes de sistema, el dueño, administradores, prefijos de comando y tus listas de ignore.
|
|
845
1171
|
2. Guarda en **memoria** un historial corto por usuario y servidor. Sin base de datos.
|
|
846
|
-
3. Pasa el mensaje por: flood → duplicados → enlaces → imágenes → menciones → caps → emojis. El primero que dispare gana.
|
|
1172
|
+
3. Pasa el mensaje por: archivos → palabras → flood → hop → duplicados → enlaces → imágenes → menciones → zalgo → líneas → puntuación → spoilers → cuentas → longitud → caps → emojis. El primero que dispare gana.
|
|
847
1173
|
4. Suma un strike (con caducidad) y aplica el castigo configurado.
|
|
848
|
-
5. Las ediciones
|
|
1174
|
+
5. Las ediciones revisan **enlaces**, **menciones** y **palabras**.
|
|
1175
|
+
6. Los borrados pueden disparar **ghost** ping si `ghostPing.enabled` es true.
|
|
849
1176
|
|
|
850
1177
|
Llama `antispam.stop()` al apagar el proceso.
|
|
851
1178
|
|
|
@@ -878,8 +1205,12 @@ Todo es opcional. Lo que no pongas usa el preset.
|
|
|
878
1205
|
| `ignoreWebhooks` | `boolean` | `true` | Ignora webhooks. |
|
|
879
1206
|
| `ignoreOwner` | `boolean` | `true` | Ignora al dueño. |
|
|
880
1207
|
| `ignoreAdministrators` | `boolean` | `true` | Ignora quien tenga Administrator. |
|
|
881
|
-
| `checkEdits` | `boolean` | `true` | Revisa ediciones (enlaces y
|
|
1208
|
+
| `checkEdits` | `boolean` | `true` | Revisa ediciones (enlaces, menciones y palabras). |
|
|
1209
|
+
| `checkDeletes` | `boolean` | `true` | Escucha `messageDelete` (ghost pings). |
|
|
1210
|
+
| `ignoreThreads` | `boolean` | `false` | Ignora hilos. |
|
|
1211
|
+
| `ignoreSystem` | `boolean` | `true` | Ignora mensajes de sistema. |
|
|
882
1212
|
| `cleanupIntervalMs` | `number` | `60000` | Limpieza de memoria. |
|
|
1213
|
+
| `roleOverrides` | `object` | `{}` | Parches por rol. |
|
|
883
1214
|
|
|
884
1215
|
### Listas de ignore
|
|
885
1216
|
|
|
@@ -890,6 +1221,7 @@ ignored: {
|
|
|
890
1221
|
channels: ["id"],
|
|
891
1222
|
categories: ["id"],
|
|
892
1223
|
guilds: ["id"],
|
|
1224
|
+
prefixes: ["!", "/", "."],
|
|
893
1225
|
}
|
|
894
1226
|
```
|
|
895
1227
|
|
|
@@ -934,13 +1266,16 @@ links: {
|
|
|
934
1266
|
suspiciousTlds: [],
|
|
935
1267
|
customPatterns: ["steamcommunity\\.ru"],
|
|
936
1268
|
extraPhishingKeywords: ["sorteo falso"],
|
|
1269
|
+
maxLinks: 0,
|
|
1270
|
+
scanEmbeds: true,
|
|
1271
|
+
blockOauth: true,
|
|
937
1272
|
severity: "high",
|
|
938
1273
|
}
|
|
939
1274
|
```
|
|
940
1275
|
|
|
941
1276
|
La `allowList` gana a las heurísticas. `discord.com` y `youtube.com` ya vienen permitidos.
|
|
942
1277
|
|
|
943
|
-
Heurísticas incluidas (todas se pueden apagar): acortadores, IPs, punycode, clones de marcas, palabras de estafa + enlace, invitaciones si `blockInvites` es `true`,
|
|
1278
|
+
Heurísticas incluidas (todas se pueden apagar): acortadores, IPs, punycode, clones de marcas, palabras de estafa + enlace, invitaciones si `blockInvites` es `true`, enlaces enmascarados `[texto](url)`, y rutas de login/OAuth si `blockOauth` es `true`.
|
|
944
1279
|
|
|
945
1280
|
### Imágenes
|
|
946
1281
|
|
|
@@ -972,11 +1307,23 @@ emojis: { enabled: true, maxEmojis: 12, maxStickers: 3, severity: "low" },
|
|
|
972
1307
|
### Archivos, zalgo, saltos de línea
|
|
973
1308
|
|
|
974
1309
|
```js
|
|
975
|
-
files: { enabled: true, blockedExtensions: ["exe", "bat", "cmd", "dll", "msi"], severity: "critical" },
|
|
1310
|
+
files: { enabled: true, blockedExtensions: ["exe", "bat", "cmd", "dll", "msi"], maxBytes: 0, severity: "critical" },
|
|
976
1311
|
zalgo: { enabled: true, maxCombining: 20, severity: "medium" },
|
|
977
1312
|
newlines: { enabled: true, maxNewlines: 15, severity: "low" },
|
|
978
1313
|
```
|
|
979
1314
|
|
|
1315
|
+
### Palabras, hop, puntuación, spoilers, ghost ping
|
|
1316
|
+
|
|
1317
|
+
```js
|
|
1318
|
+
words: { enabled: false, list: ["raid-now"], regex: [], ignoreCase: true, matchWholeWord: true, severity: "high" },
|
|
1319
|
+
hop: { enabled: true, maxChannels: 5, windowMs: 8_000, severity: "high" },
|
|
1320
|
+
punctuation: { enabled: true, maxRepeated: 10, severity: "low" },
|
|
1321
|
+
spoilers: { enabled: true, maxSpoilers: 8, severity: "low" },
|
|
1322
|
+
ghostPing: { enabled: false, minMentions: 1, maxAgeMs: 15_000, severity: "high" },
|
|
1323
|
+
```
|
|
1324
|
+
|
|
1325
|
+
`lenient` apaga hop y puntuación. `strict` enciende ghost ping y aprieta hop a 3 canales / 6s.
|
|
1326
|
+
|
|
980
1327
|
### Castigos
|
|
981
1328
|
|
|
982
1329
|
Kick y ban van **apagados**. Actívalos solo si lo tienes claro.
|
|
@@ -995,12 +1342,15 @@ punishment: {
|
|
|
995
1342
|
strikeDecayMs: 15 * 60_000,
|
|
996
1343
|
cooldownMs: 8_000,
|
|
997
1344
|
deleteDuringCooldown: true,
|
|
1345
|
+
addRoleIds: [],
|
|
1346
|
+
removeRoleIds: [],
|
|
1347
|
+
minStrikesForRoles: 1,
|
|
998
1348
|
}
|
|
999
1349
|
```
|
|
1000
1350
|
|
|
1001
1351
|
Placeholders: `{user}` `{reason}` `{type}` `{strikes}`.
|
|
1002
1352
|
|
|
1003
|
-
Con `escalate: true` se aplica **un** castigo fuerte (timeout, kick o ban). Aviso y borrado se pueden sumar.
|
|
1353
|
+
Con `escalate: true` se aplica **un** castigo fuerte (timeout, kick o ban). Aviso y borrado se pueden sumar. `addRole` / `removeRole` corren si las listas no están vacías.
|
|
1004
1354
|
|
|
1005
1355
|
## Callbacks
|
|
1006
1356
|
|
|
@@ -1012,6 +1362,7 @@ new AntiSpam(client, {
|
|
|
1012
1362
|
onError(error, context) {
|
|
1013
1363
|
console.error(context, error);
|
|
1014
1364
|
},
|
|
1365
|
+
onCooldown(message) {},
|
|
1015
1366
|
});
|
|
1016
1367
|
```
|
|
1017
1368
|
|
|
@@ -1024,11 +1375,15 @@ const antispam = new AntiSpam(client, options);
|
|
|
1024
1375
|
|
|
1025
1376
|
antispam.start();
|
|
1026
1377
|
antispam.stop();
|
|
1378
|
+
antispam.pause();
|
|
1379
|
+
antispam.resume();
|
|
1027
1380
|
antispam.getConfig();
|
|
1028
1381
|
antispam.setConfig({ flood: { maxMessages: 8 } });
|
|
1029
1382
|
antispam.getStrikes(guildId, userId);
|
|
1030
1383
|
antispam.resetUser(guildId, userId);
|
|
1031
1384
|
antispam.setGuildConfig(guildId, { flood: { maxMessages: 3 } });
|
|
1385
|
+
antispam.setChannelConfig(guildId, channelId, { flood: { maxMessages: 12 } });
|
|
1386
|
+
antispam.setRoleConfig(roleId, { emojis: { maxEmojis: 40 } });
|
|
1032
1387
|
antispam.getStats();
|
|
1033
1388
|
|
|
1034
1389
|
const incident = await antispam.analyze(message);
|
|
@@ -1060,6 +1415,8 @@ new AntiSpam(client, {
|
|
|
1060
1415
|
|
|
1061
1416
|
**Quitar strikes:** `antispam.resetUser(guildId, userId)`.
|
|
1062
1417
|
|
|
1418
|
+
**Mute por rol:** `punishment: { addRoleIds: ["ID_MUTE"], timeout: { enabled: false, durationMs: 0, minStrikes: 99 } }`. El rol del bot debe estar por encima del mute.
|
|
1419
|
+
|
|
1063
1420
|
**Cambiar a strict en caliente**
|
|
1064
1421
|
|
|
1065
1422
|
```js
|
|
@@ -1097,9 +1454,14 @@ Espera unos segundos entre categorías.
|
|
|
1097
1454
|
| Archivo | Sube un `.exe` o `.bat` (aunque sea de mentira) |
|
|
1098
1455
|
| Zalgo | Texto con muchos diacríticos apilados |
|
|
1099
1456
|
| Líneas | Un mensaje con más de 15 enters |
|
|
1457
|
+
| Hop | El mismo usuario en 5 canales distintos en 8s |
|
|
1458
|
+
| Puntuación | `aaaaaaaaaaa` o `!!!!!!!!!!!` |
|
|
1459
|
+
| Spoilers | Más de 8 pares `\|\|spoiler\|\|` |
|
|
1460
|
+
| Palabra | Activa `words` y manda una de la lista |
|
|
1461
|
+
| Ghost ping | Menciona a alguien y borra el mensaje en menos de 15s (`ghostPing.enabled: true`) |
|
|
1100
1462
|
| Edición | Manda `hola` y edítalo a `Free Nitro https://bit.ly/test` |
|
|
1101
1463
|
|
|
1102
|
-
En la terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji|file|zalgo|newline`.
|
|
1464
|
+
En la terminal: `[detect] flood|duplicate|link|image|mention|caps|emoji|file|zalgo|newline|word|hop|punctuation|spoiler|ghost`.
|
|
1103
1465
|
|
|
1104
1466
|
Al segundo strike el ejemplo mete timeout de 1 minuto. Los strikes caducan a los 15 minutos, o usa `resetUser`.
|
|
1105
1467
|
|