diff --git a/docs/moderators.md b/docs/moderators.md new file mode 100644 index 0000000..dee9c72 --- /dev/null +++ b/docs/moderators.md @@ -0,0 +1,83 @@ +# Moderator's guide to Mjolnir (bot edition) + +Moderating a community shouldn't be difficult - Mjolnir gives you the tools to make moderation simple and +impersonal. + +## Quick usage + +If you're actively dealing with an incident, here's what you need to know: + +* Always talk to Mjolnir in your coordination room. +* `!mjolnir ban user @spammer:example.org` will ban someone. +* `!mjolnir ban server example.org` will ban a whole server. +* `!mjolnir rules` will tell you what the shortcodes are for your ban lists (needed above). +* `!mjolnir redact @spammer:example.org #room:example.org` will redact someone's posts in a specific room. +* `!mjolnir redact @spammer:example.org` will redact someone's posts in all rooms Mjolnir protects. + +## How Mjolnir works + +Mjolnir uses rules to define its behaviours, with rules defined in ban lists. The rules Mjolnir gets from +ban lists are additive, meaning they cannot be cancelled out. The first rule that matches will be the one +that bans an entity. + +Entities are rooms, users, and servers. The Mjolnir bot only handles users and servers, representing them +as membership bans and server ACLs. ACLs are automatically applied because the rules transfer directly into +the ACL format while membership bans are applied on sight. Within Matrix it is not currently possible to +ban a set of users by glob/regex, so Mjolnir monitors the rooms it protects for membership changes and +bans people who match rules when they join/are invited. + +Mjolnir can run through Pantalaimon if your coordination room is encrypted (this is recommended). Your +coordination/management room is where you and all of your moderators can speak to Mjolnir and update the +rules it uses. Be sure to keep this room private to avoid unauthorized access to the bot. + +Note that Mjolnir performs all its moderation actions as itself rather than encouraging you to use your +own personal account. Banning someone with a personal account can feel like a targeted attack, leading to +further abuse sent to you - using a bot can sometimes diminish the effect. You're welcome to ban someone +without using Mjolnir - the bot won't interfere. + +## List management + +Mjolnir can manage ban lists created through commands. These ban lists can be shared with the general +public or kept private for internal reference. Lists that can be managed are referenced by shortcode - a +string that identifies the room without spaces. For example, a terms of service list might have the shortcode +`tos`. + +To create a new list, run `!mjolnir list create tos terms-of-service-bans`. This creates a new list with +the shortcode `tos` and the alias `#terms-of-service-bans:yourserver.org`. Bans can then be added with +`!mjolnir ban tos user @spammer:example.org` (see `!mjolnir help` for full command reference). + +Mjolnir can also watch other people's ban lists through `!mjolnir watch #matrix-org-bans:example.org`. +To unsubscribe, use `!mjolnir unwatch #list:example.org`. + +## Bans + +Bans are appended to ban lists and enforced immediately. There are three kinds of bans that can be issued: +user, server, and room. Currently the bot won't act upon room bans, but other parts of Mjolnir might. As +mentioned earlier, user and server bans are enforced at the room level through existing support in Matrix. + +Bans support wildcards (`*`) as well, allowing you to ban entire subdomains where required. If you wanted +to ban all of example.org for instance, you'd ban `example.org` and `*.example.org`. + +To issue a ban, use `!mjolnir ban [reason]`. Reasons are optional. For example: +`!mjolnir ban tos server *.example.org Known for spam` to ban the `*.example.org` server for spam. + +If you've banned someone from mistake, you can remove the rule from the ban list using the unban command: +`!mjolnir unban [apply]`. Note that this just removes the rule and might not +cause an unban because another list may still ban the entity. The `[apply]` argument can be specified as `true` +or `false` (default `false`) then the unban is applied immediately regardless of rules, though the unban +might be reversed immediately afterwards due to another rule banning the entity. + +Rules (bans) can be imported with `!mjolnir import ` - this will inspect the +room's state and generate rules for `` to populate. + +## Redactions + +Often it is desirable to remove some content without having to do it yourself. Mjolnir can look up past +events sent by a user and redact them with `!mjolnir redact @spammer:example.org #room:example.org`. If +you want to redact events by that person from all protected rooms, don't specify a room at the end. + +## Management + +Sometimes you might want to see what Mjolnir is up to. There's some commands in `!mjolnir help` that could +be of use to you, such as `!mjolnir rules` to see what rules it is actually enforcing and `!mjolnir status` +to see if Mjolnir is even running where you expect it to. diff --git a/src/commands/CommandHandler.ts b/src/commands/CommandHandler.ts index 45976d6..3e338c7 100644 --- a/src/commands/CommandHandler.ts +++ b/src/commands/CommandHandler.ts @@ -68,6 +68,8 @@ export async function handleCommand(roomId: string, event: any, mjolnir: Mjolnir "!mjolnir sync - Force updates of all lists and re-apply rules\n" + "!mjolnir verify - Ensures Mjolnir can moderate all your rooms\n" + "!mjolnir list create - Creates a new ban list with the given shortcode and alias\n" + + "!mjolnir watch - Watches a ban list\n" + + "!mjolnir unwatch - Unwatches a ban list\n" + "!mjolnir import - Imports bans and ACLs into the given list\n" + "!mjolnir help - This menu\n"; const html = `Mjolnir help:
${htmlEscape(menu)}
`; diff --git a/src/commands/DumpRulesCommand.ts b/src/commands/DumpRulesCommand.ts index 3147f43..a904546 100644 --- a/src/commands/DumpRulesCommand.ts +++ b/src/commands/DumpRulesCommand.ts @@ -28,8 +28,10 @@ export async function execDumpRulesCommand(roomId: string, event: any, mjolnir: hasLists = true; let hasRules = false; - html += `${list.roomId}:
    `; - text += `${list.roomRef}:\n`; + const shortcodeInfo = list.listShortcode ? ` (shortcode: ${list.listShortcode})` : ''; + + html += `${list.roomId}${shortcodeInfo}:
      `; + text += `${list.roomRef}${shortcodeInfo}:\n`; for (const rule of list.serverRules) { hasRules = true;