161 lines
6.7 KiB
Python
161 lines
6.7 KiB
Python
|
|
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))
|