import logging import asyncio import aiohttp import os from datetime import datetime from dotenv import load_dotenv from telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters # Chargement des variables d'environnement load_dotenv() # Configuration du logging logging.basicConfig( format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO ) logger = logging.getLogger(__name__) # Config NocoDB & Telegram NOCODB_BASE_URL = os.getenv("NOCODB_BASE_URL") TABLE_BANNIES_ID = os.getenv("TABLE_BANNIES_ID") TABLE_HISTORY_ID = os.getenv("TABLE_HISTORY_ID") NOCODB_TOKEN = os.getenv("NOCODB_TOKEN") API_TOKEN = os.getenv("API_TOKEN") if not API_TOKEN: logger.error("❌ API_TOKEN manquant dans le fichier .env !") exit(1) # Liste globale des mots bannis BANNED_KEYWORDS = [] async def fetch_banned_keywords(): """Récupère les mots depuis NocoDB""" global BANNED_KEYWORDS url = f"{NOCODB_BASE_URL}{TABLE_BANNIES_ID}/records" headers = {"xc-token": NOCODB_TOKEN} params = {"limit": 100} try: async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers, params=params) as response: if response.status == 200: data = await response.json() new_keywords = [ row["MotBannies"].strip().lower() for row in data.get("list", []) if row.get("MotBannies") ] BANNED_KEYWORDS = new_keywords logger.info(f"✅ Liste des mots bannis mise à jour ({len(BANNED_KEYWORDS)} mots)") return True else: logger.error(f"❌ Erreur NocoDB : {response.status}") return False except Exception as e: logger.error(f"❌ Erreur connexion NocoDB : {e}") return False async def log_to_history(update: Update, action: str): """Enregistre l'action dans la table History de NocoDB""" url = f"{NOCODB_BASE_URL}{TABLE_HISTORY_ID}/records" headers = {"xc-token": NOCODB_TOKEN} # On récupère l'objet message ou channel_post msg = update.message or update.channel_post if not msg: return # Identification de l'auteur user_name = "Utilisateur Inconnu" user_id = "N/A" logger.info(f"🎯 get info : msg '{msg}'") if msg.from_user: # Cas classique (Groupe/Privé) user_full_name = msg.from_user.full_name user_username = msg.from_user.username user_name = f"{user_full_name} (@{user_username or 'N/A'})" user_id = str(msg.from_user.id) elif msg.author_signature: # Cas Canal avec signature user_name = f"Admin: {msg.author_signature}" user_id = "Canal (Anonyme)" elif msg.sender_chat: # Cas Canal ou Groupe anonyme user_name = f"Chat: {msg.sender_chat.title}" user_id = str(msg.sender_chat.id) payload = { "Title": f"Mod-{datetime.now().strftime('%H%M%S')}", "Message": msg.text or "[Média]", "User": user_name, "UserID": user_id, "Timestamp": datetime.now().isoformat(), "Action": action, "Channel": f"{msg.chat.title or 'Privé'} ({msg.chat.id})" } try: async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, json=payload) as response: if response.status in [200, 201]: logger.info(f"📊 Historique enregistré pour {user_name}") else: logger.error(f"❌ Échec archivage ({response.status})") except Exception as e: logger.error(f"❌ Erreur lors de l'archivage : {e}") async def filter_logic(update: Update, context: ContextTypes.DEFAULT_TYPE): """Analyse les messages et applique la modération""" msg = update.message or update.channel_post if not msg or not msg.text: return text_lower = msg.text.lower() # Log radar pour la console source = "Inconnu" if msg.from_user: source = f"@{msg.from_user.username or msg.from_user.full_name}" elif msg.chat: source = f"ID:{msg.chat.id} ({msg.chat.title})" logger.info(f"📩 Message de [{source}] : {msg.text}") for word in BANNED_KEYWORDS: if word in text_lower: try: # Suppression du message await msg.delete() # Avertissement (dans les groupes/privé uniquement) if update.message: await context.bot.send_message( chat_id=msg.chat.id, text="🚫 Mot interdit détecté et supprimé." ) logger.info(f"🎯 Action : Suppression du mot '{word}'") await log_to_history(update, f"Suppression (Mot: {word})") except Exception as e: logger.error(f"❌ Erreur lors de la modération : {e}") return async def refresh(update: Update, context: ContextTypes.DEFAULT_TYPE): """Rafraîchit la liste des mots depuis la commande /refresh""" if await fetch_banned_keywords(): await update.message.reply_text(f"✅ Liste mise à jour ! {len(BANNED_KEYWORDS)} mots actifs.") else: await update.message.reply_text("❌ Échec du rafraîchissement.") async def post_init(application): """Effectue les tâches d'initialisation après le démarrage du bot""" await fetch_banned_keywords() if __name__ == '__main__': # Initialisation de l'application application = ApplicationBuilder().token(API_TOKEN).post_init(post_init).build() # Ajout des handlers application.add_handler(CommandHandler("refresh", refresh)) # Filtre pour capturer tous les messages textes (Groupes ET Canaux) application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), filter_logic)) logger.info("🚀 Bot démarré avec python-telegram-bot...") application.run_polling()