Не удалось запустить мультибота по кнопке
У меня есть файл main.py
:
import asyncio
import logging
from aiogram import Bot, Dispatcher, F
from aiogram.filters.command import Command
from aiogram.filters.text import Text
from aiogram.fsm.storage.memory import SimpleEventIsolation
from aiogram.exceptions import TelegramUnauthorizedError
from config import dp, bot
from utils.polling_manager import PollingManager
from handlers import client
from mb_handlers import client as mb_client
from database.database import *
logger = logging.getLogger(__name__)
def get_bot_tokens_from_database():
users = Users.select()
bot_tokens = [user.USERS_TOKENS for user in users]
return bot_tokens
async def main():
logging.getLogger("schedule").setLevel(logging.ERROR)
# TODO: Handlers by main bot
dp.message.register(client.start_message_handler, F.chat.type == 'private', Command(commands="start"))
dp.message.register(client.settings, F.chat.type == 'private', Text(text="⚙️ Настройки"))
dp.message.register(client.my_bots, F.chat.type == 'private', Text(text="🤖 Мои боты"))
# dp.message.register(client.add_bot_father, F.chat.type == 'private', Text(text="back_in_my_bot"))
# dp.message.register(client.adding_token, F.chat.type == 'private', Text(text=['text'],state=client.AddTokenStates.add_token))
# ----
bots_setting = get_bot_tokens_from_database()
multi_dp = Dispatcher(events_isolation=SimpleEventIsolation())
# TODO: Handlers by multibots
multi_dp.message.register(mb_client.send_welcome_multi, F.chat.type == 'private', Command(commands="start"))
# ----
polling_manager = PollingManager()
if bots_setting != list():
for mbot_ in bots_setting:
try:
mbot = Bot(mbot_)
polling_manager.start_bot_polling(
dp=multi_dp, bot=mbot, polling_manager=polling_manager, dp_for_new_bot=multi_dp
)
# Проверка обновлений в ботах при включение, пока они были выключены
await mbot.get_updates(offset=-1)
except TelegramUnauthorizedError:
await bot.send_message(chat_id=mbot_['owner_user_id'], text=f'Бот с пользовательским названием "@{mbot_["username_bot"]}" не был авторизирован\nРешением этой проблемы может быть изменение токена бота в настройках проекта')
await dp.start_polling(bot, dp_for_new_bot=multi_dp, polling_manager=polling_manager)
if __name__ == "__main__":
try:
print('Starting main bot')
asyncio.run(main())
except (KeyboardInterrupt, SystemExit):
logger.error("Exit")
poolling_manager.py
:
import asyncio
import functools
import logging
from asyncio import AbstractEventLoop, CancelledError, Task, get_running_loop
from contextvars import Context
from typing import Any, Awaitable, Dict, List, Optional
from aiogram import Bot
from aiogram.dispatcher.dispatcher import DEFAULT_BACKOFF_CONFIG, Dispatcher
from aiogram.types import User
from aiogram.utils.backoff import BackoffConfig
logger = logging.getLogger(__name__)
class PollingManager:
def __init__(self):
self.polling_tasks: Dict[int, Task] = {}
def _create_pooling_task(
self,
dp: Dispatcher,
bot: Bot,
polling_timeout: int,
handle_as_tasks: bool,
backoff_config: BackoffConfig,
allowed_updates: Optional[List[str]],
**kwargs: Any,
):
asyncio.create_task(
self._start_bot_polling(
dp=dp,
bot=bot,
polling_timeout=polling_timeout,
handle_as_tasks=handle_as_tasks,
backoff_config=backoff_config,
allowed_updates=allowed_updates,
**kwargs,
)
)
def start_bot_polling(
self,
dp: Dispatcher,
bot: Bot,
polling_timeout: int = 10,
handle_as_tasks: bool = True,
backoff_config: BackoffConfig = DEFAULT_BACKOFF_CONFIG,
allowed_updates: Optional[List[str]] = None,
**kwargs: Any,
):
loop: AbstractEventLoop = get_running_loop()
# noinspection PyArgumentList
loop.call_soon(
functools.partial(
self._create_pooling_task,
dp=dp,
bot=bot,
polling_timeout=polling_timeout,
handle_as_tasks=handle_as_tasks,
backoff_config=backoff_config,
allowed_updates=allowed_updates,
**kwargs,
),
context=Context(),
)
async def _start_bot_polling(
self,
dp: Dispatcher,
bot: Bot,
polling_timeout: int = 10,
handle_as_tasks: bool = True,
backoff_config: BackoffConfig = DEFAULT_BACKOFF_CONFIG,
allowed_updates: Optional[List[str]] = None,
on_bot_startup: Optional[Awaitable] = None,
on_bot_shutdown: Optional[Awaitable] = None,
**kwargs: Any,
):
logger.info("Start poling")
user: User = await bot.me()
if on_bot_startup:
await on_bot_startup
try:
logger.info(
"Run polling for bot @%s id=%d - %r",
user.username,
bot.id,
user.full_name,
)
polling_task = asyncio.create_task(
dp._polling(
bot=bot,
handle_as_tasks=handle_as_tasks,
polling_timeout=polling_timeout,
backoff_config=backoff_config,
allowed_updates=allowed_updates,
**kwargs,
)
)
self.polling_tasks[bot.id] = polling_task
await polling_task
except CancelledError:
logger.info("Polling task Canceled")
finally:
logger.info(
"Polling stopped for bot @%s id=%d - %r",
user.username,
bot.id,
user.full_name,
)
if on_bot_shutdown:
await on_bot_shutdown
await bot.session.close()
def stop_bot_polling(self, bot_id: int):
polling_task = self.polling_tasks.pop(bot_id)
polling_task.cancel()
Вопрос в том, что я пытаюсь запустить бота вот таким вот кодом по кнопке:
@dp.callback_query(Text("options_bot_"))
async def handle_bot_settings(callback_query: types.CallbackQuery):
user_id = callback_query.from_user.id
user = Users.get_or_none(Users.USER_ID == user_id)
if user:
bot_username = user.BOT_USERNAME
user_token = user.USERS_TOKENS
bot_id = user.ID_BOT
settings_menu_keyboard = types.InlineKeyboardMarkup(inline_keyboard=[
[types.InlineKeyboardButton(text="Принятие заявок", callback_data=f"accept_requests_{bot_username}")],
[types.InlineKeyboardButton(text="Запустить бота", callback_data=f"toggle_bot_{user_token}")],
])
await callback_query.message.edit_text(options_text(user), reply_markup=settings_menu_keyboard)
@dp.callback_query()
async def handle_callback_query(callback_query: types.CallbackQuery):
if re.search(r'toggle_bot_', callback_query.data):
user_id = callback_query.from_user.id
user = Users.get_or_none(Users.USER_ID == user_id)
user_token = user.USERS_TOKENS
multi_dp = Dispatcher(events_isolation=SimpleEventIsolation())
polling_manager = PollingManager()
if user_token:
mbot = Bot(user_token)
polling_manager.start_bot_polling(
dp=multi_dp, bot=mbot, polling_manager=polling_manager, dp_for_new_bot=multi_dp
)
await mbot.get_updates(offset=-1)
await dp.start_polling(multi_dp, mbot, polling_manager)
await dp.start_polling(bot, dp_for_new_bot=multi_dp, polling_manager=polling_manager)
Но у меня ошибка вот такая:
RuntimeError: Task <Task pending name='Task-30' coro=<Dispatcher._process_update() running
at C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\site-packages\aiogram\dispatcher\dispatcher.py:293>>
got Future <Future pending> attached to a different loop
Источник: Stack Overflow на русском