Riy777 commited on
Commit
7117c2a
·
verified ·
1 Parent(s): 60c8394

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -71
app.py CHANGED
@@ -55,51 +55,71 @@ class MedicalLabBot:
55
  self.file_cache = {}
56
  self.application = None
57
  self.is_initialized = False
 
58
  self.load_all_materials()
59
 
60
  async def initialize_application(self):
61
- """تهيئة تطبيق التليجرام بشكل غير متزامن مع محاولات إعادة"""
62
  try:
63
- if not self.application:
64
- logger.info("🔄 جاري تهيئة تطبيق التليجرام...")
65
- self.application = (
66
- Application.builder()
67
- .token(TELEGRAM_BOT_TOKEN)
68
- .build()
69
- )
70
- await self.setup_handlers()
71
-
72
- # ========== !! الحــل !! ==========
73
- # إعادة تفعيل `initialize` مع إضافة محاولات إعادة للتعامل مع أخطاء الشبكة المؤقتة
74
-
75
- max_retries = 3
76
- retry_delay = 5 # ثواني
77
-
78
- for attempt in range(max_retries):
79
- try:
80
- logger.info(f"🚀 محاولة تهيئة الاتصال بـ Telegram (محاولة {attempt + 1}/{max_retries})...")
81
- await self.application.initialize()
82
- self.is_initialized = True
83
- logger.info("✅ تم تهيئة تطبيق التليجرام بنجاح")
84
- return True # نجح، اخرج من الدالة
85
- except Exception as e:
86
- logger.warning(f"⚠️ فشلت محاولة التهيئة {attempt + 1}: {e}")
87
- if attempt < max_retries - 1:
88
- logger.info(f"⏳ الانتظار {retry_delay} ثواني قبل إعادة المحاولة...")
89
- await asyncio.sleep(retry_delay)
90
- else:
91
- logger.error(f"❌ فشل تهيئة التطبيق نهائياً بعد {max_retries} محاولات.")
92
- # لا تطلق الخطأ، فقط سجل الفشل وأكمل
93
- self.is_initialized = False
94
- return False
95
-
96
- # في حالة الفشل بعد كل المحاولات
97
- self.is_initialized = False
98
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  except Exception as e:
101
  logger.error(f"❌ خطأ فادح في تهيئة التطبيق: {e}")
102
  self.is_initialized = False
 
103
  return False
104
 
105
  async def setup_handlers(self):
@@ -765,33 +785,11 @@ bot = MedicalLabBot()
765
  # ========== دوال FastAPI ==========
766
  @app.on_event("startup")
767
  async def on_startup():
768
- """إعداد Webhook عند بدء التشغيل"""
769
- try:
770
- # تهيئة التطبيق أولاً (مع آلية إعادة المحاولة)
771
- success = await bot.initialize_application()
772
-
773
- if not success:
774
- logger.error("❌ فشل في تهيئة التطبيق الأساسي بعد عدة محاولات")
775
- # التطبيق سيعمل، لكن is_initialized ستكون False
776
- return
777
-
778
- if SPACE_URL:
779
- webhook_url = f"{SPACE_URL.rstrip('/')}/telegram"
780
- logger.info(f"ℹ️ جاري إعداد الويب هوك على: {webhook_url}")
781
- await bot.application.bot.set_webhook(
782
- url=webhook_url,
783
- allowed_updates=Update.ALL_TYPES,
784
- drop_pending_updates=True
785
- )
786
- logger.info(f"✅ Webhook set to: {webhook_url}")
787
- else:
788
- logger.warning("⚠️ SPACE_URL not set, using polling instead (if run locally)")
789
-
790
- except Exception as e:
791
- logger.error(f"❌ Error during startup (likely setting webhook): {e}")
792
- # إذا فشل الويب هوك، التطبيق لا يزال "مهيأ" من ناحية الكود
793
- # لكنه لن يستقبل تحديثات
794
- pass
795
 
796
  @app.get("/", response_class=HTMLResponse)
797
  async def root():
@@ -799,6 +797,16 @@ async def root():
799
  materials_count = len(bot.available_materials)
800
  total_files = sum(len(material['files']) for material in bot.available_materials.values())
801
 
 
 
 
 
 
 
 
 
 
 
