aiogram/examples/multibot.py
Rishat-F 1df3adaba1
Fail redis and mongo tests if incorrect URI provided + some storages tests refactoring (#1510)
* Smaller timeout for MongoStorage connection

By default serverSelectionTimeoutMS=30000. This is too much

* Correct ConnectionError for RedisStorage in tests

* Remove unused import in conftest.py

* Refactor skipping redis and mongo tests

* Fail redis and mongo tests if incorrect URI

If incorrect URIs provided to "--redis" and/or "--mongo" options
tests should fail with ERRORs instead of skipping.
Otherwise the next scenario is possible:
  1) developer breaks RedisStorage and/or MongoStorage code
  2) tests are run with incorrect redis and/or mongo URIs
     provided by "--redis" and "--mongo" options.
     For example, wrong port specified.
  3) tests pass because skipping doesn't fail tests run
  4) developer or reviewer doesn't notice
     that redis and/or mongo tests were skipped
  5) broken code gets in codebase

* Remove unused fixtures passing in storages tests

* Define create_storage_key fixture in conftest.py

* Linters formatting

* Changes description

* Revert "Smaller timeout for MongoStorage connection"

This reverts commit d88b7ec612.

* Smaller timeout for MongoStorage connection in tests

The default 30s timeout is too long

* Add test for MongoStorage for 100% coverage

* Linters formatting

* Move skipping redis/mongo tests in earlier fixtures

* Replace vars with constants in conftest.py

* Linters formatting
2024-06-17 00:55:59 +03:00

91 lines
3 KiB
Python

import logging
import sys
from os import getenv
from typing import Any, Dict, Union
from aiohttp import web
from finite_state_machine import form_router
from aiogram import Bot, Dispatcher, F, Router
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.enums import ParseMode
from aiogram.exceptions import TelegramUnauthorizedError
from aiogram.filters import Command, CommandObject
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message
from aiogram.utils.token import TokenValidationError, validate_token
from aiogram.webhook.aiohttp_server import (
SimpleRequestHandler,
TokenBasedRequestHandler,
setup_application,
)
main_router = Router()
BASE_URL = getenv("BASE_URL", "https://example.com")
MAIN_BOT_TOKEN = getenv("BOT_TOKEN")
WEB_SERVER_HOST = "127.0.0.1"
WEB_SERVER_PORT = 8080
MAIN_BOT_PATH = "/webhook/main"
OTHER_BOTS_PATH = "/webhook/bot/{bot_token}"
REDIS_DSN = "redis://127.0.0.1:6479"
OTHER_BOTS_URL = f"{BASE_URL}{OTHER_BOTS_PATH}"
def is_bot_token(value: str) -> Union[bool, Dict[str, Any]]:
try:
validate_token(value)
except TokenValidationError:
return False
return True
@main_router.message(Command("add", magic=F.args.func(is_bot_token)))
async def command_add_bot(message: Message, command: CommandObject, bot: Bot) -> Any:
new_bot = Bot(token=command.args, session=bot.session)
try:
bot_user = await new_bot.get_me()
except TelegramUnauthorizedError:
return message.answer("Invalid token")
await new_bot.delete_webhook(drop_pending_updates=True)
await new_bot.set_webhook(OTHER_BOTS_URL.format(bot_token=command.args))
return await message.answer(f"Bot @{bot_user.username} successful added")
async def on_startup(dispatcher: Dispatcher, bot: Bot):
await bot.set_webhook(f"{BASE_URL}{MAIN_BOT_PATH}")
def main():
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
session = AiohttpSession()
bot_settings = {"session": session, "parse_mode": ParseMode.HTML}
bot = Bot(token=MAIN_BOT_TOKEN, **bot_settings)
storage = MemoryStorage()
# In order to use RedisStorage you need to use Key Builder with bot ID:
# storage = RedisStorage.from_url(REDIS_DSN, key_builder=DefaultKeyBuilder(with_bot_id=True))
main_dispatcher = Dispatcher(storage=storage)
main_dispatcher.include_router(main_router)
main_dispatcher.startup.register(on_startup)
multibot_dispatcher = Dispatcher(storage=storage)
multibot_dispatcher.include_router(form_router)
app = web.Application()
SimpleRequestHandler(dispatcher=main_dispatcher, bot=bot).register(app, path=MAIN_BOT_PATH)
TokenBasedRequestHandler(
dispatcher=multibot_dispatcher,
bot_settings=bot_settings,
).register(app, path=OTHER_BOTS_PATH)
setup_application(app, main_dispatcher, bot=bot)
setup_application(app, multibot_dispatcher)
web.run_app(app, host=WEB_SERVER_HOST, port=WEB_SERVER_PORT)
if __name__ == "__main__":
main()