Skip to content

Instantly share code, notes, and snippets.

@Tishka17
Last active March 17, 2024 04:55
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Tishka17/72b0e4748285636e0c234c88a51d2124 to your computer and use it in GitHub Desktop.
Save Tishka17/72b0e4748285636e0c234c88a51d2124 to your computer and use it in GitHub Desktop.
Multibot manager
import asyncio
from asyncio import get_running_loop, AbstractEventLoop
from contextvars import Context
from logging import getLogger
from typing import Dict, List
from aiogram import Dispatcher, Bot
from .database import Repo
from .handlers import register_sender
from .handlers.utils.permissions import PermissionsFilter
logger = getLogger(__name__)
class BotManager():
def __init__(self, middleware_factory, hidden_ids: List[int], permissions: PermissionsFilter):
self.dps: Dict[int, Dispatcher] = {}
self.permissions = permissions
self.hidden_ids = hidden_ids
self.middleware_factory = middleware_factory
async def start_bot(self, name: str, category_id: int, repo: Repo) -> bool:
dp = self.dps.get(category_id)
if dp:
logger.warning("Bot for category `%s` (%s) is already running: %s", name, category_id, dp)
return True
# dp = None
token = await repo.category_token(category_id)
if not token:
logger.warning("No token found for category `%s` (%s)", name, category_id)
return False
logger.info("Starting bot for category `%s` (%s)", name, category_id)
callback = lambda: asyncio.create_task(self._start_bot(token, category_id))
loop: AbstractEventLoop = get_running_loop()
# noinspection PyArgumentList
loop.call_soon(callback, context=Context())
return True
async def _start_bot(self, token: str, category_id: int):
bot = Bot(token=token)
dp = Dispatcher(bot)
dp.middleware.setup(self.middleware_factory())
register_sender(dp, category_id, self.hidden_ids, self.permissions)
self.dps[category_id] = dp
await dp.start_polling(timeout=10)
async def stop_bot(self, name: str, category_id: int):
dp = self.dps.pop(category_id, None)
if not dp:
logger.info("No running bot found for category `%s` (%s)", name, category_id)
return
logger.info("Stopping bot for category `%s` (%s)", name, category_id)
dp.stop_polling()
await dp.wait_closed()
@Tishka17
Copy link
Author

этот бот менеджер для поллинг. Он содержит кучу диспатчеров, каждый из которых независимо работает

  1. Делаешь репо, которое по айди категории умеет возвращать токен
  2. Создаешь bm = BotManager() с передачей нужных фильтро и фабрик мидлварей, чтобы они в ботов прокидывались
  3. Каждый раз когда надо стартнуть бота делаешь bn.start_bot(somename, id, repo)
  4. При старте просто выгребаешь список id и стартуешь по очереди
  5. Для остановки соответственно наоборот stop_bot
  6. name юзается только для отладки, можно выкинуть

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment