Reputation: 47
I'm building a Discord bot using Discord.NET which is supposed to report a user joining, leaving, being kicked and being banned to a mod/admin-only auditing channel, except I can't get the relevant function to trigger when a user joins the guild.
I removed my message sending code and replaced it with a console output to determine whether or not the problem is the event not triggering or the send message request not working and found the event wasn't being triggered.
I've enabled all the intents in the Bot management console.
I've added intents according to the documentation:
var socketConfig = new DiscordSocketConfig
{
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.GuildBans
};
_client = new DiscordSocketClient(socketConfig);
I've then registered the event: (Note: _client = client;
is used before this)
client.UserJoined += UserJoined;
And finally written the function to be triggered:
public Task UserJoined(SocketGuildUser user)
{
Console.Write("User ");
Console.Write(user.Username);
Console.WriteLine(" joined.");
return Task.CompletedTask;
}
Is there anything I've not done or done wrong here? I've spent about two days on this with absolutely no idea what the problem is, everything seems to point to me doing everything right yet I'm unable to receive this event from Discord.
Every change I've made I've additionally tried removing and re-adding the bot to my test server. I also don't receive any kind of message similar to [12/8/2018 10:01:30 PM at Gateway] Received Dispatch (GUILD_MEMBER_ADD)
as mentioned in this post.
I've included my full Program.cs below:
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();
}
}
}
Upvotes: 0
Views: 2010
Reputation: 2658
You create an instance of DiscordSocketClient
and include the appropriate DiscordSocketConfig
//good
var socketConfig = new DiscordSocketConfig
{
GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.GuildMembers | GatewayIntents.GuildBans
};
_client = new DiscordSocketClient(socketConfig);
However, in ConfigureServices
you should be adding the DiscordSocketClient
that you created previously to the ServiceProvider
. Instead you do this
//bad
.AddSingleton<DiscordSocketClient>()
while what you should have done is
//good
.AddSingleton(_client)
Because you didn't add an instance of the client to your service provider in configure services, retrieving the client from the service provider will actually instantiate a new DiscordSocketClient
as one does not yet exist in the provider.
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.
Upvotes: 3