不一致.NET API Bot -命令不起作用

hfsqlsce  于 2023-03-13  发布在  .NET
关注(0)|答案(1)|浏览(130)

由于我是相当新的.NET和编程一般,我卡住了,而创建一个机器人与不和谐的.NET API。

using Discord;
using Discord.Interactions;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using System.Reflection;
using System.Windows.Input;

public class Program
{
    public static Task Main(string[] args) => new Program().MainAsync();

    private static DiscordSocketClient _client;
    private CommandHandler _commandHandler;
    private static CommandService _commands;
    

    public async Task MainAsync()
    {
        _client = new DiscordSocketClient();
        _commands = new CommandService();
        _commandHandler = new CommandHandler(_client, _commands);
        await _commandHandler.InstallCommandsAsync();

        _client.Log += Log;

        var token = "XXXXXX";

        
        await _client.LoginAsync(TokenType.Bot, token);
        await _client.StartAsync();
        
       
        

        // Block this task until the program is closed.
        await Task.Delay(-1);
    }

    //--Commandhandler--//

    public class CommandHandler
    {
        private readonly DiscordSocketClient _client;
        private readonly CommandService _commands;

        // Retrieve client and CommandService instance via ctor
        public CommandHandler(DiscordSocketClient client, CommandService commands)
        {
            _commands = commands;
            _client = client;
        }

        public async Task InstallCommandsAsync()
        {
            // Hook the MessageReceived event into our command handler
            _client.MessageReceived += HandleCommandAsync;

            // Here we discover all of the command modules in the entry 
            // assembly and load them. Starting from Discord.NET 2.0, a
            // service provider is required to be passed into the
            // module registration method to inject the 
            // required dependencies.
            //
            // If you do not use Dependency Injection, pass null.
            // See Dependency Injection guide for more information.
            await _commands.AddModulesAsync(assembly: Assembly.GetEntryAssembly(),
                                            services: null);
        }

        private async Task HandleCommandAsync(SocketMessage messageParam)
        {
            // Don't process the command if it was a system message
            var message = messageParam as SocketUserMessage;
            if (message == null) return;

            // Create a number to track where the prefix ends and the command begins
            int argPos = 0;

            // Determine if the message is a command based on the prefix and make sure no bots trigger commands
            if (!(message.HasCharPrefix('!', ref argPos) ||
                message.HasMentionPrefix(_client.CurrentUser, ref argPos)) ||
                message.Author.IsBot)
                return;

            // Create a WebSocket-based command context based on the message
            var context = new SocketCommandContext(_client, message);

            // Execute the command with the command context we just
            // created, along with the service provider for precondition checks.
            await _commands.ExecuteAsync(
                context: context,
                argPos: argPos,
                services: null);
        }
    }

    public class InfoModule : InteractionModuleBase<SocketInteractionContext>
    {
        // ~say hello world -> hello world
        [Command("say")]
        public Task SayAsync(string echo)
        {
           return ReplyAsync(echo);
        }

    }
    public class ExampleCommands : InteractionModuleBase<SocketInteractionContext>
    {
        // dependencies can be accessed through Property injection, public properties with public setters will be set by the service provider
        public InteractionService Commands { get; set; }
        private CommandHandler _handler;

        // constructor injection is also a valid way to access the dependecies
        public ExampleCommands(CommandHandler handler)
        {
            _handler = handler;
        }

        // our first /command!
        [SlashCommand("8ball", "find your answer!")]
        public async Task EightBall(string question)
        {
            // create a list of possible replies
            var replies = new List<string>();

            // add our possible replies
            replies.Add("yes");
            replies.Add("no");
            replies.Add("maybe");
            replies.Add("hazzzzy....");

            // get the answer
            var answer = replies[new Random().Next(replies.Count - 1)];

            // reply with the answer
            await RespondAsync($"You asked: [**{question}**], and your answer is: [**{answer}**]");
        }
    }

