Docfile commited on
Commit
b86a175
·
verified ·
1 Parent(s): 3b3892b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -362
app.py CHANGED
@@ -2,20 +2,13 @@ from flask import Flask, request, render_template, jsonify
2
  import PIL.Image
3
  from google import genai
4
  from google.genai import types
5
- import telebot
 
6
  import os
7
  from tempfile import NamedTemporaryFile
8
  import tempfile
9
- from datetime import datetime
10
- import logging
11
- import time
12
-
13
  app = Flask(__name__)
14
 
15
- # Configuration du logging pour débugger
16
- logging.basicConfig(level=logging.DEBUG)
17
- logger = logging.getLogger(__name__)
18
-
19
  # Configuration de Gemini
20
  generation_config = {
21
  "temperature": 1,
@@ -41,238 +34,22 @@ safety_settings = [
41
  ),
42
  ]
43
 
44
- # Configuration des tokens et IDs
45
  GOOGLE_API_KEY = os.environ.get("TOKEN")
46
- TELEGRAM_BOT_TOKEN = "8180304240:AAGJZ_MJ6eKtbymxkqzjgOJCr6PWb7uas9U"
47
- TELEGRAM_CHAT_ID = "-4972732072"
48
 
49
  gen = GOOGLE_API_KEY
50
  client = genai.Client(api_key=gen)
51
 
52
- # Initialisation du bot Telegram avec options avancées
53
- try:
54
- bot = telebot.TeleBot(
55
- TELEGRAM_BOT_TOKEN,
56
- parse_mode='HTML',
57
- disable_web_page_preview=True,
58
- timeout=60, # Timeout plus long
59
- num_threads=2 # Utiliser plusieurs threads
60
- )
61
- logger.info("Bot Telegram initialisé avec succès")
62
- except Exception as e:
63
- logger.error(f"Erreur initialisation bot: {e}")
64
- bot = None
65
-
66
- def send_image_to_telegram(image_path, caption="", max_retries=3):
67
- """Envoie une image vers le groupe Telegram avec pyTelegramBotAPI."""
68
- if not bot:
69
- return False, "Bot Telegram non initialisé"
70
-
71
- try:
72
- # Vérifications de base
73
- if not os.path.exists(image_path):
74
- logger.error(f"Le fichier {image_path} n'existe pas")
75
- return False, f"Le fichier {image_path} n'existe pas"
76
-
77
- file_size = os.path.getsize(image_path)
78
- if file_size > 50 * 1024 * 1024: # 50MB limite pour les documents
79
- logger.error(f"Fichier trop volumineux: {file_size} bytes")
80
- return False, f"Fichier trop volumineux: {file_size} bytes (limite: 50MB)"
81
-
82
- if file_size == 0:
83
- logger.error(f"Fichier vide: {image_path}")
84
- return False, f"Fichier vide: {image_path}"
85
-
86
- logger.info(f"Envoi de l'image: {image_path} (taille: {file_size} bytes)")
87
-
88
- # Tentatives d'envoi avec retry automatique
89
- for attempt in range(max_retries):
90
- try:
91
- logger.info(f"Tentative {attempt + 1}/{max_retries}")
92
-
93
- with open(image_path, 'rb') as photo:
94
- # Si le fichier est < 10MB, l'envoyer comme photo
95
- if file_size < 10 * 1024 * 1024:
96
- message = bot.send_photo(
97
- chat_id=TELEGRAM_CHAT_ID,
98
- photo=photo,
99
- caption=caption[:1024] if caption else "",
100
- timeout=120
101
- )
102
- else:
103
- # Sinon l'envoyer comme document
104
- message = bot.send_document(
105
- chat_id=TELEGRAM_CHAT_ID,
106
- document=photo,
107
- caption=caption[:1024] if caption else "",
108
- timeout=120
109
- )
110
-
111
- logger.info(f"✅ Image envoyée avec succès (Message ID: {message.message_id})")
112
- return True, f"Image envoyée avec succès (tentative {attempt + 1})"
113
-
114
- except telebot.apihelper.ApiTelegramException as e:
115
- logger.error(f"Erreur API Telegram (tentative {attempt + 1}): {e}")
116
- if attempt == max_retries - 1: # Dernière tentative
117
- return False, f"Erreur API Telegram après {max_retries} tentatives: {str(e)}"
118
- time.sleep(2 ** attempt) # Backoff exponentiel
119
-
120
- except Exception as e:
121
- logger.error(f"Erreur inattendue (tentative {attempt + 1}): {e}")
122
- if attempt == max_retries - 1:
123
- return False, f"Erreur inattendue après {max_retries} tentatives: {str(e)}"
124
- time.sleep(2 ** attempt)
125
-
126
- return False, f"Échec après {max_retries} tentatives"
127
-
128
- except Exception as e:
129
- logger.error(f"Erreur critique lors de l'envoi: {str(e)}")
130
- return False, f"Erreur critique: {str(e)}"
131
-
132
- def send_message_to_telegram(message, max_retries=3):
133
- """Envoie un message texte vers le groupe Telegram."""
134
- if not bot:
135
- return False, "Bot Telegram non initialisé"
136
-
137
- try:
138
- # Diviser le message s'il est trop long (limite Telegram: 4096 caractères)
139
- max_length = 4000 # On garde une marge
140
- messages = []
141
-
142
- if len(message) <= max_length:
143
- messages = [message]
144
- else:
145
- # Diviser le message en chunks
146
- for i in range(0, len(message), max_length):
147
- chunk = message[i:i + max_length]
148
- messages.append(chunk)
149
-
150
- # Envoyer chaque partie
151
- for i, msg_part in enumerate(messages):
152
- for attempt in range(max_retries):
153
- try:
154
- logger.info(f"Envoi message partie {i + 1}/{len(messages)} (tentative {attempt + 1})")
155
-
156
- sent_message = bot.send_message(
157
- chat_id=TELEGRAM_CHAT_ID,
158
- text=msg_part,
159
- parse_mode='HTML',
160
- timeout=60
161
- )
162
-
163
- logger.info(f"✅ Message partie {i + 1} envoyé (ID: {sent_message.message_id})")
164
- break # Sortir de la boucle de retry si réussi
165
-
166
- except telebot.apihelper.ApiTelegramException as e:
167
- logger.error(f"Erreur API Telegram partie {i + 1} (tentative {attempt + 1}): {e}")
168
- if attempt == max_retries - 1:
169
- return False, f"Erreur API après {max_retries} tentatives: {str(e)}"
170
- time.sleep(2 ** attempt)
171
-
172
- except Exception as e:
173
- logger.error(f"Erreur inattendue partie {i + 1} (tentative {attempt + 1}): {e}")
174
- if attempt == max_retries - 1:
175
- return False, f"Erreur inattendue après {max_retries} tentatives: {str(e)}"
176
- time.sleep(2 ** attempt)
177
-
178
- return True, f"Message envoyé avec succès ({len(messages)} partie(s))"
179
-
180
- except Exception as e:
181
- logger.error(f"Erreur critique envoi message: {str(e)}")
182
- return False, f"Erreur critique: {str(e)}"
183
-
184
- def test_bot_permissions():
185
- """Teste les permissions du bot dans le groupe."""
186
- if not bot:
187
- return False, "Bot Telegram non initialisé"
188
-
189
- try:
190
- logger.info("Test des permissions du bot...")
191
-
192
- # Obtenir les informations du chat
193
- chat = bot.get_chat(TELEGRAM_CHAT_ID)
194
- logger.info(f"Chat trouvé: {chat.title if hasattr(chat, 'title') else 'Chat privé'}")
195
-
196
- # Obtenir les informations du bot
197
- bot_info = bot.get_me()
198
- logger.info(f"Bot: @{bot_info.username} ({bot_info.first_name})")
199
-
200
- # Tester l'envoi d'un message simple
201
- test_message = bot.send_message(
202
- chat_id=TELEGRAM_CHAT_ID,
203
- text="🔧 Test de permissions réussi",
204
- timeout=30
205
- )
206
-
207
- return True, f"Bot @{bot_info.username} autorisé dans '{chat.title if hasattr(chat, 'title') else 'le chat'}'"
208
-
209
- except telebot.apihelper.ApiTelegramException as e:
210
- logger.error(f"Erreur API lors du test: {e}")
211
- return False, f"Erreur API Telegram: {str(e)}"
212
- except Exception as e:
213
- logger.error(f"Erreur lors du test des permissions: {str(e)}")
214
- return False, f"Erreur: {str(e)}"
215
-
216
- def get_bot_status():
217
- """Obtient le statut du bot et des connexions."""
218
- status = {
219
- "bot_initialized": bot is not None,
220
- "bot_info": None,
221
- "chat_info": None,
222
- "api_accessible": False
223
- }
224
-
225
- if bot:
226
- try:
227
- # Informations du bot
228
- bot_info = bot.get_me()
229
- status["bot_info"] = {
230
- "username": bot_info.username,
231
- "first_name": bot_info.first_name,
232
- "id": bot_info.id,
233
- "is_bot": bot_info.is_bot
234
- }
235
- status["api_accessible"] = True
236
-
237
- # Informations du chat
238
- try:
239
- chat = bot.get_chat(TELEGRAM_CHAT_ID)
240
- status["chat_info"] = {
241
- "id": chat.id,
242
- "type": chat.type,
243
- "title": getattr(chat, 'title', 'N/A'),
244
- "member_count": getattr(chat, 'member_count', 'N/A')
245
- }
246
- except Exception as e:
247
- status["chat_error"] = str(e)
248
-
249
- except Exception as e:
250
- status["bot_error"] = str(e)
251
-
252
- return status
253
-
254
- # Routes Flask
255
- @app.route('/bot_status', methods=['GET'])
256
- def bot_status():
257
- """Route pour obtenir le statut du bot."""
258
- return jsonify(get_bot_status())
259
-
260
- @app.route('/test_bot_permissions', methods=['GET'])
261
- def test_bot_permissions_route():
262
- """Route pour tester les permissions du bot."""
263
- success, message = test_bot_permissions()
264
- return jsonify({
265
- "success": success,
266
- "message": message,
267
- "bot_status": get_bot_status()
268
- })
269
 
270
  @app.route('/', methods=['GET'])
271
  def svt():
272
  """Renders the SVT page."""
273
  return render_template("svt.html")
274
 
 
275
  methodologie_svt = {
 
276
  "Restitution organisée des connaissances": """
277
  **Restitution organisée des connaissances (ROC)**
278
 
@@ -301,6 +78,8 @@ methodologie_svt = {
301
  * L'exercice est pondéré sur 7 à 8 points.
302
  """,
303
  "Exploitation du document": """
 
 
304
  **Exploitation de documents (ED)**
305
 
306
  **Objectif:** Trouver le lien entre les informations présentées par un des documents et les connaissances d'un segment de connaissances (partie du programme) en vue de la résolution d'un problème scientifique.
@@ -325,6 +104,7 @@ methodologie_svt = {
325
  * La tâche 4 (CP4) est spécifique à cet exercice.
326
  * Mentionner le document traité (ex: Document 1).
327
 
 
328
  réponse attendu uniquement en langue française.
329
  """,
330
  "Synthèse": """
@@ -354,159 +134,46 @@ réponse attendu uniquement en langue française.
354
  """
355
  }
356
 
 
357
  @app.route('/svt_submit', methods=['POST'])
358
  def svt_submit():
359
  """Handles the submission of SVT exercises."""
360
  option = request.form.get('option')
361
  images = request.files.getlist('images')
362
 
363
- logger.info(f"Traitement d'un exercice SVT: {option}")
364
- logger.info(f"Nombre d'images reçues: {len(images)}")
365
-
366
  content = [f"J'aimerais que tu traites entièrement cet exercice en respectant scrupuleusement la méthodologie d'SVT suivante :\n\n{methodologie_svt[option]}\n\nLe type d'exercice selon la méthodologie est : {option}. Voici les images de l'exercice:"]
367
  temp_files = []
368
- telegram_results = []
369
 
370
  try:
371
- # Test du statut du bot avant traitement
372
- bot_status = get_bot_status()
373
- logger.info(f"Statut du bot: {bot_status}")
374
-
375
- # Traitement des images
376
- for i, image in enumerate(images):
377
- if image and image.filename:
378
- logger.info(f"Traitement de l'image {i+1}: {image.filename}")
379
-
380
- # Créer un fichier temporaire avec l'extension correcte
381
- file_extension = os.path.splitext(image.filename)[1].lower()
382
- if not file_extension:
383
- file_extension = '.jpg' # Extension par défaut
384
-
385
- with tempfile.NamedTemporaryFile(delete=False, suffix=file_extension) as temp_file:
386
- # Sauvegarder l'image
387
  image.save(temp_file.name)
388
  temp_files.append(temp_file.name)
