qrkodbot / app.py
ibrohm's picture
Upload app.py with huggingface_hub
54b53dc verified
"""
Hugging Face Spaces uchun Webhook rejimidagi Telegram Bot
aiodns + custom DNS resolver (8.8.8.8) ishlatiladi
"""
import logging
import sys
import os
from fastapi import FastAPI, Request
from fastapi.responses import Response, RedirectResponse, HTMLResponse
from aiogram import Bot, Dispatcher
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.default import DefaultBotProperties
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.enums import ParseMode
from aiogram.types import Update
import aiohttp
from aiohttp.resolver import AsyncResolver
from config import BOT_TOKEN
from services.db import init_db
# Handlerlar
from handlers import start, generate, read_qr, settings, batch, history, inline, admin, dynamic
# Logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
stream=sys.stdout,
)
logger = logging.getLogger("app")
# Custom DNS resolver bilan aiohttp session yaratish
session = AiohttpSession()
resolver = AsyncResolver(nameservers=["8.8.8.8", "8.8.4.4"])
# aiogram 3.x uchun resolver ni init orqali beramiz
session._connector_init["resolver"] = resolver
bot = Bot(
token=BOT_TOKEN,
default=DefaultBotProperties(parse_mode=ParseMode.HTML),
session=session,
)
dp = Dispatcher(storage=MemoryStorage())
dp.include_router(admin.router)
dp.include_router(start.router)
dp.include_router(generate.router)
dp.include_router(settings.router)
dp.include_router(batch.router)
dp.include_router(history.router)
dp.include_router(inline.router)
dp.include_router(read_qr.router)
dp.include_router(dynamic.router)
# FastAPI
app = FastAPI(title="QR Bot Webhook Service")
SPACE_HOST = os.environ.get("SPACE_HOST", "ibrohm-qrkodbot.hf.space")
WEBHOOK_PATH = f"/webhook/{BOT_TOKEN}"
WEBHOOK_URL = f"https://{SPACE_HOST}{WEBHOOK_PATH}"
@app.on_event("startup")
async def on_startup():
await init_db()
logger.info("[OK] Database tayyor")
try:
await bot.set_webhook(
url=WEBHOOK_URL,
drop_pending_updates=True,
allowed_updates=["message", "callback_query", "inline_query"]
)
logger.info(f"[OK] Webhook o'rnatildi: {WEBHOOK_URL}")
except Exception as e:
logger.warning(f"[!] Webhook xatolik: {e}")
logger.info("[INFO] Webhook kompyuterdan o'rnating: python set_webhook.py")
@app.on_event("shutdown")
async def on_shutdown():
try:
await bot.session.close()
except Exception:
pass
@app.post(WEBHOOK_PATH)
async def webhook_handler(request: Request):
try:
data = await request.json()
update = Update.model_validate(data, context={"bot": bot})
await dp.feed_update(bot=bot, update=update)
except Exception as e:
logger.error(f"Webhook xatosi: {e}")
return {"ok": True}
@app.get("/")
async def root():
return {"status": "running", "mode": "webhook"}
@app.get("/r/{code}")
async def redirect_dynamic_qr(code: str, request: Request):
"""Dinamik QR kod skanerlaganda — skanerni yozib, maqsad URL ga yo'naltirish"""
from services.db import get_link_by_code, log_scan
link = await get_link_by_code(code)
if not link:
return HTMLResponse(
"<h2>QR kod topilmadi yoki muddati tugagan</h2><p>Bu havola mavjud emas.</p>",
status_code=404
)
# Skanerni qayd qilish
ip = request.client.host if request.client else ""
ua = request.headers.get("user-agent", "")
await log_scan(code, ip=ip, user_agent=ua)
return RedirectResponse(url=link["target_url"], status_code=302)
@app.get("/api/qr")
async def api_qr(data: str = ""):
"""Inline rejim uchun QR kod rasmini qaytaruvchi endpoint"""
if not data:
return Response(content="No data", status_code=400)
from services.qr_generator import QRGenerator
generator = QRGenerator()
img_buf = await generator.generate_async(data)
return Response(
content=img_buf.read(),
media_type="image/png",
headers={"Cache-Control": "public, max-age=86400"}
)
if __name__ == "__main__":
import uvicorn
uvicorn.run("app:app", host="0.0.0.0", port=7860)