import discord from discord.ext import commands import json import os import asyncio from datetime import datetime SETTINGS_FILE = "data/security_settings.json" WHITELIST_FILE = "data/whitelist.json" class AntiSpam(commands.Cog): def __init__(self, bot): self.bot = bot # Compteurs pour le Spam self.message_counts = {} self.spam_warnings = {} # Compteurs pour les Liens self.link_warnings = {} def is_whitelisted(self, guild_id, user_id): """Vérifie si l'utilisateur est protégé (Whitelist ou Owner)""" # 1. Le propriétaire est toujours whitelist guild = self.bot.get_guild(guild_id) if guild and user_id == guild.owner_id: return True # 2. Vérification fichier Whitelist 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 @commands.Cog.listener() async def on_message(self, message): if message.author.bot or not message.guild: return # --- 1. IMMUNITÉ TOTALE --- # Si Whitelisté, on ignore tout (Spam et Liens) if self.is_whitelisted(message.guild.id, message.author.id): return # --- 2. CHARGEMENT CONFIG --- if not os.path.exists(SETTINGS_FILE): return with open(SETTINGS_FILE, "r", encoding='utf-8') as f: settings = json.load(f).get(str(message.guild.id), {}) # ================================================================= # MODULE ANTI-LINK (3 Avertissements -> Mute) # ================================================================= if settings.get("anti_link"): # Liste des déclencheurs interdits forbidden = ["discord.gg/", "http://", "https://", "www."] # On vérifie si le message contient un lien interdit if any(trigger in message.content.lower() for trigger in forbidden): # Si l'auteur a la permission de gérer les messages, on laisse passer (optionnel, sinon retirer cette ligne) if not message.author.guild_permissions.manage_messages: await self.handle_link_violation(message) return # On arrête là, pas besoin de vérifier le spam si le message est supprimé # ================================================================= # MODULE ANTI-SPAM (3 Avertissements -> Mute) # ================================================================= if settings.get("anti_spam"): user_id = message.author.id now = datetime.now().timestamp() if user_id not in self.message_counts: self.message_counts[user_id] = [] self.message_counts[user_id].append(now) # Fenêtre de temps : 5 secondes self.message_counts[user_id] = [t for t in self.message_counts[user_id] if now - t < 5] # Seuil dynamique (défaut: 5) limit = settings.get("spam_threshold", 5) if len(self.message_counts[user_id]) > limit: await self.handle_spam_violation(message) # --- GESTION DES VIOLATIONS LIENS --- async def handle_link_violation(self, message): try: await message.delete() except: pass # Message déjà supprimé ou manque de perms user_id = message.author.id warnings = self.link_warnings.get(user_id, 0) + 1 self.link_warnings[user_id] = warnings if warnings <= 3: embed = discord.Embed( title="🔗 Liens Interdits", description=f"{message.author.mention}, les liens ne sont pas autorisés.\n**Avertissement : {warnings}/3**", color=0xFFA500 ) await message.channel.send(embed=embed, delete_after=5) else: await self.sanction_user(message, "Publication de liens interdits") self.link_warnings[user_id] = 0 # Reset après sanction # --- GESTION DES VIOLATIONS SPAM --- async def handle_spam_violation(self, message): user_id = message.author.id # Nettoyage visuel du spam try: await message.channel.purge(limit=5, check=lambda m: m.author == message.author) except: pass warnings = self.spam_warnings.get(user_id, 0) + 1 self.spam_warnings[user_id] = warnings # Reset le compteur de messages pour éviter le spam d'avertissements self.message_counts[user_id] = [] if warnings <= 3: embed = discord.Embed( title="🛡️ Anti-Spam", description=f"{message.author.mention}, veuillez cesser de spammer.\n**Avertissement : {warnings}/3**", color=0xFFA500 ) await message.channel.send(embed=embed, delete_after=5) else: await self.sanction_user(message, "Spam excessif") self.spam_warnings[user_id] = 0 # Reset après sanction # --- SANCTION COMMUNE (TIMEOUT 5 MIN) --- async def sanction_user(self, message, reason): try: # Durée : 5 minutes duration = discord.utils.utcnow() + asyncio.timedelta(minutes=5) # Application du Timeout (Exclusion temporaire) await message.author.timeout(duration, reason=f"Kuby Security: {reason} (3 Warns)") embed = discord.Embed( title="⛔ Exclusion Temporaire", description=f"**Utilisateur :** {message.author.mention}\n**Durée :** 5 minutes\n**Raison :** {reason} (Limite atteinte).", color=0xFF0000 ) await message.channel.send(embed=embed) except discord.Forbidden: await message.channel.send("⚠️ Je n'ai pas la permission d'exclure ce membre (Vérifiez ma hiérarchie).") except Exception as e: print(f"Erreur Sanction: {e}") async def setup(bot): await bot.add_cog(AntiSpam(bot))