fix: replace global username if also offensive after nickname reset
After resetting an offensive server nickname to the global username, check the global username against gambling/scam keyword list. If it also violates, generate a random 'UserXXXXX' nickname to prevent circumvention via offensive global usernames.
This commit is contained in:
@@ -94,6 +94,26 @@ export async function resetOffensiveNickname(
|
||||
}
|
||||
// setNickname(null) = remove nickname → Discord shows global username
|
||||
await member.setNickname(null, "[auto] nickname melanggar aturan server");
|
||||
|
||||
// ── Check if the global username is ALSO offensive ──────────────
|
||||
// After reset, the member shows their global username. If that is
|
||||
// also offensive (gambling/scam keywords), replace it with a random
|
||||
// generated username so the user can't circumvent the filter by
|
||||
// having an offensive global username.
|
||||
const refreshedMember = await guild.members.fetch(userId);
|
||||
const globalUsername = refreshedMember.user?.username ?? "";
|
||||
if (isGlobalUsernameOffensive(globalUsername)) {
|
||||
const randomName = generateRandomUsername();
|
||||
await refreshedMember.setNickname(
|
||||
randomName,
|
||||
"[auto] global username juga melanggar, diganti random",
|
||||
);
|
||||
logger.info(
|
||||
{ messageId, guildId, userId, globalUsername, randomName },
|
||||
"Global username also offensive — replaced with random username",
|
||||
);
|
||||
}
|
||||
|
||||
recentNicknameResets.set(cooldownKey, Date.now());
|
||||
logger.info(
|
||||
{ messageId, guildId, userId },
|
||||
@@ -119,6 +139,53 @@ export async function resetOffensiveNickname(
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Offensive Username Detection (global username check) ─────────────
|
||||
|
||||
/** Keywords that indicate a gambling/scam/spam username (case-insensitive). */
|
||||
const OFFENSIVE_USERNAME_KEYWORDS = [
|
||||
"bandar",
|
||||
"togel",
|
||||
"slot",
|
||||
"casino",
|
||||
"judi",
|
||||
"poker",
|
||||
"bet",
|
||||
"jackpot",
|
||||
"pragmatic",
|
||||
"deposit",
|
||||
"withdraw",
|
||||
"agen",
|
||||
"bo",
|
||||
"bocoran",
|
||||
"rtp",
|
||||
"maxwin",
|
||||
"scatter",
|
||||
"gacor",
|
||||
"apk",
|
||||
"situs",
|
||||
"link",
|
||||
"klik",
|
||||
"daftar",
|
||||
];
|
||||
|
||||
/**
|
||||
* Check if a global username contains known gambling/scam keywords.
|
||||
* Uses simple substring matching — fast and deterministic, no LLM call.
|
||||
*/
|
||||
function isGlobalUsernameOffensive(username: string): boolean {
|
||||
const lower = username.toLowerCase();
|
||||
return OFFENSIVE_USERNAME_KEYWORDS.some((kw) => lower.includes(kw));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random fallback username: "User" + 5-digit number.
|
||||
* Guaranteed unique per call (random suffix).
|
||||
*/
|
||||
function generateRandomUsername(): string {
|
||||
const suffix = Math.floor(10000 + Math.random() * 90000);
|
||||
return `User${suffix}`;
|
||||
}
|
||||
|
||||
// ─── Error Handling Utilities ────────────────────────────────────────
|
||||
|
||||
function getErrorCode(error: unknown): number | string | undefined {
|
||||
|
||||
Reference in New Issue
Block a user