802
  return f"""
803
  <html>
804
  <head>
@@ -806,7 +814,7 @@ async def root():
806
  <style>
807
  body {{ font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }}
808
  .container {{ max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 15px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }}
809
- .status {{ padding: 20px; background: #f0f8ff; border-radius: 10px; border-left: 5px solid #007bff; }}
810
  h1 {{ color: #2c3e50; text-align: center; }}
811
  ul {{ line-height: 1.8; }}
812
  li {{ margin: 10px 0; }}
@@ -816,8 +824,7 @@ async def root():
816
  <div class="container">
817
  <h1>🏥 بوت المختبرات الطبية الذكي</h1>
818
  <div class="status">
819
- <h2>✅ البوت يعمل</h2>
820
- <p><strong>الحالة:</strong> {'✅ نشط ومهيأ' if bot.is_initialized else '❌ غير مهيأ (فشل الاتصال بـ Telegram)'}</p>
821
  <p><strong>المواد المحملة:</strong> {materials_count} مادة</p>
822
  <p><strong>إجمالي الملفات:</strong> {total_files} ملف</p>
823
  </div>
@@ -843,8 +850,8 @@ async def handle_telegram_update(request: Request):
843
  try:
844
  # التحقق من أن التطبيق مهيأ
845
  if not bot.is_initialized or not bot.application:
846
- logger.error("❌ التطبيق غير مهيأ، لا يمكن معالجة التحديث.")
847
- raise HTTPException(status_code=503, detail="Application not initialized")
848
 
849
  update_data = await request.json()
850
  update = Update.de_json(update_data, bot.application.bot)
@@ -863,10 +870,18 @@ async def health_check():
863
  materials_count = len(bot.available_materials)
864
  total_files = sum(len(material['files']) for material in bot.available_materials.values())
865
 
 
 
 
 
 
 
 
 
866
  return {
867
- "status": "healthy" if bot.is_initialized else "unhealthy",
868
  "service": "medical-lab-bot",
869
- "initialized": bot.is_initialized,
870
  "materials_loaded": materials_count,
871
  "total_files": total_files,
872
  "timestamp": datetime.now().isoformat()
 
55
  self.file_cache = {}
56
  self.application = None
57
  self.is_initialized = False
58
+ self.initialization_status = "pending" # تتبع حالة التهيئة
59
  self.load_all_materials()
60
 
61
  async def initialize_application(self):
62
+ """تهيئة تطبيق التليجرام بشكل غير متزامن مع محاولات إعادة (للتشغيل في الخلفية)"""
63
  try:
64
+ if self.is_initialized:
65
+ return True
66
+
67
+ logger.info("🔄 جاري تهيئة تطبيق التليجرام...")
68
+ self.application = (
69
+ Application.builder()
70
+ .token(TELEGRAM_BOT_TOKEN)
71
+ .build()
72
+ )
73
+ await self.setup_handlers()
74
+
75
+ # ========== !! الحــل !! ==========
76
+ # زيادة المحاولات والتأخير بشكل كبير للتعامل مع بطء شبكة HFS
77
+ max_retries = 5 # زيادة إلى 5 محاولات
78
+ retry_delay = 10 # زيادة إلى 10 ثواني
79
+
80
+ for attempt in range(max_retries):
81
+ try:
82
+ logger.info(f"🚀 محاولة تهيئة الاتصال بـ Telegram (محاولة {attempt + 1}/{max_retries})...")
83
+ # 1. الاتصال بـ Telegram (getMe)
84
+ await self.application.initialize()
85
+ logger.info("✅ تم تهيئة الاتصال بـ Telegram بنجاح.")
86
+
87
+ # 2. ضبط الـ Webhook (فقط بعد نجاح الاتصال)
88
+ if SPACE_URL:
89
+ webhook_url = f"{SPACE_URL.rstrip('/')}/telegram"
90
+ logger.info(f"ℹ️ جاري إعداد الويب هوك على: {webhook_url}")
91
+ await self.application.bot.set_webhook(
92
+ url=webhook_url,
93
+ allowed_updates=Update.ALL_TYPES,
94
+ drop_pending_updates=True
95
+ )
96
+ logger.info(f"✅ Webhook set to: {webhook_url}")
97
+ else:
98
+ logger.warning("⚠️ SPACE_URL not set. Webhook cannot be set.")
99
+
100
+ # 3. ضبط الحالة على "ناجح"
101
+ self.is_initialized = True
102
+ self.initialization_status = "success"
103
+ logger.info("✅✅✅ التطبيق جاهز لاستقبال الطلبات.")
104
+ return True # نجح، اخرج من الدالة
105
+
106
+ except Exception as e:
107
+ logger.warning(f"⚠️ فشلت ��حاولة التهيئة {attempt + 1}: {e}")
108
+ if attempt < max_retries - 1:
109
+ logger.info(f"⏳ الانتظار {retry_delay} ثواني قبل إعادة المحاولة...")
110
+ await asyncio.sleep(retry_delay)
111
+ else:
112
+ logger.error(f"❌ فشل تهيئة التطبيق نهائياً بعد {max_retries} محاولات.")
113
+
114
+ # فشل بعد كل المحاولات
115
+ self.is_initialized = False
116
+ self.initialization_status = "failed"
117
+ return False
118
 
119
  except Exception as e:
120
  logger.error(f"❌ خطأ فادح في تهيئة التطبيق: {e}")
121
  self.is_initialized = False
122
+ self.initialization_status = "failed"
123
  return False
124
 
125
  async def setup_handlers(self):
 
785
  # ========== دوال FastAPI ==========
786
  @app.on_event("startup")
787
  async def on_startup():
788
+ """بدء تشغيل التطبيق وبدء تهيئة البوت في الخلفية"""
789
+ logger.info("🚀 بدء تشغيل FastAPI... بدء مهمة تهيئة البوت في الخلفية.")
790
+ # لا ننتظر (no await) - سيبدأ الخادم فوراً، وستعمل هذه المهمة في الخلفية
791
+ asyncio.create_task(bot.initialize_application())
792
+ logger.info("✅ خادم FastAPI يعمل. التهيئة (الاتصال بـ Telegram) جارية في الخلفية.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
793
 
794
  @app.get("/", response_class=HTMLResponse)
795
  async def root():
 
797
  materials_count = len(bot.available_materials)
798
  total_files = sum(len(material['files']) for material in bot.available_materials.values())
799
 
800
+ # تحديد رسالة الحالة بناءً على حالة التهيئة
801
+ status_message = "⏳ جاري التهيئة (الاتصال بـ Telegram)..."
802
+ status_color = "#ffc107" # أصفر
803
+ if bot.initialization_status == "success":
804
+ status_message = "✅ نشط ومهيأ"
805
+ status_color = "#28a745" # أخضر
806
+ elif bot.initialization_status == "failed":
807
+ status_message = "❌ فشل التهيئة (خطأ في الاتصال بـ Telegram)"
808
+ status_color = "#dc3545" # أحمر
809
+
810
  return f"""
