From 81e26b68fcaeb1bd6388af0fde40c5c540605432 Mon Sep 17 00:00:00 2001 From: hfgd123 Date: Sun, 15 Feb 2026 23:51:01 +0100 Subject: [PATCH] Added module name-list-cleaner as per Sukram2.0's suggestion also added tabs in en.json... --- locales/en.json | 127 +++++++++--------- modules/name-list-cleaner/configs/config.json | 90 +++++++++++++ modules/name-list-cleaner/events/botReady.js | 7 + .../events/guildMemberUpdate.js | 9 ++ modules/name-list-cleaner/module.json | 24 ++++ modules/name-list-cleaner/renameMember.js | 52 +++++++ 6 files changed, 248 insertions(+), 61 deletions(-) create mode 100644 modules/name-list-cleaner/configs/config.json create mode 100644 modules/name-list-cleaner/events/botReady.js create mode 100644 modules/name-list-cleaner/events/guildMemberUpdate.js create mode 100644 modules/name-list-cleaner/module.json create mode 100644 modules/name-list-cleaner/renameMember.js diff --git a/locales/en.json b/locales/en.json index 171abe2..340e460 100644 --- a/locales/en.json +++ b/locales/en.json @@ -930,66 +930,71 @@ "nickname-error": "An error occurred while trying to change the nickname of %u: %e" }, "ping-protection": { - "log-not-a-member": "[Ping Protection] Punishment failed: The pinger is not a member.", - "log-punish-role-error": "[Ping Protection] Punishment failed: I cannot punish %tag because their role is higher than or equal to my highest role.", - "log-mute-error": "[Ping Protection] Punishment failed: I cannot mute %tag: %e", - "log-kick-error": "[Ping Protection] Punishment failed: I cannot kick %tag: %e", - "log-action-log-failed": "[Ping Protection] Punishment logging failed: %e", - "log-manual-delete": "All data for <@%u> (%u) has been deleted successfully.", - "log-manual-delete-logs": "[Ping Protection] All data for user with ID %u has been deleted successfully.", - "log-automod-keyword-limit": "[Ping Protection] Automod keywords exceed 1000 characters limit. Keywords were truncated.", - "punish-log-failed-title": "Punishment failed for user %u", - "punish-log-failed-desc": "An error occured while trying to punish the user %m. Please check the bot's permissions and role hierarchy. See the message below for the error.", - "punish-log-error": "Error: ```%e```", - "punish-role-error": "I cannot punish %tag because their role is higher than or equal to my highest role.", - "reason-basic": "User reached %c pings in the last %w weeks.", - "reason-advanced": "User reached %c pings in the last %d days (Custom timeframe).", - "cmd-desc-module": "Ping protection related commands", - "cmd-desc-group-user": "Every command related to the users", - "cmd-desc-history": "View the ping history of a user", - "cmd-opt-user": "The user to check", - "cmd-desc-actions": "View the moderation action history of a user", - "cmd-desc-panel": "Admin: Open the user management panel", - "cmd-desc-group-list": "Lists protected or whitelisted entities", - "cmd-desc-list-protected": "List all protected users and roles", - "cmd-desc-list-wl": "List all whitelisted roles and channels", - "embed-history-title": "Ping history of %u", - "embed-leaver-warning": "This user left the server at %t. These logs will stay until automatic deletion.", - "no-data-found": "No logs found for this user.", - "embed-actions-title": "Moderation history of %u", - "label-reason": "Reason", - "actions-retention-note": "Note: Moderation actions are retained for 1 - 12 months based on the configuration.", - "no-permission": "You don't have sufficient permissions to use this command.", - "panel-title": "User Panel: %u", - "panel-description": "Manage and view data for %u (%i). View a quick recap of their ping and moderation history, or delete all data stored for this user (Risky).", - "btn-history": "Ping history", - "btn-actions": "Actions history", - "btn-delete": "Delete all data (Risky)", - "list-protected-title": "Protected Users and Roles", - "list-protected-desc": "View all protected users and roles here. When someone pings one of these protected user(s)/role(s), a warning will be sent. Exceptions are whitelisted roles, and when sent in a whitelisted channel.", - "field-prot-users": "Protected Users", - "field-prot-roles": "Protected Roles", - "list-whitelist-title": "Whitelisted Roles and Channels", - "list-whitelist-desc": "View all whitelisted roles and channels here. Whitelisted roles will not get a warning for pinging a protected entity, and pings will be ignored in whitelisted channels.", - "field-wl-roles": "Whitelisted Roles", - "field-wl-channels": "Whitelisted Channels", - "list-none": "None are configured.", - "modal-title": "Confirm data deletion for this user", - "modal-label": "Confirm data deletion by typing this phrase:", - "modal-phrase": "I understand that all data of this user will be deleted and that this action cannot be undone.", - "modal-failed": "The phrase you entered is incorrect. Data deletion cancelled.", - "field-quick-history": "Quick history view (Last %w weeks)", - "field-quick-desc": "Pings history amount: %p\nModeration actions amount: %m", - "history-disabled": "History logging has been disabled by a bot-configurator.\nAre you (one of) the bot-configurators? You can enable history logging in the \"storage\" tab in the 'ping-protection' module ^^", - "leaver-warning-long": "User left at %d. These logs will stay until automatic deletion.", - "leaver-warning-short": "User left at %d.", - "meme-why": "😐 [Why are you the way that you are?]() - You just pinged yourself..", - "meme-played": "🔑 [Congratulations, you played yourself.]()", - "meme-spider": "🕷️ [Is this you?]() - You just pinged yourself.", - "meme-rick": "🎵 [Never gonna give you up, never gonna let you down...]() You just Rick Rolled yourself. Also congrats you unlocked the secret easter egg that only has a 1% chance of appearing!!1!1!!", - "meme-grind": "Why are you even pinging yourself 5 times in a row? Anyways continue some more to possibly get the secret meme\n-# (good luck grinding, only a 1% chance of getting it and during testing I had it once after 83 pings)", - "label-jump": "Jump to Message", - "no-message-link": "This ping was blocked by AutoMod", - "list-entry-text": "%index. **Pinged %target** at %time\n%link" + "log-not-a-member": "[Ping Protection] Punishment failed: The pinger is not a member.", + "log-punish-role-error": "[Ping Protection] Punishment failed: I cannot punish %tag because their role is higher than or equal to my highest role.", + "log-mute-error": "[Ping Protection] Punishment failed: I cannot mute %tag: %e", + "log-kick-error": "[Ping Protection] Punishment failed: I cannot kick %tag: %e", + "log-action-log-failed": "[Ping Protection] Punishment logging failed: %e", + "log-manual-delete": "All data for <@%u> (%u) has been deleted successfully.", + "log-manual-delete-logs": "[Ping Protection] All data for user with ID %u has been deleted successfully.", + "log-automod-keyword-limit": "[Ping Protection] Automod keywords exceed 1000 characters limit. Keywords were truncated.", + "punish-log-failed-title": "Punishment failed for user %u", + "punish-log-failed-desc": "An error occured while trying to punish the user %m. Please check the bot's permissions and role hierarchy. See the message below for the error.", + "punish-log-error": "Error: ```%e```", + "punish-role-error": "I cannot punish %tag because their role is higher than or equal to my highest role.", + "reason-basic": "User reached %c pings in the last %w weeks.", + "reason-advanced": "User reached %c pings in the last %d days (Custom timeframe).", + "cmd-desc-module": "Ping protection related commands", + "cmd-desc-group-user": "Every command related to the users", + "cmd-desc-history": "View the ping history of a user", + "cmd-opt-user": "The user to check", + "cmd-desc-actions": "View the moderation action history of a user", + "cmd-desc-panel": "Admin: Open the user management panel", + "cmd-desc-group-list": "Lists protected or whitelisted entities", + "cmd-desc-list-protected": "List all protected users and roles", + "cmd-desc-list-wl": "List all whitelisted roles and channels", + "embed-history-title": "Ping history of %u", + "embed-leaver-warning": "This user left the server at %t. These logs will stay until automatic deletion.", + "no-data-found": "No logs found for this user.", + "embed-actions-title": "Moderation history of %u", + "label-reason": "Reason", + "actions-retention-note": "Note: Moderation actions are retained for 1 - 12 months based on the configuration.", + "no-permission": "You don't have sufficient permissions to use this command.", + "panel-title": "User Panel: %u", + "panel-description": "Manage and view data for %u (%i). View a quick recap of their ping and moderation history, or delete all data stored for this user (Risky).", + "btn-history": "Ping history", + "btn-actions": "Actions history", + "btn-delete": "Delete all data (Risky)", + "list-protected-title": "Protected Users and Roles", + "list-protected-desc": "View all protected users and roles here. When someone pings one of these protected user(s)/role(s), a warning will be sent. Exceptions are whitelisted roles, and when sent in a whitelisted channel.", + "field-prot-users": "Protected Users", + "field-prot-roles": "Protected Roles", + "list-whitelist-title": "Whitelisted Roles and Channels", + "list-whitelist-desc": "View all whitelisted roles and channels here. Whitelisted roles will not get a warning for pinging a protected entity, and pings will be ignored in whitelisted channels.", + "field-wl-roles": "Whitelisted Roles", + "field-wl-channels": "Whitelisted Channels", + "list-none": "None are configured.", + "modal-title": "Confirm data deletion for this user", + "modal-label": "Confirm data deletion by typing this phrase:", + "modal-phrase": "I understand that all data of this user will be deleted and that this action cannot be undone.", + "modal-failed": "The phrase you entered is incorrect. Data deletion cancelled.", + "field-quick-history": "Quick history view (Last %w weeks)", + "field-quick-desc": "Pings history amount: %p\nModeration actions amount: %m", + "history-disabled": "History logging has been disabled by a bot-configurator.\nAre you (one of) the bot-configurators? You can enable history logging in the \"storage\" tab in the 'ping-protection' module ^^", + "leaver-warning-long": "User left at %d. These logs will stay until automatic deletion.", + "leaver-warning-short": "User left at %d.", + "meme-why": "😐 [Why are you the way that you are?]() - You just pinged yourself..", + "meme-played": "🔑 [Congratulations, you played yourself.]()", + "meme-spider": "🕷️ [Is this you?]() - You just pinged yourself.", + "meme-rick": "🎵 [Never gonna give you up, never gonna let you down...]() You just Rick Rolled yourself. Also congrats you unlocked the secret easter egg that only has a 1% chance of appearing!!1!1!!", + "meme-grind": "Why are you even pinging yourself 5 times in a row? Anyways continue some more to possibly get the secret meme\n-# (good luck grinding, only a 1% chance of getting it and during testing I had it once after 83 pings)", + "label-jump": "Jump to Message", + "no-message-link": "This ping was blocked by AutoMod", + "list-entry-text": "%index. **Pinged %target** at %time\n%link" + }, + "name-list-cleaner": { + "owner-cannot-be-renamed": "The owner of the server (%u) cannot be renamed.", + "nickname-error": "An error occurred while trying to change the nickname of %u: %e", + "nickname-reset": "The nickname of %u has been reset, as it started with a blacklisted character." } } \ No newline at end of file diff --git a/modules/name-list-cleaner/configs/config.json b/modules/name-list-cleaner/configs/config.json new file mode 100644 index 0000000..9180dbe --- /dev/null +++ b/modules/name-list-cleaner/configs/config.json @@ -0,0 +1,90 @@ +{ + "description": { + "en": "Configure the function of the module here", + "de": "Stelle hier die Funktionen des Modules ein" + }, + "humanName": { + "en": "Configuration", + "de": "Konfiguration" + }, + "filename": "config.json", + "content": [ + { + "name": "keepNickname", + "humanName": { + "en": "Keep nickname", + "de": "Nickname behalten" + }, + "default": { + "en": true + }, + "description": { + "en": "If yes: special characters will be removed from nicknames; if no: the nickname will be removed and the username will be shown instead.", + "de": "Wenn ja: Sonderzeichen werden aus den Nicknames entfernt; wenn nein: der Nickname wird entfernt und stattdessen der Benutzername angezeigt." + }, + "type": "boolean" + }, + { + "name": "symbolWhitelist", + "humanName": { + "en": "Character Whitelist/Blacklist", + "de": "Zeichen Whitelist/Blacklist" + }, + "default": { + "en": [] + }, + "description": { + "en": "A list of characters that should be allowed (whitelist) or blocked (blacklist) at the start of usernames. If the list is empty, all non-alphanumeric characters will be removed.", + "de": "Eine Liste von Zeichen, die am Anfang von Benutzernamen erlaubt (Whitelist) oder blockiert (Blacklist) werden sollen. Wenn die Liste leer ist, werden alle nicht-alphanumerischen Zeichen entfernt." + }, + "type": "array", + "content": "string" + }, + { + "name": "isBlacklist", + "humanName": { + "en": "Use blacklist instead of whitelist", + "de": "Blacklist statt Whitelist verwenden" + }, + "default": { + "en": false + }, + "description": { + "en": "If yes: the list of characters will be treated as a blacklist (characters in the list will be blocked); if no: the list will be treated as a whitelist (only characters in the list and alphanumeric characters will be allowed).", + "de": "Wenn ja: die Liste der Zeichen wird als Blacklist behandelt (Zeichen in der Liste werden blockiert); wenn nein: die Liste wird als Whitelist behandelt (nur Zeichen in der Liste und alphanumerische Zeichen werden erlaubt)." + }, + "type": "boolean" + }, + { + "name": "userWhitelist", + "humanName": { + "en": "User Whitelist", + "de": "Benutzer-Whitelist" + }, + "default": { + "en": [] + }, + "description": { + "en": "A list of user IDs that should be exempt from the username check. Usernames of these users will not be modified.", + "de": "Eine Liste von Benutzer-IDs, die von der Benutzernamenprüfung ausgenommen werden sollen. Die Benutzernamen dieser Benutzer werden nicht geändert." + }, + "type": "array", + "content": "userID" + }, + { + "name": "alsoCheckUsernames", + "humanName": { + "en": "Also check usernames", + "de": "Auch Benutzernamen überprüfen" + }, + "default": { + "en": false + }, + "description": { + "en": "If yes: not only nicknames but also usernames will be checked for special characters and modified accordingly. If no: only nicknames will be checked and modified, usernames will be left unchanged.", + "de": "Wenn ja: nicht nur Nicknames, sondern auch Benutzernamen werden auf Sonderzeichen überprüft und entsprechend geändert. Wenn nein: nur Nicknames werden überprüft und geändert, Benutzernamen bleiben unverändert." + }, + "type": "boolean" + } + ] +} \ No newline at end of file diff --git a/modules/name-list-cleaner/events/botReady.js b/modules/name-list-cleaner/events/botReady.js new file mode 100644 index 0000000..aeb44e6 --- /dev/null +++ b/modules/name-list-cleaner/events/botReady.js @@ -0,0 +1,7 @@ +const {renameMember} = require('../renameMember'); + +module.exports.run = async function (client) { + for (const member of client.guild.members.cache.values()) { + await renameMember(client, member); + } +} \ No newline at end of file diff --git a/modules/name-list-cleaner/events/guildMemberUpdate.js b/modules/name-list-cleaner/events/guildMemberUpdate.js new file mode 100644 index 0000000..1e8d39d --- /dev/null +++ b/modules/name-list-cleaner/events/guildMemberUpdate.js @@ -0,0 +1,9 @@ +const {renameMember} = require("../renameMember"); +module.exports.run = async function (client, oldGuildMember, newGuildMember) { + + if (!client.botReadyAt) return; + if (newGuildMember.guild.id !== client.guild.id) return; + if (oldGuildMember.nickname === newGuildMember.nickname && oldGuildMember.user.username === newGuildMember.user.username) return; + await renameMember(client, newGuildMember); +} + diff --git a/modules/name-list-cleaner/module.json b/modules/name-list-cleaner/module.json new file mode 100644 index 0000000..431ec80 --- /dev/null +++ b/modules/name-list-cleaner/module.json @@ -0,0 +1,24 @@ +{ + "name": "name-list-cleaner", + "humanReadableName": { + "en": "Name List Cleaner", + "de": "Namenslisten Cleaner" + }, + "author": { + "name": "hfgd", + "link": "https://github.com/hfgd123", + "scnxOrgID": "2" + }, + "openSourceURL": "https://github.com/hfgd123/CustomDCBot/tree/main/modules/username-check", + "config-example-files": [ + "configs/config.json" + ], + "events-dir": "/events", + "tags": [ + "tools" + ], + "description": { + "en": "Remove special characters from the beginning of usernames", + "de": "Entferne Sonderzeichen vom Anfang von Benutzernamen" + } +} \ No newline at end of file diff --git a/modules/name-list-cleaner/renameMember.js b/modules/name-list-cleaner/renameMember.js new file mode 100644 index 0000000..945aaf9 --- /dev/null +++ b/modules/name-list-cleaner/renameMember.js @@ -0,0 +1,52 @@ +const {localize} = require("../../src/functions/localize"); +renameMember = async function (client, guildMember) { + let newName; + const moduleConf = client.configurations['name-list-cleaner']['config']; + if (moduleConf.userWhitelist.includes(guildMember.user.id)) return; + + + if (guildMember.nickname !== null) { + newName = await checkUsername(client, guildMember.nickname); + if (newName === guildMember.nickname) return; + } else if (moduleConf.alsoCheckUsername) { + newName = await checkUsername(client, guildMember.user.username); + if (newName === guildMember.user.username) return; + } else return; + if (guildMember.guild.ownerId === guildMember.id) { + client.logger.error('[nicknames] ' + localize('name-list-cleaner', 'owner-cannot-be-renamed', {u: guildMember.user.username})) + return; + } + if (moduleConf.keepNickname) { + try { + await guildMember.setNickname(newName); + } catch (e) { + client.logger.error('[name-list-cleaner] ' + localize('name-list-cleaner', 'nickname-error', {u: guildMember.user.username, e: e})) + } + } else { + await guildMember.setNickname(null, localize('name-list-cleaner', 'nickname-reset', {u: guildMember.user.username})); + } +} + +module.exports.renameMember = renameMember; + +async function checkUsername(client, name) { + const moduleConf = client.configurations['name-list-cleaner']['config']; + if (name.length === 0) return 'INVALID NAME'; + if (moduleConf.symbolWhitelist === []) { + if (name.charAt(0).match(/^[a-zA-Z0-9]$/)) { + return name; + } else { + return await checkUsername(client, name.substring(1)); + } + } else if (!moduleConf.symbolWhitelist.includes(name.charAt(0)) && !moduleConf.isBlacklist) { + if (name.charAt(0).match(/^[a-zA-Z0-9]$/)) { + return name; + } else { + return await checkUsername(client, name.substring(1)); + } + } else if (moduleConf.symbolWhitelist.includes(name.charAt(0)) && moduleConf.isBlacklist) { + return await checkUsername(client, name.substring(1)); + } else { + return name; + } +} \ No newline at end of file