Discord.NET: 未调用 UserJoined 事件

Discord.NET: UserJoined Event not being called

我正在使用 Discord.NET 构建一个 Discord 机器人,它应该报告用户加入、离开、被踢和被禁止进入 mod/admin-only 审核频道,但我无法获得加入公会时触发的相关函数

我删除了我的消息发送代码并将其替换为控制台输出以确定问题是事件未触发还是发送消息请求不工作并发现事件未被触发。

我已经在 Bot 管理控制台中启用了所有意图。

我已经根据 documentation 添加了意图:

var socketConfig = new DiscordSocketConfig
{
    GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.GuildBans
};

_client = new DiscordSocketClient(socketConfig);

然后我注册了事件:(注:_client = client;是之前用的)

client.UserJoined += UserJoined;

最后写了要触发的函数:

public Task UserJoined(SocketGuildUser user)
{
    Console.Write("User ");
    Console.Write(user.Username);
    Console.WriteLine(" joined.");

    return Task.CompletedTask;
}

这里有什么我没做过或做错的吗?我花了大约两天时间解决这个问题,完全不知道问题出在哪里,一切似乎都指向我做的一切都是正确的,但我无法从 Discord 收到这个事件。

我所做的每项更改都另外尝试删除机器人并将其重新添加到我的测试服务器。我也没有收到任何类似于 [12/8/2018 10:01:30 PM at Gateway] Received Dispatch (GUILD_MEMBER_ADD) 的消息,如 post.

中所述

我在下面包含了我的完整 Program.cs:

using System;
using Discord;
using Discord.Net;
using Discord.Commands;
using Discord.WebSocket;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.DependencyInjection;
using BanBot2.Bot.Services;

namespace BanBot2.Bot
{
    class Program
    {
        // setup our fields we assign later
        private readonly IConfiguration _iconfig;
        private DiscordSocketClient _client;

        static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();

        public Program()
        {
            var socketConfig = new DiscordSocketConfig
            {
                GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.GuildBans
            };

            _client = new DiscordSocketClient(socketConfig);
            
            // create the configuration
            var _builder = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile(path: "application.json");  

            // build the configuration and assign to _config          
            _iconfig = _builder.Build();
        }

        public async Task MainAsync()
        {
            // call ConfigureServices to create the ServiceCollection/Provider for passing around the services
            using (var services = ConfigureServices())
            {
                // get the client and assign to client 
                // you get the services via GetRequiredService<T>
                var client = services.GetRequiredService<DiscordSocketClient>();
                _client = client;

                // setup logging and the ready event
                client.Log += LogAsync;
                client.Ready += ReadyAsync;
                client.UserJoined += UserJoined;
                services.GetRequiredService<CommandService>().Log += LogAsync;

                // this is where we get the Token value from the configuration file, and start the bot
                await client.LoginAsync(TokenType.Bot, _iconfig["Token"]);
                await client.StartAsync();

                // we get the CommandHandler class here and call the InitializeAsync method to start things up for the CommandHandler service
                await services.GetRequiredService<CommandHandler>().InitializeAsync();

                await Task.Delay(-1);
            }
        }

        public Task UserJoined(SocketGuildUser user)
        {
            Console.Write("User @");
            Console.Write(user.Username);
            Console.WriteLine(" joined.");

            return Task.CompletedTask;
        }

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

        private Task ReadyAsync()
        {
            Console.WriteLine($"Connected as -> [{_client.CurrentUser}] :)");
            return Task.CompletedTask;
        }

        // this method handles the ServiceCollection creation/configuration and builds out the service provider we can call on later
        private ServiceProvider ConfigureServices()
        {
            // this returns a ServiceProvider that is used later to call for those services
            // we can add types we have access to here, hence adding the new using statement:
            // using BanBot2.Bot.Services;
            // the config we build is also added, which comes in handy for setting the command prefix!
            return new ServiceCollection()
                .AddSingleton(_iconfig)
                .AddSingleton<DiscordSocketClient>()
                .AddSingleton<CommandService>()
                .AddSingleton<CommandHandler>()
                .BuildServiceProvider();
        }
    }
}

您创建了 DiscordSocketClient 的实例并包含了适当的 DiscordSocketConfig

//good
            var socketConfig = new DiscordSocketConfig
            {
                GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.GuildBans
            };

            _client = new DiscordSocketClient(socketConfig);

但是,在 ConfigureServices 中,您应该将之前创建的 DiscordSocketClient 添加到 ServiceProvider。相反,你这样做

//bad
.AddSingleton<DiscordSocketClient>()

而你应该做的是

//good
.AddSingleton(_client)

因为您没有在配置服务中将客户端实例添加到您的服务提供者,从服务提供者检索客户端实际上会实例化一个新的 DiscordSocketClient,因为提供者中尚不存在.

var client = services.GetRequiredService<DiscordSocketClient>();

tl;dr - ensure you are only using a single instance of DiscordSocketClient. This instance should be configured with the appropriate intents.