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.dispatcher.filters import Command, CommandObject from aiogram.dispatcher.fsm.storage.redis import DefaultKeyBuilder, RedisStorage from aiogram.dispatcher.webhook.aiohttp_server import ( SimpleRequestHandler, TokenBasedRequestHandler, setup_application, ) from aiogram.exceptions import TelegramUnauthorizedError from aiogram.types import Message from aiogram.utils.token import TokenValidationError, validate_token main_router = Router() BASE_URL = getenv("BASE_URL", "https://example.com") MAIN_BOT_TOKEN = getenv("TELEGRAM_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(commands=["add"], command_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)) 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(): session = AiohttpSession() bot_settings = {"session": session, "parse_mode": "HTML"} bot = Bot(token=MAIN_BOT_TOKEN, **bot_settings) 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()