    private Task Log(LogMessage msg)
    {
        Console.WriteLine(msg.ToString());
        return Task.CompletedTask;
    }

}

我的问题是机器人不响应我已经添加的2个命令模块。其中一些代码来自API指南...机器人不响应这些命令...
我已经授予它发送消息、读取消息历史记录和使用斜杠命令的权限。我已经尝试在Main中添加.InstallCommandsAsync(),但我不知道从现在开始该怎么做。我没有调用需要在Main中调用的方法吗?我做错了什么?

gudnpqoy

gudnpqoy1#

首先,您在这里遇到了两个错误,类InteractionModuleBase<SocketInteractionContext>用于斜线命令,而不是基于文本的命令,因此您的HandleCommandAsync任务将仅注册基于聊天文本的命令,并且您没有任何处理程序和斜线命令的注册。此外,您还应编辑MainAsync任务调用,根据文档,它应为static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
关于基于文本的命令:

  • 包含命令的类必须继承自ModuleBase<SocketCommandContext>

关于斜线命令(带属性):

  • 使用InteractionService
  • 使用IServiceProvider
  • 添加模块和注册命令
  • 生成交互(命令)的处理程序
  • 为了确保一切正常,您应该在_client.Ready事件中执行此操作

示例:
添加使用(如有必要,请更新此包):

using Microsoft.Extensions.DependencyInjection;

正确的主要方法:

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

其他变量:

private static DiscordSocketClient _client;
private CommandHandler _commandHandler;
private static CommandService _commands;

private InteractionService _interactionService; //+
private readonly IServiceProvider _serviceProvider = CreateServices(); //+

创建服务方法:

static IServiceProvider CreateServices()
        {
            var config = new DiscordSocketConfig()
            {
                GatewayIntents = GatewayIntents.All
            }; //This is only example config, feel free to make own
            
            var collection = new ServiceCollection()
                .AddSingleton(config)
                .AddSingleton<DiscordSocketClient>();

            return collection.BuildServiceProvider();
        }

调整MainAsync任务:

//_client = new DiscordSocketClient(); //Remove this
    //_commands = new CommandService(); //You can remove this too its not necessary for slash commands
    //_commandHandler = new CommandHandler(_client, _commands); //You can remove this too its not necessary for slash commands
    //await _commandHandler.InstallCommandsAsync(); //You can remove this too its not necessary for slash commands
    _client = _serviceProvider.GetRequiredService<DiscordSocketClient>(); //+

    _client.Ready += _client_Ready;

最后添加模块和交互处理:

private async Task _client_Ready()
        {
            _interactionService = new InteractionService(_client);
            await _interactionService.AddModulesAsync(Assembly.GetEntryAssembly(), _serviceProvider);
            await _interactionService.RegisterCommandsGloballyAsync();

            _client.InteractionCreated += async (x) =>
            {
                var ctx = new SocketInteractionContext(_client, x);
                await _interactionService.ExecuteCommandAsync(ctx, _serviceProvider);
            };
        }

删除此代码片段,因为它是不必要的:

// dependencies can be accessed through Property injection, public properties with public setters will be set by the service provider
        public InteractionService Commands { get; set; }
        private CommandHandler _handler;

        // constructor injection is also a valid way to access the dependecies
        public ExampleCommands(CommandHandler handler)
        {
            _handler = handler;
        }

为了确保我测试了这个,斜线命令工作完美。同样,当我测试基于文本的命令时(修复继承后),它工作正常,但只能通过提到@botmention say something而不是通过前缀调用bot,所以我不知道是什么原因导致了这个问题。另外,如果你想让say命令处理多个单词,请添加如下剩余属性:1米10英寸1x

资料来源:
https://discordnet.dev/guides/concepts/events.html
https://discordnet.dev/guides/int_basics/application-commands/slash-commands/creating-slash-commands.html
https://discordnet.dev/guides/dependency_injection/basics.html
https://discordnet.dev/guides/dependency_injection/services.html
https://discordnet.dev/guides/int_framework/intro.html

相关问题