Skip to content

Commit d0e3770

Browse files
committed
Fix profanity filter + new username generator
The profanity filter was fixed up to account for cases like [C]rap and C_rap. The filter was extended slightly, and the `RegExpMatcher` ctor was fixed (transformers can't use the same `...` syntax like `englishDataset` and `englishRecommendedTransformers` Additionally, the scattered set of name generators used for players was replaced with one single name generator that comes up with some snazzy stuff like "Space Cow", "Secret Gnome Agenda", and "Comically Large Snail". Copyright: No AI was used in the making of this patch.
1 parent 73bf583 commit d0e3770

File tree

4 files changed

+140
-21
lines changed

4 files changed

+140
-21
lines changed

src/client/UsernameInput.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
MAX_USERNAME_LENGTH,
88
validateUsername,
99
} from "../core/validations/username";
10+
import { getRandomUsername } from "../core/utilities/UsernameGenerator";
1011

1112
const usernameKey: string = "username";
1213

@@ -94,7 +95,7 @@ export class UsernameInput extends LitElement {
9495
}
9596

9697
private generateNewUsername(): string {
97-
const newUsername = "Anon" + this.uuidToThreeDigits();
98+
const newUsername = getRandomUsername(Math.random())
9899
this.storeUsername(newUsername);
99100
return newUsername;
100101
}

src/core/Util.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ import {
1212
Winner,
1313
} from "./Schemas";
1414

15-
import {
16-
BOT_NAME_PREFIXES,
17-
BOT_NAME_SUFFIXES,
18-
} from "./execution/utils/BotNames";
15+
import { getRandomUsername } from "./utilities/UsernameGenerator";
1916

