#.net-core #discord #discord.net
#.net-core #Discord #discord.net
Вопрос:
Я пытаюсь создать своего собственного бота Discord, который мягко запрещает людям, которые пишут расистские или антисемитские слова. Я пытаюсь сделать это с помощью MessageReceivedAsync, но он постоянно вылетает с ошибкой «Обработчик MessageReceived блокирует задачу шлюза».
Вот код моей 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();
}
}
}
И вот мой код для службы обработки:
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}");
}
}
}
Как я могу исправить эту проблему?
Комментарии:
1. обработка кода в вашем обработчике занимает слишком много времени. Все, выполнение чего займет более 3 секунд, заблокирует регистрацию этого сообщения. Любой долго выполняющийся код должен выполняться в другой задаче (т.е. Не в задаче шлюза).
2. @Anu6is как мне это сделать, например? Не могли бы вы показать мне это при использовании моего кода?
3. Просто оберните всю логику внутри обработчика событий черного списка в
Task.Run()
. Кроме того, вашProgram.cs
не должен наследоваться отModuleBase
иContext
будет недействительным в этом классе, поскольку он фактически никогда не создавался.4. @Anu6is Я все еще не понимаю. Не могли бы вы переписать мой код при использовании Task.Run()?
Ответ №1:
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;
}
Комментарии:
1. Но теперь я не могу использовать «using (BlacklistDatabaseContext lite = new BlacklistDatabaseContext ())»
2. Почему вы не можете его использовать?
3. В нем написано «недопустимое выражение»
4. это не должно иметь ничего общего с синтаксисом
Task.Run()
проверки вашего кода5. ааааа, я забыл написать ‘async’ в Task.Run