Discord.net 宣布新用户加入时出现问题
Discord.net Problem with announcing new users joining
我使用 C# 和 Discord.net 制作了我自己的 Discord 机器人,但是在宣布新用户时有些东西不起作用。
当有人加入时,它会发送消息,一切都很好,但紧接着,机器人崩溃并出现错误
System.NullReferenceException: 'Object reference not set to an instance of an object.'
第
行
var context = new SocketCommandContext(_client, message);
关于原因有什么想法吗?
完整代码如下:
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.IO;
using Discord.Rest;
namespace DiscordBot2
{
class Program
{
static void Main()
{
Thread t = new Thread(new ThreadStart(input));
t.Start();
new Program().RunBotAsync().GetAwaiter().GetResult();
}
private DiscordSocketClient _client;
private CommandService _commands;
private IServiceProvider _services;
public async Task RunBotAsync()
{
_client = new DiscordSocketClient();
_commands = new CommandService();
_services = new ServiceCollection()
.AddSingleton(_client)
.AddSingleton(_commands)
.BuildServiceProvider();
string token = "lol you wish";
_client.Log += _client_Log;
await HandleNewUser();
await RegisterCommandsAsync();
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();
await _client.SetGameAsync("with the flock!");
await _client.SetStatusAsync(UserStatus.Online);
await Task.Delay(-1);
}
private Task _client_Log(LogMessage arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
public async Task RegisterCommandsAsync()
{
_client.MessageReceived += HandleCommandAsync; //Handle incoming commands
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
}
public async Task HandleNewUser()
{
_client.UserJoined += AnnounceJoinedUser;
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
}
public async Task AnnounceJoinedUser(SocketGuildUser user)
{
var channel = _client.GetChannel(743578569476931626) as SocketTextChannel; // Gets the channel to send the message in
await channel.SendMessageAsync($"Welcome {user.Mention} to {channel.Guild.Name}"); //Welcomes the new user
return;
}
private async Task HandleCommandAsync(SocketMessage arg)
{
var message = arg as SocketUserMessage;
var context = new SocketCommandContext(_client, message);
//Prevent looping
if (message.Author.IsBot) return;
//Check for prefix
int argPos = 0;
await BadWordsWarn(message);
if (message.HasStringPrefix("c!", ref argPos))
{
//Execute command
var result = await _commands.ExecuteAsync(context, argPos, _services);
//If it failed, log the error
if (!result.IsSuccess)
{
Console.WriteLine(@"'" + message.Content + @"' has thrown an error: " + result.ErrorReason);
//Handle errors in commands
result = await _commands.ExecuteAsync(context, argPos, _services);
if (result.ErrorReason != null)
switch (result.ErrorReason)
{
//Not enough paramaters
case "The input text has too few parameters.":
await context.Channel.SendMessageAsync(
"This command lacks parameters. Check the command description for more details.");
break;
//Bad command
case "Unknown command.":
await context.Channel.SendMessageAsync(
"I don't understand this command. :frowning: You can type **c!list** to see the list of avaliable commands.");
break;
//Some other shenanigans
default:
await context.Channel.SendMessageAsync(
$"{result.ErrorReason}");
break;
}
}
}
}
private async Task BadWordsWarn(SocketMessage message)
{
string[] badWords = File.ReadAllLines("Banned.txt");
if (badWords.Any(word => message.Content.IndexOf(word, 0, message.Content.Length, StringComparison.OrdinalIgnoreCase) >= 0))
{
var m = (RestUserMessage)await message.Channel.GetMessageAsync(message.Id);
await m.DeleteAsync();
}
}
我不确定 Main()
中变量 input
的来源,但我启动机器人的方式如下:
static void Main() => new Program().RunBotAsync().GetAwaiter().GetResult();
您只需调用 AddModulesAsync()
一次。您在 RegisterCommandsAsync()
和 HandleNewUser()
中调用了它。多次调用它可能会导致问题,因此我将其移至 RunBotAsync()
方法并将其从其他两个方法中删除。我还将行 _client.MessageReceived += HandleCommandAsync;
和 _client.UserJoined += AnnounceJoinedUser;
移动到 RunBotAsync()
方法中,因为我留下了两个单独的方法,每个 运行 一行代码,只需要被调用一次,我觉得不需要额外的方法。 RegisterCommandsAsync()
和HandleNewUser()
方法可以删除。
public async Task RunBotAsync()
{
_client = new DiscordSocketClient();
_commands = new CommandService();
_services = new ServiceCollection()
.AddSingleton(_client)
.AddSingleton(_commands)
.BuildServiceProvider();
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services); // This should only be called once. You were calling it in RegisterCommandsAsync() and RegisterCommandsAsync()
string token = "lol you wish";
_client.Log += _client_Log;
_client.UserJoined += AnnounceJoinedUser;
_client.MessageReceived += HandleCommandAsync; //Handle incoming commands
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();
await _client.SetGameAsync("with the flock!");
await _client.SetStatusAsync(UserStatus.Online);
await Task.Delay(-1);
}
您的 HandleCommandAsync()
方法中的行 var message = arg as SocketUserMessage;
可能导致 null
,这看起来像是问题的原因。为了处理这个问题,我将该行替换为 if (arg is SocketUserMessage message)
并将所有代码包装在其中。这样您就可以在执行其余代码之前检查 null
。或者,您可以保留原始行并在其下方添加 if (message == null) return;
。
您还使用 _commands.ExecuteAsync
执行您的命令,如果它们失败,您将再次执行它们,然后再向 Discord 频道发送错误响应。如果一个命令第一次失败,那么它第二次也可能失败,所以我不确定你为什么要再次执行它们。我已经评论了第二行,所以它现在只执行一次。
private async Task HandleCommandAsync(SocketMessage arg)
{
if (arg is SocketUserMessage message)
{
var context = new SocketCommandContext(_client, message);
//Prevent looping
if (message.Author.IsBot) return;
//Check for prefix
int argPos = 0;
await BadWordsWarn(message);
if (message.HasStringPrefix("c!", ref argPos))
{
//Execute command
var result = await _commands.ExecuteAsync(context, argPos, _services);
//If it failed, log the error
if (!result.IsSuccess)
{
Console.WriteLine(@"'" + message.Content + @"' has thrown an error: " + result.ErrorReason);
//Handle errors in commands
//result = await _commands.ExecuteAsync(context, argPos, _services); // Why are you executing the command again after it failed?
if (result.ErrorReason != null)
switch (result.ErrorReason)
{
//Not enough paramaters
case "The input text has too few parameters.":
await context.Channel.SendMessageAsync(
"This command lacks parameters. Check the command description for more details.");
break;
//Bad command
case "Unknown command.":
await context.Channel.SendMessageAsync(
"I don't understand this command. :frowning: You can type **c!list** to see the list of avaliable commands.");
break;
//Some other shenanigans
default:
await context.Channel.SendMessageAsync(
$"{result.ErrorReason}");
break;
}
}
}
}
}
这个 YouTube 视频帮助我开始使用 Discord.Net。也许它也会对您有所帮助:https://www.youtube.com/watch?v=ccsf5Rcu9mM
我使用 C# 和 Discord.net 制作了我自己的 Discord 机器人,但是在宣布新用户时有些东西不起作用。 当有人加入时,它会发送消息,一切都很好,但紧接着,机器人崩溃并出现错误
System.NullReferenceException: 'Object reference not set to an instance of an object.'
第
行 var context = new SocketCommandContext(_client, message);
关于原因有什么想法吗?
完整代码如下:
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.IO;
using Discord.Rest;
namespace DiscordBot2
{
class Program
{
static void Main()
{
Thread t = new Thread(new ThreadStart(input));
t.Start();
new Program().RunBotAsync().GetAwaiter().GetResult();
}
private DiscordSocketClient _client;
private CommandService _commands;
private IServiceProvider _services;
public async Task RunBotAsync()
{
_client = new DiscordSocketClient();
_commands = new CommandService();
_services = new ServiceCollection()
.AddSingleton(_client)
.AddSingleton(_commands)
.BuildServiceProvider();
string token = "lol you wish";
_client.Log += _client_Log;
await HandleNewUser();
await RegisterCommandsAsync();
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();
await _client.SetGameAsync("with the flock!");
await _client.SetStatusAsync(UserStatus.Online);
await Task.Delay(-1);
}
private Task _client_Log(LogMessage arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
public async Task RegisterCommandsAsync()
{
_client.MessageReceived += HandleCommandAsync; //Handle incoming commands
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
}
public async Task HandleNewUser()
{
_client.UserJoined += AnnounceJoinedUser;
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
}
public async Task AnnounceJoinedUser(SocketGuildUser user)
{
var channel = _client.GetChannel(743578569476931626) as SocketTextChannel; // Gets the channel to send the message in
await channel.SendMessageAsync($"Welcome {user.Mention} to {channel.Guild.Name}"); //Welcomes the new user
return;
}
private async Task HandleCommandAsync(SocketMessage arg)
{
var message = arg as SocketUserMessage;
var context = new SocketCommandContext(_client, message);
//Prevent looping
if (message.Author.IsBot) return;
//Check for prefix
int argPos = 0;
await BadWordsWarn(message);
if (message.HasStringPrefix("c!", ref argPos))
{
//Execute command
var result = await _commands.ExecuteAsync(context, argPos, _services);
//If it failed, log the error
if (!result.IsSuccess)
{
Console.WriteLine(@"'" + message.Content + @"' has thrown an error: " + result.ErrorReason);
//Handle errors in commands
result = await _commands.ExecuteAsync(context, argPos, _services);
if (result.ErrorReason != null)
switch (result.ErrorReason)
{
//Not enough paramaters
case "The input text has too few parameters.":
await context.Channel.SendMessageAsync(
"This command lacks parameters. Check the command description for more details.");
break;
//Bad command
case "Unknown command.":
await context.Channel.SendMessageAsync(
"I don't understand this command. :frowning: You can type **c!list** to see the list of avaliable commands.");
break;
//Some other shenanigans
default:
await context.Channel.SendMessageAsync(
$"{result.ErrorReason}");
break;
}
}
}
}
private async Task BadWordsWarn(SocketMessage message)
{
string[] badWords = File.ReadAllLines("Banned.txt");
if (badWords.Any(word => message.Content.IndexOf(word, 0, message.Content.Length, StringComparison.OrdinalIgnoreCase) >= 0))
{
var m = (RestUserMessage)await message.Channel.GetMessageAsync(message.Id);
await m.DeleteAsync();
}
}
我不确定 Main()
中变量 input
的来源,但我启动机器人的方式如下:
static void Main() => new Program().RunBotAsync().GetAwaiter().GetResult();
您只需调用 AddModulesAsync()
一次。您在 RegisterCommandsAsync()
和 HandleNewUser()
中调用了它。多次调用它可能会导致问题,因此我将其移至 RunBotAsync()
方法并将其从其他两个方法中删除。我还将行 _client.MessageReceived += HandleCommandAsync;
和 _client.UserJoined += AnnounceJoinedUser;
移动到 RunBotAsync()
方法中,因为我留下了两个单独的方法,每个 运行 一行代码,只需要被调用一次,我觉得不需要额外的方法。 RegisterCommandsAsync()
和HandleNewUser()
方法可以删除。
public async Task RunBotAsync()
{
_client = new DiscordSocketClient();
_commands = new CommandService();
_services = new ServiceCollection()
.AddSingleton(_client)
.AddSingleton(_commands)
.BuildServiceProvider();
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services); // This should only be called once. You were calling it in RegisterCommandsAsync() and RegisterCommandsAsync()
string token = "lol you wish";
_client.Log += _client_Log;
_client.UserJoined += AnnounceJoinedUser;
_client.MessageReceived += HandleCommandAsync; //Handle incoming commands
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();
await _client.SetGameAsync("with the flock!");
await _client.SetStatusAsync(UserStatus.Online);
await Task.Delay(-1);
}
您的 HandleCommandAsync()
方法中的行 var message = arg as SocketUserMessage;
可能导致 null
,这看起来像是问题的原因。为了处理这个问题,我将该行替换为 if (arg is SocketUserMessage message)
并将所有代码包装在其中。这样您就可以在执行其余代码之前检查 null
。或者,您可以保留原始行并在其下方添加 if (message == null) return;
。
您还使用 _commands.ExecuteAsync
执行您的命令,如果它们失败,您将再次执行它们,然后再向 Discord 频道发送错误响应。如果一个命令第一次失败,那么它第二次也可能失败,所以我不确定你为什么要再次执行它们。我已经评论了第二行,所以它现在只执行一次。
private async Task HandleCommandAsync(SocketMessage arg)
{
if (arg is SocketUserMessage message)
{
var context = new SocketCommandContext(_client, message);
//Prevent looping
if (message.Author.IsBot) return;
//Check for prefix
int argPos = 0;
await BadWordsWarn(message);
if (message.HasStringPrefix("c!", ref argPos))
{
//Execute command
var result = await _commands.ExecuteAsync(context, argPos, _services);
//If it failed, log the error
if (!result.IsSuccess)
{
Console.WriteLine(@"'" + message.Content + @"' has thrown an error: " + result.ErrorReason);
//Handle errors in commands
//result = await _commands.ExecuteAsync(context, argPos, _services); // Why are you executing the command again after it failed?
if (result.ErrorReason != null)
switch (result.ErrorReason)
{
//Not enough paramaters
case "The input text has too few parameters.":
await context.Channel.SendMessageAsync(
"This command lacks parameters. Check the command description for more details.");
break;
//Bad command
case "Unknown command.":
await context.Channel.SendMessageAsync(
"I don't understand this command. :frowning: You can type **c!list** to see the list of avaliable commands.");
break;
//Some other shenanigans
default:
await context.Channel.SendMessageAsync(
$"{result.ErrorReason}");
break;
}
}
}
}
}
这个 YouTube 视频帮助我开始使用 Discord.Net。也许它也会对您有所帮助:https://www.youtube.com/watch?v=ccsf5Rcu9mM