389
-
390
- # Vérifier que l'image a été sauvegardée correctement
391
- if os.path.getsize(temp_file.name) > 0:
392
- logger.info(f"Image sauvegardée: {temp_file.name} ({os.path.getsize(temp_file.name)} bytes)")
393
-
394
- # Ajouter l'image au contenu pour Gemini
395
- try:
396
- pil_image = PIL.Image.open(temp_file.name)
397
- content.append(pil_image)
398
- logger.info(f"Image ajoutée au contenu Gemini: {pil_image.size}")
399
- except Exception as e:
400
- logger.error(f"Erreur lors de l'ouverture de l'image pour Gemini: {e}")
401
-
402
- # Envoi de l'image vers Telegram
403
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
404
- caption = f"📚 Exercice SVT - {option}\n🕐 {timestamp}\n📄 Image {i+1}/{len([img for img in images if img.filename])}"
405
-
406
- logger.info(f"Tentative d'envoi vers Telegram: {temp_file.name}")
407
- success, message = send_image_to_telegram(temp_file.name, caption)
408
- telegram_results.append({
409
- 'image': f"Image {i+1} - {image.filename}",
410
- 'success': success,
411
- 'message': message
412
- })
413
-
414
- if success:
415
- logger.info(f"✅ Image {i+1} envoyée avec succès")
416
- else:
417
- logger.error(f"❌ Échec envoi image {i+1}: {message}")
418
- else:
419
- logger.error(f"Fichier temporaire vide pour l'image {i+1}")
420
- telegram_results.append({
421
- 'image': f"Image {i+1} - {image.filename}",
422
- 'success': False,
423
- 'message': "Fichier temporaire vide"
424
- })
425
-
426
- logger.info(f"Résultats Telegram: {telegram_results}")
427
-
428
- # Génération de la réponse avec Gemini
429
- logger.info("Génération de la réponse avec Gemini...")
430
  response = client.models.generate_content(
431
  model="gemini-2.5-flash",
432
  contents=[content],
433
- config=types.GenerateContentConfig(
434
- safety_settings=safety_settings,
435
- )
 
436
  )
437
-
438
  answer = response.candidates[0].content.parts[0].text
439
- logger.info("Réponse générée avec succès")
440
-
441
- # Envoi de la réponse vers Telegram
442
- telegram_message = f"🤖 <b>Réponse générée</b>\n\n📝 <b>Type:</b> {option}\n\n{answer}"
443
- msg_success, msg_message = send_message_to_telegram(telegram_message)
444
- logger.info(f"Envoi réponse Telegram: {msg_success} - {msg_message}")
445
-
446
- return jsonify({
447
- "response": answer,
448
- "telegram_status": telegram_results,
449
- "bot_status": bot_status,
450
- "response_sent": {"success": msg_success, "message": msg_message}
451
- })
452
 
453
  except Exception as e:
454
- logger.error(f"Erreur lors du traitement: {str(e)}")
455
- error_message = f"❌ <b>Erreur lors du traitement</b>\n\n🔍 <b>Type:</b> {option}\n💥 <b>Erreur:</b> {str(e)}"
456
- send_message_to_telegram(error_message)
457
-
458
- return jsonify({
459
- "error": "Erreur lors du traitement",
460
- "details": str(e),
461
- "telegram_status": telegram_results,
462
- "bot_status": get_bot_status()
463
- }), 500
464
-
465
  finally:
466
- # Nettoyage des fichiers temporaires
467
  for temp_file in temp_files:
468
  try:
469
- if os.path.exists(temp_file):
470
- os.unlink(temp_file)
471
- logger.info(f"Fichier temporaire supprimé: {temp_file}")
472
  except Exception as e:
473
- logger.error(f"Erreur lors de la suppression du fichier {temp_file}: {e}")
474
-
475
- @app.route('/test_telegram', methods=['GET'])
476
- def test_telegram():
477
- """Route pour tester la connexion Telegram."""
478
- success, message = send_message_to_telegram("🧪 Test de connexion du bot SVT avec pyTelegramBotAPI")
479
- return jsonify({
480
- "success": success,
481
- "message": message,
482
- "bot_status": get_bot_status()
483
- })
484
-
485
- @app.route('/debug_telegram', methods=['GET'])
486
- def debug_telegram():
487
- """Route pour débugger les problèmes Telegram."""
488
- results = {}
489
-
490
- # Test 1: Statut du bot
491
- results['bot_status'] = get_bot_status()
492
-
493
- # Test 2: Permissions du bot
494
- perm_success, perm_message = test_bot_permissions()
495
- results['permissions'] = {"success": perm_success, "message": perm_message}
496
-
497
- # Test 3: Envoi d'un message simple
498
- msg_success, msg_message = send_message_to_telegram("🔧 Test de débogage avec pyTelegramBotAPI")
499
- results['message_test'] = {"success": msg_success, "message": msg_message}
500
-
501
- # Test 4: Vérification des variables d'environnement
502
- results['config'] = {
503
- "bot_token_set": bool(TELEGRAM_BOT_TOKEN),
504
- "chat_id_set": bool(TELEGRAM_CHAT_ID),
505
- "bot_token_format": TELEGRAM_BOT_TOKEN.startswith("8180304240:") if TELEGRAM_BOT_TOKEN else False,
506
- "chat_id_format": TELEGRAM_CHAT_ID.startswith("-") if TELEGRAM_CHAT_ID else False
507
- }
508
-
509
- return jsonify(results)
510
-
511
- if __name__ == '__main__':
512
- app.run(debug=True)
 
