WebHook telegram bot test
This commit is contained in:
62
app/webhooks/telegram.py
Normal file
62
app/webhooks/telegram.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import os
|
||||||
|
from fastapi import APIRouter, Request, HTTPException
|
||||||
|
from telebot import TeleBot, types
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||||
|
WEBHOOK_SECRET = os.getenv("TELEGRAM_WEBHOOK_SECRET", "") # опционально
|
||||||
|
bot = TeleBot(BOT_TOKEN, threaded=False) # threaded=False обычно проще в async-сервисах
|
||||||
|
|
||||||
|
# ====== ВАШИ ХЕНДЛЕРЫ (почти без изменений) ======
|
||||||
|
import httpx
|
||||||
|
|
||||||
|
API_URL = os.getenv("API_URL")
|
||||||
|
user_states = {} # ⚠️ см. примечание ниже про хранение
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['start'])
|
||||||
|
def start(message):
|
||||||
|
if len(message.text.split()) > 1:
|
||||||
|
username = message.text.split()[1]
|
||||||
|
user_states[message.chat.id] = {"username": username}
|
||||||
|
bot.reply_to(message, "📋 Введите код из лаунчера:")
|
||||||
|
else:
|
||||||
|
bot.reply_to(message, "🔑 Введите ваш игровой никнейм:")
|
||||||
|
bot.register_next_step_handler(message, process_username)
|
||||||
|
|
||||||
|
def process_username(message):
|
||||||
|
user_states[message.chat.id] = {"username": message.text.strip()}
|
||||||
|
bot.reply_to(message, "📋 Теперь введите код из лаунчера:")
|
||||||
|
|
||||||
|
@bot.message_handler(func=lambda m: m.chat.id in user_states)
|
||||||
|
def verify_code(message):
|
||||||
|
username = user_states[message.chat.id]["username"]
|
||||||
|
code = message.text.strip()
|
||||||
|
|
||||||
|
try:
|
||||||
|
r = httpx.post(
|
||||||
|
f"{API_URL}/auth/verify_code",
|
||||||
|
json={"username": username, "code": code, "telegram_chat_id": message.chat.id},
|
||||||
|
)
|
||||||
|
if r.status_code == 200:
|
||||||
|
bot.reply_to(message, "✅ Аккаунт подтвержден!")
|
||||||
|
else:
|
||||||
|
bot.reply_to(message, f"❌ Ошибка: {r.json().get('detail')}")
|
||||||
|
except Exception as e:
|
||||||
|
bot.reply_to(message, "⚠️ Сервер недоступен. Детальная информация: " + str(e))
|
||||||
|
|
||||||
|
user_states.pop(message.chat.id, None)
|
||||||
|
|
||||||
|
# ====== WEBHOOK ENDPOINT ======
|
||||||
|
@router.post("/telegram/webhook")
|
||||||
|
async def telegram_webhook(request: Request):
|
||||||
|
# простой секрет, чтобы никто кроме Telegram не слал апдейты
|
||||||
|
if WEBHOOK_SECRET:
|
||||||
|
header = request.headers.get("X-Telegram-Bot-Api-Secret-Token")
|
||||||
|
if header != WEBHOOK_SECRET:
|
||||||
|
raise HTTPException(status_code=403, detail="forbidden")
|
||||||
|
|
||||||
|
update_json = await request.json()
|
||||||
|
update = types.Update.de_json(update_json)
|
||||||
|
bot.process_new_updates([update])
|
||||||
|
return {"ok": True}
|
||||||
@ -15,17 +15,17 @@ services:
|
|||||||
- mongodb
|
- mongodb
|
||||||
command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"]
|
command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"]
|
||||||
|
|
||||||
telegram_bot:
|
# telegram_bot:
|
||||||
container_name: telegram_bot
|
# container_name: telegram_bot
|
||||||
build:
|
# build:
|
||||||
context: .
|
# context: .
|
||||||
dockerfile: Dockerfile
|
# dockerfile: Dockerfile
|
||||||
user: "${UID:-1000}:${GID:-1000}"
|
# user: "${UID:-1000}:${GID:-1000}"
|
||||||
volumes:
|
# volumes:
|
||||||
- ./telegram_bot.py:/app/telegram_bot.py
|
# - ./telegram_bot.py:/app/telegram_bot.py
|
||||||
env_file:
|
# env_file:
|
||||||
- .env
|
# - .env
|
||||||
command: ["python", "telegram_bot.py"]
|
# command: ["python", "telegram_bot.py"]
|
||||||
|
|
||||||
mongodb:
|
mongodb:
|
||||||
container_name: mongodb
|
container_name: mongodb
|
||||||
|
|||||||
39
main.py
39
main.py
@ -1,12 +1,50 @@
|
|||||||
|
from contextlib import asynccontextmanager
|
||||||
|
import os
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
import httpx
|
||||||
from app.api import news, users, skins, capes, meta, server, store, pranks, marketplace, bonuses, case
|
from app.api import news, users, skins, capes, meta, server, store, pranks, marketplace, bonuses, case
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
from app.core.config import CAPES_DIR, CAPES_STORE_DIR, SKINS_DIR
|
from app.core.config import CAPES_DIR, CAPES_STORE_DIR, SKINS_DIR
|
||||||
|
from app.webhooks import telegram
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
###################### БОТ ######################
|
||||||
|
|
||||||
|
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||||
|
PUBLIC_WEBHOOK_URL = os.getenv("PUBLIC_WEBHOOK_URL") # https://minecraft.api.popa-popa.ru/telegram/webhook
|
||||||
|
WEBHOOK_SECRET = os.getenv("TELEGRAM_WEBHOOK_SECRET", "")
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def lifespan(app: FastAPI):
|
||||||
|
# ===== STARTUP =====
|
||||||
|
if BOT_TOKEN and PUBLIC_WEBHOOK_URL:
|
||||||
|
payload = {"url": PUBLIC_WEBHOOK_URL}
|
||||||
|
if WEBHOOK_SECRET:
|
||||||
|
payload["secret_token"] = WEBHOOK_SECRET
|
||||||
|
|
||||||
|
async with httpx.AsyncClient(timeout=20) as client:
|
||||||
|
await client.post(
|
||||||
|
f"https://api.telegram.org/bot{BOT_TOKEN}/setWebhook",
|
||||||
|
json=payload,
|
||||||
|
)
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
# ===== SHUTDOWN =====
|
||||||
|
async with httpx.AsyncClient(timeout=20) as client:
|
||||||
|
await client.post(
|
||||||
|
f"https://api.telegram.org/bot{BOT_TOKEN}/deleteWebhook"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = FastAPI(lifespan=lifespan)
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
|
||||||
app.include_router(meta.router)
|
app.include_router(meta.router)
|
||||||
app.include_router(users.router)
|
app.include_router(users.router)
|
||||||
app.include_router(skins.router)
|
app.include_router(skins.router)
|
||||||
@ -18,6 +56,7 @@ app.include_router(marketplace.router)
|
|||||||
app.include_router(bonuses.router)
|
app.include_router(bonuses.router)
|
||||||
app.include_router(news.router)
|
app.include_router(news.router)
|
||||||
app.include_router(case.router)
|
app.include_router(case.router)
|
||||||
|
app.include_router(telegram.router)
|
||||||
|
|
||||||
# Монтируем статику
|
# Монтируем статику
|
||||||
app.mount("/skins", StaticFiles(directory=str(SKINS_DIR)), name="skins")
|
app.mount("/skins", StaticFiles(directory=str(SKINS_DIR)), name="skins")
|
||||||
|
|||||||
Reference in New Issue
Block a user