Как можно интегрировать FastAPI с библиотекой aiogram для настройки вебхуков?

Как правильно интегрировать скрипт на FastAPI для обработки вебхуков от платежной системы с ботом на aiogram 3.x.x, чтобы оба работали одновременно? <br/><br/> Вот файл для запуска бота: <br/><br/> <pre><code class="python">import asyncio
from utils import router
from loader import bot, dp
from utils.middlewares import ThrottlingMiddleware


async def startup():
    print("Bot started!")


async def main():
    dp.include_router(router.user)
    dp.message.middleware(ThrottlingMiddleware())

    await startup()
    await bot.delete_webhook(drop_pending_updates=True)
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())</code></pre>
  • 23 сентября 2024 г. 19:33
Ответы на вопрос 2
Чтобы интегрировать FastAPI с библиотекой aiogram для обработки вебхуков и запуска бота одновременно, вы можете использовать asyncio для создания асинхронного контекста, в котором будут работать оба приложения. Ниже представлен пример, как это можно сделать.

### Полный пример интеграции FastAPI и aiogram:

1. Установите необходимые пакеты:

```bash
pip install fastapi[all] aiogram uvicorn
```

2. Создайте структуру вашего проекта, например:

```
/your_project
    ├── bot.py
    ├── main.py
    └── utils/
        ├── loader.py
        └── router.py
```

3. В файле `loader.py` инициализируйте бота и диспетчер:

```python
# utils/loader.py

from aiogram import Bot, Dispatcher

bot = Bot(token='YOUR_BOT_TOKEN')
dp = Dispatcher()
```

4. В файле `router.py` создайте роутер для обработки запросов:

```python
# utils/router.py

from fastapi import APIRouter, Request

router = APIRouter()

@router.post("/webhook")
async def webhook(request: Request):
    # Обработка вебхуков
    json_data = await request.json()
    # Тут можно добавить логику обработки данных
    return {"status": "success"}
```

5. В файле `main.py` интегрируйте FastAPI и aiogram:

```python
# main.py

import asyncio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from utils import router
from utils.loader import bot, dp

app = FastAPI()

# Настройка CORS (если необходимо)
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])

# Включаем маршруты из utils/router.py
app.include_router(router.router)

async def on_startup():
    print("Starting bot...")
    await bot.delete_webhook(drop_pending_updates=True)
    # Установите вебхук для FastAPI
    await bot.set_webhook("https://your_domain.com/webhook")

async def on_shutdown():
    print("Shutting down bot...")
    await bot.delete_webhook()

async def run_bot():
    await on_startup()
    await dp.start_polling(bot)

if __name__ == "__main__":
    # Создаем и запускаем все задачи
    loop = asyncio.get_event_loop()
    loop.create_task(run_bot())
    # Запускаем FastAPI
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
```

### Объяснение:

1. **FastAPI**: Мы создаем экземпляр `FastAPI`, настраиваем CORS (при необходимости) и добавляем маршруты для обработки вебхуков.

2. **Вебхуки**: При запуске приложения FastAPI устанавливает вебхук через `bot.set_webhook()`, который будет обрабатывать запросы по указанному пути.

3. **Запуск бота**: Мы создаем асинхронную задачу для запуска бота через `run_bot()`, чтобы он работал параллельно с FastAPI.

4. **Асинхронность**: Используя `asyncio`, мы можем обеспечить асинхронную работу бота и HTTP-сервера одновременно.

### Запуск приложения:
Теперь вы можете запустить ваше приложение с помощью следующей команды:

```bash
python main.py
```

Не забудьте заменить `YOUR_BOT_TOKEN` на ваш токен бота, а также указать правильный URL для вебхука.
У себя делал примерно следующим образом: 

WEBHOOK_PATH = f"/bot/{settings.token}"
WEBHOOK_URL = settings.webhook_url + WEBHOOK_PATH

app = FastAPI()

@app.on_event("startup")
async def on_startup():
    webhook_info = await bot.get_webhook_info()
    if webhook_info != WEBHOOK_URL:
        await bot.set_webhook(url=WEBHOOK_URL)
    logger.info("Bot started")

@app.post(WEBHOOK_PATH)
async def bot_webhook(update: dict):
    telegram_update = types.Update(**update)
    await dp.feed_update(bot=bot, update=telegram_update)

@app.on_event("shutdown")
async def on_shutdown():
    await bot.session.close()
    await bot.delete_webhook()
    logger.info("Bot stopped")
Похожие вопросы