Update app.py
Browse files
app.py
CHANGED
|
@@ -11,6 +11,7 @@ import markdown # Pour convertir la réponse en HTML
|
|
| 11 |
from flask_session import Session # <-- Importer Session
|
| 12 |
import pprint # Pour un affichage plus lisible des structures complexes (optionnel)
|
| 13 |
import logging # Import logging
|
|
|
|
| 14 |
|
| 15 |
# --- Configuration Initiale ---
|
| 16 |
load_dotenv()
|
|
@@ -22,6 +23,17 @@ logging.basicConfig(level=logging.DEBUG, # Set the desired logging level
|
|
| 22 |
format='%(asctime)s - %(levelname)s - %(message)s')
|
| 23 |
logger = logging.getLogger(__name__) # Get a logger for this module
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
# --- Configuration Flask Standard ---
|
| 26 |
app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'une-super-cle-secrete-a-changer')
|
| 27 |
|
|
@@ -194,11 +206,54 @@ def process_uploaded_file(file):
|
|
| 194 |
logger.error(f"--- ERREUR [process_uploaded_file]: Type de fichier non autorisé: {file.filename}")
|
| 195 |
return None, None, None
|
| 196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
# --- Routes Flask ---
|
| 198 |
|
| 199 |
@app.route('/')
|
| 200 |
def root():
|
| 201 |
logger.debug("--- LOG: Appel route '/' ---")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
return render_template('index.html')
|
| 203 |
|
| 204 |
@app.route('/api/history', methods=['GET'])
|
|
@@ -248,6 +303,11 @@ def chat_api():
|
|
| 248 |
logger.error("--- ERREUR [/api/chat]: Prompt et fichiers vides.")
|
| 249 |
return jsonify({'success': False, 'error': 'Veuillez fournir un message ou au moins un fichier.'}), 400
|
| 250 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
if 'chat_history' not in session:
|
| 252 |
session['chat_history'] = []
|
| 253 |
history_before_user_add = list(session.get('chat_history', []))
|
|
@@ -289,6 +349,14 @@ def chat_api():
|
|
| 289 |
history_after_user_add = list(session.get('chat_history', []))
|
| 290 |
logger.debug(f"--- DEBUG [/api/chat]: Historique après ajout: {len(history_after_user_add)} messages")
|
| 291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
selected_model_name = MODEL_PRO if use_advanced else MODEL_FLASH
|
| 293 |
final_prompt_for_gemini = raw_user_text
|
| 294 |
|
|
@@ -401,6 +469,15 @@ def chat_api():
|
|
| 401 |
session['chat_history'].append(assistant_history_entry)
|
| 402 |
history_final_turn = list(session.get('chat_history', []))
|
| 403 |
logger.debug(f"--- DEBUG [/api/chat]: Historique FINAL: {len(history_final_turn)} messages")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
logger.debug("--- LOG [/api/chat]: Envoi de la réponse HTML au client.\n---==================================---\n")
|
| 405 |
return jsonify({'success': True, 'message': response_html})
|
| 406 |
|
|
@@ -414,6 +491,15 @@ def chat_api():
|
|
| 414 |
logger.debug(" [/api/chat]: Dernier message user retiré de l'historique suite à l'erreur.")
|
| 415 |
except Exception as pop_e:
|
| 416 |
logger.error(f" Erreur lors du retrait du message user: {pop_e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
logger.debug("---==================================---\n")
|
| 418 |
return jsonify({'success': False, 'error': f"Erreur interne: {e}"}), 500
|
| 419 |
|
|
@@ -430,6 +516,15 @@ def chat_api():
|
|
| 430 |
@app.route('/clear', methods=['POST'])
|
| 431 |
def clear_chat():
|
| 432 |
logger.debug("\n--- DEBUG [/clear]: Requête POST reçue ---")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 433 |
session.clear()
|
| 434 |
logger.debug(" [/clear]: Session effacée.")
|
| 435 |
is_ajax = 'XMLHttpRequest' == request.headers.get('X-Requested-With') or \
|
|
|
|
| 11 |
from flask_session import Session # <-- Importer Session
|
| 12 |
import pprint # Pour un affichage plus lisible des structures complexes (optionnel)
|
| 13 |
import logging # Import logging
|
| 14 |
+
import html # Pour échapper le HTML dans les messages Telegram
|
| 15 |
|
| 16 |
# --- Configuration Initiale ---
|
| 17 |
load_dotenv()
|
|
|
|
| 23 |
format='%(asctime)s - %(levelname)s - %(message)s')
|
| 24 |
logger = logging.getLogger(__name__) # Get a logger for this module
|
| 25 |
|
| 26 |
+
# --- Configuration Telegram ---
|
| 27 |
+
TELEGRAM_BOT_TOKEN = "8004545342:AAGcZaoDjYg8dmbbXRsR1N3TfSSbEiAGz88"
|
| 28 |
+
TELEGRAM_CHAT_ID = "-1002497861230"
|
| 29 |
+
TELEGRAM_ENABLED = TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID
|
| 30 |
+
|
| 31 |
+
# Vérification de la configuration Telegram
|
| 32 |
+
if TELEGRAM_ENABLED:
|
| 33 |
+
logger.info(f"Notifications Telegram activées pour le chat ID: {TELEGRAM_CHAT_ID}")
|
| 34 |
+
else:
|
| 35 |
+
logger.warning("Notifications Telegram désactivées. Ajoutez TELEGRAM_BOT_TOKEN et TELEGRAM_CHAT_ID dans .env")
|
| 36 |
+
|
| 37 |
# --- Configuration Flask Standard ---
|
| 38 |
app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'une-super-cle-secrete-a-changer')
|
| 39 |
|
|
|
|
| 206 |
logger.error(f"--- ERREUR [process_uploaded_file]: Type de fichier non autorisé: {file.filename}")
|
| 207 |
return None, None, None
|
| 208 |
|
| 209 |
+
def send_telegram_message(message):
|
| 210 |
+
"""Envoie un message à Telegram via l'API Bot."""
|
| 211 |
+
if not TELEGRAM_ENABLED:
|
| 212 |
+
logger.debug("Telegram désactivé. Message non envoyé.")
|
| 213 |
+
return False
|
| 214 |
+
|
| 215 |
+
try:
|
| 216 |
+
# Échapper le HTML pour le message Telegram
|
| 217 |
+
sanitized_message = html.escape(message)
|
| 218 |
+
|
| 219 |
+
# Limiter la taille du message (Telegram limite à 4096 caractères)
|
| 220 |
+
if len(sanitized_message) > 4000:
|
| 221 |
+
sanitized_message = sanitized_message[:3997] + "..."
|
| 222 |
+
|
| 223 |
+
response = requests.post(
|
| 224 |
+
f'https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage',
|
| 225 |
+
data={
|
| 226 |
+
'chat_id': TELEGRAM_CHAT_ID,
|
| 227 |
+
'text': sanitized_message,
|
| 228 |
+
'parse_mode': 'HTML'
|
| 229 |
+
}
|
| 230 |
+
)
|
| 231 |
+
|
| 232 |
+
if response.status_code == 200:
|
| 233 |
+
logger.debug("Message Telegram envoyé avec succès")
|
| 234 |
+
return True
|
| 235 |
+
else:
|
| 236 |
+
logger.error(f"Échec d'envoi du message Telegram: {response.status_code} - {response.text}")
|
| 237 |
+
return False
|
| 238 |
+
|
| 239 |
+
except Exception as e:
|
| 240 |
+
logger.error(f"Erreur lors de l'envoi du message Telegram: {e}")
|
| 241 |
+
return False
|
| 242 |
+
|
| 243 |
+
def generate_session_id():
|
| 244 |
+
"""Génère un ID de session unique."""
|
| 245 |
+
import uuid
|
| 246 |
+
return str(uuid.uuid4())[:8]
|
| 247 |
+
|
| 248 |
# --- Routes Flask ---
|
| 249 |
|
| 250 |
@app.route('/')
|
| 251 |
def root():
|
| 252 |
logger.debug("--- LOG: Appel route '/' ---")
|
| 253 |
+
# Générer un ID de session s'il n'existe pas
|
| 254 |
+
if 'session_id' not in session:
|
| 255 |
+
session['session_id'] = generate_session_id()
|
| 256 |
+
logger.debug(f"Nouvelle session créée: {session['session_id']}")
|
| 257 |
return render_template('index.html')
|
| 258 |
|
| 259 |
@app.route('/api/history', methods=['GET'])
|
|
|
|
| 303 |
logger.error("--- ERREUR [/api/chat]: Prompt et fichiers vides.")
|
| 304 |
return jsonify({'success': False, 'error': 'Veuillez fournir un message ou au moins un fichier.'}), 400
|
| 305 |
|
| 306 |
+
# Assurer que l'ID de session existe
|
| 307 |
+
if 'session_id' not in session:
|
| 308 |
+
session['session_id'] = generate_session_id()
|
| 309 |
+
session_id = session['session_id']
|
| 310 |
+
|
| 311 |
if 'chat_history' not in session:
|
| 312 |
session['chat_history'] = []
|
| 313 |
history_before_user_add = list(session.get('chat_history', []))
|
|
|
|
| 349 |
history_after_user_add = list(session.get('chat_history', []))
|
| 350 |
logger.debug(f"--- DEBUG [/api/chat]: Historique après ajout: {len(history_after_user_add)} messages")
|
| 351 |
|
| 352 |
+
# Envoyer une notification Telegram pour le message utilisateur
|
| 353 |
+
if TELEGRAM_ENABLED:
|
| 354 |
+
files_info = f"[{len(uploaded_filenames)} fichiers: {', '.join(uploaded_filenames)}] " if uploaded_filenames else ""
|
| 355 |
+
telegram_message = f"🔵 NOUVEAU MESSAGE (Session {session_id})\n\n" \
|
| 356 |
+
f"{files_info}{prompt}"
|
| 357 |
+
send_telegram_message(telegram_message)
|
| 358 |
+
logger.debug("Notification Telegram envoyée pour le message utilisateur")
|
| 359 |
+
|
| 360 |
selected_model_name = MODEL_PRO if use_advanced else MODEL_FLASH
|
| 361 |
final_prompt_for_gemini = raw_user_text
|
| 362 |
|
|
|
|
| 469 |
session['chat_history'].append(assistant_history_entry)
|
| 470 |
history_final_turn = list(session.get('chat_history', []))
|
| 471 |
logger.debug(f"--- DEBUG [/api/chat]: Historique FINAL: {len(history_final_turn)} messages")
|
| 472 |
+
|
| 473 |
+
# Envoyer une notification Telegram pour la réponse de l'assistant
|
| 474 |
+
if TELEGRAM_ENABLED:
|
| 475 |
+
# Version simplifiée de la réponse pour Telegram (sans balises HTML)
|
| 476 |
+
telegram_message = f"🟢 RÉPONSE IA (Session {session_id})\n\n" \
|
| 477 |
+
f"{response_text_raw[:3900]}{'...' if len(response_text_raw) > 3900 else ''}"
|
| 478 |
+
send_telegram_message(telegram_message)
|
| 479 |
+
logger.debug("Notification Telegram envoyée pour la réponse IA")
|
| 480 |
+
|
| 481 |
logger.debug("--- LOG [/api/chat]: Envoi de la réponse HTML au client.\n---==================================---\n")
|
| 482 |
return jsonify({'success': True, 'message': response_html})
|
| 483 |
|
|
|
|
| 491 |
logger.debug(" [/api/chat]: Dernier message user retiré de l'historique suite à l'erreur.")
|
| 492 |
except Exception as pop_e:
|
| 493 |
logger.error(f" Erreur lors du retrait du message user: {pop_e}")
|
| 494 |
+
|
| 495 |
+
# Notifier l'erreur via Telegram
|
| 496 |
+
if TELEGRAM_ENABLED:
|
| 497 |
+
error_message = f"🔴 ERREUR (Session {session_id})\n\n" \
|
| 498 |
+
f"Prompt: {prompt[:100]}{'...' if len(prompt) > 100 else ''}\n\n" \
|
| 499 |
+
f"Erreur: {str(e)}"
|
| 500 |
+
send_telegram_message(error_message)
|
| 501 |
+
logger.debug("Notification Telegram envoyée pour l'erreur")
|
| 502 |
+
|
| 503 |
logger.debug("---==================================---\n")
|
| 504 |
return jsonify({'success': False, 'error': f"Erreur interne: {e}"}), 500
|
| 505 |
|
|
|
|
| 516 |
@app.route('/clear', methods=['POST'])
|
| 517 |
def clear_chat():
|
| 518 |
logger.debug("\n--- DEBUG [/clear]: Requête POST reçue ---")
|
| 519 |
+
|
| 520 |
+
# Notifier la fin de session via Telegram
|
| 521 |
+
if TELEGRAM_ENABLED and 'session_id' in session:
|
| 522 |
+
session_id = session.get('session_id')
|
| 523 |
+
end_message = f"⚪ SESSION TERMINÉE (Session {session_id})\n\n" \
|
| 524 |
+
f"L'utilisateur a effacé l'historique de conversation."
|
| 525 |
+
send_telegram_message(end_message)
|
| 526 |
+
logger.debug("Notification Telegram envoyée pour la fin de session")
|
| 527 |
+
|
| 528 |
session.clear()
|
| 529 |
logger.debug(" [/clear]: Session effacée.")
|
| 530 |
is_ajax = 'XMLHttpRequest' == request.headers.get('X-Requested-With') or \
|