Search code examples
c#discordbots

How to get a bot to respond to a bot in discord?


I'm trying to get 2 bots to talk to eachother on discord and currently, I have the bots set up. One is javascript and the other is in c# (it's a personal project with trying to learn different languages and ended up building off of that but the languages aren't the issue, it's only on the c# side). Currently, I have it where I set off a command and my goal is to get one bot to trigger another bot's command. Here's a visual.

User command -> (sets off command in ) bot 1 -> (set's off command in ) bot 2

Currently I have the first bit working, but the second bit is having problems. I've isolated it down to the intents I think because bot 2 is geting that the bot is sending a message, but isn't getting the content. Is there another permission that can be used to get the bot's message?

I don't know if this will help, but for bot 1, this is the code I've used

Javascript

const { Client, IntentsBitField } = require('discord.js');
const token = "Token_here";

const client = new Client({
    intents: [
        IntentsBitField.Flags.Guilds,
        IntentsBitField.Flags.GuildMembers,
        IntentsBitField.Flags.GuildMessages,
        IntentsBitField.Flags.MessageContent
    ]
});

client.on('ready', (clientTemp) => {
    console.log(`${clientTemp.user.tag} is online`);
});

client.on('messageCreate', (message) => {
    if (message.content === 'say ping') {
        message.channel.send('@bot2 ping');
    }
    
})

client.login(token);

and for bot 2, it's using a slight modifications to https://github.com/Hawxy/Discord.Addons.Hosting simple.simple example. But the main bit I've figured out that isn't coming through is the command handler

using Discord.Commands;
using Discord.WebSocket;
using Discord;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Reflection;
using Discord.Addons.Hosting;
using System.Runtime.InteropServices;
using Discord.Webhook;

namespace CommunicationServerBot
{
    public class CommandHandler : DiscordClientService
    {
        private readonly IServiceProvider _provider;
        private readonly CommandService _commandService;
        private readonly IConfiguration _config;

        public CommandHandler(DiscordSocketClient client, ILogger<CommandHandler> logger, IServiceProvider provider, CommandService commandService, IConfiguration config) : base(client, logger)
        {
            _provider = provider;
            _commandService = commandService;
            _config = config;
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            Client.MessageReceived += HandleMessage;
            _commandService.CommandExecuted += CommandExecutedAsync;
            await _commandService.AddModulesAsync(Assembly.GetEntryAssembly(), _provider);
        }

        private async Task HandleMessage(SocketMessage incomingMessage)
        {
            if (incomingMessage is not SocketUserMessage message) return;
            if ((message.Source != MessageSource.User) && (message.Source != MessageSource.Bot)) return;

            if (message.Source == MessageSource.Bot)
            {
                Console.WriteLine($"{message.Author.Username} saying {message.CleanContent}");
            };

            int argPos = 0;
            if (!message.HasStringPrefix(_config["Prefix"], ref argPos)
                && !message.HasMentionPrefix(Client.CurrentUser, ref argPos))
                return;

            var context = new SocketCommandContext(Client, message);
            await _commandService.ExecuteAsync(context, argPos, _provider);
        }

        public async Task CommandExecutedAsync(Optional<CommandInfo> command, ICommandContext context, IResult result)
        {
            Logger.LogInformation("User {user} attempted to use command {command}", context.User, command.Value.Name);

            if (!command.IsSpecified || result.IsSuccess)
                return;

            await context.Channel.SendMessageAsync($"Error: {result}");
        }
    }
}

What I try to do is for me to say "say ping" bot 1 would say "@bot2 ping" and bot 2 would say "pong". But instead, the content isn't going through, only logging that the content came through. I've given both administrator permissions, changed gateway intents and allowed for MessageContent for bot2. Is there something else I'm missing that allows for bots to communicate to eachother?


Solution

  • You can check if the author is a bot, however be careful as bots replying to bots can get out of hand quickly!

    private async Task HandleMessage(SocketMessage incomingMessage)
    {
        if (incomingMessage.Author.IsBot)
        {
            //do something with bot commands,
            //be careful as bots talking to bots can cause infinite loops!
        }
        else
        {
          //not a bot, run your code as is...
        }
    }
    

    and as Luka pointed out, you are returning early correctly if the message is not from a human.

    if (incomingMessage is not SocketUserMessage message) return;