Spaces:
Runtime error
Runtime error
| import os | |
| import json | |
| import asyncio | |
| import httpx | |
| from fastapi import FastAPI, Request, Response | |
| from fastapi.responses import JSONResponse | |
| from contextlib import asynccontextmanager | |
| import gradio as gr | |
| import uvicorn | |
| # ================== التكوينات ================== | |
| TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") | |
| WORKER_URL = os.getenv("WORKER_URL", "https://your-worker.workers.dev") | |
| if not TOKEN: | |
| raise ValueError("❌ TELEGRAM_BOT_TOKEN غير موجود") | |
| # الرابط الرئيسي لإرسال الطلبات عبر الوكيل الخاص بك | |
| BASE_API_URL = f"{WORKER_URL}/bot{TOKEN}" | |
| # ================== وظائف الاتصال بتيليجرام ================== | |
| async def send_telegram_request(method: str, payload: dict): | |
| """إرسال الطلبات مباشرة إلى واجهة تيليجرام البرمجية عبر الوكيل""" | |
| try: | |
| async with httpx.AsyncClient(timeout=30.0) as client: | |
| url = f"{BASE_API_URL}/{method}" | |
| response = await client.post(url, json=payload) | |
| response.raise_for_status() | |
| return response.json() | |
| except Exception as e: | |
| print(f"❌ خطأ أثناء إرسال الطلب [{method}]: {e}") | |
| return None | |
| def get_main_keyboard(): | |
| """بناء لوحة الأزرار الشفافة بتنسيق ومصفوفات JSON مخصصة""" | |
| return { | |
| "inline_keyboard": [ | |
| [ | |
| {"text": "📚 زر 1 - معلومات", "callback_data": "btn_1"}, | |
| {"text": "💡 زر 2 - نصائح", "callback_data": "btn_2"}, | |
| ], | |
| [ | |
| {"text": "🎯 زر 3 - عروض", "callback_data": "btn_3"}, | |
| ] | |
| ] | |
| } | |
| RESPONSES = { | |
| "btn_1": "📚 هذا رد الزر الأول: معلومات عامة عن البوت.", | |
| "btn_2": "💡 هذا رد الزر الثاني: نصائح مفيدة لتجاوز الحظر.", | |
| "btn_3": "🎯 هذا رد الزر الثالث: عروض حصرية للمستخدمين." | |
| } | |
| # ================== إدارة دورة حياة التطبيق (Lifespan) ================== | |
| async def lifespan(app: FastAPI): | |
| """يتم تشغيل هذا الجزء عند إقلاع الحاوية لربط الـ Webhook فقط دون تهيئة البوت""" | |
| space_host = os.getenv("SPACE_HOST") | |
| if space_host: | |
| # تأخير بسيط لضمان جاهزية شبكة الحاوية للاتصال الخارجي | |
| await asyncio.sleep(2) | |
| webhook_url = f"https://{space_host}/webhook" | |
| print(f"🔄 جاري ضبط الـ Webhook على الرابط: {webhook_url}") | |
| # إرسال طلب ربط الـ Webhook | |
| async with httpx.AsyncClient(timeout=20.0) as client: | |
| try: | |
| url = f"{BASE_API_URL}/setWebhook" | |
| # أضفنا drop_pending_updates لتجاهل الرسائل القديمة المتراكمة أثناء توقف البوت | |
| resp = await client.post(url, json={"url": webhook_url, "drop_pending_updates": True}) | |
| if resp.status_code == 200: | |
| print(f"✅ تم ضبط الـ Webhook بنجاح: {resp.text}") | |
| else: | |
| print(f"⚠️ فشل ضبط Webhook (خطأ HTTP {resp.status_code}): {resp.text}") | |
| except Exception as e: | |
| # استخدام repr(e) لطباعة التفاصيل الدقيقة للخطأ إذا حدث | |
| print(f"⚠️ تحذير: تعذر ضبط الـ Webhook: {repr(e)}") | |
| yield | |
| # ================== إنشاء تطبيق FastAPI ================== | |
| app = FastAPI(title="Telegram Bot with Gradio Dashboard", lifespan=lifespan) | |
| async def webhook(request: Request): | |
| """استقبال التحديثات مباشرة من تيليجرام ومعالجتها فورياً كـ JSON""" | |
| try: | |
| data = await request.json() | |
| # 1. معالجة الرسائل النصية العادية (مثل أمر /start) | |
| if "message" in data: | |
| message = data["message"] | |
| chat_id = message["chat"]["id"] | |
| text = message.get("text", "") | |
| if text == "/start": | |
| welcome_text = "👋 <b>مرحباً بك في البوت!</b>\n\nاختر أحد الأزرار أدناه:" | |
| payload = { | |
| "chat_id": chat_id, | |
| "text": welcome_text, | |
| "parse_mode": "HTML", | |
| "reply_markup": get_main_keyboard() | |
| } | |
| # تشغيل المهمة بالخلفية لسرعة استجابة السيرفر الـ Webhook | |
| asyncio.create_task(send_telegram_request("sendMessage", payload)) | |
| # 2. معالجة النقرات على الأزرار الشفافة (Callback Queries) | |
| elif "callback_query" in data: | |
| callback_query = data["callback_query"] | |
| callback_id = callback_query["id"] | |
| chat_id = callback_query["message"]["chat"]["id"] | |
| callback_data = callback_query.get("data", "") | |
| # إخطار تيليجرام باستلام النقرة لإيقاف مؤشر التحميل على الزر | |
| asyncio.create_task(send_telegram_request("answerCallbackQuery", {"callback_query_id": callback_id})) | |
| # جلب النص المقابل للزر وإرساله | |
| response_text = RESPONSES.get(callback_data, "⚠️ زر غير معروف") | |
| payload = { | |
| "chat_id": chat_id, | |
| "text": response_text, | |
| "parse_mode": "HTML", | |
| "reply_markup": get_main_keyboard() | |
| } | |
| asyncio.create_task(send_telegram_request("sendMessage", payload)) | |
| return Response(status_code=200) | |
| except Exception as e: | |
| print(f"❌ خطأ داخلي في معالجة الـ Webhook: {e}") | |
| return JSONResponse(status_code=500, content={"error": str(e)}) | |
| async def health(): | |
| return {"status": "healthy", "bot": "running", "proxy_url": WORKER_URL} | |
| # ================== إنشاء واجهة Gradio ================== | |
| def create_gradio_interface(): | |
| with gr.Blocks(title="🤖 Telegram Bot Dashboard") as demo: | |
| gr.Markdown("# 🤖 Telegram Bot Dashboard") | |
| gr.Markdown(f"**الوكيل المستخدم:** `{WORKER_URL}`") | |
| gr.Markdown("**حالة النظام:** 🟢 يعمل بثبات وبدون تهيئة معقدة") | |
| return demo | |
| gradio_app = create_gradio_interface() | |
| # دمج واجهة وبوابات Gradio مع FastAPI في المسار الفرعي /gradio | |
| app = gr.mount_gradio_app(app, gradio_app, path="/gradio") | |
| # ================== تشغيل خادم التطبيق ================== | |
| #if __name__ == "__main__": | |
| # print("🚀 تشغيل السيرفر الرئيسي على المنفذ 7860...") | |
| # uvicorn.run(app, host="0.0.0.0", port=7860) | |