811
  <html>
812
  <head>
 
814
  <style>
815
  body {{ font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }}
816
  .container {{ max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 15px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }}
817
+ .status {{ padding: 20px; background: #f0f8ff; border-radius: 10px; border-left: 5px solid {status_color}; }}
818
  h1 {{ color: #2c3e50; text-align: center; }}
819
  ul {{ line-height: 1.8; }}
820
  li {{ margin: 10px 0; }}
 
824
  <div class="container">
825
  <h1>🏥 بوت المختبرات الطبية الذكي</h1>
826
  <div class="status">
827
+ <h2>حالة البوت: {status_message}</h2>
 
828
  <p><strong>المواد المحملة:</strong> {materials_count} مادة</p>
829
  <p><strong>إجمالي الملفات:</strong> {total_files} ملف</p>
830
  </div>
 
850
  try:
851
  # التحقق من أن التطبيق مهيأ
852
  if not bot.is_initialized or not bot.application:
853
+ logger.error("❌ التطبيق غير مهيأ، لا يمكن معالجة التحديث (ربما لا يزال قيد التهيئة).")
854
+ raise HTTPException(status_code=503, detail="Application not initialized or still initializing")
855
 
856
  update_data = await request.json()
857
  update = Update.de_json(update_data, bot.application.bot)
 
870
  materials_count = len(bot.available_materials)
871
  total_files = sum(len(material['files']) for material in bot.available_materials.values())
872
 
873
+ status = "unhealthy"
874
+ if bot.initialization_status == "pending":
875
+ status = "initializing"
876
+ elif bot.initialization_status == "success":
877
+ status = "healthy"
878
+ elif bot.initialization_status == "failed":
879
+ status = "unhealthy_failed_init"
880
+
881
  return {
882
+ "status": status,
883
  "service": "medical-lab-bot",
884
+ "initialization_status": bot.initialization_status,
885
  "materials_loaded": materials_count,
886
  "total_files": total_files,
887
  "timestamp": datetime.now().isoformat()