Search code examples
.net-corediscorddiscord.net

How to fix 'A MessageReceived handler is blocking the gateway task.' in DiscordBot


I am trying to build my own Discord Bot, that soft bans people, who write racist or anti-Semitic words. I try to do this with MessageReceivedAsync but it crashes all the time with the error 'A MessageReceived handler is blocking the gateway task.'

Here is the code of my Program.cs:

namespace NoNetworcc
{
class Program : ModuleBase<SocketCommandContext>
    {
        static void Main(string[] args)
            => new Program().MainAsync().GetAwaiter().GetResult();

        public async Task MainAsync()
        {
            using (var services = ConfigureServices())
            {
                var client = services.GetRequiredService<DiscordSocketClient>();

                client.Log += LogAsync;
                client.MessageReceived += MessageReceivedAsync;
                services.GetRequiredService<CommandService>().Log += LogAsync;

                await client.LoginAsync(TokenType.Bot, "NzEyNDA2MDAxMjAxOTcxMjcw.XsRF4A.8YENNInx3D4kqJyK9N8xjTU3mcs");
                await client.StartAsync();

                await services.GetRequiredService<CommandHandlingService>().InitializeAsync();

                await Task.Delay(Timeout.Infinite);
            }
        }

        private Task LogAsync(LogMessage log)
        {
            Console.WriteLine(log.ToString());

            return Task.CompletedTask;
        }

        private async Task MessageReceivedAsync(SocketMessage message)
        {
            using (BlacklistDatabaseContext lite = new BlacklistDatabaseContext())
            {
                var blacklistWords = lite.BlacklistWords;

                foreach(var word in blacklistWords)
                {
                    if(message.Content.Contains(word.Blacklistword.ToString()))
                    {
                        ulong roleID = 756500011331616840;
                        var role = Context.Guild.GetRole(roleID);
                        await ((IGuildUser)Context.User).AddRoleAsync(role);
                        await message.Channel.SendMessageAsync($"{Context.User} got softbanned for using the word '{word}'");
                    }
                }
            }
        }

        private ServiceProvider ConfigureServices()
        {
            return new ServiceCollection()
                .AddSingleton<DiscordSocketClient>()
                .AddSingleton<CommandService>()
                .AddSingleton<CommandHandlingService>()
                .AddSingleton<HttpClient>()
                .AddSingleton<PictureService>()
                .BuildServiceProvider();
        }
    }
}

And here is my Code for the HandlingService:

namespace NoNetworcc.Services
{
    public class CommandHandlingService
    {
        private readonly CommandService _commands;
        private readonly DiscordSocketClient _discord;
        private readonly IServiceProvider _services;

        public CommandHandlingService(IServiceProvider services)
        {
            _commands = services.GetRequiredService<CommandService>();
            _discord = services.GetRequiredService<DiscordSocketClient>();
            _services = services;

            _commands.CommandExecuted += CommandExecutedAsync;
            _discord.MessageReceived += MessageReceivedAsync;
        }

        public async Task InitializeAsync()
        {
            await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
        }

        public async Task MessageReceivedAsync(SocketMessage rawMessage)
        {
            if (!(rawMessage is SocketUserMessage message)) return;
            if (message.Source != MessageSource.User) return;

            var argPos = 0;

            var context = new SocketCommandContext(_discord, message);
            await _commands.ExecuteAsync(context, argPos, _services); 
        }

        public async Task CommandExecutedAsync(Optional<CommandInfo> command, ICommandContext context, IResult result)
        {
            if (!command.IsSpecified)
                return;

            if (result.IsSuccess)
                return;

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

How can I fix this issue?


Solution

  • private Task MessageReceivedAsync(SocketMessage message) {
        _ = Task.Run(async () => {
                using (BlacklistDatabaseContext lite = new BlacklistDatabaseContext()) {
                    var blacklistWords = lite.BlacklistWords;
                    foreach (var word in blacklistWords) {
                        if(message.Content.Contains(word.Blacklistword.ToString())) {
                            ulong roleID = 756500011331616840;
                            var role = (message.Channel as ITextChannel)?.Guild.GetRole(roleID);
                            if (role != null) {
                                await (message.Author as SocketGuildUser)?.AddRoleAsync(role);
                                await message.Channel.SendMessageAsync($"{message.Author} got softbanned for using the word '{word}'");
                            }
                        }
                    }
                }
            });
            return Task.CompletedTask; 
    }