Riy777 commited on
Commit
b12e196
·
verified ·
1 Parent(s): 3133e36

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -23
app.py CHANGED
@@ -20,9 +20,10 @@ import uvicorn
20
  import random
21
  import docx # لإضافة دعم .docx
22
 
23
- # ========== (الحل) إضافة المكتبات اللازمة لحل مشكلة DNS ==========
24
  import httpx
25
- import httpx_dnspython
 
26
  # ==========================================================
27
 
28
  # ========== تكوين السجلات ==========
@@ -49,16 +50,58 @@ REPO_ID = "Riy777/Study"
49
  # ========== حالات المحادثة ==========
50
  SELECTING_SUBJECT, SELECTING_ACTION, WAITING_FOR_QUESTION = range(3)
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  # ========== تطبيق FastAPI ==========
53
- # تعديل: استخدام lifespan بدلاً من on_event
54
  @asyncio.contextmanager
55
  async def lifespan(app: FastAPI):
56
- # الكود الذي كان في on_startup
57
  logger.info("🚀 بدء تشغيل FastAPI... بدء مهمة تهيئة البوت في الخلفية.")
58
  asyncio.create_task(bot.initialize_application())
59
  logger.info("✅ خادم FastAPI يعمل. التهيئة (الاتصال بـ Telegram) جارية في الخلفية.")
60
  yield
61
- # كود إيقاف التشغيل (on_shutdown) (إن وجد)
62
  logger.info("🛑 إيقاف تشغيل خادم FastAPI.")
63
 
64
  app = FastAPI(title="Medical Lab Bot", version="1.0.0", lifespan=lifespan)
@@ -83,12 +126,9 @@ class MedicalLabBot:
83
  logger.info("🔄 جاري تهيئة تطبيق التليجرام...")
84
 
85
  # ========== !! الحل الجذري (DNS) !! ==========
86
- logger.info("🔧 إعداد عميل HTTP مخصص مع DNS (1.1.1.1)...")
87
- transport = httpx_dnspython.AsyncDNSTransport(
88
- resolver=httpx_dnspython.SyncResolver(nameservers=["1.1.1.1", "8.8.8.8"])
89
- )
90
- # نستخدم httpx.AsyncClient مع الناقل المخصص
91
- custom_client = httpx.AsyncClient(transport=transport)
92
  # ============================================
93
 
94
  self.application = (
@@ -99,8 +139,8 @@ class MedicalLabBot:
99
  )
100
  await self.setup_handlers()
101
 
102
- max_retries = 3 # تقليل المحاولات لأن المشكلة يفترض أن تُحل
103
- retry_delay = 5 # تقليل التأخير
104
 
105
  for attempt in range(max_retries):
106
  try:
@@ -545,7 +585,7 @@ class MedicalLabBot:
545
  keyboard.append([InlineKeyboardButton(display_name, callback_data=f"subject_{subject}")])
546
 
547
  keyboard.append([InlineKeyboardButton("🔄 تحديث قائمة المواد", callback_data="refresh_materials")])
548
- keyboard.append([InlineKeyboardButton("❓ مساعدة", callback_Ddata="general_help")])
549
  return keyboard
550
 
