Соединение aiogram и telethon

Вопрос или проблема

Я пишу телеграм-бота, который должен отправлять некоторые сообщения с помощью клиента telethon, а некоторые — с помощью aiogram. Он выдает ошибку, которую я не понимаю

Я пробовал следующий код:

bot = Bot(token=bot_token)
dp = Dispatcher()
client = TelegramClient("session", api_id, api_hash).start(bot_token=bot_token)

@dp.message(CommandStart())
async def start(message: types.Message):
    await message.answer("текст aiogram")
    await client_send(message)

async def client_send(message: types.Message):
    async with client:
        await client.send_message(message.chat.id, "текст telethon")

async def main():
    await dp.start_polling(bot)

if __name__ == '__main__':
    asyncio.run(main())

Когда бот получает сообщение, я получаю этот длинный трассировку ошибок:

Cause exception while process update id=xxx by bot id=xxx
RuntimeError: The asyncio event loop must not change after connection (see the FAQ for details)
Traceback (most recent call last):
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 309, in _process_update
    response = await self.feed_update(bot, update, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 158, in feed_update
    response = await self.update.wrap_outer_middleware(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...

  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\aiogram\dispatcher\event\handler.py", line 43, in call
    return await wrapped()
           ^^^^^^^^^^^^^^^
  File "C:\Users\Artyxx\Documents\Python\bot\bot-check-in\testcode.py", line 19, in start
    await client_send(message)
  File "C:\Users\Artyxx\Documents\Python\bot\bot-check-in\testcode.py", line 23, in client_send
    async with client:
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\telethon\client\auth.py", line 657, in __aenter__
    return await self.start()
           ^^^^^^^^^^^^^^^^^^
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\telethon\client\auth.py", line 141, in _start
    me = await self.get_me()
         ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\telethon\client\users.py", line 165, in get_me
    me = (await self(
          ^^^^^^^^^^^
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\telethon\client\users.py", line 30, in __call__
    return await self._call(self._sender, request, ordered=ordered)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Artyxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\telethon\client\users.py", line 34, in _call
    raise RuntimeError('The asyncio event loop must not change after connection (see the FAQ for details)')
RuntimeError: The asyncio event loop must not change after connection (see the FAQ for details)

Как я могу подключить и использовать эти две библиотеки

asyncio.run создает новый цикл событий. После того как вы установили соединение (что вы делаете с помощью .start() Telethon), вы не можете изменить цикл (строка .start() использует стандартный цикл, но asyncio.run создает новый).

Уберите .start(). Когда вы используете async with client, это также вызывает .start(), поэтому первый раз вызова избыточен и вызывает проблемы.

Также обратите внимание, что Telethon может управлять аккаунтами ботов тоже. Если вам нужны и пользователь, и бот, использование одной библиотеки может быть проще.

Ответ или решение

Для успешного соединения и работы с библиотеками Aiogram и Telethon в одном проекте, важно правильно управлять контекстом событий (event loop) и избегать ошибок изменения цикла после его использования. Рассмотрим код, который у вас есть, и исправим его.

Проблема

Основная проблема возникает из-за того, что вы используете .start() у клиента Telethon и одновременно запускаете новое событие с помощью asyncio.run(main()), что создаёт два разных цикла событий. Это приводит к ошибке: RuntimeError: The asyncio event loop must not change after connection.

Решение

Мы можем избежать этой ошибки, устранив дублирование вызова .start() и используя только один контекст событий. Telethon самостоятельно управляет подключением, если мы используем async with. Так что, давайте уберём вызов .start() при создании клиента Telethon и создадим обязательный контекст для работы с клиентом Telethon.

Вот исправленный код:

import asyncio
from aiogram import Bot, Dispatcher, types
from aiogram.filters import CommandStart
from telethon import TelegramClient

bot_token = 'YOUR_BOT_TOKEN'
api_id = 'YOUR_API_ID'
api_hash = 'YOUR_API_HASH'

# Инициализация бота
bot = Bot(token=bot_token)
dp = Dispatcher()

# Инициализация клиента Telethon
client = TelegramClient("session_name", api_id, api_hash)

async def client_send(chat_id, message_text):
    async with client:
        await client.send_message(chat_id, message_text)

@dp.message(CommandStart())
async def start(message: types.Message):
    await message.answer("text aiogram")
    await client_send(message.chat.id, "text telethon")

async def main():
    async with client:
        await dp.start_polling(bot)

if __name__ == '__main__':
    asyncio.run(main())

Объяснение изменений

  1. Удаление вызова .start() у клиента: Мы убрали вызов client = TelegramClient(...).start(bot_token=bot_token), так как это вызывает подключение до того, как мы используем его в async with.

  2. Использование async with client в функции main: Теперь мы управляем подключением клиента Telethon в контексте main(), гарантируя, что клиент правильно подключится и отключится.

  3. Передача chat_id в функцию client_send: Передаем идентификатор чата в client_send, чтобы сделать функцию более гибкой.

Заключение

С помощью этих изменений вы сможете успешно использовать Aiogram и Telethon в одном Telegram боте. Также не забывайте, что Telethon может управлять как пользовательскими аккаунтами, так и аккаунтами ботов, и использование одной библиотеки может быть проще в ряде случаев.

Если у вас остались вопросы или возникли новые проблемы, не стесняйтесь задавать их.

Оцените материал
Добавить комментарий

Капча загружается...