diff --git a/bot.py b/bot.py index 9f94e5c..bc36f3d 100755 --- a/bot.py +++ b/bot.py @@ -13,7 +13,6 @@ import asyncio from src.logger import kuby_logger, log_performance import logging from src.advanced_logger import AdvancedLogger -import subprocess SENSITIVE_PERMISSIONS = { "administrator", "manage_guild", "manage_roles", "manage_channels", @@ -30,7 +29,6 @@ class RoleApprovalView(disnake.ui.View): @disnake.ui.button(label="Accepter", style=disnake.ButtonStyle.green, emoji="✅") async def accept(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction): - # Check if member still in guild guild = self.member.guild current_member = guild.get_member(self.member.id) if not current_member: @@ -41,8 +39,7 @@ class RoleApprovalView(disnake.ui.View): try: await current_member.add_roles(*self.roles, reason="Restauration sécurisée approuvée par le propriétaire") await interaction.response.send_message(f"✅ Rôles sensibles restaurés pour {self.member.mention}.", ephemeral=True) - - # Update original message + components = [ disnake.ui.Container( disnake.ui.TextDisplay(f"✅ Vous avez approuvé la restauration des rôles pour {self.member.mention}."), @@ -57,8 +54,7 @@ class RoleApprovalView(disnake.ui.View): @disnake.ui.button(label="Refuser", style=disnake.ButtonStyle.red, emoji="✖️") async def deny(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction): await interaction.response.send_message(f"❌ Vous avez refusé la restauration pour {self.member.mention}.", ephemeral=True) - - # Update original message + components = [ disnake.ui.Container( disnake.ui.TextDisplay(f"❌ Vous avez refusé la restauration des rôles pour {self.member.mention}."), @@ -68,6 +64,7 @@ class RoleApprovalView(disnake.ui.View): await interaction.edit_original_response(embed=None, components=components, view=None) self.stop() + # Récupération et validation de l'ID d'application application_id_raw = os.getenv("APPLICATION_ID") kuby_logger.debug(f"Raw APPLICATION_ID: {application_id_raw}") @@ -80,11 +77,12 @@ except ValueError: # Configuration des intents Disnake intents = disnake.Intents.default() -intents.message_content = True -intents.members = True +intents.message_content = True +intents.members = True intents.voice_states = True kuby_logger.debug(f"Disnake intents configured: {intents}") + class MyBot(commands.Bot): def __init__(self): kuby_logger.debug("Initializing MyBot class") @@ -95,34 +93,16 @@ class MyBot(commands.Bot): command_sync_flags=commands.CommandSyncFlags.all() ) kuby_logger.info("MyBot instance created successfully") - + # Initialize advanced logger self.advanced_logger = AdvancedLogger(self) kuby_logger.info("✅ Advanced logger initialized") - # Start the Flask Webhook Server - self.flask_process = None - try: - flask_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "serveur_flask.py") - if os.path.exists(flask_path): - self.flask_process = subprocess.Popen( - [sys.executable, flask_path], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - cwd=os.path.dirname(flask_path) - ) - kuby_logger.info(f"✅ Serveur Flask démarré (PID: {self.flask_process.pid})") - else: - kuby_logger.warning(f"⚠️ Fichier serveur_flask.py introuvable") - except Exception as e: - kuby_logger.error(f"❌ Impossible de démarrer le serveur Flask: {e}") - + # Flask est géré par PM2 (kuby-flask), pas besoin de le lancer ici async def do_async_setup(self): - # --- INITIALIZATION LOGIC (Called before start() in kuby.py) --- kuby_logger.info("🚀 Configuration initiale du bot Kuby...") - # Charger les extensions extensions = [ "commandes.whitelist", "commandes.whitelist_monitor", @@ -154,31 +134,6 @@ class MyBot(commands.Bot): except Exception as e: kuby_logger.error(f"❌ Erreur lors du chargement de {extension} : {e}", exc_info=True) - # --- SYSTÈME DE WHITELIST (DÉDIÉ SLASH COMMANDS) --- - async def global_slash_whitelist_check(inter: disnake.ApplicationCommandInteraction): - try: - if await self.is_owner(inter.author): - return True - command_name = inter.data.name - if command_name in ["ticketconfig", "ticketpanel", "ticket_config", "ticket_panel", "ticket_whitelist_config", "invitations"]: - return True - whitelist_cog = self.get_cog("WhitelistMonitor") - if not whitelist_cog: - return True - is_whitelisted = whitelist_cog.is_whitelisted(inter.guild.id, inter.author.id) - if not is_whitelisted: - kuby_logger.info(f"🚫 [Check] Accès refusé : {inter.author} sur /{command_name}") - msg = "❌ Vous n'êtes pas autorisé à utiliser cette commande. Veuillez demander à être ajouté à la whitelist." - if not inter.response.is_done(): - await inter.response.send_message(msg, ephemeral=True) - return False - return True - except Exception as e: - kuby_logger.error(f"⚠️ [Check] Erreur critique: {e}", exc_info=True) - return True - - # self.add_app_command_check(global_slash_whitelist_check) - # --- LOGGING DES INTERACTIONS --- @self.listen("on_interaction") async def log_interaction(inter: disnake.Interaction): @@ -187,17 +142,6 @@ class MyBot(commands.Bot): kuby_logger.info("✅ Configuration terminée") - async def close(self): - if hasattr(self, 'flask_process') and self.flask_process: - kuby_logger.info("Arrêt du serveur Flask interne...") - self.flask_process.terminate() - try: - self.flask_process.wait(timeout=5) - except subprocess.TimeoutExpired: - self.flask_process.kill() - await super().close() - - # --- ÉVÉNEMENTS RESTAURÉS --- async def on_ready(self): kuby_logger.info(f"🤖 Bot connecté : {self.user} (ID : {self.user.id})") kuby_logger.info(f"📊 Serveurs : {len(self.guilds)}") @@ -224,23 +168,16 @@ class MyBot(commands.Bot): roles_to_add = [guild.get_role(rid) for rid in previous_roles.get("role_ids", [])] roles_to_add = [r for r in roles_to_add if r and r < guild.me.top_role] if roles_to_add: - # Separate roles into safe and sensitive safe_roles = [] sensitive_roles = [] - + for role in roles_to_add: - is_sensitive = False - for perm in SENSITIVE_PERMISSIONS: - if getattr(role.permissions, perm, False): - is_sensitive = True - break - + is_sensitive = any(getattr(role.permissions, perm, False) for perm in SENSITIVE_PERMISSIONS) if is_sensitive: sensitive_roles.append(role) else: safe_roles.append(role) - # Restore safe roles automatically if safe_roles: retries = 3 for i in range(retries): @@ -250,8 +187,8 @@ class MyBot(commands.Bot): break except (disnake.HTTPException, disnake.GatewayNotFound, asyncio.TimeoutError) as e: is_transient = isinstance(e, disnake.HTTPException) and e.status in [500, 502, 503, 504] - if not isinstance(e, disnake.HTTPException): is_transient = True - + if not isinstance(e, disnake.HTTPException): + is_transient = True if is_transient and i < retries - 1: await asyncio.sleep((i + 1) * 2) continue @@ -261,7 +198,6 @@ class MyBot(commands.Bot): kuby_logger.error(f"Error restoring safe roles for {member}: {e}") break - # Handle sensitive roles with owner approval if sensitive_roles: try: owner = guild.owner or await guild.fetch_member(guild.owner_id) @@ -298,19 +234,23 @@ class MyBot(commands.Bot): kuby_logger.error(f"Error in leave notification: {e}") async def on_message_delete(self, message): - if message.author.bot: return + if message.author.bot: + return if hasattr(self, 'advanced_logger'): self.advanced_logger.log_message_event(message, "deleted") async def on_message_edit(self, before, after): - if before.author.bot or before.content == after.content: return + if before.author.bot or before.content == after.content: + return if hasattr(self, 'advanced_logger'): self.advanced_logger.log_message_event(before, "edited", { - "before_content": before.content, "after_content": after.content + "before_content": before.content, + "after_content": after.content }) async def on_voice_state_update(self, member, before, after): - if member.bot: return + if member.bot: + return if before.channel != after.channel and hasattr(self, 'advanced_logger'): if before.channel is None: self.advanced_logger.log_voice_event(member, after.channel, "joined") @@ -322,9 +262,10 @@ class MyBot(commands.Bot): async def on_command_error(self, ctx, error): if isinstance(error, commands.CommandNotFound): - return # Ignorer les erreurs "Command not found" pour éviter de polluer les logs (ex: !!) + return if isinstance(error, commands.CheckFailure): return kuby_logger.error(f"Command error in {ctx.command}: {str(error)}", exc_info=True) + bot = MyBot() \ No newline at end of file