Moderation
Warning, timing out, kicking and banning, with a numbered case behind each one.
Module: moderation.
The commands
/warn member: @Ada reason: <why>
/timeout member: @Ada duration: 30m reason: <why>
/untimeout member: @Ada
/kick member: @Ada reason: <why>
/ban member: @Ada reason: <why>
/unban
/softban member: @Ada delete_days: 1
/purge
/softban bans and immediately unbans, which clears somebody's recent messages
without keeping them out. It is the tool for a spam wave, not for a person you
want gone.
/purge deletes recent messages in the channel you run it in.
/ban takes an optional duration. Leave it off for permanent, set it and the
bot lifts the ban itself when it expires.
Every action gets a case number
/case view
/case reason
/case history member: @Ada
Each case carries who did it, to whom, why, when, and whether it is still in
force. /case reason corrects the wording afterwards, which matters because the
reason is what an appeal is judged against.
The case is written before Discord is touched. A case with no ban behind it is a record of something that failed, and a moderator can see that. A ban with no case is a member who vanished and nobody can say who removed them or why.
What it refuses to do
Anything you could not do by hand. Your top role is checked against the target's, and the bot's against theirs too. A junior moderator holding the command cannot ban somebody above them.
Acting on yourself, or on the bot.
People are told before they are removed
A kicked or banned member cannot receive a DM afterwards, so the message goes out first. If it fails, the moderator is told it failed rather than assuming it landed. Somebody handling an appeal needs to know whether the person was ever informed.
Roles come back
Turn on role persistence and the bot remembers what somebody held when they left. Rejoin and they get it back.
@everyone and managed roles are left out. A managed role belongs to an
integration, and handing one back would put somebody in a subscriber or bot role
they no longer have.
No automod
Spam filters, invite blocking, banned words, mention floods and raid detection are not in this. All of them need Discord's Message Content intent, which is privileged and has not been granted yet.
Nothing else in the module needs it, which is why the rest shipped without waiting.
It's not working
"You cannot moderate that member." They are above you in the role list, or above the bot. Discord will not let the bot act on somebody higher than itself whatever permission you hold.
A ban worked but the case says it failed. The case is written first, so the row exists before Discord is called. If Discord then refused, the case records that rather than being deleted. Read the case rather than guessing from the member list.
A tempban did not lift. The bot lifts these itself on a timer. A restart at the wrong moment delays it to the next pass rather than losing it.
A timeout is still showing in a case after it expired. Discord expires timeouts itself, so the bot does not lift them and the case keeps its original end time. The member is not still timed out.
Somebody rejoined without their roles. Role persistence is off in that server, or they held only managed roles.
/purge deleted fewer messages than you asked for.
Discord refuses to bulk-delete anything older than two weeks. Nothing is wrong;
that is the limit.