Message filters
Block links, invites, banned words, music files and mass pings per channel, and choose what happens to whoever posts them.
The message filters delete messages and, optionally, punish whoever sent them. Most of them are set per channel, so you can allow links in one place and block them everywhere else. The banned-word list is the exception and applies across the whole server. Everything here needs the Manage Messages permission.
Block something in a channel
Turn one on
The per-channel filters all share one shape. Turn one on for a single channel or for every channel at once, and turn it off the same way.
Syntax
,filter <type> <on|off> <#channel|all> [++punish <punishment>]
Example
,filter links on #general ++punish mute
What each filter catches
| Filter | Command | Deletes |
|---|---|---|
| Links | ,filter links | any message containing a link |
| Invites | ,filter invites | Discord invites to other servers |
| Music files | ,filter mp3 | attachments ending .mp3, .wav, .m4a, .flac, .ogg, .aac, .wma, .opus |
| Mass mentions | ,filter mention | messages pinging at least ++threshold people |
| Image only | ,filter words | any message with no attachment |
An invite to your own server is not treated as an invite. Mass mentions take
++threshold <number> for how many pings are too many.
Syntax
,filter mention on <#channel|all> [++punish <punishment>] [++threshold <number>]
Example
,filter mention on all ++punish ban ++threshold 7
The two that surprise people
filter words is the image-only filter
It is the one command name on this page that does not describe what it does. ,filter words on #media makes #media an image-only channel: anything posted without an attachment is deleted.
The banned-word list is ,filter add, covered below.
The music filter reads the filename, not the file
It matches the extension on the end of the attachment's name and nothing else. Rename a track to
song.png and it goes straight through, and a genuine image called cover.mp3 is deleted. That is
the first thing most people hit when they test it. The filter is a deterrent against people
dumping music into a channel, not a check on what a file really contains.
Ban a word across the server
The word list is separate, and it applies everywhere rather than per channel.
Add and remove words
,filter add takes a word of at least two characters
and an optional punishment. Give no punishment and the message is deleted, with nothing happening
to whoever sent it.
Syntax
,filter add <word> [punishment]
Example
,filter add loser ban
Syntax
,filter remove <word>
Example
,filter remove loser
A word matches anywhere inside a message, so a short entry catches longer words that contain it.
Adding ass also catches "class" and "passenger". Prefer whole words you actually mean, or keep the
short one and add ++exact.
Syntax
,filter add <word> [punishment] [++exact]
Example
,filter add ass ban ++exact
With ++exact on, ass stops matching inside "class" and "passenger" but still catches it on its
own, next to punctuation, or sitting between underscores. It is off by default, so turning it on for
one word never changes how any other word on your list matches, and /filter add has the same
thing as an exact option you can switch on.
Exact is not an obfuscation filter
It only moves where a real, unbroken match is allowed to sit next to other letters. It does
nothing for "l o s e r" spaced out or "l0ser" with a digit swapped in: both get past ,filter add loser whether ++exact is on or off. Catching a spelled-out or leetspeak variant means adding
that spelling as its own word.
Edits are re-checked, so changing a message after it is posted does not get a banned word past the filter.
Review the list
,filter list shows the words you have added.
,filter clear empties the list.
,filter type shows which channel filters are on, and
where.
Syntax
,filter list
Decide what happens to the sender
Every filter deletes the message. The punishment is what happens to the person on top of that, and it is optional.
| Punishment | Bot needs |
|---|---|
| none | nothing: the message is deleted and that is all |
warn | nothing |
mute | Manage Roles, plus a mute role |
jail | Manage Roles, plus a jail role |
stripstaff | Manage Roles, plus a staff-role list |
kick | Kick Members |
ban | Ban Members |
Set the roles that mute, jail and stripstaff depend on with
,config muterole,
,config jailrole and
,staff add <role>.
A message that breaks a rule three times over still produces one punishment, not three.
Exempt the people who should be
,filter whitelist exempts a user, a role, or
your whole staff list, from some or all of the filters.
Syntax
,filter whitelist <add|remove|scope|list|clear|on|off> [user|role|staff] [kind ...]
Example
,filter whitelist add @Staff links invites
| Action | Does |
|---|---|
add <user|role|staff> [kind ...] | Exempts the target. No kinds means every filter |
remove <user|role|staff> | Removes the target |
scope <user|role|staff> [kind ...] | Changes what an existing entry bypasses. Refuses if the target isn't whitelisted yet, so add it first |
list | Shows every entry and what each one bypasses |
clear | Removes every entry |
on / off | Turns the whole whitelist on, or suspends every entry without deleting any |
Exempt from some filters, not all of them
List the kinds you want after the target, separated by spaces, and the entry is scoped to just those. Leave the list off and the entry bypasses everything, which is also what every entry did before scoping existed, so nothing already on your whitelist changed when this shipped.
The kind names are words, links, invites, mp3, mentions, imageonly and spam. The last
one is flood protection rather than one of the six filters on
this page: it already reads the same whitelist, so scoping a role to spam exempts it from
,antispam without touching anything else here.
Syntax
,filter whitelist scope <user|role|staff> [kind ...]
Example
,filter whitelist scope @Staff words
,filter whitelist scope edits, it never
creates.
Exempt your whole staff list at once
staff is not a placeholder for a role, it is a reserved word, and it tracks whatever
,staff add <role> currently lists rather than a fixed
set you have to keep updating by hand. Add a role to the staff list later and it is exempt
immediately. Remove one and it stops being exempt the same way, with nothing on the whitelist entry
itself ever needing to change.
Syntax
,filter whitelist add staff [kind ...]
Example
,filter whitelist add staff
Because staff is reserved, typing it targets that live list even in a server that also has a role
called Staff. Mention the role instead (,filter whitelist add @Staff) to whitelist the role itself
rather than the reserved meaning.
Suspend the whitelist without losing it
Syntax
,filter whitelist <on|off>
Example
,filter whitelist off
,filter whitelist off stops every entry
being honoured, and ,filter whitelist list says so at the top while it is off. Nothing is deleted,
so ,filter whitelist on brings back exactly
what was there. Use it for a day you want everyone filtered, staff included, without rebuilding the
list afterward.
Moderators are filtered like everyone else
Holding Manage Messages does not exempt anybody. The exempt list is the bot owner, the server owner, and whitelisted users and roles, nothing else. If you want your staff to be able to post links in a filtered channel, whitelist the staff role.
Check what a message would trip before you post it
,filter test runs a line of text through every
filter configured for the current channel and reports what would happen, without deleting the
message or punishing anyone. It's the fastest way to find out whether a whitelist scope you just set
actually does what you meant.
Syntax
,filter test <text> [@member]
Example
,filter test youre a loser @Nick
Mention someone and the test runs as them: their roles, their whitelist entries, their exemptions. Leave the mention off and it runs as you. The report names which filter would trip, what punishment it carries, and, where an exemption applies, which whitelist entry it came from and what it covers.
Two of the filters can't be simulated from text alone, and the report says so rather than guessing.
Music files need a real attachment, and mass mentions can't be told apart from the @member this
command already uses to pick who to test as. Both still show their configured punishment; neither
gets a verdict.
Manage everything from one panel
Syntax
,filter panel
,filter panel opens a menu instead of typing out
commands, with five pages: Overview (what's on, how many words, whitelist status, at a glance),
Channels (pick a filter, then pick every channel it watches, in one selection), Words (add,
browse and remove banned words), Whitelist (the same add, scope, and on/off this page just
covered, through dropdowns and buttons) and Punishments (set a filter's punishment, or the
mention threshold, across every channel it's already active on at once).
The channel picker on the Channels page replaces the whole list
Submitting it sets that filter's channels to exactly what's selected: anything left out turns off. A server with more than 25 channels filtered for one kind can't show the extras in the picker, so use All off to clear those too rather than assuming an empty-looking picker means an empty list.
Editing one whitelist entry's scope opens a private card only you can see. The whitelist page itself is shared with everyone who has the panel open, and a per-entry editor has nowhere to put one viewer's in-progress edit without showing it to everyone else watching.
What the filters can see
Forwarded messages are inspected as though their contents had been posted directly, and so is text inside an embed: a title, a description, a field or a footer. A banned word or an invite hidden in one of those is treated the same as one typed in the message.
One command turns something a member supplied into text and then redacts what it posts.
,transcribe runs a voice-note transcription through the
link, invite and word filters before sending it. That redaction hides the text and never punishes
anybody, because a transcript is a guess at what somebody said rather than something they typed.
A command with the same shape is not covered
/translate also turns member-supplied content into
bot-posted text, and it does not redact it. It can be pointed at a message somebody else wrote,
so a filtered word can be read back into the channel through it. Turn it off for a channel you
are filtering strictly, or treat the filters as covering what people type rather than everything
that ends up on screen.
/ocr has the same hole. It is switched off at the moment and has no reference page, so there
is nothing to turn off today, but it is worth knowing if it comes back.
Common issues
A message was deleted but nobody was muted. The mute or jail role is missing or was deleted. Set
it with ,config muterole or
,config jailrole. The bot says so in three
places rather than staying silent: a short error in the channel the message was posted in, an entry
in your moderation log channel, and a line in the host's own process log. If you only ever check the
log channel you will still see it, but the in-channel message is the one people notice first.
A whole channel emptied itself after I ran ,filter words. That is the image-only filter. Turn
it off with ,filter words off <#channel>.
Adding a word deleted my own message. It should not: the ,filter command itself is exempt from
the word filter. If a different command's message is being caught, whitelist the role that runs it.
Staff keep getting caught. Run
,filter whitelist add staff once and it covers
whoever ,staff add lists, from then on, without editing
the whitelist again when your staff changes. A permission alone never exempts anybody.
The invite filter is deleting invites to my own server. The bot needs Manage Server to read your server's own invite list. Without it, it cannot tell your invites apart from anybody else's and deletes them all.
A link filter is catching something that is not a link. Turn the filter off for that channel and use the word list instead, which matches exactly what you type.