Docs/Plugins/Censor
Censor
Filter invites, domains, words, tokens, zalgo, caps and mentions - with per-level and per-channel sub-configs and an anti-raid layer.
Censor watches every message (and some things that are not messages, like nicknames) and removes content that matches your rules. Violations can warn, and repeat violations can auto-mute.
plugins:
censor:
levels:
0: # applies to regular members (level 0)
filter_invites: true
filter_zalgo: true
blocked_words: [scamword]
50: # applies to everyone up to level 50 (mods included)
blocked_words: [superbadword]
channels:
665875009507426304: # extra rules just for this channel
filter_domains: true
Setup checklist
- Open Setup > Filters and add rules under level
0for ordinary members. Do not put a normal member rule under level50unless moderators should be filtered too. - Start with one literal test word in one private channel. Add that channel to an allowlist only after the enforcement test.
- Choose whether hits only delete, also warn, or escalate to a mute. A mute requires the infractions plugin, a working mute role, and role hierarchy.
- Subscribe a mod log channel to Censored message and any raid events you intend to use.
- Save and paste the exact message into the simulator with the test member's real level and channel.
- Post the same message as a regular test account. Confirm deletion, warning or mute, and the named config key in the log.
- Test one allowed near-match so the rule does not block more than intended.
- Add production lists and channels gradually. For image text, configure Image Scan OCR separately.
How rules are scoped
The top level holds two maps of sub-configs: levels and channels
(extra rules per channel or category). A levels key is a ceiling: rules
under it apply to members at or below that level. Rules under 0 apply
only to regular members - trusted members, mods and admins are above them.
To also filter staff, put the rules under a higher key like 50 or 100.
Each sub-config carries the same filter set; the first matching rule wins.
The filters
- Invites -
filter_invites, with guild/vanity whitelists and blacklists (invites_guild_whitelist,invites_whitelist,invites_blacklist) and a per-channel exemption list. - Domains -
filter_domainswithdomains_whitelist/domains_blacklist. Blocked domains match with or withouthttps://, so a barebad-site.comis caught too, subdomains included. The allow-list only judges real links (with a scheme), so ordinary text can never trip it. List entries are forgiving: paste a full link (https://bad-site.com/whatever) or just the domain - both mean the same thing, and awww.prefix is ignored. - Words and tokens -
blocked_words(whole words) andblocked_tokens(substring matches - use these to catchn1tro-style respellings of a blocked word). Entries are matched literally, so$5means a real dollar sign - you never need to escape anything, and a stray symbol can never break your filter. If you want actual regex matching, that lives in two places: a channel rule's text pattern (whitelist_text_regex, on the Channel Rules page - see the Utilities docs) and the AutoMod page's regex patterns, which Discord itself enforces. - Zalgo -
filter_zalgo, plusblock_zalgo_nicknamesfor names. - Caps -
filter_all_caps. It only fires on repetition: a message counts when it carries at leastall_caps_min_char_lengthcapitals in a row, and the filter acts afterall_caps_min_message_countsuch messages withinall_caps_intervalseconds. All three thresholds are editable right next to the toggle on the dashboard's Censor form. - Mentions / nicknames / hoisting -
blocked_mentions(see below),blocked_nicknames,hoist_blacklist. - Message length -
message_char_limit.
Blocked mentions
blocked_mentions protects specific people, roles, or channels from being
pinged. Every entry needs a one-letter prefix saying what the id is - a
bare id on its own matches nothing at all:
| Prefix | Blocks | Example |
|---|---|---|
u |
mentions of a user | u80351110224678912 |
r |
mentions of a role | r175028798551982080 |
c |
mentions of a channel | c290923757399310346 |
plugins:
censor:
levels:
0:
blocked_mentions:
- u80351110224678912 # the owner
- r175028798551982080 # the admin role
mention_channel_whitelist:
- 290923757399310346 # staff channel, no filtering here
You can paste a mention straight from Discord (<@806…>, <@&175…>,
<#290…>) and it is converted to the right prefixed form when the config is
saved. What does not work is a plain id with no prefix, or the placeholder
text uid / rid / cid - those never match anything, and the filter stays
silent because there is nothing to match. If a blocked mention is not being
caught, check the prefix first.
Ids are easiest to get with Developer Mode on in Discord (Settings, Advanced), then right-click a member, role, or channel and Copy ID.
What counts as a mention:
- Typing the mention in a message.
- Replying to someone with the @ left on. That pings them just like a
written mention, so it is treated the same way. The log entry says
(reply ping)so you can tell which form fired. - A reply with the ping switched off pings nobody, so it is left alone.
mention_channel_whitelist exempts channels where the filter should not run.
Most filters take a *_channel_whitelist to exempt specific channels. A
whitelisted channel exempts its threads and forum posts too - the filters
themselves also run inside threads, like everywhere else.
Escalation
warn_on_censorissues a warning infraction alongside the deletion.mute_violationsauto-mutes aftermute_violations_counthits withinmute_violations_intervalseconds, formute_violations_durationseconds. All three numbers are editable next to the "Mute repeat offenders" toggle on the dashboard's Censor form.
Anti-raid
The antiraid block goes inside a level, next to that level's filters
(plugins.censor.levels.0.antiraid), not at the top of the censor block.
It watches join velocity: count joins within interval seconds starts a
lockdown for lockdown_duration seconds. While it is active, every new join
receives raid_action - a quarantine role (raidrole), a kick, a ban, or a
tempban for raid_action_duration - and notifyrole gets pinged. That ping
goes to the first mod log channel subscribed to the Raid detected event,
so give one of your log channels that event or the ping has nowhere to go.
The optional shield block pauses server invites and/or member DMs at the Discord level
(pause_invites, pause_dms) for the lockdown window, so the influx stops
at the source.
You can also drive the lockdown by hand:
!raid status(or bare!raid) - is a lockdown active, and for how much longer.!raid on [duration]- start (or extend) the lockdown manually, for example ahead of a raid you can see forming. New joins receive the configuredraid_actionexactly as if the detector had tripped, and the shield goes up if configured. Duration defaults tolockdown_duration.!raid off- lift the lockdown early and return quarantined members to normal (stripsraidrole).
Manual enables and lifts write their own mod log entries naming the moderator, alongside the automatic raid detection events.
Testing your rules
Setup → Filters includes a message simulator: paste a message, pick the
channel and the member's level, and it shows exactly which censor rule (if
any) would catch it - the same first-hit-wins order the bot uses. Every hit
names the exact config key that fired (for example
plugins.censor.levels.50.blocked_words), so you can jump straight to that
line in your config to change or whitelist it.
Commands
Arguments in {curly braces} are required. Arguments in [square brackets] are optional.
| Command | What it does |
|---|---|
/antiraid [action] |
Inspect, manually enable, or lift the anti-raid lockdown: status / on [duration] / off. |
Image-based scams are the Image Scan plugin's job; when its OCR layer is on, text found inside images is run through these same censor lists.
Troubleshooting
- The simulator catches a message but live Discord does not: confirm the live member level, channel scope, bot Manage Messages permission, and that the plugin block saved.
- A blocked word catches too little:
blocked_wordsuses whole words; useblocked_tokensfor substring variants. - A domain entry behaves oddly: paste the domain or full URL. The loader
normalizes schemes and
www.. - A reply ping slips through: user entries need the
uprefix and the reply must have its ping left on. - Mute escalation records a hit but cannot mute: configure the infractions mute role below the bot and check Manage Roles.
- Raid alerts do not ping:
notifyroleuses the first mod log channel subscribed to Raid detected, so that subscription must exist.