base demo
This commit is contained in:
15
.dockerignore
Normal file
15
.dockerignore
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
.db/
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
.env
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
test_chatid.py
|
||||||
|
*.md
|
||||||
|
Dockerfile
|
||||||
|
docker-compose.yml
|
||||||
6
.env
Normal file
6
.env
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
NOCODB_BASE_URL = "https://dbtest.kaelstudio.tech/api/v2/tables/"
|
||||||
|
TABLE_BANNIES_ID = "m7mwhc3qnlmgahy"
|
||||||
|
TABLE_HISTORY_ID = "m65949r27wwrawn"
|
||||||
|
NOCODB_TOKEN = "dbgK7YJNZuW2mTK4O3umr9j08sr9GwjaKZj5cN5p" # Remplacez par votre token valide
|
||||||
|
|
||||||
|
API_TOKEN = "5724216572:AAFdyvymS-F39dsU3KcQhG3U3GXGCknRGNM" # Remp
|
||||||
28
Dockerfile
Normal file
28
Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Image de base légère
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Éviter la génération de fichiers .pyc et forcer l'affichage des logs
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
# Dossier de travail
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Installation des dépendances système si nécessaire
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copie des fichiers de dépendances
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
# Installation des bibliothèques Python
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copie de tout le code source
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Le port 8599 est exposé pour Streamlit
|
||||||
|
EXPOSE 8599
|
||||||
|
|
||||||
|
# Par défaut, on ne définit pas de CMD ici car elle sera surchargée par Docker Compose
|
||||||
182
dashboard.py
Normal file
182
dashboard.py
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
import streamlit as st
|
||||||
|
import pandas as pd
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Chargement du fichier .env pour le token Telegram
|
||||||
|
load_dotenv()
|
||||||
|
API_TOKEN = os.getenv("API_TOKEN")
|
||||||
|
|
||||||
|
# --- CONFIGURATION ---
|
||||||
|
st.set_page_config(page_title="ModoBot Admin", layout="wide")
|
||||||
|
|
||||||
|
NOCODB_BASE_URL = "https://dbtest.kaelstudio.tech/api/v2/tables/"
|
||||||
|
TABLE_BANNIES_ID = "m7mwhc3qnlmgahy"
|
||||||
|
TABLE_HISTORY_ID = "m65949r27wwrawn"
|
||||||
|
NOCODB_TOKEN = os.getenv("NOCODB_TOKEN", "dbgK7YJNZuW2mTK4O3umr9j08sr9GwjaKZj5cN5p")
|
||||||
|
|
||||||
|
HEADERS = {"xc-token": NOCODB_TOKEN}
|
||||||
|
|
||||||
|
def fetch_data(table_id):
|
||||||
|
url = f"{NOCODB_BASE_URL}{table_id}/records"
|
||||||
|
response = requests.get(url, headers=HEADERS, params={"limit": 100})
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json().get("list", [])
|
||||||
|
return []
|
||||||
|
|
||||||
|
def add_keyword(keyword):
|
||||||
|
url = f"{NOCODB_BASE_URL}{TABLE_BANNIES_ID}/records"
|
||||||
|
data = {"MotBannies": keyword}
|
||||||
|
requests.post(url, headers=HEADERS, json=data)
|
||||||
|
|
||||||
|
def delete_keyword(id):
|
||||||
|
url = f"{NOCODB_BASE_URL}{TABLE_BANNIES_ID}/records"
|
||||||
|
requests.delete(url, headers=HEADERS, json={"Id": id})
|
||||||
|
|
||||||
|
def telegram_api_call(method, params):
|
||||||
|
"""Envoie une requête directement à l'API Telegram"""
|
||||||
|
url = f"https://api.telegram.org/bot{API_TOKEN}/{method}"
|
||||||
|
try:
|
||||||
|
resp = requests.post(url, json=params)
|
||||||
|
return resp.json()
|
||||||
|
except Exception as e:
|
||||||
|
return {"ok": False, "description": str(e)}
|
||||||
|
|
||||||
|
def extract_chat_id(channel_str):
|
||||||
|
"""Extrait l'ID entre parenthèses à la fin d'une chaîne comme 'Mon Salon (-100123)'"""
|
||||||
|
match = re.search(r'\( (-?\d+) \)$'.replace(' ',''), str(channel_str))
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# --- UI ---
|
||||||
|
st.title("🛡️ ModoBot Dashboard")
|
||||||
|
st.markdown("---")
|
||||||
|
|
||||||
|
tab1, tab2, tab3, tab4 = st.tabs(["📊 Statistiques", "📜 Historique", "🚫 Gestion des Mots", "🛡️ Modération"])
|
||||||
|
|
||||||
|
# Chargement initial des données
|
||||||
|
history_data = fetch_data(TABLE_HISTORY_ID)
|
||||||
|
bannies_data = fetch_data(TABLE_BANNIES_ID)
|
||||||
|
|
||||||
|
# --- TAB 1: STATISTICS ---
|
||||||
|
with tab1:
|
||||||
|
st.header("État du système")
|
||||||
|
col1, col2, col3 = st.columns(3)
|
||||||
|
col1.metric("Total Suppressions", len(history_data))
|
||||||
|
col2.metric("Mots Filtrés", len(bannies_data))
|
||||||
|
col3.metric("Dernière Activité", history_data[0]['Timestamp'] if history_data else "N/A")
|
||||||
|
|
||||||
|
if history_data:
|
||||||
|
df_hist = pd.DataFrame(history_data)
|
||||||
|
st.subheader("Volume de suppressions par salon")
|
||||||
|
st.bar_chart(df_hist['Channel'].value_counts())
|
||||||
|
|
||||||
|
# --- TAB 2: HISTORY ---
|
||||||
|
with tab2:
|
||||||
|
st.header("📜 Historique des messages supprimés")
|
||||||
|
if history_data:
|
||||||
|
df_hist = pd.DataFrame(history_data)
|
||||||
|
cols = ['Timestamp', 'User', 'UserID', 'Message', 'Channel', 'Action']
|
||||||
|
display_cols = [c for c in cols if c in df_hist.columns]
|
||||||
|
# Utilisation de width='stretch' au lieu de use_container_width
|
||||||
|
st.dataframe(df_hist[display_cols].sort_values(by='Timestamp', ascending=False), width='stretch')
|
||||||
|
else:
|
||||||
|
st.info("Aucun message dans l'historique.")
|
||||||
|
|
||||||
|
# --- TAB 3: MANAGEMENT ---
|
||||||
|
with tab3:
|
||||||
|
st.header("🚫 Liste des mots bannis")
|
||||||
|
new_word = st.text_input("Ajouter un nouveau mot interdit")
|
||||||
|
if st.button("Ajouter"):
|
||||||
|
if new_word:
|
||||||
|
add_keyword(new_word)
|
||||||
|
st.success(f"Mot '{new_word}' ajouté !")
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
st.subheader("Mots actifs")
|
||||||
|
if bannies_data:
|
||||||
|
for item in bannies_data:
|
||||||
|
col_word, col_btn = st.columns([4, 1])
|
||||||
|
col_word.write(item['MotBannies'])
|
||||||
|
if col_btn.button("Supprimer", key=f"del_{item['Id']}"):
|
||||||
|
delete_keyword(item['Id'])
|
||||||
|
st.rerun()
|
||||||
|
else:
|
||||||
|
st.write("La liste est vide.")
|
||||||
|
|
||||||
|
# --- TAB 4: MANUAL MODERATION ---
|
||||||
|
with tab4:
|
||||||
|
st.header("🛡️ Gestion des Utilisateurs")
|
||||||
|
|
||||||
|
if not history_data:
|
||||||
|
st.warning("Aucun utilisateur dans l'historique pour le moment.")
|
||||||
|
else:
|
||||||
|
# Création d'une copie propre pour éviter le SettingWithCopyWarning
|
||||||
|
df_full = pd.DataFrame(history_data).copy()
|
||||||
|
|
||||||
|
# On extrait l'ID du salon pour chaque ligne
|
||||||
|
df_full['ExtractedChatID'] = df_full['Channel'].apply(extract_chat_id)
|
||||||
|
|
||||||
|
# Filtrage pour n'avoir que des données exploitables
|
||||||
|
df_mod = df_full[df_full['ExtractedChatID'].notnull() & df_full['UserID'].notnull()].copy()
|
||||||
|
|
||||||
|
if df_mod.empty:
|
||||||
|
st.info("Aucun ID utilisateur/salon exploitable trouvé dans l'historique.")
|
||||||
|
else:
|
||||||
|
# Création d'un label clair
|
||||||
|
df_mod.loc[:, 'label'] = df_mod['User'] + " | Salon: " + df_mod['Channel']
|
||||||
|
|
||||||
|
# On ne garde que les doublons UserID + ChatID
|
||||||
|
unique_targets = df_mod.drop_duplicates(['UserID', 'ExtractedChatID'])
|
||||||
|
|
||||||
|
selected_label = st.selectbox("Choisir une cible de modération", unique_targets['label'])
|
||||||
|
target_row = unique_targets[unique_targets['label'] == selected_label].iloc[0]
|
||||||
|
|
||||||
|
target_user_id = target_row['UserID']
|
||||||
|
target_chat_id = target_row['ExtractedChatID']
|
||||||
|
|
||||||
|
st.info(f"👉 **Cible sélectionnée** : User `{target_user_id}` sur Chat `{target_chat_id}`")
|
||||||
|
|
||||||
|
col_act, col_timer = st.columns([2, 2])
|
||||||
|
action = col_act.selectbox("Action à effectuer", ["Kick (Expulser)", "Ban (Bannir)", "Mute (Silencier)", "Unban (Débannir)"])
|
||||||
|
|
||||||
|
duration = 0
|
||||||
|
if action in ["Ban (Bannir)", "Mute (Silencier)"]:
|
||||||
|
duration = col_timer.select_slider(
|
||||||
|
"Durée / Timer",
|
||||||
|
options=[0, 15, 60, 360, 1440, 10080],
|
||||||
|
format_func=lambda x: "Permanent" if x == 0 else (f"{x} min" if x < 60 else (f"{x//60}h" if x < 1440 else f"{x//1440}j"))
|
||||||
|
)
|
||||||
|
|
||||||
|
confirm = st.checkbox(f"Confirmer {action} sur cet utilisateur")
|
||||||
|
|
||||||
|
if st.button("🚀 Appliquer la sanction", disabled=not confirm):
|
||||||
|
result = {"ok": False}
|
||||||
|
until_date = int(time.time() + (duration * 60)) if duration > 0 else None
|
||||||
|
|
||||||
|
with st.spinner("Action en cours..."):
|
||||||
|
if "Kick" in action:
|
||||||
|
result = telegram_api_call("banChatMember", {"chat_id": target_chat_id, "user_id": target_user_id})
|
||||||
|
telegram_api_call("unbanChatMember", {"chat_id": target_chat_id, "user_id": target_user_id})
|
||||||
|
elif "Ban" in action:
|
||||||
|
p = {"chat_id": target_chat_id, "user_id": target_user_id}
|
||||||
|
if until_date: p["until_date"] = until_date
|
||||||
|
result = telegram_api_call("banChatMember", p)
|
||||||
|
elif "Mute" in action:
|
||||||
|
perms = {"can_send_messages": False, "can_send_media_messages": False, "can_send_other_messages": False}
|
||||||
|
p = {"chat_id": target_chat_id, "user_id": target_user_id, "permissions": perms}
|
||||||
|
if until_date: p["until_date"] = until_date
|
||||||
|
result = telegram_api_call("restrictChatMember", p)
|
||||||
|
elif "Unban" in action:
|
||||||
|
result = telegram_api_call("unbanChatMember", {"chat_id": target_chat_id, "user_id": target_user_id, "only_if_banned": False})
|
||||||
|
|
||||||
|
if result.get("ok"):
|
||||||
|
st.success("✅ Sanction appliquée !")
|
||||||
|
else:
|
||||||
|
st.error(f"❌ Erreur Telegram : {result.get('description', 'Inconnue')}")
|
||||||
26
docker-compose.yml
Normal file
26
docker-compose.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# Service du Bot Telegram
|
||||||
|
bot:
|
||||||
|
build: .
|
||||||
|
container_name: modobot-service
|
||||||
|
restart: always
|
||||||
|
command: python main.py
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
|
||||||
|
# Service du Dashboard Streamlit
|
||||||
|
dashboard:
|
||||||
|
build: .
|
||||||
|
container_name: modobot-dashboard
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "8599:8599"
|
||||||
|
command: streamlit run dashboard.py --server.port 8599 --server.address 0.0.0.0
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
168
main.py
Normal file
168
main.py
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
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()
|
||||||
6
requirements.txt
Normal file
6
requirements.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
python-telegram-bot
|
||||||
|
aiohttp
|
||||||
|
streamlit
|
||||||
|
pandas
|
||||||
|
requests
|
||||||
|
python-dotenv
|
||||||
64
test_chatid.py
Normal file
64
test_chatid.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import asyncio
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from telegram import Update
|
||||||
|
from telegram.ext import ApplicationBuilder, ContextTypes, MessageHandler, filters
|
||||||
|
|
||||||
|
# Chargement du token
|
||||||
|
load_dotenv()
|
||||||
|
API_TOKEN = os.getenv("API_TOKEN")
|
||||||
|
|
||||||
|
# Configuration du logging
|
||||||
|
logging.basicConfig(
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
|
level=logging.INFO
|
||||||
|
)
|
||||||
|
|
||||||
|
async def get_info(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
"""Affiche toutes les informations disponibles lors de la réception d'un message"""
|
||||||
|
user = update.effective_user
|
||||||
|
chat = update.effective_chat
|
||||||
|
msg = update.effective_message
|
||||||
|
|
||||||
|
print("\n" + "="*40)
|
||||||
|
print("🎯 NOUVELLE INTERACTION DÉTECTÉE")
|
||||||
|
print("="*40)
|
||||||
|
|
||||||
|
if user:
|
||||||
|
print(f"👤 UTILISATEUR (Auteur) :")
|
||||||
|
print(f" - ID : {user.id}")
|
||||||
|
print(f" - Nom : {user.full_name}")
|
||||||
|
print(f" - Username : @{user.username if user.username else 'N/A'}")
|
||||||
|
print(f" - Est un Bot : {user.is_bot}")
|
||||||
|
else:
|
||||||
|
print("👤 UTILISATEUR : Non disponible (Post de canal anonyme)")
|
||||||
|
|
||||||
|
print(f"\n💬 CONTEXTE DU CHAT :")
|
||||||
|
print(f" - Chat ID : {chat.id}")
|
||||||
|
print(f" - Titre : {chat.title if chat.title else 'Conversation Privée'}")
|
||||||
|
print(f" - Type : {chat.type}")
|
||||||
|
|
||||||
|
print(f"\n📝 MESSAGE :")
|
||||||
|
print(f" - Contenu : {msg.text if msg.text else '[Média/Autre]'}")
|
||||||
|
print("="*40 + "\n")
|
||||||
|
|
||||||
|
# On répond à l'utilisateur pour confirmer
|
||||||
|
if msg:
|
||||||
|
await msg.reply_text(f"✅ Infos reçues !\nTon ID : {user.id if user else 'N/A'}\nChat ID : {chat.id}")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if not API_TOKEN:
|
||||||
|
print("❌ Erreur : API_TOKEN non trouvé dans le .env")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Création de l'application de test
|
||||||
|
application = ApplicationBuilder().token(API_TOKEN).build()
|
||||||
|
|
||||||
|
# On écoute absolument TOUT (messages, posts de canaux, etc.)
|
||||||
|
application.add_handler(MessageHandler(filters.ALL, get_info))
|
||||||
|
|
||||||
|
print("🚀 SCRIPT DE TEST DÉMARRÉ")
|
||||||
|
print("👉 Envoie un message au bot pour voir tes informations s'afficher ici...")
|
||||||
|
|
||||||
|
application.run_polling()
|
||||||
Reference in New Issue
Block a user