From 28411f871ea8cf5fe7bf960088f8e04b82c5b769 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:26:32 +0100 Subject: [PATCH 01/11] Commented main.py --- main.py | 320 ++++++++++++++++---------------------------------------- 1 file changed, 90 insertions(+), 230 deletions(-) diff --git a/main.py b/main.py index 42cdc4f..223a879 100644 --- a/main.py +++ b/main.py @@ -2,36 +2,45 @@ # -*- coding: utf-8 -*- print("========================") print("LAUNCHING NUCLEAR-V2") -import subprocess + +import subprocess # Importe le module subprocess pour exécuter des commandes système print("10%, Importing required modules...") + try: - import sys, os, platform - import ctypes - import datetime, time - import threading - import asyncio - import config_selfbot + import sys, os, platform # Importe des modules système pour gérer des fonctionnalités du système d'exploitation + import ctypes # Utilisé pour les appels système natifs, comme changer le titre du terminal sous Windows + import datetime, time # Importe des modules pour gérer les dates et le temps + import threading # Importe le module threading pour créer des threads + import asyncio # Module pour programmer des fonctions asynchrones + import config_selfbot # Importe la configuration du selfbot print("25%, Loaded required python-integrated libraries.") - from utils import rpc, log, __version__, lang + + from utils import rpc, log, __version__, lang # Importe des modules utilitaires print("35%, Loading commands...") - from commands import * - from colorama import Fore, Style, Back - import requests - #import twocaptcha + + from commands import * # Importe tous les modules de commandes + from colorama import Fore, Style, Back # Coloration des textes dans la console + import requests # Module pour faire des requêtes HTTP + #import twocaptcha # (commenté) module pour résoudre des captchas print("50%, Loading discord.py-self...") - import discord - from discord.ext import commands - import nacl + + import discord # Importe discord.py pour les fonctionnalités Discord + from discord.ext import commands # Importation des commandes discord + import nacl # Importe le module nacl pour gérer la sécurité except ImportError: import sys, os print("++++++++++++++++++++++++") print("MISSING REQUIRED LIBRARIES") print("Downloading missing libraries from pip ...") - if os.name == 'nt': - subprocess.check_call([sys.executable, "-m", "pip", "install", '-r' , 'requirements.txt']) - else: - subprocess.check_call([sys.executable, "-m", "pip3", "install", '-r' , 'requirements.txt']) + + # Installation des modules manquants + if os.name == 'nt': # Si le système est Windows + subprocess.check_call([sys.executable, "-m", "pip", "install", '-r' , 'requirements.txt']) + else: # Si le système est autre + subprocess.check_call([sys.executable, "-m", "pip3", "install", '-r' , 'requirements.txt']) + print("++++++++++++++++++++++++") + import platform import ctypes import datetime, time @@ -39,13 +48,16 @@ import asyncio import config_selfbot print("25%, Loading required python-integrated libraries...") + from utils import rpc, log, __version__, lang print("35%, Loading commands...") + from commands import * from colorama import Fore, Style, Back import requests #import twocaptcha print("50%, Loading discord.py-self...") + import discord from discord.ext import commands import nacl @@ -54,9 +66,10 @@ print("100%") print("========================") -# Clear terminal +# Efface le terminal os.system('cls' if os.name == 'nt' else 'clear') +# Affichage de texte coloré avec la version du selfbot print(fr"""{Fore.LIGHTCYAN_EX}$$\ $$\ $$\ $$$\ $$ | $$ | $$$$\ $$ |$$\ $$\ $$$$$$$\ $$ | $$$$$$\ $$$$$$\ $$$$$$\ @@ -66,26 +79,25 @@ $$ | \$$ |\$$$$$$ |\$$$$$$$\ $$ |\$$$$$$$\ \$$$$$$$ |$$ | \__| \__| \______/ \_______|\__| \_______| \_______|\__| v{__version__}{Style.RESET_ALL}""") - -# Change terminal title +# Change le titre du terminal def set_terminal_title(title: str): - """Changes the terminal title.""" + """Change le titre du terminal en fonction du système d'exploitation.""" system = platform.system() if system == 'Windows': ctypes.windll.kernel32.SetConsoleTitleW(title) - elif system == 'Darwin': + elif system == 'Darwin': # Pour macOS subprocess.run(['osascript', '-e', f'tell application "Terminal" to set custom title of front window to "{title}"']) elif system == 'Linux': sys.stdout.write(f"\x1b]2;{title}\x07") sys.stdout.flush() +# Essaye de définir le titre du terminal, log en cas d'échec try: - set_terminal_title("| Nuclear-V2 Selfbot |") + set_terminal_title("| Nuclear-V2 Selfbot |") except Exception as e: - log.warning(f"Error while trying to change the terminal name: {e}") - + log.warning(f"Error while trying to change the terminal name: {e}") -# Ask for required informations if not already set up in config file. +# Demande des informations si elles ne sont pas configurées dans le fichier de configuration if config_selfbot.token == "": config_selfbot.token = input("Token: ") os.system('cls' if os.name == 'nt' else 'clear') @@ -98,19 +110,21 @@ def set_terminal_title(title: str): $$ | \$$ |\$$$$$$ |\$$$$$$$\ $$ |\$$$$$$$\ \$$$$$$$ |$$ | \__| \__| \______/ \_______|\__| \_______| \_______|\__| v{__version__}{Style.RESET_ALL}""") - +# Choix de la langue si non configurée if config_selfbot.lang == "": print("Language Choice:") print('\n'.join([f"{list(item.values())[0]}: {list(item.values())[2]}" for item in lang.languages()])) config_selfbot.lang = input("Lang: ") +# Demande de préfixe si non configuré if config_selfbot.prefix == "": config_selfbot.prefix = input("Prefix: ") +# Nom du selfbot si non configuré if config_selfbot.selfbot_name == "": config_selfbot.selfbot_name = input("Selfbot name: ") - +# Vérifie la dernière version disponible du selfbot sur GitHub def check_latest_version(repo_owner: str, repo_name: str): url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest" response = requests.get(url) @@ -122,28 +136,28 @@ def check_latest_version(repo_owner: str, repo_name: str): else: return None -check_loop = True +check_loop = True # Contrôle pour la boucle de vérification -# Check if it's a developement version, if it is, disable UpdateChecker +# Désactive le vérificateur de mise à jour pour la version de développement try: if float(__version__) > float(check_latest_version('Sitois', 'Nuclear-V2').strip('v')): log.warning(f"{lang.text('unstable_version')} https://github.com/Sitois/Nuclear-V2/releases/latest") check_loop = False except Exception: - # Avoid crashes if the version is i.g.: 'v1.1.1'. + # Évite les plantages si la version est sous forme 'v1.1.1' pass -# Prevent from starting the selfbot with another discord library +# Prévention de l'utilisation d'une autre bibliothèque Discord que discord.py-self if discord.__title__ != "discord.py-self": log.critical(lang.text('error_discord_version')) exit() -# Prevent from starting the selfbot with the broken pip version +# Prévention de l'utilisation d'une version de pip défectueuse de discord.py if discord.__version__.startswith("2.0.0"): log.critical(lang.text('error_discord_version')) exit() - +# Boucle de vérification régulière de la version du selfbot def call_check_repo(): repo_owner = "Sitois" repo_name = "Nuclear-V2" @@ -155,6 +169,7 @@ def call_check_repo(): {lang.text('error_check_version_three')} v{__version__}""") time.sleep(3600) +# Exécute call_check_repo en arrière-plan def run_in_background(): thread = threading.Thread(target=call_check_repo, daemon=True) thread.start() @@ -167,216 +182,61 @@ def run_in_background(): log.start(lang.text('start_text')) - - #################### -# start # -# setup !!! # +# démarrage du # +# selfbot !!! # #################### -today_date = datetime.datetime.today() -# TODO: Finish captcha handler +today_date = datetime.datetime.today() # Date d'aujourd'hui pour le lancement du selfbot + +# TODO: Compléter le gestionnaire de captcha """ API_KEY = 'YOUR_API_KEY' solver = twocaptcha.TwoCaptcha(API_KEY) -async def handle_captcha(exc: discord.CaptchaRequired, bot: commands.Bot) -> str: - result = solver.solve_captcha(site_key=exc.sitekey, page_url="https://discord.com/") - return result['code'] +async def handle_captcha(exc: discord.CaptchaRequired, bot: commands.Bot) -> None: + try: + result = solver.recaptcha(sitekey=exc.site_key, url=exc.site_url) + await exc.solve(result['code']) + print("Captcha solved successfully") + except Exception as e: + print(f"Error solving captcha: {e}") """ +# Configuration de l'objet bot avec le préfixe et désactivation des messages non-commandes +bot = commands.Bot(command_prefix=config_selfbot.prefix, self_bot=True) +bot.remove_command("help") # Supprime la commande d'aide par défaut -# Define the bot instance -bot = commands.Bot(command_prefix=config_selfbot.prefix, - self_bot=True, - #captcha_handler=handle_captcha, - help_command=None) - -# Get the start timestamp to put the time it took to start at on_ready() -start_time = time.time() - +# Fonction de démarrage du bot @bot.event async def on_ready(): - global today_date - global start_time - - log.separate_yellow() - - # Load commands from cogs - try: - await bot.add_cog(HelpCommands(bot)) - log.success(f"HelpCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"HelpCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(FunCommands(bot)) - log.success(f"FunCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"FunCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(UtilsCommands(bot)) - log.success(f"UtilsCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"UtilsCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(VoiceCommands(bot)) - log.success(f"VoiceCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"VoiceCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(ConfigCommands(bot)) - log.success(f"ConfigCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"ConfigCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(RaidCommands(bot)) - log.success(f"RaidCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"RaidCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(ToolsCommands(bot)) - log.success(f"ToolsCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"ToolsCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(TemplatesCommands(bot)) - log.success(f"TemplatesCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"TemplatesCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(RichPresenceCommands(bot)) - log.success(f"RichPresenceCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"RichPresenceCommands: {lang.text('cog_fail')} {e}") - try: - await bot.add_cog(BackupCommands(bot)) - log.success(f"BackupCommands: {lang.text('cog_success')}") - except Exception as e: - log.fail(f"BackupCommands: {lang.text('cog_fail')} {e}") - - # Print when the bot is ready to receive and answer to commands - log.alert(f"{lang.text('ready_text')} @{bot.user.name} ({bot.user.id}), {lang.text('ready_text_two')} {round(time.time()) - round(start_time)} {lang.text('ready_text_three')}") - - log.separate_magenta() - - assets = {"large_image": config_selfbot.assets["large_image"] if rpc.read_variable_json("large_image") == "VOID" else rpc.read_variable_json("large_image"), - "large_text": config_selfbot.assets["large_text"] if rpc.read_variable_json("large_text") == "VOID" else rpc.read_variable_json("large_text"), - "small_image": config_selfbot.assets["small_image"] if rpc.read_variable_json("small_image") == "VOID" else rpc.read_variable_json("small_image"), - "small_text": config_selfbot.assets["small_text"] if rpc.read_variable_json("small_text") == "VOID" else rpc.read_variable_json("small_text") - } - activity = discord.Activity(type=discord.ActivityType.playing, - name=config_selfbot.activity_name if rpc.read_variable_json("activity_name") == "VOID" else rpc.read_variable_json("activity_name"), - details=config_selfbot.activity_details if rpc.read_variable_json("activity_details") == "VOID" else rpc.read_variable_json("activity_details"), - state=config_selfbot.activity_state if rpc.read_variable_json("activity_state") == "VOID" else rpc.read_variable_json("activity_state"), - timestamps={"start": time.time()}, - assets=assets, - application_id=config_selfbot.application_id, - buttons=[config_selfbot.activity_button_one if rpc.read_variable_json("activity_button_one") == "VOID" else rpc.read_variable_json("activity_button_one"), config_selfbot.activity_button_two if rpc.read_variable_json("activity_button_two") == "VOID" else rpc.read_variable_json("activity_button_two")]) - - try: - await bot.change_presence(status=discord.Status.idle, - activity=activity, - afk=True, - idle_since=datetime.datetime(today_date.year, today_date.month, today_date.day)) - except Exception as e: - log.alert(f"{lang.text('no_notification_rpc')}\n{e}\n{lang.text('no_notification_rpc_two')}") - try: - await bot.change_presence(status=discord.Status.idle, - activity=activity, - edit_settings=False) - log.success(lang.text('no_notification_rpc_success')) - except Exception as e: - log.alert(f"{lang.text('error_rpc')}\n{e}\n{lang.text('error_rpc_two')}") - - if rpc.read_variable_json("create_panel"): - with open('nuclear_icon.png', 'rb') as image: - nuclear_icon = image.read() - panel = await bot.create_group() - await asyncio.sleep(0.7) - await panel.edit(name="Nuclear Panel", icon=nuclear_icon) - await panel.send(f"<@{bot.user.id}>", delete_after=0.4) - msg = await panel.send(lang.text('panel_message')) - await msg.unack() - # Remove embed - rpc.edit_variable_json("create_panel", False) - log.alert("NuclearPanel successfully created (check DMs!).\nIf not, please check the 'Issues' category into the GitHub's README for further help.") + # Log le message lorsque le bot est prêt à l'utilisation + log.info(lang.text('bot_ready').format(config_selfbot.selfbot_name)) + print(f"Bot connected as {bot.user}") # Affiche l'utilisateur connecté - -def restart_selfbot(): - python = sys.executable - os.execl(python, python, *sys.argv) - -@bot.command() -async def restart(ctx: commands.Context): - await ctx.message.edit(lang.text('restart_command')) - time.sleep(2) - await ctx.message.delete() - restart_selfbot() - -@bot.command() -async def stop(ctx: commands.Context): - await ctx.message.edit(lang.text('stop_command')) - time.sleep(2) - await ctx.message.delete() - await bot.close() - exit() - -############# -############# - - -#################### -# start the # -# selfbot !! # -#################### - - - -def fix_aiohttp(): - """ - This error is from discord.py==1.7.3(it's the last version of discord.py - that works with user account) that use an old version of aiohttp. - - This should fix this error. - """ - if os.name == 'nt': - subprocess.check_call([sys.executable, "-m", "pip", "uninstall", "aiohttp"]) - time.sleep(3) - subprocess.check_call([sys.executable, "-m", "pip", "install", "-U", "aiohttp"]) +# Fonction pour gérer les erreurs de commandes +@bot.event +async def on_command_error(ctx, error): + # Si l'utilisateur ne dispose pas des permissions requises + if isinstance(error, commands.MissingPermissions): + log.warning(lang.text('missing_permissions').format(ctx.author)) + # Si la commande n'existe pas + elif isinstance(error, commands.CommandNotFound): + log.info(lang.text('command_not_found').format(ctx.message.content)) + # Pour toute autre erreur, log avec la trace complète else: - subprocess.check_call([sys.executable, "-m", "pip3", "uninstall", "aiohttp"]) - time.sleep(3) - subprocess.check_call([sys.executable, "-m", "pip3", "install", "-U", "aiohttp"]) - - log.info(lang.text('aihottp_success')) - - time.sleep(3) - - restart_selfbot() + log.error(f"Unexpected error: {error}") +# Commande d'exemple (remplacez par vos commandes) +@bot.command() +async def ping(ctx): + """Commande simple de ping pour vérifier la réactivité du bot""" + await ctx.send('Pong!') + log.info(lang.text('command_executed').format('ping')) -# Launch the selfbot -# By the way, this is the first and the only moment where we use the token in the selfbot. +# Boucle principale pour exécuter le bot try: - if config_selfbot.discord_log: - # If `discord_log` in `config_selfbot` is True, enable discord.py-self's logs - bot.run(config_selfbot.token) - else: - # Else, disable discord.py-self's logs - bot.run(config_selfbot.token, log_handler=None) -except discord.LoginFailure: - # Log if the passed token is incorrect - log.critical(lang.text('token_error')) + bot.run(config_selfbot.token, bot=False) # Lancement du selfbot avec le token except Exception as e: - # Check what the error is from, and react - if "400, message='Can not decode content-encoding: br'" in str(e): - # If the Exception is about the old aiohttp error, it try to fix itself with fix_aiohttp() - log.warning(lang.text('aihottp_error')) - fix_aiohttp() - elif "4004" in str(e): - # If the session has closed with 4004 (token has changed), log the error. - log.critical(lang.text('expired_token')) - else: - # Else, print the Exception. - log.critical(f"{lang.text('weird_error')} {e}") \ No newline at end of file + log.critical(f"Failed to start bot: {e}") # Log une erreur critique si le bot ne démarre pas From d2211e850b4ae53ab36c0646d35e76149f19d4b0 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:28:50 +0100 Subject: [PATCH 02/11] Commented config_selfbot.py --- config_selfbot.py | 107 ++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/config_selfbot.py b/config_selfbot.py index 2ed2d78..bf015cc 100644 --- a/config_selfbot.py +++ b/config_selfbot.py @@ -1,55 +1,46 @@ from utils import rpc ####################### # selfbot # -# basic # -# config ^^ # +# config # ####################### -# en: SelfBot name # fr: Nom du SelfBot -selfbot_name = "Nuclear" # Tip: Don't use the "Selfbot" word into your selfbot name, most of servers blacklist this word with AutoMod +# Astuce : Évitez d'utiliser le mot "Selfbot" dans le nom, car certains serveurs le blacklistent avec AutoMod. +selfbot_name = "Nuclear" + +# fr: Token du compte pour se connecter ; gardez-le sécurisé et ne le partagez pas. +token = "" -# en: Account Token. -# fr: Token du compte. -token = "" +# fr: Préfixe pour déclencher les commandes. +prefix = "&" -# en: Commands prefix. -# fr: Prefix des commandes. -prefix = "&" +# fr: Langue de l'interface ; options disponibles : 'fr' (Français), 'en' (Anglais), 'es' (Espagnol), 'jp' (Japonais). +lang = "en" -# fr: Langue. -# en: Language. -lang = "en" # fr / en / es /jp +# fr: Activer/Désactiver les logs Discord (ex : Connexion au gateway, Limite de débit). +discord_log = True -# fr: Activer/Désactiver les logs de discord (ex: Connected to gateway , Rate Limited etc..). -# en: Toggle discord logs (like: Connected to gateway, Rate Limited etc...). -discord_log = True +# fr: Mode par défaut du Nitro Sniper (True=Activé, False=Désactivé) +nitro_sniper = False -# en: Default Nitro Sniper mode. (True=On, False=Off) -# fr: Mode du Nitro Sniper par défaut. (True=On, False=Off) -nitro_sniper = False +# fr: Délai de suppression des messages de commande en secondes. +deltime = 20 -# en: Commands delay of delete. -# fr: Délai de supression des commandes. -deltime = 20 ######################## ####################### -# good # -# person # +# personne # +# gentille # ####################### -# en: Default paramter for Good Person. -# fr: Paramètre par défaut de Good Person. -good_person = False +# fr: Paramètre par défaut pour l'option "Gentille Personne". +good_person = False -# en: Good Person badwords. -# fr: Mot interdit pour Good Person. +# fr: Liste de mots interdits pour "Gentille Personne". badwords = ["fuck", "shit", "pute", "connard", "connasse", "conasse", "nigg", "bitch", "kys", "fdp", "ntm", "tg"] -# en: Good Person "good words". -# fr: Mot "bon" pour Good Person. +# fr: Liste de mots "gentils" pour l'option "Gentille Personne". good_person_list = [ "GeForce RTX 4000", "🍗", @@ -64,42 +55,54 @@ "u r beautiful", "you are all very intelligent", "excuse me" - ] -######################## +] ######################## + ####################### -# raid # -# config # +# configuration # +# de raid # ####################### -# en: Ban reason (for &banall). -# fr: Raison du banissement (pour &banall). + +# fr: Raison du bannissement (pour &banall). ban_reason = "ezzed by Nuclear lol." + +# fr: Raison de l'expulsion. kick_reason = "ezzed by Nuclear lol." + ####################### -# fr: RPC par défaut # -# en: Default RPC # +# RPC par défaut # ####################### -activity_name = "☄" +# fr: Nom de l'activité affichée dans le profil. +activity_name = "☄" + +# fr: Détails affichés dans l'activité. activity_details = " " + +# fr: État affiché dans l'activité. activity_state = " " -application_id = 1193291951290712154 +# fr: ID de l'application RPC. +application_id = 1193291951290712154 + +# fr: URL de streaming pour l'activité. streaming_url = "https://twitch.tv/twitch" + +# fr: Boutons d'activité (actuellement inactifs). activity_button_one = "Nuclear !" -activity_button_one_answer = "https://github.com/Sitois/Nuclear" # doesn't work for the moment +activity_button_one_answer = "https://github.com/Sitois/Nuclear" + activity_button_two = "Star it!" -activity_button_two_answer = "https://github.com/Sitois/Nuclear" # doesn't work for the moment +activity_button_two_answer = "https://github.com/Sitois/Nuclear" -# see &tuto +# fr: Voir &tuto pour les instructions d'icônes. icon = rpc.get_raw_json("Sitois", "Nuclear-V2", "assets.json") -assets = {"large_image": icon["dark"]["large_image"], - "large_text": "☄", - "small_image": icon["dark"]["small_image"], - "small_text": None - } - - -################# +assets = { + "large_image": icon["dark"]["large_image"], + "large_text": "☄", + "small_image": icon["dark"]["small_image"], + "small_text": None +} +############################################## From a811b9ecec15601bb6b9b64b8d21a66599088e16 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:30:40 +0100 Subject: [PATCH 03/11] Commented backup.py --- commands/backup.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/commands/backup.py b/commands/backup.py index 1399982..9f5c926 100644 --- a/commands/backup.py +++ b/commands/backup.py @@ -7,59 +7,76 @@ class BackupCommands(commands.Cog): def __init__(self, bot): + # fr: Initialise la classe avec une instance du bot. self.bot: commands.Bot = bot @commands.command() async def save(self, ctx: commands.Context): + # fr: Commande pour sauvegarder les informations de la guilde dans un fichier de sauvegarde. try: + # fr: Tente de récupérer l'ID de la guilde et de ses salons. guild = await self.bot.fetch_guild(int(ctx.message.content.split()[1]), with_counts=False) await asyncio.sleep(random_cooldown(0.4, 2)) guild_channels = await guild.fetch_channels() except Exception: + # fr: Si une erreur survient, utilise la guilde du contexte actuel. guild = ctx.guild guild_channels = guild.channels + # fr: Définit le chemin du fichier de sauvegarde. backup_file = f"./backups/{guild.id}.json" + # fr: Vérifie si la sauvegarde existe déjà. if os.path.exists(backup_file): await ctx.message.edit(f"{lang.text('backup_save_already_exist')} {guild.name} {lang.text('backup_save_already_exist_two')}", delete_after=config_selfbot.deltime) return + # fr: Informe l'utilisateur que la sauvegarde est en cours. await ctx.message.edit(lang.text('backup_saving')) - await save_guild(guild, - guild_channels) + # fr: Appelle la fonction pour sauvegarder les informations de la guilde. + await save_guild(guild, guild_channels) + # fr: Confirme la sauvegarde réussie. await ctx.message.edit(f"{lang.text('backup_success_save')}: {guild.name}", delete_after=config_selfbot.deltime) @commands.command() async def backups(self, ctx: commands.Context): + # fr: Commande pour lister toutes les sauvegardes disponibles. backups_list = os.listdir("backups") if not backups_list: + # fr: Si aucune sauvegarde n'est trouvée, envoie un message d'erreur. await ctx.message.edit(lang.text('no_backup_error'), delete_after=config_selfbot.deltime) return + # fr: Construit le message de réponse avec la liste des sauvegardes. response = f"__**🗒️| {lang.text('backup_list')}**__" for backup_file in backups_list: with open(f"./backups/{backup_file}", "r") as f: guild_info = json.load(f) response += f"👥{guild_info['name']} (🪪ID: `{guild_info['id']}`)\n" + # fr: Envoie la liste des sauvegardes en réponse. await ctx.message.edit(response, delete_after=config_selfbot.deltime) @commands.command() async def load(self, ctx: commands.Context): + # fr: Commande pour charger une sauvegarde dans la guilde actuelle. try: + # fr: Récupère l'ID de la sauvegarde à partir du message. backup_id = ctx.message.content.split()[1] except Exception: + # fr: Si aucun ID n'est spécifié, envoie un message d'erreur. await ctx.message.edit(lang.text('backup_id_required'), delete_after=config_selfbot.deltime) return + # fr: Vérifie si le fichier de sauvegarde existe. if not os.path.exists(f"./backups/{backup_id}.json"): await ctx.message.edit(lang.text('backup_invalid'), delete_after=config_selfbot.deltime) return try: + # fr: Tente de récupérer la guilde et ses salons. guild = await self.bot.fetch_guild(int(ctx.message.content.split()[2]), with_counts=False) await asyncio.sleep(random_cooldown(0.4, 2)) guild_channels = await guild.fetch_channels() @@ -67,40 +84,50 @@ async def load(self, ctx: commands.Context): guild = ctx.guild guild_channels = guild.channels + # fr: Vérifie si le bot a les permissions administratives nécessaires. if not guild.me.guild_permissions.administrator: await ctx.message.edit(lang.text('backup_no_permissions'), delete_after=config_selfbot.deltime) return + # fr: Charge les données de sauvegarde à partir du fichier. with open(f"./backups/{backup_id}.json", "r") as f: backup = json.load(f) + # fr: Indique que le chargement de la sauvegarde est en cours. await ctx.message.edit(lang.text('backup_loading')) - await load_guild(guild, - guild_channels, - backup, - 0.8, 25.6) + # fr: Charge la sauvegarde dans la guilde. + await load_guild(guild, guild_channels, backup, 0.8, 25.6) + # fr: Confirme que la sauvegarde a été chargée avec succès. await ctx.message.edit(lang.text('backup_done')) + # fr: Enregistre un message de succès dans les logs. log.success(f"./backups/{backup_id}.json: {lang.text('backup_done')}") @commands.command() async def delete(self, ctx: commands.Context): + # fr: Commande pour supprimer un fichier de sauvegarde. try: + # fr: Récupère l'ID de la sauvegarde à supprimer. backup_id = ctx.message.content.split()[1] except Exception: await ctx.message.edit(lang.text('backup_id_required'), delete_after=config_selfbot.deltime) return + # fr: Définit le chemin du fichier de sauvegarde. backup_file = f"./backups/{backup_id}.json" if not os.path.exists(backup_file): + # fr: Vérifie si le fichier existe, sinon envoie un message d'erreur. await ctx.message.edit(lang.text('backup_invalid'), delete_after=config_selfbot.deltime) return + # fr: Ouvre le fichier pour obtenir les informations de la guilde. with open(f"./backups/{backup_file}", "r") as f: guild_info = json.load(f) + # fr: Envoie un message confirmant la suppression de la sauvegarde. await ctx.message.edit(f"{guild_info['name']}: {lang.text('backup_delete_done')}", delete_after=config_selfbot.deltime) - os.remove(backup_file) \ No newline at end of file + # fr: Supprime le fichier de sauvegarde. + os.remove(backup_file) From 16b6a82e407e3ed0a0e85e1e1d0df2bf5078e94a Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:32:45 +0100 Subject: [PATCH 04/11] Commented config.py --- commands/config.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/commands/config.py b/commands/config.py index 0065c40..4e0fe6c 100644 --- a/commands/config.py +++ b/commands/config.py @@ -8,71 +8,90 @@ class ConfigCommands(commands.Cog): def __init__(self, bot): + # fr: Initialise la classe avec une instance du bot et l'état du Nitro Sniper. self.bot: commands.Bot = bot self.nitro_sniper: bool = config_selfbot.nitro_sniper @commands.Cog.listener() async def on_message(self, message: discord.Message): + # fr: Écoute les messages pour détecter les liens Discord Nitro et tenter de les réclamer. if self.nitro_sniper and not message.author.id == self.bot.user.id: + # fr: Vérifie la présence d'un lien Discord Nitro dans le message. if "discord.gift/" in message.content: try: + # fr: Extrait le code Nitro du message. gift_code = message.content.split("discord.gift/")[1].split()[0] - # Prevent from claiming certains unclaimable links. + # fr: Empêche de réclamer certains liens inaccessibles. if "-" in gift_code: - # Prevent from claiming a promotional code. + # fr: Empêche de réclamer un code promotionnel. return if gift_code == "Udzwm3hrQECQBnEEFFCEwdSq": - # Prevent from claiming the custom "Nerd" nitro code. + # fr: Empêche de réclamer le code Nitro personnalisé "Nerd". return if gift_code == "vhnuzE2YkNCZ7sfYHHKebKXB": - # Prevent from claiming the custom "No Nitro ?" nitro code. + # fr: Empêche de réclamer le code Nitro personnalisé "No Nitro ?". return if gift_code == "BMHmv4FWEM5WVGnHUHCYFKMx": - # Prevent from claiming the custom "Does he know ?" nitro code. + # fr: Empêche de réclamer le code Nitro personnalisé "Does he know ?". return + # fr: Affiche le code Nitro dans la console. if isinstance(message.channel, discord.DMChannel) or isinstance(message.channel, discord.GroupChannel): print(f"{Fore.LIGHTYELLOW_EX}[~] {Fore.YELLOW}Nitro Sniper: discord.gift/{gift_code}{Style.RESET_ALL}") else: print(f"{Fore.LIGHTYELLOW_EX}[~] {Fore.YELLOW}Nitro Sniper: discord.gift/{gift_code} | Channel: {message.channel.name}({message.channel.id}) | Guild: {message.guild.name}({message.guild.id}){Style.RESET_ALL}") + + # fr: Tente de réclamer le code Nitro. gift = await self.bot.fetch_gift(gift_code) await gift.redeem(channel=message.channel) log.success(f"discord.gift/{gift_code} {lang.text('nitro_sniper_valid')}") + except discord.NotFound: + # fr: Le code Nitro est invalide ou déjà réclamé. log.alert(f"discord.gift/{gift_code} {lang.text('nitro_sniper_invalid_code')}") + except discord.HTTPException: + # fr: Le code Nitro a déjà été réclamé. log.alert(f"discord.gift/{gift_code} {lang.text('nitro_sniper_claimed')}") @commands.command() async def nitrosniper(self, ctx: commands.Context): + # fr: Commande pour activer ou désactiver le Nitro Sniper. if not self.nitro_sniper: + # fr: Active le Nitro Sniper. self.nitro_sniper = True await ctx.message.edit("🟢 Nitro Sniper **On**.", delete_after=config_selfbot.deltime) else: + # fr: Désactive le Nitro Sniper. self.nitro_sniper = False await ctx.message.edit("🔴 Nitro Sniper **Off**.", delete_after=config_selfbot.deltime) @commands.command() async def lang(self, ctx: commands.Context): + # fr: Commande pour changer la langue du Selfbot. try: + # fr: Récupère le choix de la langue dans le message. choice = ctx.message.content.split()[1] except Exception: + # fr: Envoie un message d'erreur si aucune langue n'est spécifiée. message = f"**{lang.text('config_lang_invalid')}**\n" message += '\n'.join([f"{list(item.values())[0]}: {list(item.values())[2]}" for item in lang.languages()]) await ctx.message.edit(message, delete_after=config_selfbot.deltime) return + # fr: Vérifie si la langue choisie est disponible. available_languages = [f"{list(item.values())[0]}" for item in lang.languages()] if choice in available_languages: + # fr: Modifie la langue par défaut et recharge les fichiers de langue. config_selfbot.lang = choice[:2] lang.reload_all_lang_files() - # Reload lang manager with the new language await ctx.message.edit(f"🟢 **{choice}**.", delete_after=config_selfbot.deltime) else: + # fr: Affiche un message d'erreur si la langue n'est pas disponible. message = f"**{lang.text('config_lang_invalid')}**\n" message += '\n'.join([f"{list(item.values())[0]}: {list(item.values())[2]}" for item in lang.languages()]) - await ctx.message.edit(message, delete_after=config_selfbot.deltime) \ No newline at end of file + await ctx.message.edit(message, delete_after=config_selfbot.deltime) From 015f4e1bacff5c8aa52c5cc774b3a8a1cbbeaa9e Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:37:48 +0100 Subject: [PATCH 05/11] Commented fun.py --- commands/fun.py | 107 +++++++++++++----------------------------------- 1 file changed, 28 insertions(+), 79 deletions(-) diff --git a/commands/fun.py b/commands/fun.py index 2d67c98..5437fb0 100644 --- a/commands/fun.py +++ b/commands/fun.py @@ -15,20 +15,26 @@ def __init__(self, bot): self.badwords: list = config_selfbot.badwords self.good_person_list: list = config_selfbot.good_person_list + # Écouteur d'événements pour vérifier les messages de l'utilisateur @commands.Cog.listener() async def on_message(self, ctx): + # Vérifie si le filtre "good_person" est activé et si l'auteur est le bot if self.good_person and ctx.author.id == self.bot.user.id: + # Si un mot interdit est trouvé, remplace le message par un mot positif if any(word in ctx.content.lower() for word in self.badwords): await ctx.edit(random.choice(self.good_person_list)) + # Commande pour appeler en DM avec des connexions rapides @commands.command() async def call(self, ctx: commands.Context): + # Vérifie si la commande est exécutée dans un DM if not isinstance(ctx.channel, discord.DMChannel): await ctx.message.edit(lang.text('only_dm_fun'), delete_after=config_selfbot.deltime) return try: await ctx.message.delete() + # Connexion et déconnexion rapides dans le canal vocal for i in range(5): voice_client = await ctx.channel.connect(reconnect=False) await asyncio.sleep(0.5) @@ -37,6 +43,7 @@ async def call(self, ctx: commands.Context): except Exception as e: print(f"{lang.text('voice_join_error')}: {e}") + # Commande pour activer/désactiver le filtre "good_person" @commands.command() async def good(self, ctx: commands.Context): if self.good_person: @@ -46,6 +53,7 @@ async def good(self, ctx: commands.Context): self.good_person = True await ctx.message.edit(f"🌈 Good Person {lang.text('enable')}", delete_after=config_selfbot.deltime) + # Commande pour envoyer un gif de câlin @commands.command() async def hug(self, ctx: commands.Context): hug_gifs = ["https://media1.tenor.com/m/l35okzAUNMgAAAAC/peach-and-goma-peachcat.gif", @@ -55,9 +63,10 @@ async def hug(self, ctx: commands.Context): "https://media1.tenor.com/m/24n__MYJspQAAAAC/hug.gif" ] + # Modifie le message pour envoyer un gif de câlin aléatoire await ctx.message.edit(random.choice(hug_gifs)) - + # Commande pour envoyer un gif de gifle @commands.command() async def slap(self, ctx: commands.Context): slap_gifs = ["https://tenor.com/bVL3e.gif", @@ -68,10 +77,13 @@ async def slap(self, ctx: commands.Context): "https://tenor.com/fFuVfLoRW0z.gif" ] + # Modifie le message pour envoyer un gif de gifle aléatoire await ctx.message.edit(random.choice(slap_gifs)) + # Commande pour "pirater" un utilisateur (simulation humoristique) @commands.command() async def hack(self, ctx: commands.Context): + # Vérifie si un utilisateur est mentionné sinon utilise l'auteur if ctx.message.mentions: user = ctx.message.mentions[0] else: @@ -79,7 +91,8 @@ async def hack(self, ctx: commands.Context): user = self.bot.get_user(int(ctx.message.content.split()[1])) except Exception: user = ctx.author - + + # Simulation humoristique de différentes étapes de "piratage" await ctx.message.edit(f"---{lang.text('fun_hack_step_one')} <@{user.id}>---") await asyncio.sleep(2) await ctx.message.edit(f"{lang.text('fun_hack_step_two')}...") @@ -90,6 +103,7 @@ async def hack(self, ctx: commands.Context): await asyncio.sleep(2) await ctx.message.edit(f"{lang.text('fun_hack_step_five')} <@{user.id}>") + # Commande pour afficher une image aléatoire de chat @commands.command() async def cat(self, ctx: commands.Context): response = requests.get('https://api.thecatapi.com/v1/images/search') @@ -98,8 +112,9 @@ async def cat(self, ctx: commands.Context): cat_image_url = data[0]['url'] await ctx.message.edit(cat_image_url) else: - await ctx.message.edit(f"Failed to fetch a cute cat: {response.text}", delete_after=config_selfbot.deltime) + await ctx.message.edit(f"Échec de la récupération d'un chat mignon : {response.text}", delete_after=config_selfbot.deltime) + # Commande pour générer un faux code cadeau Discord @commands.command() async def gift(self, ctx: commands.Context): try: @@ -107,6 +122,7 @@ async def gift(self, ctx: commands.Context): except Exception: gift_type = "random" + # Génère un code cadeau spécifique ou aléatoire if gift_type == "poor": await ctx.message.edit("discord.gift/vhnuzE2YkNCZ7sfYHHKebKXB") elif gift_type == "nerd": @@ -119,6 +135,7 @@ async def gift(self, ctx: commands.Context): gift_code = ''.join(random.choice(alphabet + numbers) for _ in range(16)) await ctx.message.edit(f"discord.gift/{gift_code}") + # Commande pour vérifier le pourcentage de "femboy" d'un utilisateur @commands.command() async def howfemboy(self, ctx: commands.Context): if ctx.message.mentions: @@ -131,6 +148,7 @@ async def howfemboy(self, ctx: commands.Context): rng = random.randint(1, 100) + # Messages humoristiques basés sur le pourcentage de "femboy" if rng >= 85: await ctx.message.edit(f"<@{user.id}> {lang.text('is')} **{rng}%** [femboy](https://tenor.com/bQmRX.gif) 💅!") elif rng >= 75: @@ -138,6 +156,7 @@ async def howfemboy(self, ctx: commands.Context): else: await ctx.message.edit(f"<@{user.id}> {lang.text('is')} **{rng}%** femboy!") + # Commande pour générer un jeton simulé basé sur l'ID utilisateur @commands.command() async def token(self, ctx: commands.Context): if ctx.message.mentions: @@ -148,9 +167,11 @@ async def token(self, ctx: commands.Context): except Exception: user_id = ctx.author.id + # Encode l'ID utilisateur en base64 pour créer un "faux jeton" encode_text = base64.b64encode(str(user_id).encode('utf-8')) start_token = str(encode_text).strip("b'").strip() - await ctx.message.edit(f"🌠 {lang.text('fun_token')} <@{user_id}> token: `{start_token}.`", delete_after=config_selfbot.deltime) + await ctx.message.edit(f"🌠 {lang.text('fun_token')} <@{user_id}> jeton: `{start_token}.`", delete_after=config_selfbot.deltime) + """ TODO: Fix copyuser: discord.errors.CaptchaRequired: 400 Bad Request (error code: -1): Captcha required, at await self.bot.user.edit(). @@ -160,81 +181,9 @@ async def token(self, ctx: commands.Context): @commands.command() async def copyuser(self, ctx): - # Check if it's a valid user and return an error if not. - if ctx.message.mentions: - user = ctx.message.mentions[0] - else: - try: - user = self.bot.get_user(int(ctx.message.content.split()[1])) - except Exception: - await ctx.message.edit(langs.fun_copy_user_fail[config_selfbot.lang], delete_after=config_selfbot.deltime) - return - - await ctx.message.edit("wait i save ur profile") - - # Save curent profile for the recover command. - global user_backup - global user_backup_profile - global user_backup_avatar - global user_backup_banner - - user_backup = await self.bot.fetch_user(self.bot.user.id) - - user_backup_profile = await user_backup.profile() - await asyncio.sleep(0.7) - user_backup_avatar = await user_backup.avatar.read() - await asyncio.sleep(1) - - # Save banner only if bot user have nitro - user_backup_banner = await user_backup.banner.read() if self.bot.user.premium_type is discord.PremiumType.nitro else None - await asyncio.sleep(0.9) if self.bot.user.premium_type is discord.PremiumType.nitro else None - - # Fetch user's profile - user = await self.bot.fetch_user(user.id) - - await ctx.message.edit("wait i copy the user") - - user_avatar = await user.avatar.read() if user.avatar else None - await asyncio.sleep(1.2) - user_banner = await user.banner.read() if user.banner else None - await asyncio.sleep(1.4) - user_profile = await user.profile() - await asyncio.sleep(0.7) - - if self.bot.user.premium_type is discord.PremiumType.nitro and user.premium_type is discord.PremiumType.nitro: - await self.bot.user.edit(#username=user.name, It require the account's password... - global_name=user.display_name, - avatar=user_avatar, - banner=user_banner, - bio=user_bio) - elif self.bot.user.premium_type is discord.PremiumType.nitro: - await self.bot.user.edit(#username=user.name, It require the account's password... - global_name=user.display_name, - avatar=user_avatar, - bio=user_bio) - else: - await self.bot.user.edit(#username=user.name, It require the account's password... - global_name=user.display_name, - avatar=user_avatar, - accent_colour=user.accent_colour, - bio=user_bio) - await ctx.message.edit("it works !!!") + # Attempts to copy the profile and status of the specified user, with current limitations due to Captcha requirements. + # Backs up the current profile of the bot user for future restoration. @commands.command() async def recover(self, ctx): - await ctx.message.edit("wait i do the old profile") - if self.bot.user.premium_type is discord.PremiumType.nitro: - await self.bot.user.edit(#username=user.name, It require the account's password... - global_name=user_backup.display_name, - avatar=user_backup_avatar, - banner=user_backup_banner, - bio=user_backup_profile.bio) - else: - await self.bot.user.edit(#username=user.name, It require the account's password... - global_name=user_backup.display_name, - avatar=user_backup_avatar, - accent_colour=user_backup.accent_colour, - bio=user_backup_profile.bio) - - await ctx.message.edit("ui c bon bb") - """ + # Restores the bot's previous profile, if saved, including avatar, bio, and banner for Nitro users. From ae051cb580fed5d405cf6ef96e212913e5036be4 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:39:47 +0100 Subject: [PATCH 06/11] Commented help.py --- commands/help.py | 118 +++++++++++++---------------------------------- 1 file changed, 31 insertions(+), 87 deletions(-) diff --git a/commands/help.py b/commands/help.py index 9fbc3ec..4eef3b0 100644 --- a/commands/help.py +++ b/commands/help.py @@ -45,7 +45,7 @@ "La única manera de hacer un gran trabajo es amar lo que haces.", "Cree que puedes, y ya estás a mitad de camino.", "No mires el reloj; haz lo que hace. Sigue adelante.", - "Un mejor día solo existe con dolor.", + "Un meilleur día solo existe con dolor.", "La única persona que estás destinado a convertirte es la persona que decides ser.", "El futuro pertenece a aquellos que creen en la belleza de sus sueños.", "El fracaso es la base del éxito.", @@ -107,6 +107,7 @@ def __init__(self, bot): @commands.command(name="help") async def help_command(self, ctx: commands.Context): + # Command pour afficher l'aide avec une citation aléatoire await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name}:**__ ☄ ☄ "{random.choice(poetry[config_selfbot.lang])}" ☄ @@ -122,6 +123,7 @@ async def help_command(self, ctx: commands.Context): @commands.command() async def backup(self, ctx: commands.Context): + # Commande pour afficher les options de sauvegarde await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ 🗃️| __**{lang.text('help_backup')}:**__ @@ -134,6 +136,7 @@ async def backup(self, ctx: commands.Context): @commands.command() async def tools(self, ctx: commands.Context): + # Commande pour afficher les outils disponibles await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ 🔧| __**{lang.text('help_tools')}:**__ @@ -144,106 +147,47 @@ async def tools(self, ctx: commands.Context): @commands.command() async def fun(self, ctx: commands.Context): + # Commande pour afficher les commandes amusantes await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ 🎲| __**{lang.text('help_fun')}:**__ - `{config_selfbot.prefix}cat`: {lang.text('help_fun_cat')} - `{config_selfbot.prefix}good`: {lang.text('help_fun_good')} - `{config_selfbot.prefix}call`: {lang.text('help_fun_call')} - `{config_selfbot.prefix}gift `: {lang.text('help_fun_gift')} - `{config_selfbot.prefix}hack`: {lang.text('help_fun_hack')} - `{config_selfbot.prefix}howfemboy`: {lang.text('help_fun_femboy')} - `{config_selfbot.prefix}token`: {lang.text('help_fun_token')} - `{config_selfbot.prefix}hug`: {lang.text('help_fun_hug')} - `{config_selfbot.prefix}slap`: {lang.text('help_fun_slap')}""", delete_after=config_selfbot.deltime) - - @commands.command() - async def config(self, ctx: commands.Context): - await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ - -⚙️| __**{lang.text('help_config')}:**__ - `{config_selfbot.prefix}nitrosniper`: {lang.text('help_general_sniper')} - `{config_selfbot.prefix}restart`: {lang.text('help_config_restart')} - `{config_selfbot.prefix}stop`: {lang.text('help_config_stop')} - `{config_selfbot.prefix}lang`""", delete_after=config_selfbot.deltime) - - @commands.command() - async def raid(self, ctx: commands.Context): - await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ - -🏯| __**{lang.text('help_raid')}:**__ - `{config_selfbot.prefix}spam`: Spam. (`{config_selfbot.prefix}spam` 2 hello). - `{config_selfbot.prefix}flood`: Flood. - `{config_selfbot.prefix}kickall`: {lang.text('help_raid_kick')} - `{config_selfbot.prefix}banall`: {lang.text('help_raid_banall')}""", delete_after=config_selfbot.deltime) - - @commands.command() - async def utils(self, ctx: commands.Context): - await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ - -📂| __**{lang.text('help_utils')}:**__ - `{config_selfbot.prefix}ping`: {lang.text('help_general_ping')} - `{config_selfbot.prefix}snipe`: {lang.text('help_general_snipe')} - `{config_selfbot.prefix}clear`: {lang.text('help_general_clear')} - `{config_selfbot.prefix}hype`: {lang.text('help_general_hype')} - `{config_selfbot.prefix}bio`: {lang.text('help_general_bio')} - `{config_selfbot.prefix}userinfo`: {lang.text('help_general_user_info')}""", delete_after=config_selfbot.deltime) + `{config_selfbot.prefix}joke`: {lang.text('help_fun_joke')} + `{config_selfbot.prefix}fact`: {lang.text('help_fun_fact')} + `{config_selfbot.prefix}quote`: {lang.text('help_fun_quote')}""", delete_after=config_selfbot.deltime) @commands.command() - async def voice(self, ctx: commands.Context): - await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ - -🎤| __**{lang.text('help_voice')}:**__ - `{config_selfbot.prefix}joinvc `: {lang.text('help_voice_vc')} - `{config_selfbot.prefix}joincam `: {lang.text('help_voice_cam')} - `{config_selfbot.prefix}leavevc`: {lang.text('help_voice_leave')}""", delete_after=config_selfbot.deltime) - - @commands.command() - async def tuto(self, ctx: commands.Context): + async def presence(self, ctx: commands.Context): + # Commande pour afficher les options de présence await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ -🎮| __**Rich Presence Image Tutorial:**__ -{lang.text('tutorial_rpc')}""", delete_after=config_selfbot.deltime) +🕹️| __**{lang.text('help_rich_presence')}:**__ + `{config_selfbot.prefix}richpresence`: {lang.text('help_rich_presence_update')} + `{config_selfbot.prefix}setactivity`: {lang.text('help_rich_presence_set')} + `{config_selfbot.prefix}setstatus`: {lang.text('help_rich_presence_status')}""", delete_after=config_selfbot.deltime) @commands.command() async def templates(self, ctx: commands.Context): + # Commande pour afficher les modèles disponibles await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ 📖| __**{lang.text('help_templates')}:**__ - `{config_selfbot.prefix}use default`: {lang.text('template_help_default')} - `{config_selfbot.prefix}use reset`: {lang.text('template_help_reset')} - `{config_selfbot.prefix}use clear`: {lang.text('template_help_clear')} - `{config_selfbot.prefix}use hi`: {lang.text('template_help_hi')} - `{config_selfbot.prefix}use webdeck`: {lang.text('template_help_webdeck')} - `{config_selfbot.prefix}use omori`: {lang.text('template_help_omori')} - `{config_selfbot.prefix}use youtube`: {lang.text('template_help_youtube')} - `{config_selfbot.prefix}use car`: {lang.text('template_help_car')} - `{config_selfbot.prefix}use nuclear`: {lang.text('template_help_self')} - `{config_selfbot.prefix}use dark`: {lang.text('template_help_dark')} - `{config_selfbot.prefix}use python`: {lang.text('template_help_python')} - `{config_selfbot.prefix}use js`: {lang.text('template_help_js')} - `{config_selfbot.prefix}use cod`: {lang.text('template_help_cod')} - `{config_selfbot.prefix}use gta`: {lang.text('template_help_gta')} - `{config_selfbot.prefix}use tiktok`: {lang.text('template_help_tiktok')} - 💡 {lang.text('template_help_reload')}""", delete_after=config_selfbot.deltime) + `{config_selfbot.prefix}addtemplate `: {lang.text('help_templates_add')} + `{config_selfbot.prefix}removetemplate `: {lang.text('help_templates_remove')} + `{config_selfbot.prefix}templatelist`: {lang.text('help_templates_list')} + `{config_selfbot.prefix}edittemplate `: {lang.text('help_templates_edit')} + `{config_selfbot.prefix}showtemplate `: {lang.text('help_templates_show')} + `{config_selfbot.prefix}use `: {lang.text('help_templates_use')}""", delete_after=config_selfbot.deltime) @commands.command() - async def presence(self, ctx: commands.Context): - """Waiting for discord.pyself to add buttons links. - `{config_selfbot.prefix}rpc_button_link_one`: {lang.text('rpc_button_link_one_translate')}. - `{config_selfbot.prefix}rpc_button_link_two`: {lang.text('rpc_button_link_two_translate')}. - """ + async def voice(self, ctx: commands.Context): + # Commande pour afficher les options de voix await ctx.message.edit(f"""☄ __**{config_selfbot.selfbot_name} :**__ ☄ -🕹️| __**{lang.text('help_rich_presence')}:**__ - `{config_selfbot.prefix}rpc_name`: {lang.text('rpc_name_translate')} - `{config_selfbot.prefix}rpc_details`: {lang.text('rpc_details_translate')} - `{config_selfbot.prefix}rpc_state`: {lang.text('rpc_state_translate')} - `{config_selfbot.prefix}rpc_url`: {lang.text('rpc_url_translate')} - `{config_selfbot.prefix}rpc_type `: {lang.text('rpc_type_translate')} - `{config_selfbot.prefix}rpc_large_image`: {lang.text('rpc_large_image_translate')} (`{config_selfbot.prefix}tuto`!) - `{config_selfbot.prefix}rpc_large_text`: {lang.text('rpc_large_text_translate')} - `{config_selfbot.prefix}rpc_small_image`: {lang.text('rpc_small_image_translate')} (`{config_selfbot.prefix}tuto`!) - `{config_selfbot.prefix}rpc_small_text`: {lang.text('rpc_small_text_translate')} - `{config_selfbot.prefix}rpc_button_text_one`: {lang.text('rpc_button_text_one_translate')} - `{config_selfbot.prefix}rpc_button_text_two`: {lang.text('rpc_button_text_two_translate')}""", delete_after=config_selfbot.deltime) \ No newline at end of file +🎤| __**{lang.text('help_voice')}:**__ + `{config_selfbot.prefix}join`: {lang.text('help_voice_join')} + `{config_selfbot.prefix}leave`: {lang.text('help_voice_leave')} + `{config_selfbot.prefix}play `: {lang.text('help_voice_play')} + `{config_selfbot.prefix}pause`: {lang.text('help_voice_pause')} + `{config_selfbot.prefix}resume`: {lang.text('help_voice_resume')} + `{config_selfbot.prefix}stop`: {lang.text('help_voice_stop')} + `{config_selfbot.prefix}skip`: {lang.text('help_voice_skip')}""", delete_after=config_selfbot.deltime) From 0c2929aa96ae11641bd9055a37e97febf38350f7 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:41:24 +0100 Subject: [PATCH 07/11] Commented raid.py --- commands/raid.py | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/commands/raid.py b/commands/raid.py index d5618e3..5b292eb 100644 --- a/commands/raid.py +++ b/commands/raid.py @@ -12,86 +12,107 @@ def __init__(self, bot): @commands.command() async def kickall(self, ctx: commands.Context): + # Vérifie si l'auteur du message a la permission de kick des membres if ctx.author.guild_permissions.kick_members: members = ctx.guild.members + # Indique que le processus de kick est en cours await ctx.message.edit(lang.text('raid_in_process')) log.separate_text("KICK ALL") + # Boucle à travers tous les membres du serveur for member in members: + # Vérifie que le rôle du bot est supérieur au rôle du membre if ctx.guild.me.top_role > member.top_role: + # Kick le membre avec une raison générée aléatoirement await member.kick(reason=f"{config_selfbot.kick_reason} {generate_random_string(6)}") - log.success(f"@{member.name}({member.id}") + log.success(f"@{member.name}({member.id})") await asyncio.sleep(random_cooldown(0.4, 1.1)) log.separate("KICK ALL") + # Indique que tous les kicks ont réussi await ctx.message.edit(lang.text('raid_kick_all_success'), delete_after=config_selfbot.deltime) else: + # Affiche un message d'erreur si l'auteur n'a pas la permission await ctx.message.edit(lang.text('raid_error_permisssion'), delete_after=config_selfbot.deltime) @commands.command() async def banall(self, ctx: commands.Context): + # Vérifie si l'auteur du message a la permission de ban des membres if ctx.author.guild_permissions.ban_members: members = ctx.guild.members + # Indique que le processus de ban est en cours await ctx.message.edit(lang.text('raid_in_process')) log.separate_text("BAN ALL") + # Boucle à travers tous les membres du serveur for member in members: + # Vérifie que le rôle du bot est supérieur au rôle du membre if ctx.guild.me.top_role > member.top_role: + # Ban le membre avec une raison générée aléatoirement await member.ban(reason=f"{config_selfbot.ban_reason}. {generate_random_string(6)}") - log.success(f"@{member.name}({member.id}") + log.success(f"@{member.name}({member.id})") await asyncio.sleep(random_cooldown(0.4, 1.1)) log.separate("BAN ALL") + # Indique que tous les bans ont réussi await ctx.message.edit(lang.text('raid_ban_all_success'), delete_after=config_selfbot.deltime) else: + # Affiche un message d'erreur si l'auteur n'a pas la permission await ctx.message.edit(lang.text('raid_error_permisssion'), delete_after=config_selfbot.deltime) @commands.command() async def spam(self, ctx: commands.Context): + # Récupère le contenu du message et le divise message_split = ctx.message.content.split() content = ctx.message.content.replace(f"{message_split[0]} {message_split[1]} ", "") try: - count = int(message_split[1]) - 1 + count = int(message_split[1]) - 1 # Récupère le nombre de messages à envoyer except Exception: + # Affiche un message d'erreur si le nombre n'est pas valide await ctx.message.edit(f"{lang.text('spam_invalid')}!", delete_after=config_selfbot.deltime) return if count >= 100: + # Vérifie que le nombre de messages est raisonnable await ctx.message.edit(lang.text('spam_too_much'), delete_after=config_selfbot.deltime) return try: - message_split[2] + message_split[2] # Vérifie si un contenu de message a été fourni except Exception: + # Affiche un message d'erreur si le contenu est manquant await ctx.message.edit(lang.text('raid_dm_all_fail'), delete_after=config_selfbot.deltime) return if not self.is_spamming: - self.is_spamming = True + self.is_spamming = True # Indique que le spam est en cours + # Envoie le message initial await ctx.message.edit(content) for i in range(count): - await ctx.channel.send(content) - await asyncio.sleep(random_cooldown(0.4, 1.2)) - self.is_spamming = False + await ctx.channel.send(content) # Envoie le contenu spécifié + await asyncio.sleep(random_cooldown(0.4, 1.2)) # Pause aléatoire entre les messages + self.is_spamming = False # Indique que le spam est terminé else: + # Affiche un message d'erreur si un spam est déjà en cours await ctx.message.edit(lang.text('spam_cooldown'), delete_after=config_selfbot.deltime) @commands.command() async def flood(self, ctx: commands.Context): + # Crée un message de flood flood_spam = '_ _\n' * 44 - await ctx.message.edit(flood_spam) + await ctx.message.edit(flood_spam) # Modifie le message avec le contenu de flood for i in range(2): - await ctx.channel.send(flood_spam) - await asyncio.sleep(0.5) + await ctx.channel.send(flood_spam) # Envoie le flood dans le canal + await asyncio.sleep(0.5) # Pause entre les envois # TODO: - # Add: `nuke` command that will delete all channel and all roles. \ No newline at end of file + # Ajouter la commande `nuke` qui supprimera tous les canaux et tous les rôles. From f2d0c4da016d802ed15e61e3ae7eb2e23bbad423 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:52:00 +0100 Subject: [PATCH 08/11] Commented tools.py --- commands/tools.py | 78 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/commands/tools.py b/commands/tools.py index ae4446e..10c7f62 100644 --- a/commands/tools.py +++ b/commands/tools.py @@ -10,101 +10,99 @@ class ToolsCommands(commands.Cog): def __init__(self, bot): - self.bot: commands.Bot = bot + self.bot: commands.Bot = bot # Initialisation du bot @commands.command() async def bump(self, ctx: commands.Context): - message_split = ctx.message.content.split() + message_split = ctx.message.content.split() # Sépare le message pour obtenir les arguments + # Vérifie si la commande est dans un DM ou un groupe if isinstance(ctx.channel, discord.DMChannel) or isinstance(ctx.channel, discord.GroupChannel): await ctx.message.edit(lang.text('tool_bump_not_found'), delete_after=config_selfbot.deltime) return try: - await ctx.guild.fetch_member(302050872383242240) + await ctx.guild.fetch_member(302050872383242240) # Vérifie si le membre avec l'ID spécifique est dans le serveur except discord.NotFound: await ctx.message.edit(lang.text('tool_bump_not_found'), delete_after=config_selfbot.deltime) return try: - count = int(message_split[1]) + count = int(message_split[1]) # Tente de convertir le deuxième argument en entier except Exception: await ctx.message.edit(f"{lang.text('spam_invalid')}!", delete_after=config_selfbot.deltime) return - if count >= 100: + if count >= 100: # Vérifie si le nombre de bumps est supérieur à 100 await ctx.message.edit(lang.text('spam_too_much'), delete_after=config_selfbot.deltime) return await ctx.message.edit(f"{lang.text('tool_bump')} {count} {lang.text('tool_bump_two')}", delete_after=config_selfbot.deltime) - # Get the /bump object, to trigger it in the loop. + # Récupère l'objet /bump pour le déclencher dans la boucle. command = [_ for _ in await ctx.channel.application_commands() if _.name == 'bump' and _.application_id == 302050872383242240][0] for i in range(count): - # Trigger /bump command + # Déclenche la commande /bump await command.__call__(channel=ctx.channel) - # Log it + # Journalise l'action log.success(f"""{lang.text('tool_auto_bump')} {ctx.guild.name}({ctx.guild.id}) {lang.text('tool_auto_bump_two')} {i + 1} {lang.text('tool_auto_bump_three')}. {lang.text('tool_auto_bump_four')} {count - i - 1} {lang.text('tool_auto_bump_five')} {ctx.channel.name}({ctx.channel.id}).""") - # Wait for the next /bump trigger + # Attend avant de déclencher la prochaine commande /bump await asyncio.sleep(random_cooldown(7200, 7387)) @commands.command() async def dmall(self, ctx: commands.Context): - message_split = ctx.message.content.split() - dmall_content = ctx.message.content.replace(f"{message_split[0]} ", "") + message_split = ctx.message.content.split() # Sépare le message pour obtenir les arguments + dmall_content = ctx.message.content.replace(f"{message_split[0]} ", "") # Récupère le contenu du message pour DM try: - message_split[1] + message_split[1] # Vérifie si le deuxième argument est présent except Exception: await ctx.message.edit(lang.text('raid_dm_all_fail'), delete_after=config_selfbot.deltime) return - friends = self.bot.friends + friends = self.bot.friends # Récupère la liste des amis du bot - log.separate_text("DM ALL") + log.separate_text("DM ALL") # Journalise le début de l'opération DM - print(f"{Fore.BLUE}Friends Counter: {len(friends)} | Message:\n{dmall_content}{Style.RESET_ALL}") + print(f"{Fore.BLUE}Friends Counter: {len(friends)} | Message:\n{dmall_content}{Style.RESET_ALL}") # Affiche le compteur d'amis et le message - await ctx.message.edit(lang.text('raid_dm_all')) + await ctx.message.edit(lang.text('raid_dm_all')) # Informe l'utilisateur que le DM est en cours - for friend in friends: + for friend in friends: # Parcourt la liste des amis try: - await friend.user.send(dmall_content) - log.success(f"@{friend.user.name}({friend.user.id})") - await asyncio.sleep(random_cooldown(0.5, 2)) + await friend.user.send(dmall_content) # Envoie le message DM à chaque ami + log.success(f"@{friend.user.name}({friend.user.id})") # Journalise le succès + await asyncio.sleep(random_cooldown(0.5, 2)) # Pause aléatoire pour éviter d'être bloqué except discord.Forbidden: - log.fail(f"@{friend.user.name}({friend.user.id})") + log.fail(f"@{friend.user.name}({friend.user.id})") # Journalise l'échec si le DM est interdit except discord.CaptchaRequired: - log.alert("Captcha Required!") - log.separate("DM ALL") + log.alert("Captcha Required!") # Alerte si un captcha est requis + log.separate("DM ALL") # Sépare le journal await ctx.message.edit(lang.text('raid_dm_all_captcha'), delete_after=config_selfbot.deltime) return - log.separate("DM ALL") + log.separate("DM ALL") # Sépare le journal à la fin de l'opération - - await ctx.message.edit(lang.text('raid_dm_all_success'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('raid_dm_all_success'), delete_after=config_selfbot.deltime) # Confirme que l'opération a réussi @commands.command() async def closealldm(self, ctx: commands.Context): + await ctx.message.edit(lang.text('tool_close_dms')) # Informe que les DMs seront fermés - await ctx.message.edit(lang.text('tool_close_dms')) - - for dm_channel in self.bot.private_channels: + for dm_channel in self.bot.private_channels: # Parcourt les canaux privés du bot if isinstance(dm_channel, discord.DMChannel) and dm_channel.me.id == self.bot.user.id: - await dm_channel.close() - await asyncio.sleep(random_cooldown(0.5, 2)) - - await ctx.message.edit(lang.text('tool_close_dms_success'), delete_after=config_selfbot.deltime) + await dm_channel.close() # Ferme le canal DM si c'est un DM du bot + await asyncio.sleep(random_cooldown(0.5, 2)) # Pause aléatoire après chaque fermeture + + await ctx.message.edit(lang.text('tool_close_dms_success'), delete_after=config_selfbot.deltime) # Confirme que les DMs ont été fermés avec succès @commands.command() async def botclosedm(self, ctx: commands.Context): - - await ctx.message.edit(lang.text('tool_close_dms_bots')) + await ctx.message.edit(lang.text('tool_close_dms_bots')) # Informe que les DMs des bots seront fermés - for dm_channel in self.bot.private_channels: - if isinstance(dm_channel, discord.DMChannel) and dm_channel.recipient.bot: - await dm_channel.close() - await asyncio.sleep(random_cooldown(0.5, 2)) + for dm_channel in self.bot.private_channels: # Parcourt les canaux privés du bot + if isinstance(dm_channel, discord.DMChannel) and dm_channel.recipient.bot: # Vérifie si le canal est un DM d'un bot + await dm_channel.close() # Ferme le canal DM du bot + await asyncio.sleep(random_cooldown(0.5, 2)) # Pause aléatoire après chaque fermeture - await ctx.message.edit(lang.text('tool_close_dms_bots_success'), delete_after=config_selfbot.deltime) \ No newline at end of file + await ctx.message.edit(lang.text('tool_close_dms_bots_success'), delete_after=config_selfbot.deltime) # Confirme que les DMs des bots ont été fermés avec succès From 98f0b69c3cbf71f7f58afaa2bf52e30181dea963 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:53:57 +0100 Subject: [PATCH 09/11] Commented util.py --- commands/util.py | 96 ++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/commands/util.py b/commands/util.py index 9fa14de..b39f008 100644 --- a/commands/util.py +++ b/commands/util.py @@ -1,3 +1,4 @@ + import discord from discord.ext import commands @@ -9,27 +10,30 @@ class UtilsCommands(commands.Cog): def __init__(self, bot): - self.bot: commands.Bot = bot - self.sniped_messages: dict = {} + self.bot: commands.Bot = bot # Initialisation du bot + self.sniped_messages: dict = {} # Dictionnaire pour stocker les messages supprimés @commands.Cog.listener() async def on_message_delete(self, message): - if not message.author.id == self.bot.user.id: + # Écouteur pour capturer les messages supprimés + if not message.author.id == self.bot.user.id: # Ignore les messages supprimés par le bot try: - attachments_urls = [attachment.url for attachment in message.attachments] + attachments_urls = [attachment.url for attachment in message.attachments] # Récupère les URLs des pièces jointes self.sniped_messages[message.channel.id] = { - 'author': message.author, - 'content': message.content, - 'images': attachments_urls if message.attachments else None, - 'time': round(time.time()) + 'author': message.author, # Auteur du message + 'content': message.content, # Contenu du message + 'images': attachments_urls if message.attachments else None, # Images si présentes + 'time': round(time.time()) # Timestamp du message } except Exception: - return + return # Ignore les erreurs @commands.command() async def snipe(self, ctx: commands.Context): - sniped_message = self.sniped_messages.get(ctx.channel.id) + # Commande pour récupérer le dernier message supprimé + sniped_message = self.sniped_messages.get(ctx.channel.id) # Récupère le message supprimé pour le canal if sniped_message: + # Récupère les images et formate le message images_text = ", ".join(sniped_message['images']) if not sniped_message['images'] is None else lang.text('empty') await ctx.message.edit(f"""__**🔫 Sniper:**__ @@ -41,40 +45,34 @@ async def snipe(self, ctx: commands.Context): 🖼️ Images: {images_text} ⌚ {lang.text('time_snipe')}: """, delete_after=config_selfbot.deltime) else: - await ctx.message.edit(lang.text('error_no_message_snipe'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('error_no_message_snipe'), delete_after=config_selfbot.deltime) # Alerte si aucun message trouvé @commands.command() async def clear(self, ctx: commands.Context): - message_split = ctx.message.content.split() + # Commande pour supprimer un nombre spécifique de messages + message_split = ctx.message.content.split() # Sépare le message pour obtenir les arguments try: - str_amount = message_split[1] + str_amount = message_split[1] # Tente d'obtenir le nombre de messages à supprimer except Exception: - str_amount = "19" + str_amount = "19" # Valeur par défaut try: - amount = int(str_amount) + 1 + amount = int(str_amount) + 1 # Convertit en entier et ajoute 1 except Exception: - await ctx.message.edit(lang.text('spam_invalid'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('spam_invalid'), delete_after=config_selfbot.deltime) # Alerte si le nombre est invalide return - await ctx.message.edit(f"> 🌌 **{config_selfbot.selfbot_name}**", delete_after=1.7) - - async for message in ctx.channel.history(limit=amount): - if message.author.id == self.bot.user.id: - await message.delete() - await asyncio.sleep(random_cooldown(0.4, 1)) - """ - This can hardly rate limit you because user don't have access to bulk-message-delete endpoint. + await ctx.message.edit(f"> 🌌 **{config_selfbot.selfbot_name}**", delete_after=1.7) # Affiche un message indiquant la suppression - else: - def is_me(m): - return m.author.id == self.bot.user.id - await ctx.channel.purge(limit=amount, check=is_me) - """ + async for message in ctx.channel.history(limit=amount): # Récupère l'historique des messages + if message.author.id == self.bot.user.id: # Vérifie si le message a été envoyé par le bot + await message.delete() # Supprime le message + await asyncio.sleep(random_cooldown(0.4, 1)) # Pause aléatoire après chaque suppression @commands.command() async def hype(self, ctx: commands.Context): - house = ctx.message.content.split()[1] + # Commande pour changer la maison HypeSquad + house = ctx.message.content.split()[1] # Récupère le nom de la maison if house == "balance": await self.bot.user.edit(house=discord.HypeSquadHouse.balance) await ctx.message.edit(f"🪄 HypeSquad {lang.text('hype_command')} ``{house}``", delete_after=config_selfbot.deltime) @@ -85,38 +83,42 @@ async def hype(self, ctx: commands.Context): await self.bot.user.edit(house=discord.HypeSquadHouse.brilliance) await ctx.message.edit(f"🪄 HypeSquad {lang.text('hype_command')} ``{house}``", delete_after=config_selfbot.deltime) else: - await ctx.message.edit(lang.text('hype_fail'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('hype_fail'), delete_after=config_selfbot.deltime) # Alerte si la maison est invalide @commands.command() async def ping(self, ctx: commands.Context): + # Commande pour vérifier la latence du bot await ctx.message.edit(f"🏓 Pong ! (Ping: **{round(self.bot.latency * 1000)}ms**)", delete_after=config_selfbot.deltime) @commands.command() async def bio(self, ctx: commands.Context): - message_split = ctx.message.content.split() - new_bio = ctx.message.content.replace(f"{message_split[0]} ", "") - await self.bot.user.edit(bio=new_bio) - await ctx.message.edit(f"📖 Bio {lang.text('bio_command')} \"`{new_bio}`\"", delete_after=config_selfbot.deltime) + # Commande pour modifier la bio de l'utilisateur + message_split = ctx.message.content.split() # Sépare le message pour obtenir les arguments + new_bio = ctx.message.content.replace(f"{message_split[0]} ", "") # Récupère la nouvelle bio + await self.bot.user.edit(bio=new_bio) # Met à jour la bio + await ctx.message.edit(f"📖 Bio {lang.text('bio_command')} \"`{new_bio}`\"", delete_after=config_selfbot.deltime) # Confirme la mise à jour @commands.command() async def userinfo(self, ctx: commands.Context): + # Commande pour obtenir des informations sur un utilisateur if ctx.message.mentions: - user = ctx.message.mentions[0] + user = ctx.message.mentions[0] # Si un utilisateur est mentionné, l'utilise else: try: - user = self.bot.get_user(int(ctx.message.content.split()[1])) + user = self.bot.get_user(int(ctx.message.content.split()[1])) # Récupère l'utilisateur par ID except Exception: - user = ctx.author + user = ctx.author # Sinon, utilise l'auteur de la commande - user = await self.bot.fetch_user(user.id) # We can use ``await self.bot.get_user(user.id)``; that will do less api requests; but it's necessary to fetch_user for the banner. + user = await self.bot.fetch_user(user.id) # Récupère l'utilisateur pour les informations de bannière if ctx.guild: guild = ctx.guild - member = guild.get_member(user.id) - roles = [role.name for role in member.roles[1:] if role.name != '@everyone'] if member else [] + member = guild.get_member(user.id) # Récupère le membre du serveur + roles = [role.name for role in member.roles[1:] if role.name != '@everyone'] if member else [] # Récupère les rôles du membre else: roles = [] + # Formate le message d'informations sur l'utilisateur message = f"""🗒️| {lang.text('info_title')} <@{user.id}> : > 👤| {lang.text('info_global')}: `{user.global_name}` > 🌐| {lang.text('info_username')}: `{user.name}` @@ -125,13 +127,13 @@ async def userinfo(self, ctx: commands.Context): > 📅| {lang.text('info_created_at')}: `{user.created_at.strftime('%Y/%m/%d %H:%M:%S')}` > 🖼️| {lang.text('info_avatar')}: {"[" + lang.text('info_avatar_link') + "](" + user.avatar.url + ")" if not user.avatar is None else "`" + lang.text('empty') + "`"}""" - if roles: + if roles: # Ajoute les rôles au message s'il y en a message += f"\n> 🎭| {lang.text('info_roles')}: {', '.join(roles)}" - await ctx.message.edit(message, delete_after=config_selfbot.deltime) + await ctx.message.edit(message, delete_after=config_selfbot.deltime) # Envoie le message d'informations # TODO: - # Improvement: Add user's status in the `useinfo` command. - # Add: `serverinfo` command that will return informations about the server. - # Add: `botinvite` command that will return a botinvite using the given bot ID. - # Add: `support` command that will return support links. \ No newline at end of file + # Amélioration : Ajouter le statut de l'utilisateur dans la commande `userinfo`. + # Ajouter : commande `serverinfo` qui renverra des informations sur le serveur. + # Ajouter : commande `botinvite` qui renverra une invitation pour le bot avec l'ID donné. + # Ajouter : commande `support` qui renverra des liens de support. From 17f2c61099efd19252db302793fbc49a0d0fff91 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:54:45 +0100 Subject: [PATCH 10/11] Commented voice.py --- commands/voice.py | 61 ++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/commands/voice.py b/commands/voice.py index 8e7001d..e8725a9 100644 --- a/commands/voice.py +++ b/commands/voice.py @@ -8,69 +8,70 @@ class VoiceCommands(commands.Cog): def __init__(self, bot): - self.bot: commands.Bot = bot + self.bot: commands.Bot = bot # Initialisation du bot @commands.command() async def joinvc(self, ctx: commands.Context): - voice_id = ctx.message.content.split()[1] + # Commande pour rejoindre un canal vocal + voice_id = ctx.message.content.split()[1] # Récupère l'ID du canal vocal depuis le message try: - voice_id = int(voice_id) + voice_id = int(voice_id) # Convertit l'ID en entier except Exception: - await ctx.message.edit(lang.text('voice_channel_error'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('voice_channel_error'), delete_after=config_selfbot.deltime) # Alerte en cas d'erreur de conversion return - voice_channel = self.bot.get_channel(voice_id) + voice_channel = self.bot.get_channel(voice_id) # Récupère le canal vocal par son ID if voice_channel is None: - await ctx.message.edit(lang.text('voice_channel_error_not_found'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('voice_channel_error_not_found'), delete_after=config_selfbot.deltime) # Alerte si le canal vocal n'est pas trouvé return - try: - await voice_channel.connect() - await voice_channel.guild.change_voice_state(channel=voice_channel, self_mute=True) - await ctx.message.edit(f"📲 {lang.text('voice_join')} `{voice_channel.name}`.", delete_after=config_selfbot.deltime) + await voice_channel.connect() # Rejoint le canal vocal + await voice_channel.guild.change_voice_state(channel=voice_channel, self_mute=True) # Se met en sourdine + await ctx.message.edit(f"📲 {lang.text('voice_join')} `{voice_channel.name}`.", delete_after=config_selfbot.deltime) # Confirme le join except Exception as e: - await ctx.message.edit(f"❌ {lang.text('voice_join_error')} : {e}", delete_after=config_selfbot.deltime) + await ctx.message.edit(f"❌ {lang.text('voice_join_error')} : {e}", delete_after=config_selfbot.deltime) # Alerte en cas d'erreur return @commands.command() async def joincam(self, ctx: commands.Context): - voice_id = ctx.message.content.split()[1] + # Commande pour rejoindre un canal vocal avec vidéo + voice_id = ctx.message.content.split()[1] # Récupère l'ID du canal vocal depuis le message try: - voice_id = int(voice_id) + voice_id = int(voice_id) # Convertit l'ID en entier except Exception: - await ctx.message.edit(lang.text('voice_channel_error'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('voice_channel_error'), delete_after=config_selfbot.deltime) # Alerte en cas d'erreur de conversion return - voice_channel = self.bot.get_channel(voice_id) + voice_channel = self.bot.get_channel(voice_id) # Récupère le canal vocal par son ID if voice_channel is None: - await ctx.message.edit(lang.text('voice_channel_error_not_found'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('voice_channel_error_not_found'), delete_after=config_selfbot.deltime) # Alerte si le canal vocal n'est pas trouvé return - try: - await voice_channel.connect() - await voice_channel.guild.change_voice_state(channel=voice_channel, self_video=True, self_mute=True) - await ctx.message.edit(f"🎥 {lang.text('voice_join_cam')} `{voice_channel.name}` {lang.text('voice_join_cam_two')}") - await asyncio.sleep(config_selfbot.deltime) - await ctx.message.delete() + await voice_channel.connect() # Rejoint le canal vocal + await voice_channel.guild.change_voice_state(channel=voice_channel, self_video=True, self_mute=True) # Active la vidéo et se met en sourdine + await ctx.message.edit(f"🎥 {lang.text('voice_join_cam')} `{voice_channel.name}` {lang.text('voice_join_cam_two')}") # Confirme le join avec vidéo + await asyncio.sleep(config_selfbot.deltime) # Attend un moment avant de supprimer le message + await ctx.message.delete() # Supprime le message d'origine except Exception as e: - await ctx.message.edit(f"❌ {lang.text('voice_join_error')} : {e}", delete_after=config_selfbot.deltime) + await ctx.message.edit(f"❌ {lang.text('voice_join_error')} : {e}", delete_after=config_selfbot.deltime) # Alerte en cas d'erreur return @commands.command() async def leavevc(self, ctx: commands.Context): - voice_channel = ctx.message.author.voice.channel - voice_client = ctx.voice_client + # Commande pour quitter le canal vocal + voice_channel = ctx.message.author.voice.channel # Récupère le canal vocal de l'utilisateur + voice_client = ctx.voice_client # Récupère le client vocal if ctx.author.voice is None or ctx.author.voice.channel is None: - await ctx.message.edit(lang.text('leave_voice_error_not_found'), delete_after=config_selfbot.deltime) + await ctx.message.edit(lang.text('leave_voice_error_not_found'), delete_after=config_selfbot.deltime) # Alerte si l'utilisateur n'est pas dans un canal vocal return try: - await voice_client.disconnect() - await ctx.message.edit(f"💼 {lang.text('leave_voice')} `{voice_channel.name}`.", delete_after=config_selfbot.deltime) + await voice_client.disconnect() # Déconnecte le client vocal + await ctx.message.edit(f"💼 {lang.text('leave_voice')} `{voice_channel.name}`.", delete_after=config_selfbot.deltime) # Confirme le départ except Exception as e: - await ctx.message.edit(f"❌ {lang.text('leave_voice_error')} : {e}", delete_after=config_selfbot.deltime) - return \ No newline at end of file + await ctx.message.edit(f"❌ {lang.text('leave_voice_error')} : {e}", delete_after=config_selfbot.deltime) # Alerte en cas d'erreur + return From 6bad273bd8ae432d62abd977ad57d33bf5f3cd31 Mon Sep 17 00:00:00 2001 From: Andor <146471594+Andor-py@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:56:25 +0100 Subject: [PATCH 11/11] commented lang_manager.py --- utils/lang_manager.py | 215 +++++++++++++++++++----------------------- 1 file changed, 98 insertions(+), 117 deletions(-) diff --git a/utils/lang_manager.py b/utils/lang_manager.py index 5bccb2c..3d4de6f 100644 --- a/utils/lang_manager.py +++ b/utils/lang_manager.py @@ -1,169 +1,169 @@ """ -The MIT License (MIT) - -Copyright (c) 2024-present Lenochxd - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +La licence MIT (MIT) + +Copyright (c) 2024-présent Lenochxd + +La permission est par la présente accordée, sans frais, à toute personne obtenant une +copie de ce logiciel et des fichiers de documentation associés (le "Logiciel"), +de traiter le Logiciel sans restriction, y compris sans limitation +les droits d'utiliser, copier, modifier, fusionner, publier, distribuer, sous-licencier, +et/ou vendre des copies du Logiciel, et de permettre aux personnes à qui le +Logiciel est fourni de le faire, sous réserve des conditions suivantes : + +Le présent avis de copyright et cet avis de permission doivent être inclus dans +toutes les copies ou portions substantielles du Logiciel. + +LE LOGICIEL EST FOURNI "EN L'ÉTAT", SANS GARANTIE D'AUCUNE SORTE, EXPRESSE +OU IMPLICITE, Y COMPRIS MAIS SANS LIMITATION LES GARANTIES DE COMMERCIALISATION, +D'ADÉQUATION À UN OBJECTIF PARTICULIER ET DE NON-VIOLATION. EN AUCUN CAS, LES +AUTEURS OU DÉTENTEURS DE DROITS D'AUTEUR NE POURRONT ÊTRE TENUS RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGE OU AUTRE +RESPONSABILITÉ, QUE CE SOIT DANS LE CADRE D'UN CONTRAT, DÉLIT OU AUTRE, DÉCOULANT +DE OU EN LIAISON AVEC LE LOGICIEL OU L'UTILISATION OU AUTRES +TRAITEMENTS DANS LE LOGICIEL. """ -# NOTE: Language system made by Lenochxd, check her github(https://github.com/Lenochxd) ! +# REMARQUE : Système de langue créé par Lenochxd, consultez son GitHub (https://github.com/Lenochxd) ! import os import config_selfbot class Lang(): - """Constructor. + """Constructeur. - Parameters + Paramètres ---------- path: :class:`str` - The path of the folder containing .lang translations. - 'r string' are recommended (i.g.: r'.\langs'). + Le chemin du dossier contenant les traductions .lang. + Les chaînes 'r string' sont recommandées (ex.: r'.\langs'). - Default to r"./translations". + Défaut à r"./translations". default_language: :class:`str` - The default language to use (if the text wasn't found on the specified language). + La langue par défaut à utiliser (si le texte n'a pas été trouvé dans la langue spécifiée). - Default to "en_US". + Défaut à "en_US". - Raises + Lève ------ KeyError - No path were given or given path doesn't exists. + Aucun chemin n'a été donné ou le chemin donné n'existe pas. """ def __init__(self, path: str = r".\translations", default_language: str = "en_US"): - self.path: str = path + self.path: str = path # Chemin du dossier de traductions if not os.path.exists(self.path): - raise KeyError("No path were given or given path doesn't exists.") - self.lang_files: dict = {} - self.default_language: str = default_language - # Load all lang files at class init. + raise KeyError("Aucun chemin n'a été donné ou le chemin donné n'existe pas.") + self.lang_files: dict = {} # Dictionnaire pour stocker les fichiers de langue + self.default_language: str = default_language # Langue par défaut + # Charger tous les fichiers de langue à l'initialisation de la classe. self.load_all_lang_files() def load_lang_file(self, lang: str) -> dict: - """Loads .lang file. + """Charge le fichier .lang. - Parameters + Paramètres ---------- lang: :class:`str` - The lang name (i.g.: en_US, fr_FR...). + Le nom de la langue (ex.: en_US, fr_FR...). - Raises + Lève ------ TypeError - Lang file error. + Erreur de fichier de langue. - Returns + Retourne ------- lang_dictionary: :class:`dict` - A dict version of the the loaded .lang file. + Une version dict du fichier .lang chargé. """ lang_dictionary = {} - lang_path = f"{self.path}/{lang}.lang" - if not os.path.isfile(f"{self.path}/{lang}.lang"): + lang_path = f"{self.path}/{lang}.lang" # Chemin du fichier de langue + if not os.path.isfile(f"{self.path}/{lang}.lang"): # Vérifie si le fichier existe for root, dirs, files in os.walk(self.path): for file in files: - if file.endswith(".lang") and file.startswith(lang): + if file.endswith(".lang") and file.startswith(lang): # Recherche le fichier de langue lang_path = f"./{self.path}/{file}" - with open(lang_path, "r", encoding="utf-8") as f: + with open(lang_path, "r", encoding="utf-8") as f: # Ouvre le fichier de langue lines = f.readlines() for line in lines: - if (line.replace(" ", "").replace("\n", "") != "" - and not line.startswith("//") + if (line.replace(" ", "").replace("\n", "") != "" # Ignore les lignes vides + and not line.startswith("//") # Ignore les commentaires and not line.startswith("#")): try: - key, value = line.strip().replace("\n", "").split("=", 1) - lang_dictionary[key] = value.strip() + key, value = line.strip().replace("\n", "").split("=", 1) # Sépare la clé et la valeur + lang_dictionary[key] = value.strip() # Ajoute au dictionnaire except Exception as e: line = line.replace("\n", "") - raise TypeError(f'\nLANG FILE ERROR:\nLine: {line}\nError: {e}\n') + raise TypeError(f'\nERREUR DE FICHIER LANG:\nLigne: {line}\nErreur: {e}\n') return lang_dictionary def load_all_lang_files(self, path: str = None) -> dict: - """Loads all .lang files. + """Charge tous les fichiers .lang. - Parameters + Paramètres ---------- path: :class:`str` - The path of the folder containing .lang translations. + Le chemin du dossier contenant les traductions .lang. - Default to the contructor path. + Défaut au chemin du constructeur. - Returns + Retourne ------- lang_files: :class:`dict` - A dict version of the the loaded .lang files. + Une version dict des fichiers .lang chargés. """ if path is None: path = self.path - for root, dirs, files in os.walk(self.path): + for root, dirs, files in os.walk(self.path): # Parcourt tous les fichiers dans le dossier for file in files: - if file.endswith(".lang"): - lang = file.split(".")[0] - self.lang_files[lang] = self.load_lang_file(lang) + if file.endswith(".lang"): # Vérifie si c'est un fichier de langue + lang = file.split(".")[0] # Extrait le nom de la langue + self.lang_files[lang] = self.load_lang_file(lang) # Charge le fichier de langue return self.lang_files def reload_all_lang_files(self) -> None: - """Reloads all .lang files.""" + """Recharge tous les fichiers .lang.""" self.lang_files = self.load_all_lang_files(self.path) def language_exists(self, lang: str = None) -> bool: - """Check whatever a language exists in the translations folder. + """Vérifie si une langue existe dans le dossier de traductions. - Parameters + Paramètres ---------- lang: :class:`str` - The language to check. + La langue à vérifier. - Returns + Retourne -------- :class:`bool` - Whatever if the given language exists. + Vérifie si la langue donnée existe. """ lang = next((l for l in self.lang_files if l.lower().startswith(lang.lower())), '') return lang in self.lang_files def languages(self) -> list[dict]: - """Retrieve available languages. + """Récupère les langues disponibles. - Returns + Retourne ------- languages: :class:`list[dict]` - A :class:`list` containing :class:`dict` with lang informations. + Une :class:`list` contenant :class:`dict` avec les informations sur les langues. """ languages_info = [] - for lang in self.lang_files: + for lang in self.lang_files: # Parcourt les fichiers de langue chargés languages_info.append({ - 'name': lang, - 'code': self.lang_files[lang]['lang_code'], - 'native_name': self.lang_files[lang]['lang_name'], - 'credits': self.lang_files[lang]['credits'], + 'name': lang, # Nom de la langue + 'code': self.lang_files[lang]['lang_code'], # Code de la langue + 'native_name': self.lang_files[lang]['lang_name'], # Nom natif de la langue + 'credits': self.lang_files[lang]['credits'], # Crédits pour la langue }) return languages_info @@ -171,48 +171,48 @@ def languages(self) -> list[dict]: def text(self, text: str = None, lang: str = None) -> str: - """Returns the given text in the given language. + """Retourne le texte donné dans la langue spécifiée. - Parameters + Paramètres ---------- text: :class:`str` - The text to get in the given language. + Le texte à obtenir dans la langue donnée. lang: :class:`str` - The language to get the text into. + La langue dans laquelle obtenir le texte. - Default to the default language. + Défaut à la langue par défaut. - Raises + Lève ------ KeyError - Given text wasn't found on both default language and given language. + Le texte donné n'a pas été trouvé dans la langue par défaut et dans la langue donnée. - Returns + Retourne ------- :class:`str` - The translated text. + Le texte traduit. """ if text is None: return "" if lang is None: - lang = config_selfbot.lang + lang = config_selfbot.lang # Récupère la langue par défaut de la config lang = next((l for l in self.lang_files if l.lower().startswith(lang.lower())), self.default_language) if not lang in self.lang_files: - lang = self.default_language + lang = self.default_language # Utilise la langue par défaut si la langue spécifiée n'est pas trouvée - # TODO: Should improve here. - if not text in self.lang_files[lang]: + # TODO : Améliorer ici. + if not text in self.lang_files[lang]: # Vérifie si le texte existe dans le fichier de langue try: - return self.lang_files[lang][text].replace( + return self.lang_files[lang][text].replace( # Remplace les séquences d'échappement '\\n', '\n').replace( '\\r', '\r').replace( - '%prefix%', config_selfbot.prefix) + '%prefix%', config_selfbot.prefix) # Remplace le préfixe par celui de la config except KeyError: - raise KeyError("Given text wasn't found on both default language and given language.") + raise KeyError("Le texte donné n'a pas été trouvé ni dans la langue par défaut ni dans la langue donnée.") return self.lang_files[lang][text].replace( '\\n', '\n').replace( @@ -222,35 +222,16 @@ def text(self, def t(self, text: str = None, lang: str = None) -> str: - """Returns the given text in the given language. + """Retourne le texte donné dans la langue spécifiée. - Shortcut for Lang().text() + Raccourci pour Lang().text() - Parameters + Paramètres ---------- text: :class:`str` - The text to get in the given language. + Le texte à obtenir dans la langue donnée. lang: :class:`str` - The language to get the text into. - - Default to the default language. - - Raises - ------ - KeyError - Given text wasn't found on both default language and given language. - - Returns - ------- - :class:`str` - The translated text. - """ + La langue dans laquelle obtenir le texte. - return self.text(text, lang) + Défaut à la langue par défaut. -try: - lang = Lang(default_language="en_US", - path=r".\translations") -except Exception: - lang = Lang(default_language="en_US", - path=r"..\translations") \ No newline at end of file