Duplicate Message
Catch users who repeat the exact same message content. A volumetric trigger that hashes each message and fires when the same hash reappears too many times among the user's recent message buffer.
Open AutoMod →Duplicate Message watches the exact text a user sends and fires once the same content reappears too many times among their last N messages. It is the simplest defence against copy-paste advertising, raid shouts, and users hammering the same one-liner into every channel.
What is this?
A rule that hashes each message a user sends and fires when the same content shows up too many times in their recent buffer. Defaults to firing on the 4th identical copy within their last 10 messages, across channels.
Why you might want it
For the cross-channel spammer who posts the same promotion message in four channels in a row, and the raid recruiter copy-pasting the same pitch into every place they can. Spam Detection catches volume; this catches repetition. The two complement each other.
max_duplicates. With the default max_duplicates=3, the 4th identical message fires the rule.(guild_id, user_id).Why use this rule?
- Shuts down copy-paste advertising — the same crypto scam pasted across five channels trips the buffer once the user hits your threshold.
- Catches raid shouts and slogan-spam, where a group pastes an identical line over and over to drown out a channel.
- Stops single-user “say my line” repetition without needing a regex or word list.
- Very low false-positive rate on normal conversation — nobody types the exact same sentence four times by accident.
What it detects
A single user posting the same exact message content enough times within their recent message buffer. Each message is fingerprinted with MD5 and dropped into a per-user deque that holds the last window_size hashes — once more than max_duplicates matching hashes sit in that deque, the rule fires on the offending send.
matched_pattern = "4 duplicates". The first three silently piled up in the buffer.What it does NOT detect
- Near-duplicates — adding a period, a trailing space, an emoji, or changing one character breaks the hash.
"hello"and"hello "do not match each other. - Case variants — comparison is case-sensitive.
"Hello"and"hello"are different fingerprints. - Cross-user duplicates — the buffer is keyed per user. Two accounts pasting the same text do not contribute to each other's counts.
- Cross-guild duplicates — state is per-guild. A user spamming the same text in two servers is tracked separately in each.
- Duplicates across a bot restart — the hash deque lives in memory only and resets on restart.
- Duplicate embeds, attachment contents, stickers, or reactions — only the message's
contentstring is hashed.
Configuration
| Field | Type | Default | What it means |
|---|---|---|---|
| max_duplicates | int | 3 | Fires when the count of identical hashes in the user's recent message buffer is strictly greater than this number. With max_duplicates=3 the rule fires on the 4th identical message — the first three silently pile up. |
| window_size | int | 10 | Message-count cap on the per-user hash deque — how many of the user's most recent messages to keep around for comparison. This is not a time window: older entries drop out only when a newer message pushes them past this count. If a user sends slowly, the buffer still holds their last N messages regardless of how much time has passed between them. |
>), the same as every other volumetric trigger in AutoMod. If you want the rule to fire on the 3rd duplicate instead of the 4th, set max_duplicates=2.Recommended starter settings
A balanced baseline for most community servers:
{
"max_duplicates": 3,
"window_size": 10
}Pair with action: delete and a per-user cooldown of 30s. Start in Mode: Log Only so you can see which users and phrases trip the rule before any message is removed. Flip to Live once the Event Log looks clean.
Common false positives
- One-word replies like
yes,no,lol, orgg— enthusiastic users can hit the threshold during a hype moment. - Greeting loops —
gg,wp,ezacross match endings can stack up quickly on a competitive server. - Command retries typed as messages (rather than slash commands), like
!playrepeated because the bot is lagging. - Emoji-only reactions typed as text, e.g.
😂 😂 😂. - Translation or bridge bots that echo messages back into the same channel on behalf of a user.
How to test this rule safely
Set the rule to Log Only
Log Only records matches without taking any action. It is the right starting point for every AutoMod rule.
Pick a harmless test phrase
Choose something you would never type normally, like test_dup_msg_abc. You can trigger the rule without posting anything embarrassing.
Send it four times
In a private channel, post test_dup_msg_abc four times — no need to wait between sends, and no need to rush either. There is no timer on this rule; the buffer simply keeps your last window_size messages. Check the Event Log dashboard — the 4th send should show a match with matched_pattern = "4 duplicates". The first three generate no event.
Confirm minor variations bypass the rule
Now send test_dup_msg_abc (with a trailing space) or Test_dup_msg_abc (different case). The hash changes — no new match, and the previous count does not roll forward.
Confirm exempt roles and channels are ignored
Add your role to Exempt Roles and repeat the test — no Event Log entry. Do the same with an exempt channel. Remove the exemptions when finished.
Flip to Live
Once the Event Log looks right, switch the rule from Log Only to Live.
Known current behavior
- Current behavior: there is no time cutoff. The rule compares each new message against the user's last
window_sizemessages — regardless of how long ago those messages were sent. A slow spammer who paces their duplicates over hours (or days) will still trip the rule as long as the copies stay inside the deque.window_sizebounds message count, not elapsed time. - Current behavior: the operator is strict greater-than.
max_duplicates=3means the 4th identical copy fires the rule — the 1st, 2nd, and 3rd silently pile up in the buffer. This matches every other volumetric trigger (spam_detection,mention_spam,caps_spam,emoji_spam,attachment_spam). - Current behavior: content comparison is exact, including whitespace and case.
"Hey"and"hey"are treated as different messages."hey"and"hey "(trailing space) are also different. Determined users can bypass the rule by appending a random character each time. - Current behavior: MD5 is used as the message fingerprint. This is a non-security use — MD5 is chosen for speed, not collision resistance. Duplicate detection does not need cryptographic strength.
- Current behavior: the hash deque is shared across all duplicate_message rules for the same
(guild, user). There is one deque per user per guild. If you run two duplicate_message rules with different window sizes, the first rule evaluated for that user owns the deque'smaxlen— the second rule's larger window will not retroactively grow it. In practice, running a single duplicate_message rule per server is the cleanest setup. - Current behavior: minor variations bypass the match. Adding a punctuation mark, flipping one letter's case, inserting an emoji, or tacking on a space all produce a new hash and reset the streak. Stack with Spam Detection to catch fast-but-varied floods.
- Current behavior: the buffer is in-memory only and does not persist across bot restarts. Restarting Arkanis clears every user's duplicate-message deque, so a spammer mid-flood briefly gets a fresh count.
Action reference
Pair this trigger with any of the five AutoMod actions. delete removes only the latest duplicate, not the earlier copies that piled up in the buffer — moderators may still want to sweep the earlier messages by hand, or rely on an escalated action like mute or ban to stop further sends.
delete, warn, mute, strike, and ban actually do, plus every action_config field and required Discord permission.