Update app.py
Browse files
app.py
CHANGED
|
@@ -20,6 +20,11 @@ import uvicorn
|
|
| 20 |
import random
|
| 21 |
import docx # لإضافة دعم .docx
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
# ========== تكوين السجلات ==========
|
| 24 |
logging.basicConfig(
|
| 25 |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
@@ -45,7 +50,18 @@ REPO_ID = "Riy777/Study"
|
|
| 45 |
SELECTING_SUBJECT, SELECTING_ACTION, WAITING_FOR_QUESTION = range(3)
|
| 46 |
|
| 47 |
# ========== تطبيق FastAPI ==========
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
# ========== فئة البوت الرئيسية ==========
|
| 51 |
class MedicalLabBot:
|
|
@@ -59,23 +75,32 @@ class MedicalLabBot:
|
|
| 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 |
-
|
| 77 |
-
max_retries = 5 # زيادة إلى 5 محاولات
|
| 78 |
-
retry_delay = 10 # زيادة إلى 10 ثواني
|
| 79 |
|
| 80 |
for attempt in range(max_retries):
|
| 81 |
try:
|
|
@@ -109,7 +134,7 @@ class MedicalLabBot:
|
|
| 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
|
|
@@ -520,7 +545,7 @@ class MedicalLabBot:
|
|
| 520 |
keyboard.append([InlineKeyboardButton(display_name, callback_data=f"subject_{subject}")])
|
| 521 |
|
| 522 |
keyboard.append([InlineKeyboardButton("🔄 تحديث قائمة المواد", callback_data="refresh_materials")])
|
| 523 |
-
keyboard.append([InlineKeyboardButton("❓ مساعدة",
|
| 524 |
return keyboard
|
| 525 |
|
| 526 |
async def handle_subject_selection(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
@@ -783,13 +808,15 @@ class MedicalLabBot:
|
|
| 783 |
bot = MedicalLabBot()
|
| 784 |
|
| 785 |
# ========== دوال FastAPI ==========
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
|
|
|
|
|
|
| 793 |
|
| 794 |
@app.get("/", response_class=HTMLResponse)
|
| 795 |
async def root():
|
|
|
|
| 20 |
import random
|
| 21 |
import docx # لإضافة دعم .docx
|
| 22 |
|
| 23 |
+
# ========== (الحل) إضافة المكتبات اللازمة لحل مشكلة DNS ==========
|
| 24 |
+
import httpx
|
| 25 |
+
import httpx_dnspython
|
| 26 |
+
# ==========================================================
|
| 27 |
+
|
| 28 |
# ========== تكوين السجلات ==========
|
| 29 |
logging.basicConfig(
|
| 30 |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
|
|
| 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)
|
| 65 |
|
| 66 |
# ========== فئة البوت الرئيسية ==========
|
| 67 |
class MedicalLabBot:
|
|
|
|
| 75 |
self.load_all_materials()
|
| 76 |
|
| 77 |
async def initialize_application(self):
|
| 78 |
+
"""تهيئة تطبيق التليجرام بشكل غير متزامن مع حل DNS المخصص"""
|
| 79 |
try:
|
| 80 |
if self.is_initialized:
|
| 81 |
return True
|
| 82 |
|
| 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 = (
|
| 95 |
Application.builder()
|
| 96 |
.token(TELEGRAM_BOT_TOKEN)
|
| 97 |
+
.http_client(custom_client) # <-- تمرير العميل المخصص هنا
|
| 98 |
.build()
|
| 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:
|
|
|
|
| 134 |
logger.info(f"⏳ الانتظار {retry_delay} ثواني قبل إعادة المحاولة...")
|
| 135 |
await asyncio.sleep(retry_delay)
|
| 136 |
else:
|
| 137 |
+
logger.error(f"❌ فشل تهيئة التطبيق نهائياً بعد {max_retries} محاولات (حتى مع DNS المخصص).")
|
| 138 |
|
| 139 |
# فشل بعد كل المحاولات
|
| 140 |
self.is_initialized = False
|
|
|
|
| 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):
|
|
|
|
| 808 |
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():
|