2
  import PIL.Image
3
  from google import genai
4
  from google.genai import types
5
+
6
+
7
  import os
8
  from tempfile import NamedTemporaryFile
9
  import tempfile
 
 
 
 
10
  app = Flask(__name__)
11
 
 
 
 
 
12
  # Configuration de Gemini
13
  generation_config = {
14
  "temperature": 1,
 
34
  ),
35
  ]
36
 
 
37
  GOOGLE_API_KEY = os.environ.get("TOKEN")
38
+
39
+ #genai.configure(api_key=GOOGLE_API_KEY)
40
 
41
  gen = GOOGLE_API_KEY
42
  client = genai.Client(api_key=gen)
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
  @app.route('/', methods=['GET'])
46
  def svt():
47
  """Renders the SVT page."""
48
  return render_template("svt.html")
49
 
50
+
51
  methodologie_svt = {
52
+
53
  "Restitution organisée des connaissances": """
54
  **Restitution organisée des connaissances (ROC)**
55
 
 
78
  * L'exercice est pondéré sur 7 à 8 points.
79
  """,
80
  "Exploitation du document": """
81
+
82
+
83
  **Exploitation de documents (ED)**
84
 
85
  **Objectif:** Trouver le lien entre les informations présentées par un des documents et les connaissances d'un segment de connaissances (partie du programme) en vue de la résolution d'un problème scientifique.
 
104
  * La tâche 4 (CP4) est spécifique à cet exercice.
105
  * Mentionner le document traité (ex: Document 1).
106
 
107
+
108
  réponse attendu uniquement en langue française.
109
  """,
110
  "Synthèse": """
 
134
  """
135
  }
136
 
137
+
138
  @app.route('/svt_submit', methods=['POST'])
139
  def svt_submit():
140
  """Handles the submission of SVT exercises."""
141
  option = request.form.get('option')
142
  images = request.files.getlist('images')
143
 
 
 
 
144
  content = [f"J'aimerais que tu traites entièrement cet exercice en respectant scrupuleusement la méthodologie d'SVT suivante :\n\n{methodologie_svt[option]}\n\nLe type d'exercice selon la méthodologie est : {option}. Voici les images de l'exercice:"]
145
  temp_files = []
 
146
 
147
  try:
148
+ for image in images:
149
+ if image:
150
+ with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(image.filename)[1]) as temp_file:
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  image.save(temp_file.name)
152
  temp_files.append(temp_file.name)
153
+ content.append(PIL.Image.open(temp_file.name))
154
+
155
+ #model = genai.GenerativeModel(model_name="models/gemini-2.5-flash-preview-04-17", safety_settings=safety_settings)
156
+ #response = model.generate_content(content, request_options={"timeout": 600})
157
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  response = client.models.generate_content(
159
  model="gemini-2.5-flash",
160
  contents=[content],
161
+ config=types.GenerateContentConfig(
162
+ safety_settings=safety_settings,
163
+
164
+ )
165
  )
166
+
167
  answer = response.candidates[0].content.parts[0].text
168
+
169
+
170
+ return jsonify({"response": response.text})
 
 
 
 
 
 
 
 
 
 
171
 
172
  except Exception as e:
173
+ return jsonify({"error": "erreur"}), 500
 
 
 
 
 
 
 
 
 
 
174
  finally:
 
175
  for temp_file in temp_files:
176
  try:
177
+ os.unlink(temp_file)
 
 
178
  except Exception as e:
179
+ print(f"Error deleting temporary file {temp_file}: {e}")