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:
asepharyana
2026-08-27 12:46:33 +07:00
parent 0de393625f
commit 1590479f58
@@ -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 {