mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-05 02:36:11 +00:00
Better username censoring (#3122)
## Description: Many inapropriate names bypass the current filter. This PR does the following: 1. Moves name censoring to server side so inappropriate names are scrubbed before being sent to the client 2. Requests a list of profane words from the api, this allows us to quickly add new profane words in the admin panel without having to redeploy. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: evan
This commit is contained in:
@@ -1,92 +1,9 @@
|
||||
import {
|
||||
RegExpMatcher,
|
||||
collapseDuplicatesTransformer,
|
||||
englishDataset,
|
||||
englishRecommendedTransformers,
|
||||
resolveConfusablesTransformer,
|
||||
resolveLeetSpeakTransformer,
|
||||
skipNonAlphabeticTransformer,
|
||||
} from "obscenity";
|
||||
import { translateText } from "../../client/Utils";
|
||||
import { UsernameSchema } from "../Schemas";
|
||||
import { getClanTagOriginalCase, simpleHash } from "../Util";
|
||||
|
||||
const matcher = new RegExpMatcher({
|
||||
...englishDataset.build(),
|
||||
...englishRecommendedTransformers,
|
||||
...resolveConfusablesTransformer(),
|
||||
...skipNonAlphabeticTransformer(),
|
||||
...collapseDuplicatesTransformer(),
|
||||
...resolveLeetSpeakTransformer(),
|
||||
});
|
||||
|
||||
export const MIN_USERNAME_LENGTH = 3;
|
||||
export const MAX_USERNAME_LENGTH = 27;
|
||||
|
||||
const shadowNames = [
|
||||
"NicePeopleOnly",
|
||||
"BeKindPlz",
|
||||
"LearningManners",
|
||||
"StayClassy",
|
||||
"BeNicer",
|
||||
"NeedHugs",
|
||||
"MakeFriends",
|
||||
];
|
||||
|
||||
export function fixProfaneUsername(username: string): string {
|
||||
if (isProfaneUsername(username)) {
|
||||
return shadowNames[simpleHash(username) % shadowNames.length];
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
export function isProfaneUsername(username: string): boolean {
|
||||
return matcher.hasMatch(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes and censors profane usernames and clan tags.
|
||||
* Profane username is overwritten, profane clan tag is removed.
|
||||
*
|
||||
* Preserves non-profane clan tag:
|
||||
* prevents desync after clan team assignment because local player's own clan tag and name aren't overwritten
|
||||
*
|
||||
* Removing bad clan tags won't hurt existing clans nor cause desyncs:
|
||||
* - full name including clan tag was overwritten in the past, if any part of name was bad
|
||||
* - only each separate local player name with a profane clan tag will remain, no clan team assignment
|
||||
*
|
||||
* Examples:
|
||||
* - "GoodName" -> "GoodName"
|
||||
* - "BadName" -> "Censored"
|
||||
* - "[CLAN]GoodName" -> "[CLAN]GoodName"
|
||||
* - "[CLaN]BadName" -> "[CLaN] Censored"
|
||||
* - "[BAD]GoodName" -> "GoodName"
|
||||
* - "[BAD]BadName" -> "Censored"
|
||||
*/
|
||||
export function censorNameWithClanTag(username: string): string {
|
||||
// Don't use getClanTag because that returns upperCase and if original isn't, str replace `[{$clanTag}]` won't match
|
||||
const clanTag = getClanTagOriginalCase(username);
|
||||
|
||||
const nameWithoutClan = clanTag
|
||||
? username.replace(`[${clanTag}]`, "").trim()
|
||||
: username;
|
||||
|
||||
const clanTagIsProfane = clanTag ? isProfaneUsername(clanTag) : false;
|
||||
const usernameIsProfane = isProfaneUsername(nameWithoutClan);
|
||||
|
||||
const censoredNameWithoutClan = usernameIsProfane
|
||||
? fixProfaneUsername(nameWithoutClan)
|
||||
: nameWithoutClan;
|
||||
|
||||
// Restore clan tag if it existed and is not profane
|
||||
if (clanTag && !clanTagIsProfane) {
|
||||
return `[${clanTag.toUpperCase()}] ${censoredNameWithoutClan}`;
|
||||
}
|
||||
|
||||
// Don't restore profane or nonexistent clan tag
|
||||
return censoredNameWithoutClan;
|
||||
}
|
||||
|
||||
export function validateUsername(username: string): {
|
||||
isValid: boolean;
|
||||
error?: string;
|
||||
|
||||
Reference in New Issue
Block a user