Testbot / app.py
Mustafa-albakkar's picture
Update app.py
493a287 verified
Raw
History Blame Contribute Delete
7.15 kB
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) ==================
@asynccontextmanager
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)
@app.post("/webhook")
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)})
@app.get("/")
@app.get("/health")
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)