2017
export function manhattanDistWrapped(
2118
c1: Cell,
@@ -276,16 +273,10 @@ export function createRandomName(
276273
name: string,
277274
playerType: string,
278275
): string | null {
279-
let randomName: string | null = null;
280276
if (playerType === "HUMAN") {
281-
const hash = simpleHash(name);
282-
const prefixIndex = hash % BOT_NAME_PREFIXES.length;
283-
const suffixIndex =
284-
Math.floor(hash / BOT_NAME_PREFIXES.length) % BOT_NAME_SUFFIXES.length;
285-
286-
randomName = `👤 ${BOT_NAME_PREFIXES[prefixIndex]} ${BOT_NAME_SUFFIXES[suffixIndex]}`;
277+
return getRandomUsername(simpleHash(name));
287278
}
288-
return randomName;
279+
return null;
289280
}
290281

291282
export const emojiTable = [
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { simpleHash } from "../Util"
2+
3+
const PLURAL_NOUN = Symbol("plural!")
4+
const NOUN = Symbol("noun!")
5+
6+
const names = [
7+
["World Famous", NOUN],
8+
["Comically Large", NOUN],
9+
["Comically Small", NOUN],
10+
["Clearance Aisle", PLURAL_NOUN],
11+
[NOUN, "For Hire"],
12+
["Suspicious", NOUN],
13+
["Sopping Wet", PLURAL_NOUN],
14+
["Smelly", NOUN],
15+
["Friendly", NOUN],
16+
["Tardy", NOUN],
17+
["Evil", NOUN],
18+
[PLURAL_NOUN, "That Bite"],
19+
["Malicious", NOUN],
20+
["Spiteful", NOUN],
21+
["Mister", NOUN],
22+
["Alternate", NOUN,"Universe"],
23+
[NOUN, "Island"],
24+
[NOUN, "Kingdom"],
25+
[NOUN, "Empire"],
26+
[NOUN, "Dynasty"],
27+
[NOUN, "Cartel"],
28+
[NOUN, "Cabal"],
29+
["Not Too Fond Of", PLURAL_NOUN],
30+
["Honk For", PLURAL_NOUN],
31+
["Canonically Evil", NOUN],
32+
["Limited Edition", NOUN],
33+
[NOUN, "Scientist"],
34+
["Famous", NOUN, "Collection"],
35+
["Supersonic", NOUN, "Spaceship"],
36+
["Patent Pending", NOUN],
37+
["Patented", NOUN],
38+
["Space", NOUN],
39+
["Secret", NOUN, "Agenda"],
40+
[PLURAL_NOUN, "in my walls"],
41+
["The", PLURAL_NOUN, "are SPIES"],
42+
["Traveling", NOUN, "Circus"]
43+
]
44+
45+
const nouns = [
46+
"Snail",
47+
"Cow",
48+
"Giraffe",
49+
"Donkey",
50+
"Horse",
51+
"Mushroom",
52+
"Salad",
53+
"Kitten",
54+
"Fork",
55+
"Apple",
56+
"Pancake",
57+
"Tree",
58+
"Fern",
59+
"Seashell",
60+
"Turtle",
61+
"Casserole",
62+
"Gnome",
63+
"Frog",
64+
]
65+
66+
function isSeedAcceptable(sanitizedSeed: number) {
67+
let template = names[sanitizedSeed % names.length];
68+
let noun = nouns[Math.floor(sanitizedSeed / names.length) % nouns.length];
69+
70+
let totalLength =
71+
template.map((v) => ((v as any)?.length ?? 0)).reduce((a,b) => a + b)
72+
+ template.length
73+
+ noun.length;
74+
75+
return totalLength <= 26
76+
}
77+
/**
78+
* Generate a random username based on a numeric seed
79+
* @param seed - the seed to use to select a username
80+
* @returns a string suitable for a player username
81+
*/
82+
export function getRandomUsername(seed: number) : string {
83+
let sanitizedSeed = Math.floor((seed * 2999) % (names.length * nouns.length));
84+
let template = names[sanitizedSeed % names.length];
85+
let noun = nouns[Math.floor(sanitizedSeed / names.length) % nouns.length];
86+
let result: [string?] = [];
87+
88+
while (!isSeedAcceptable(sanitizedSeed)) {
89+
sanitizedSeed += 1;
90+
}
91+
92+
// Convert template to some somewhat-legible word string
93+
for (let step of template) {
94+
if (step == PLURAL_NOUN) {
95+
result.push(`${noun}s`);
96+
} else if (step == NOUN) {
97+
result.push(noun);
98+
} else {
99+
result.push(step.toString());
100+
}
101+
}
102+
103+
return result.join(" ")
104+
}

src/core/validations/username.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,45 @@
11
import {
2+
DataSet,
23
RegExpMatcher,
34
collapseDuplicatesTransformer,
45
englishDataset,
5-
englishRecommendedTransformers,
6+
pattern,
67
resolveConfusablesTransformer,
78
resolveLeetSpeakTransformer,
89
skipNonAlphabeticTransformer,
10+
toAsciiLowerCaseTransformer,
911
} from "obscenity";
1012
import { translateText } from "../../client/Utils";
1113
import { simpleHash } from "../Util";
14+
import { getRandomUsername } from "../utilities/UsernameGenerator";
15+
16+
const customDataset = new DataSet()
17+
.addAll(englishDataset)
18+
.addPhrase((phrase) =>
19+
phrase.setMetadata({ originalWord: 'nigg' })
20+
/* Not used by any english words */
21+
.addPattern(pattern`niqq`))
1222

1323
const matcher = new RegExpMatcher({
14-
...englishDataset.build(),
15-
...englishRecommendedTransformers,
16-
...resolveConfusablesTransformer(),
17-
...skipNonAlphabeticTransformer(),
18-
...collapseDuplicatesTransformer(),
19-
...resolveLeetSpeakTransformer(),
24+
...customDataset.build(),
25+
26+
blacklistMatcherTransformers: [
27+
resolveConfusablesTransformer(),
28+
resolveLeetSpeakTransformer(),
29+
skipNonAlphabeticTransformer(),
30+
toAsciiLowerCaseTransformer(),
31+
collapseDuplicatesTransformer({
32+
customThresholds: new Map([
33+
['b', 2],
34+
['e', 2],
35+
['o', 2],
36+
['l', 2],
37+
['s', 2],
38+
['g', 2],
39+
['q', 2]
40+
]),
41+
})
42+
]
2043
});
2144

2245
export const MIN_USERNAME_LENGTH = 3;
@@ -36,7 +59,7 @@ const shadowNames = [
3659

3760
export function fixProfaneUsername(username: string): string {
3861
if (isProfaneUsername(username)) {
39-
return shadowNames[simpleHash(username) % shadowNames.length];
62+
return getRandomUsername(simpleHash(username));
4063
}
4164
return username;
4265
}

0 commit comments

Comments
 (0)