Как отправить сообщение от другого бота при использовании события on message?

Как правильно организовать работу двух ботов, чтобы при срабатывании события on_message у первого бота, второй бот отправлял сообщение? У меня есть функция, которая запускает второго бота, но в текущей реализации он не отвечает. Как можно это исправить? 

```python
class BotHandler:
    def __init__(self, token: str):
        self.token = token
        intents = disnake.Intents.all()
        self.bot = disnake.Client(intents=intents)

        @self.bot.event
        async def on_ready():
            print(f"'{self.bot.user.name}' is online!")

    async def start(self):
        await self.bot.start(self.token)

    async def make_func(self, func):
        self.func = func
        print('succesull')
        self.func

async def send_msg(channel):
    await channel.send('pong!!')

@bot.event
async def on_message(message):
    guild_db = guilds.find_one({'guild': str(message.guild.id)})
    if message.content == '!ping':
        if guild_db['token']:
            await BotHandler(guild_db['token']).make_func(await send_msg(message.channel))
        else:
            await message.channel.send('pong!')
```
  • 20 февраля 2025 г. 18:24
Ответы на вопрос 2
Чтобы организовать работу двух ботов, так чтобы один бот реагировал на событие `on_message` другого, нужно правильно инициализировать и использовать оба бота. В данном случае, вы пытаетесь создать новый экземпляр `BotHandler` каждый раз, когда срабатывает событие `on_message`, что не совсем корректно.

Вот шаги, которые вы можете предпринять для исправления вашей реализации:

1. **Инициализируйте обоих ботов заранее**. Это поможет вам избежать создания нового экземпляра бота в момент обработки сообщения.
2. **Используйте ссылки на оба бота** в обработчиках событий.

Вот пример кода, который демонстрирует это:

```python
import disnake

class BotHandler:
    def __init__(self, token: str):
        self.token = token
        self.intents = disnake.Intents.all()
        self.bot = disnake.Client(intents=self.intents)

        @self.bot.event
        async def on_ready():
            print(f"'{self.bot.user.name}' is online!")

        @self.bot.event
        async def on_message(message):
            await self.handle_message(message)

    async def handle_message(self, message):
        guild_db = guilds.find_one({'guild': str(message.guild.id)})
        if message.content == '!ping':
            if guild_db['token']:
                # Здесь отправляем сообщение через второй бот
                await send_msg(message.channel)
            else:
                await message.channel.send('pong!')

    async def start(self):
        await self.bot.start(self.token)

async def send_msg(channel):
    await channel.send('pong!!')

# Пример инициализации двух ботов
async def main():
    first_bot_token = "YOUR_FIRST_BOT_TOKEN"
    second_bot_token = "YOUR_SECOND_BOT_TOKEN"

    first_bot = BotHandler(first_bot_token)
    second_bot = BotHandler(second_bot_token)

    # Запускаем обоих ботов
    await asyncio.gather(first_bot.start(), second_bot.start())

# Запустите ваш основной код
import asyncio

asyncio.run(main())
```

### Пояснения:
1. Мы создали класс `BotHandler`, где осуществляем обработку сообщений непосредственно в методе `handle_message`.
2. Оба бота создаются и запускаются в асинхронной функции `main`, используя `asyncio.gather()` для одновременного запуска обоих ботов.
3. Вызывая `await send_msg(message.channel)` из метода `handle_message`, мы обеспечиваем, что первый бот может вызывать функцию отправки сообщения, которая будет использовать второй бот.

Таким образом, вы можете сделать так, чтобы один бот использовал функциональность другого ровно тогда, когда это необходимо. Не забудьте заменить `"YOUR_FIRST_BOT_TOKEN"` и `"YOUR_SECOND_BOT_TOKEN"` на реальные токены ваших ботов.
Это сделать можно, но исключительно костылями, в результате чего будет теряться какой-нибудь функционал. При этом я не могу придумать ни одной задачи, которая могла бы требовать подобной странной системы из двух ботов, так что есть ощущение что вы делаете что-то не то и стоит детализировать задачу. 

Во-первых стоит прочитать сообщение Дэнни (автора библиотеки), на которое он сам ссылается при подобных ответах.
При этом подходе запуская два бота в одном цикле событий у вас не будут работать ивенты.

Второй подход, это запустить оба бота как подпроцессы с общением через каналы или очереди.
При этом подходе оба бота будут конкурировать за доступ потому что GIL.

Третий и наиболее адекватный подход в том, чтобы 2 независимых бота общались через шину данных, например RabbitMQ.
Похожие вопросы