""" Module de modération automatique pour Superviseur Bot Gère la détection et sanction des messages inappropriés automatiquement sur tous les messages """ import discord import aiohttp import json import os from datetime import datetime WARNINGS_FILE = 'warnings.json' def load_warnings(): """Charge les avertissements depuis le fichier JSON""" if os.path.exists(WARNINGS_FILE): with open(WARNINGS_FILE, 'r', encoding='utf-8') as f: content = f.read().strip() if content: return json.loads(content) return {} def save_warnings(warnings): """Sauvegarde les avertissements dans le fichier JSON""" with open(WARNINGS_FILE, 'w', encoding='utf-8') as f: json.dump(warnings, f, indent=4, ensure_ascii=False) async def check_message_content_global(bot, content): """ Vérifie le contenu d'un message pour tout contenu inapproprié Utilise une liste locale de mots inappropriés pour performance optimale """ # Liste optimisée de mots inappropriés (mots-clés critiques seulement pour performance) bad_words = { # Mots critiques (haute sévérité) 'nigger', 'nigga', 'pédé', 'bougnoul', 'viol', 'pédophile', 'inceste', 'naziste', 'hitler', 'suicide', 'se tuer', 'se suicider', 'tuer', 'assassiner', 'meurtre', # Gros mots courants 'fuck', 'shit', 'asshole', 'bitch', 'dick', 'pussy', 'cunt', 'motherfucker', 'merde', 'putain', 'salope', 'connard', 'enculé', 'bordel', 'emmerde', 'ta gueule', 'va te faire foutre', 'va te faire enculer', 'va chier', 'crève', 'branleur', 'sucer', 'pipe', 'pétasse', 'garce', 'traînée', 'salopard', 'ordure', 'fumier', 'pourri', 'dégueulasse', 'gueule', 'gueuler', # Insultes 'con', 'abruti', 'débile', 'crétin', 'imbécile', 'loser', 'nullos', 'naze', 'ridicule', 'pathétique', 'minable', 'nul', 'inutile', 'incapable', 'bon à rien', # NSFW/sexuel 'sexe', 'porn', 'porno', 'bite', 'seins', 'sodomie', 'agression sexuelle', 'harceleur', 'stalker', # Discrimination 'raciste', 'antisémite', 'fasciste', 'gay', 'homo', 'féminin', # Drogues 'drogue', 'cocaine', 'héroine', 'cannabis', 'ecstasy', 'lsd', 'crack', 'speed', 'amphétamine', 'steroide', 'anabolisant', # Autres 'cancer', 'maladie grave', 'crever', 'mourir' } content_lower = content.lower() detected_bad_words = [] # Recherche rapide avec set pour performance for bad_word in bad_words: bad_word_lower = bad_word.lower() # Recherche insensible à la casse avec délimiteurs pour éviter faux positifs if f" {bad_word_lower} " in f" {content_lower} " or content_lower == bad_word_lower: detected_bad_words.append(bad_word) # Continue pour lister tous les mots détectés, mais limite à 3 pour performance if len(detected_bad_words) >= 3: break if detected_bad_words: severity = "high" if any(word in ['nigger', 'nigga', 'pédé', 'bougnoul', 'viol', 'pédophile', 'inceste', 'naziste', 'hitler', 'suicide', 'se tuer', 'tuer', 'assassiner', 'meurtre'] for word in detected_bad_words) else "medium" return { "inappropriate": True, "severity": severity, "reason": f"Mots inappropriés détectés: {', '.join(detected_bad_words[:3])}", "bad_words": detected_bad_words[:3] } return {"inappropriate": False} async def warn_and_check_ban_global(message, reason, message_deleted=False): """ Émet un avertissement et vérifie si l'utilisateur doit être banni (3+ avertissements) """ guild_id = str(message.guild.id) all_warnings = load_warnings() if guild_id not in all_warnings: all_warnings[guild_id] = {} user_id_str = str(message.author.id) if user_id_str not in all_warnings[guild_id]: all_warnings[guild_id][user_id_str] = [] # Ajouter l'avertissement all_warnings[guild_id][user_id_str].append({ 'reason': reason, 'timestamp': datetime.now().isoformat(), 'issued_by': 'AUTOMATIC_MODERATION' }) warning_count = len(all_warnings[guild_id][user_id_str]) save_warnings(all_warnings) from commandes.autres.logger import action_logger action_logger.log_action('AUTOMATIC_MODERATION', str(message.author), str(message.guild), { 'reason': reason, 'warning_count': warning_count, 'original_message': message.content }, True) # Vérifier si bannissement automatique nécessaire if warning_count >= 3: try: await message.author.ban(reason=f"Bannissement automatique: 3 avertissements accumulés. Dernière raison: {reason}") embed = discord.Embed( title="🚫 Bannissement automatique", description=f"{message.author.mention}, vous avez été banni pour accumulation d'avertissements (3+ avertissements).\n**Dernière raison:** {reason}", color=discord.Color.red() ) embed.set_footer(text=f"Total d'avertissements: {warning_count}") await message.channel.send(embed=embed) return True # Utilisateur banni except discord.Forbidden: embed = discord.Embed( title="Ban requis", description=f"❌ {message.author.mention} a 3+ avertissements, mais le bot n'a pas les permissions de bannir.\n**Agissez manuellement!**", color=discord.Color.red() ) embed.set_footer(text=f"Total d'avertissements: {warning_count}") await message.channel.send(embed=embed) return False else: # Envoyer message d'avertissement deletion_text = "Votre message a été supprimé pour contenu inapproprié." if message_deleted else "Mots inappropriés détectés dans votre message." warning_message = f"⚠️ **Avertissement automatique** {message.author.mention}\n{deletion_text}\n**Raison:** {reason}\n**Avertissements totaux:** {warning_count}\n**Avant bannissement:** {3 - warning_count} avertissement(s)\n*Modération automatique par IA*" await message.channel.send(warning_message) return False async def moderate_message(bot, message): """ Fonction principale de modération automatique d'un message Retourne True si le message a été modéré (et donc supprimé), False sinon """ # Préparer le contenu à analyser content_to_check = message.content if message.attachments: for attachment in message.attachments: if attachment.content_type and attachment.content_type.startswith('image/'): if not content_to_check.strip(): content_to_check = f"[Image: {attachment.filename}]" else: content_to_check += f" [Image: {attachment.filename}]" # Analyser le contenu if content_to_check.strip(): print(f"[MODERATION] Analysing message from {message.author}: '{content_to_check}'") moderation_result = await check_message_content_global(bot, content_to_check) print(f"[MODERATION] Result: {moderation_result}") bad_words = moderation_result.get('bad_words', []) inappropriate = moderation_result.get('inappropriate', False) print(f"[MODERATION] bad_words: {bad_words}, inappropriate: {inappropriate}") # Toujours donner un avertissement si des mots inappropriés sont détectés if bad_words: reason = f"Mots inappropriés détectés: {', '.join(bad_words[:5])}" print(f"[MODERATION] Processing bad words, reason: {reason}") if inappropriate: print(f"[MODERATION] Message inappropriate, deleting...") try: await message.delete() print(f"[MODERATION] Message deleted successfully") except discord.Forbidden: print(f"[MODERATION] Forbidden to delete message") pass # Impossible de supprimer except Exception as e: print(f"[MODERATION] Error deleting message: {e}") await warn_and_check_ban_global(message, reason, message_deleted=True) print(f"[MODERATION] Warning sent and ban checked, returning True") return True # Message modéré else: print(f"[MODERATION] Not inappropriate, sending warning without deletion") await warn_and_check_ban_global(message, reason, message_deleted=False) return False # Message autorisé # Test function pour vérifier la fonctionnalité async def test_auto_moderation(): """Fonction de test pour vérifier que les avertissements sont toujours donnés""" print("Test auto-moderation: vérification que les avertissements sont donnés pour les mots inappropriés") # Cette fonction peut être appelée pour tester manuellement si nécessaire