- Rate limit (per-player rolling window).
- Duplicate detection (same message twice within a short window).
- Blocked-word filter (normalised substring match, leet-aware).
config.lua under the antispam and profanityEscalation blocks. The defaults are reasonable for a roleplay server; the rest of this page covers the tuning knobs.
Rate limit + duplicate detection
config.lua
Per-channel exemption
Some channels - typically/me - benefit from repeated text. Players legitimately type “*sighs*”, “*nods*”, “*looks around*” in quick succession, and the duplicate detection would flag them as flood.
Tick Bypass antispam in the Category Manager for that channel. The flag stores as bypassAntispam = true on the category row. When set:
- Rate limit + duplicate checks are skipped for messages in that channel.
- Length cap still applies (structural safety, not behavioural).
- Blocked-word filter still applies (slurs are slurs regardless of channel).
- Profanity escalation still applies on blocked-word hits.
Blocked-word filter
Substring-matched against a normalised version of the message, so common evasion tricks (leet, spacing, padding) collapse to the same canonical form as the bare word.config.lua
Normalisation pipeline
Both the message body and each blocked-word entry are normalised the same way before comparison:- Lowercased -
"SLUR"→"slur" - Leet substitutions -
1→i,3→e,4→a,5→s,7→t,8→b,9→g,@→a,$→s,!→i,|→i,+→t,0→o,2→z,6→g."61ur"→"slur". - Strip non-letters - punctuation, spaces, digits not in the leet map.
"s l u r"→"slur"."s.l.u.r"→"slur". - Collapse runs -
(.)\1+→\1. Any run of 2+ identical letters collapses to one."slurrrr"→"slu". The blocked-word list is normalised the same way, so'slur'becomes'slu'too and the haystack"slu..."contains the needle"slu". Match.
The collapse-to-one rule has one known false positive: the country / place name “Niger” (single g) normalises to the same canonical form as the slur. If your server can’t accept that collision, remove the slur from
blockedWords and live with the evasion gap.Customising the list
Add or remove entries freely. The shipped list is intentionally conservative - a handful of very short / ambiguous terms (e.g.'gay', 'fag' outside 'faggot', 'fat', 'ass', 'rape') are deliberately omitted because they collide with legitimate English words at substring level. Add them yourself if you want stricter matching and accept the false positives.
Profanity escalation
Counts blocked-word hits per-license and runs an action when the count crosses a rung.config.lua
How the ladder works
- A player trips the blocked-word filter → counter increments → highest matching rung fires.
- Counter is per-license, persists across reconnects within the session.
- Counter resets to zero after
resetAfterMsof clean behaviour (no blocked-word hits). Default: 1 hour. - Players with
awoken_chat.bypassACE never increment the counter.
Rung actions
Customising the ladder
Rungs are evaluated bottom-to-top - the highest rung whosehits threshold is matched fires. So you can add intermediate steps:
Bypass permission
- Never trips the rate limit / duplicate / blocked-word filter.
- Doesn’t increment the profanity escalation counter.
- Can send the exact same message back-to-back without throttling.
Audit trail
Every blocked-word hit, rate-limit hit, and duplicate flood posts a Discord embed towebhooks.violations if configured. See Webhooks for the embed shape and what’s included.