DUXPLIMA Documentation

Filters

The eleven filters, what each does when it catches a line, the ladder of points, automatic replies and the AI review.

Module: filters. The filters read public lines, private messages and mail, and with filter-surfaces = true in config.conf signs, books and anvil names too. A player with uxmchat.bypass.filter passes them all; staff with uxmchat.staff.filter are told about every catch.

What a catch does

ActionEffect
blockThe line does not go out, and the player is told why
censorThe bad part is starred and the line goes out
shadowOnly the player sees their line, and is not told
notifyThe line goes out and staff are told

Every filter also takes points (added to the ladder on each catch), channels (the channels it reads; empty reads every channel), enabled and censor-with.

The filters

FilterCatchesShips asIts own keys
spamToo many lines too fastblock, 1 pointlines = 5 in window-seconds = 4
duplicateThe same line again and againblock, 1 pointlookback = 3, similarity = 0.85, allowed (gg, gl, hi, ty, lol)
capsSHOUTINGcensor, 0 pointsmin-letters = 6, max-ratio = 0.7
advertLinks and server addresses, also written as "play dot example dot net"block, 5 points
phonePhone numbersblock, 2 points
parrotCopying what another player just saidblock, 1 pointmin-length = 12, similarity = 0.9
floodOne character over and overcensor, 0 pointsmax-run = 4
whitespaceLines of empty spacecensor, 0 pointsmax-run = 3
repeatOne word over and overblock, 1 pointmax-repeats = 4, allowed (ha, xd, gg)
swearSwear wordscensor, 3 pointsbelow
unicodeInvisible, direction, zalgo and full-width characterscensor, 0 pointscategories, max-foreign-ratio = 1

The allowlist holds words and domains no filter ever catches: class, assassin, scunthorpe, grape, analysis, and the domains uxplima.com and discord.gg/example. Put your own server's address there.

Swear words

The swear filter reads the words list, every file in modules/filters/words/ (one per language, one word per line), and the files word-files names in that folder. It finds a word:

  • spelled with numbers, accents or repeated letters, or one letter at a time (f u c k);
  • backwards, with reversed = true;
  • spread over the last split-lines (3) lines.

A list word of four letters or fewer matches only a whole word, so ass is not found in class; a longer one is found inside words too. A word with a Turkish or accented letter, such as göt, matches only words written with such a letter, so got passes. fuzzy = true also matches a word of seven letters or more with one letter wrong; it ships off because ordinary words sit one letter away from many list words. patterns takes regular expressions.

The ladder

Points from catches climb a ladder; each rung runs its actions when a player reaches its points. Points fall by decay-per-day (5) each day.

PointsShipped action
10A warning: the next step is a mute
25[console] mute {player} 10m Too many filter catches
50[console] mute {player} 1h Too many filter catches

{player} is the player's name and {points} the rung's points. The console mute is uxmChat's own or that of the punishment plugin you run.

Commands as chat

commands lists commands whose words pass the filters as if they were chat, such as /msg of another plugin: tell, w, whisper, r, reply, me, say ship.

Automatic replies

Module: auto-replies. A line that matches a trigger, a regular expression read without case, gets a reply sent to the asking player only. spawn answers "how do I get to spawn" and discord answers "what is the discord". A reply that starts with @ is a line of the messages files; permission limits who gets it.

The AI review

Module: ai, off by default. After a line goes out, it is sent to a model on OpenRouter with the rules you wrote, and a line the model finds against them adds points (5) to the player's ladder; staff read why. Nothing is sent without an api-key, at most per-minute (30) lines are reviewed, and lines shorter than min-length (4) are not sent. uxmchat.bypass.ai skips it.

OpenRouter bills you

The AI review sends lines to a paid service under your own key. Keep the key out of git and watch the bill.

Related: filters.conf, Mutes