import discord from discord import app_commands from discord.ext import commands import json import os # Chemins des fichiers SETTINGS_FILE = "data/security_settings.json" WHITELIST_FILE = "data/whitelist.json" # --- UTILITAIRES --- def load_settings(guild_id): if not os.path.exists(SETTINGS_FILE): return {} try: with open(SETTINGS_FILE, "r", encoding='utf-8') as f: return json.load(f).get(str(guild_id), {}) except: return {} def save_settings(guild_id, settings): data = {} if os.path.exists(SETTINGS_FILE): try: with open(SETTINGS_FILE, "r", encoding='utf-8') as f: data = json.load(f) except: pass data[str(guild_id)] = settings os.makedirs(os.path.dirname(SETTINGS_FILE), exist_ok=True) with open(SETTINGS_FILE, "w", encoding='utf-8') as f: json.dump(data, f, indent=4, ensure_ascii=False) def is_whitelisted(guild_id, user_id): if not os.path.exists(WHITELIST_FILE): return False try: with open(WHITELIST_FILE, "r", encoding='utf-8') as f: data = json.load(f) return user_id in data.get(str(guild_id), []) except: return False # --- MODAL DE RÉGLAGE DU SEUIL --- class ThresholdModal(discord.ui.Modal, title="Réglage du Seuil Anti-Spam"): threshold_input = discord.ui.TextInput( label="Messages max autorisés (en 5 secondes)", placeholder="Par défaut : 5", min_length=1, max_length=2, required=True ) def __init__(self, guild_id, settings, view): super().__init__() self.guild_id = guild_id self.settings = settings self.parent_view = view async def on_submit(self, interaction: discord.Interaction): if not self.threshold_input.value.isdigit(): return await interaction.response.send_message("❌ Erreur : Veuillez entrer un nombre entier.", ephemeral=True) new_val = int(self.threshold_input.value) self.settings["spam_threshold"] = new_val save_settings(self.guild_id, self.settings) await interaction.response.send_message(f"✅ Le seuil a été réglé sur **{new_val}** messages.", ephemeral=True) # --- VUE DE GESTION --- class SecurityView(discord.ui.View): def __init__(self, interaction, settings, category=None): super().__init__(timeout=None) self.interaction = interaction self.guild = interaction.guild self.settings = settings self.category = category self.build_view() def build_view(self): self.clear_items() if self.category is None: self.add_item(CategorySelect()) else: config_map = { "raid": [("anti_raid", "🛡️ Anti-Raid"), ("auto_ban", "🔨 Auto-Ban")], "spam": [("anti_spam", "🛡️ Anti-Spam"), ("anti_link", "🔗 Anti-Link"), ("anti_mention", "👥 Anti-Mention")], "nuke": [("anti_channel_delete", "📁 Anti-Salon"), ("anti_role_create", "🎭 Anti-Rôle")], "logs": [("server_logs", "📋 Activer Logs")] } for key, label in config_map.get(self.category, []): is_on = self.settings.get(key, False) style = discord.ButtonStyle.green if is_on else discord.ButtonStyle.red status = "✅" if is_on else "❌" btn = discord.ui.Button(label=f"{label} [{status}]", style=style, custom_id=key) btn.callback = self.toggle_setting self.add_item(btn) # BOUTON SPÉCIAL : RÉGLAGE SEUIL (uniquement dans spam) if self.category == "spam": btn_threshold = discord.ui.Button(label=f"🔢 Seuil: {self.settings.get('spam_threshold', 5)}", style=discord.ButtonStyle.blurple) btn_threshold.callback = self.open_threshold_modal self.add_item(btn_threshold) back_btn = discord.ui.Button(label="⬅️ Retour", style=discord.ButtonStyle.gray) back_btn.callback = self.back_to_main self.add_item(back_btn) async def toggle_setting(self, interaction: discord.Interaction): key = interaction.data['custom_id'] self.settings[key] = not self.settings.get(key, False) save_settings(self.guild.id, self.settings) self.build_view() await interaction.response.edit_message(view=self) async def open_threshold_modal(self, interaction: discord.Interaction): await interaction.response.send_modal(ThresholdModal(self.guild.id, self.settings, self)) async def back_to_main(self, interaction: discord.Interaction): self.category = None self.build_view() embed = self.create_main_embed() await interaction.response.edit_message(embed=embed, view=self) def create_main_embed(self): embed = discord.Embed(title="🛡️ Centre de Sécurité Kuby", description="Interface modulaire de protection.", color=0x2b2d31) if self.guild.icon: embed.set_thumbnail(url=self.guild.icon.url) embed.add_field(name="Propriétaire", value=self.guild.owner.mention) return embed class CategorySelect(discord.ui.Select): def __init__(self): options = [ discord.SelectOption(label="Anti-Raid", value="raid", emoji="⚔️"), discord.SelectOption(label="Anti-Spam", value="spam", emoji="🛡️"), discord.SelectOption(label="Anti-Nuke", value="nuke", emoji="☢️"), discord.SelectOption(label="Logs", value="logs", emoji="📋") ] super().__init__(placeholder="Sélectionnez un module...", options=options) async def callback(self, interaction: discord.Interaction): view: SecurityView = self.view view.category = self.values[0] view.build_view() embed = discord.Embed(title=f"⚙️ Configuration : {view.category.upper()}", color=0x2b2d31) await interaction.response.edit_message(embed=embed, view=view) # --- COG --- class Security(commands.Cog): def __init__(self, bot): self.bot = bot @app_commands.command(name="security", description="Ouvrir le panneau Kuby") async def security(self, interaction: discord.Interaction): if not (interaction.user.guild_permissions.administrator or interaction.user.id == interaction.guild.owner_id or is_whitelisted(interaction.guild.id, interaction.user.id)): return await interaction.response.send_message("❌ Accès refusé.", ephemeral=True) settings = load_settings(interaction.guild.id) view = SecurityView(interaction, settings) await interaction.response.send_message(embed=view.create_main_embed(), view=view) async def setup(bot): await bot.add_cog(Security(bot))