3 GrumpyMod EN
darksoon edited this page 2026-07-11 01:17:13 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Moderation

Handles auto-mod, anti-nuke, manual moderation, reports, message log — and the server audit logger.


Auto-Mod

Every message is checked against the configured filters — in this fixed order (not configurable), the first match applies its action: warn · delete · timeout · nothing.

Order Check What it does Default action
1 antiPhishing Fake Nitro/Steam links + external threat feed (see below) timeout 60 min + delete
2 antiAd Blocks Discord invites; optionally all URLs (with allow-list) warn + delete
3 antiFlood Too many user/role mentions in a single message warn + delete
4 antiCaps More than N% uppercase (above a minimum length) delete
5 wordFilter Configured words (exact / substring match) off (empty)
6 antiRepeat Same message sent N times in a row warn + delete
7 antiSpam N+ messages within Y seconds warn + delete

antiPhishing is deliberately first — a phishing hit should never be masked by a weaker check (e.g. antiCaps) matching first.

Whitelisting: Roles in whitelistRoleIds and channels in whitelistChannelIds are completely exempt — from ALL checks.

Escalation: When a user reaches an escalation threshold of active warns, the corresponding action is automatically triggered (the highest matching threshold wins, see the config example below).


Catches things like fake "Free Discord Nitro" links (pattern: dlscord-nitro.com, steam-community-gg.tk). Two independent detection paths, both active at the same time:

a) Built-in heuristics (useBuiltinHeuristics, purely local):

  • Brand impersonation — detects discord/nitro/steam as a standalone part of a domain, but NOT the real domains (discord.com, steamcommunity.com etc. are always safe). A link like steamworks.dev does NOT trigger, even though "steam" appears — only when the brand forms its own clearly delimited part.
  • Suspicious TLD + bait keyword.tk/.ml/.ga/.cf/.gq/.zip/.mov only trigger when the message ALSO contains a bait keyword (free, gratis, nitro, gift, geschenk, airdrop, claim, giveaway) — a plain .tk link by itself is not blocked.

b) URLhaus threat feed (useUrlhaus) — an external, hourly-refreshed list of known malware/phishing URLs from abuse.ch (free, no API key). Currently around 15,000 entries, cached locally (cache/urlhaus-urls.txt) — the per-message check is therefore a pure memory lookup, no network call while chatting. Catches known, already-reported malicious URLs worldwide — not just brand fakes, any kind of reported malware/phishing site.

c) Custom blocklist (customBlocklist) — fixed domains that are ALWAYS blocked (subdomains included).

Example: Free Nitro: dlscord-glft.tk 🎁 → brand impersonation triggers immediately (recognizes "dlscord"). A URL with no recognizable brand name that's already listed in the URLhaus database is still caught — even if check (a) finds nothing.


Message Log — Content of Deleted/Edited Messages

Discord's own native audit log (see server audit logger below) never shows message content and only records deletions performed by a moderator on someone else's message — if a user deletes their own message, it never shows up there. Edits aren't logged by Discord at all.

Message Log closes that gap: it posts on every deletion/edit (regardless of who triggered it) with the actual content, into channels.mod-log:

  • Deletion: author, channel, full text, attachments
  • Edit: author, channel, link to the message, text before and after
  • Bulk deletion: channel, count, up to 10 example messages with content