551
  async def handle_subject_selection(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -809,15 +849,6 @@ bot = MedicalLabBot()
809
 
810
  # ========== دوال FastAPI ==========
811
 
812
- # تم نقل @app.on_event("startup") إلى تعريف "lifespan"
813
- # @app.on_event("startup")
814
- # async def on_startup():
815
- # """بدء تشغيل التطبيق وبدء تهيئة البوت في الخلفية"""
816
- # logger.info("🚀 بدء تشغيل FastAPI... بدء مهمة تهيئة البوت في الخلفية.")
817
- # # لا ننتظر (no await) - سيبدأ الخادم فوراً، وستعمل هذه المهمة في الخلفية
818
- # asyncio.create_task(bot.initialize_application())
819
- # logger.info("✅ خادم FastAPI يعمل. التهيئة (الاتصال بـ Telegram) جارية في الخلفية.")
820
-
821
  @app.get("/", response_class=HTMLResponse)
822
  async def root():
823
  """الصفحة الرئيسية"""
 
20
  import random
21
  import docx # لإضافة دعم .docx
22
 
23
+ # ========== (الحل) إضافة المكتبات الصحيحة لحل مشكلة DNS ==========
24
  import httpx
25
+ import dns.asyncresolver
26
+ from httpx import AsyncClient, AsyncHTTPTransport, Request, Response
27
  # ==========================================================
28
 
29
  # ========== تكوين السجلات ==========
 
50
  # ========== حالات المحادثة ==========
51
  SELECTING_SUBJECT, SELECTING_ACTION, WAITING_FOR_QUESTION = range(3)
52
 
53
+
54
+ # ========== (الحل) فئة الناقل المخصص للـ DNS ==========
55
+ class CustomDNSTransport(AsyncHTTPTransport):
56
+ def __init__(self, *args, **kwargs):
57
+ super().__init__(*args, **kwargs)
58
+ self.resolver = dns.asyncresolver.Resolver()
59
+ self.resolver.nameservers = ['1.1.1.1', '8.8.8.8']
60
+ logger.info("🔧 CustomDNSTransport initialized with 1.1.1.1 and 8.8.8.8")
61
+
62
+ async def handle_async_request(self, request: Request) -> Response:
63
+ try:
64
+ host = request.url.host
65
+
66
+ # التحقق إذا كان Host هو أصلاً IP
67
+ is_ip = True
68
+ try:
69
+ parts = host.split('.')
70
+ if len(parts) != 4 or not all(p.isdigit() for p in parts):
71
+ is_ip = False
72
+ except Exception:
73
+ is_ip = False
74
+
75
+ if is_ip:
76
+ logger.info(f"Host {host} is already an IP. Skipping resolution.")
77
+ else:
78
+ logger.info(f"🔧 Resolving host: {host}")
79
+ result = await self.resolver.resolve(host, 'A')
80
+ ip = result[0].address
81
+ logger.info(f"✅ Resolved {host} to {ip}")
82
+
83
+ # تعيين SNI (مهم جداً لـ SSL/HTTPS)
84
+ request.extensions["sni_hostname"] = host
85
+ # تحديث الـ URL لاستخدام الـ IP
86
+ request.url = request.url.copy_with(host=ip)
87
+
88
+ except Exception as e:
89
+ logger.error(f"❌ DNS resolution failed for {host}: {e}. Trying request with original host...")
90
+ # إذا فشل الحل، اسمح للطلب بالاستمرار مع اسم المضيف الأصلي
91
+ pass
92
+
93
+ # استدعاء المعالج الأصلي (الأب) لإكمال الطلب
94
+ return await super().handle_async_request(request)
95
+ # ==========================================================
96
+
97
+
98
  # ========== تطبيق FastAPI ==========
 
99
  @asyncio.contextmanager
100
  async def lifespan(app: FastAPI):
 
101
  logger.info("🚀 بدء تشغيل FastAPI... بدء مهمة تهيئة البوت في الخلفية.")
102
  asyncio.create_task(bot.initialize_application())
103
  logger.info("✅ خادم FastAPI يعمل. التهيئة (الاتصال بـ Telegram) جارية في الخلفية.")
104
  yield
 
105
  logger.info("🛑 إيقاف تشغيل خادم FastAPI.")
106
 
107
  app = FastAPI(title="Medical Lab Bot", version="1.0.0", lifespan=lifespan)
 
126
  logger.info("🔄 جاري تهيئة تطبيق التليجرام...")
127
 
128
  # ========== !! الحل الجذري (DNS) !! ==========
129
+ logger.info("🔧 إعداد عميل HTTP مخصص مع CustomDNSTransport...")
130
+ custom_transport = CustomDNSTransport()
131
+ custom_client = httpx.AsyncClient(transport=custom_transport)
 
 
 
132
  # ============================================
133
 
134
  self.application = (
 
139
  )
140
  await self.setup_handlers()
141
 
142
+ max_retries = 3
143
+ retry_delay = 5
144
 
145
  for attempt in range(max_retries):
146
  try:
 
585
  keyboard.append([InlineKeyboardButton(display_name, callback_data=f"subject_{subject}")])
586
 
587
  keyboard.append([InlineKeyboardButton("🔄 تحديث قائمة المواد", callback_data="refresh_materials")])
588
+ keyboard.append([InlineKeyboardButton("❓ مساعدة", callback_data="general_help")])
589
  return keyboard
590
 
591
  async def handle_subject_selection(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
 
849
 
850
  # ========== دوال FastAPI ==========
851
 
 
 
 
 
 
 
 
 
 
852
  @app.get("/", response_class=HTMLResponse)
853
  async def root():
854
  """الصفحة الرئيسية"""