Skip to content
Open
6 changes: 5 additions & 1 deletion build/scripts/config.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions build/scripts/utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ export const bannedWords: {
],
};

export const tempMute = {
// temp mutes bakas if they use n word. oof. set duration of mute here.
nwordDurationMs: Duration.minutes(10),
};

//for some reason the external mindustry server does not read the files correctly, so we can only use ASCII
export const substitutions:Record<string, string> = Object.fromEntries<string>(Object.entries<string>({
"a": "\u0430\u1E9A\u1EA1\u1E01\u00E4\u03B1@\u0101\u0103\u0105\u03AC",
Expand Down
22 changes: 21 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ For functions that don't need values from other files, see funcs.ts.
*/

import * as api from "/api";
import { adminNames, bannedWords, Gamemode, GamemodeName, multiCharSubstitutions, substitutions, text } from "/config";
import { adminNames, bannedWords, Gamemode, GamemodeName, multiCharSubstitutions, substitutions, text, tempMute } from "/config";
import { fail, PartialFormatString } from "/frameworks/commands";
import { crash, escapeStringColorsServer, escapeTextDiscord, parseError, random, StringIO } from "/funcs";
import { fishState, ipPattern, ipPortPattern, ipRangeCIDRPattern, ipRangeWildcardPattern, maxTime, tileHistory, uuidPattern } from "/globals";
Expand Down Expand Up @@ -546,6 +546,26 @@ export function processChat(player:mindustryPlayer, message:string, effects = fa
}
Log.info(`Censored message from player ${player.name}: "${escapeStringColorsServer(message)}"; contained "${filterTripText}"`);
FishPlayer.messageStaff(`[yellow]Censored message from player ${fishPlayer.cleanedName}: "${message}" contained "${filterTripText}"`);

if (!suspicious) {
const normalized = removeFoosChars(message).toLowerCase();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to remove color tags, or it would allow things like bad[white]word.

Maybe this (strip colors, remove foos chars, lowercase) should be made into a function? something like cleanTextLight

const nwordPattern = /\bn[i1!][gq9]{2,}(?:[ea3]r|a)\b/;

if (nwordPattern.test(normalized)) {
const durationMs = tempMute.nwordDurationMs;
const muteTimestamp = Date.now();
(fishPlayer as any)._lastAutomodMuteAt = muteTimestamp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use undeclared fields like this, it's bad practice. Remove the underscore and add it to the type definition for FishPlayer with the other transients, like autoflagged.

void fishPlayer.mute("automod");
player.sendMessage(`[scarlet]You have been muted for ${Math.round(durationMs / 60000)} minutes.[lightgray] Reason: Prohibited language`);
FishPlayer.messageStaff(`[yellow]Temp-muted ${fishPlayer.cleanedName} for ${Math.round(durationMs / 60000)} minutes: n-word`);
Log.info(`[automod] Temp-muted ${player.name} (${player.uuid()}) for ${Math.round(durationMs / 60000)}m: n-word`);
Timer.schedule(() => {
if ((fishPlayer as any)._lastAutomodMuteAt === muteTimestamp) {
void fishPlayer.unmute("automod");
Copy link
Member

@BalaM314 BalaM314 Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work if the server restarts between the mute and unmute: void fishPlayer.mute("automod") syncs the mute to the backend, so the player will be muted indefinitely, but will not get unmuted.

You can fix this by storing the scheduled unmute, but that will get complicated. (What if the server doesn't come back online? What if the server crashes while saving and needs a rollback?) It's usually better design to avoid updating stored state on a timer, because it causes bugs like this. Instead, we need to change the stored muted property to be a timestamp like unmarkTime.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requires #95

}
}, durationMs / 1000);
}
}
}
message = text.chatFilterReplacement.message();
highlight ??= text.chatFilterReplacement.highlight();
Expand Down