Limitation: If a message existed before the last bot restart, or is older than the last ~200 messages in that channel, the bot never learned its content — in that case nothing is posted at all (Discord simply never told the bot the content; this isn't a GrumpyCore limitation).


Anti-Nuke

Detects coordinated or accidental server destruction in real time. Hardcoded, not configurable via YAML — runs automatically as long as addons.mod: true.

Triggers (10-second window):

  • Mass channel deletions (3)
  • Mass bans (5)
  • Mass role deletions (3)

Response:

  1. All roles are immediately stripped from the offender (a single API call, no rate-limit risk)
  2. A notification appears in the alert channel (optionally pinging the alert-ping role)
  3. A 60-second cooldown prevents double-neutralizing the same offender
  4. The server owner is exempt from role removal

/mod nuke — Fully Reset a Channel

/mod clear and /mod purge cannot delete messages older than 14 days — a hard limit of Discord's own API. /mod nuke works around that: the channel is cloned (identical name, permissions, position) and the old one is then fully deleted — this affects every message regardless of age. Afterward the bot posts an embed in the fresh channel ("☢️ CHANNEL NUKED").

Cannot be undone. Requires extra Manage Channels (not just Manage Messages like clear/purge), so a regular message moderator can't trigger it by accident.

/mod nuke

Punishment System

Every mod action receives a unique P-#-ID and is stored in the database. active controls whether an entry still counts toward escalation / is still in effect — default active status: warn/mute/ban → active; kick/note/softban/unmute/unban/unwarn → inactive.

  • View history: /mod history @user (up to 25 entries, 🟢 active / inactive, moderator, timestamp, expiry if any)
  • Deactivate a single warn: /mod unwarn <id>
  • Remove a timeout: /mod unmute @user
  • Full command list: Mod-Commands-EN

Punishment types:

  • Note (/mod note) — staff note without punishment, appears in /mod history
  • Softban (/mod softban) — kick + message cleanup (ban+unban) without a permanent ban
  • Tempban (/mod tempban) — a normal ban with an expiry, automatically lifted by the auto-unban runner (60s interval)

Searching & exporting the history:

Command Filters Description
/mod modlog-search user/moderator/type (warn/kick/ban/softban/mute/note)/days (13650), all optional Shows up to 25 matches as an embed, footer states match count vs. total
/mod modlog-export user/type/days, all optional (no moderator filter) CSV attachment (id,type,userId,moderatorId,reason,active,createdAt,expiresAt)

modlog-export is protected against CSV formula injection (a leading =, +, -, @, tab, or CR in the reason field is neutralized with a leading ').


Report System

/report user:@Someone reason:"Reason here"
  • Cooldown: 60 sec between reports per reporter
  • Limit: 10 reports per day per reporter
  • Self-reports and bot reports are not possible
  • Staff sees the report in the configured target channel with buttons: Deny / Warn / Timeout / Kick / Ban
  • Click permission: Moderate Members or a role from roles.support (base), plus the matching Discord permission for Timeout/Kick/Ban

Configuration (configs/modules/mod.yml)

enabled: true
reportChannelId: "0"             # Fallback target channel for /report

whitelistRoleIds: []              # Roles that bypass auto-mod entirely
whitelistChannelIds: []           # Channels that bypass auto-mod entirely

escalation:
  - threshold: 3                  # at 3 active warns
    action: mute
    durationMinutes: 60
  - threshold: 5
    action: kick
  - threshold: 7
    action: ban

autoMod:
  antiPhishing:
    enabled: true
    useBuiltinHeuristics: true    # brand impersonation + TLD heuristic
    useUrlhaus: true              # external threat feed (abuse.ch)
    customBlocklist: []           # your own fixed blocked domains
    action: timeout
    timeoutMinutes: 60
    deleteMessages: true

  antiAd:
    enabled: true
    blockInvites: true
    blockAllLinks: false
    allowedDomains: []
    action: warn
    deleteMessages: true

  antiFlood:
    enabled: true
    maxMentions: 5
    action: warn
    timeoutMinutes: 10
    deleteMessages: true

  antiCaps:
    enabled: true
    threshold: 0.7                # 70% uppercase ratio
    minLength: 10
    action: delete
    deleteMessages: true

  wordFilter:
    enabled: false
    words: []
    substring: false
    action: warn
    deleteMessages: true

  antiRepeat:
    enabled: true
    repeats: 3
    windowSeconds: 60
    action: warn
    deleteMessages: true

  antiSpam:
    enabled: true
    messages: 5
    windowSeconds: 5
    action: warn
    timeoutMinutes: 5
    deleteMessages: true

report:
  enabled: true
  cooldownSeconds: 60
  dailyLimit: 10

messageLog:
  enabled: true
  logEdits: true
  logDeletes: true
  ignoreBots: true                # don't log bot-authored messages

nuke:
  gifUrl: ""                      # optional image/GIF for the nuke message, empty = text only

If a newly-added key is missing from an existing mod.yml after a bot update, it gets automatically backfilled with its default on the next restart — your existing settings are left untouched.


Server Audit Logger

Automatically logs a wide range of server events to the mod-log channel — structured embeds with a category badge, executor (By:), target, and details. This does NOT overlap with Message Log above (that shows content, the audit log doesn't).

Category Events
Channels CHANNEL_CREATE · CHANNEL_DELETE · CHANNEL_UPDATE
Roles ROLE_CREATE · ROLE_DELETE · ROLE_UPDATE
Members ROLE_ADD · ROLE_REMOVE · MEMBER_UPDATE · MEMBER_KICK · MEMBER_BAN · MEMBER_UNBAN
Other INVITE_CREATE/DELETE · WEBHOOK_CREATE/DELETE · EMOJI_CREATE/DELETE

Set the channel via channels.mod-log in configs/config.yml — no additional setup required.


Permissions Overview

Command / Action Required Discord Permission
/mod (base) Moderate Members
/mod kick + Kick Members
/mod ban/tempban/softban/unban + Ban Members
/mod clear/purge + Manage Messages
/mod slowmode + Manage Channels
/mod nuke + Manage Channels
/mod reload Manage Guild
/report none (except self-/bot-/mod-exclusion)

Full command list: Mod-Commands-EN