如何修复机器人在使用 SlashCommand 和按钮编辑消息时抛出 NotFound 错误? DSharpPlus

问题描述 投票:0回答:1

因此该命令的工作原理如下。用户选择类别,然后键入查询。 Bot 使用 GraphQL 客户端搜索内容,发送包含 5 个结果的消息。用户现在单击 1-5 中的按钮来选择一个对象,机器人将编辑消息。第一次使用命令和按钮时,这完全可以正常工作。但是当第二次尝试整个过程时,机器人会在控制台中抛出消息 NotFound:

[2023-12-25 02:56:21 +01:00] [104 /EventHandler] [Error] Event handler exception for event COMPONENT_INTERACTED thrown from System.Threading.Tasks.Task <SearchCommand>b__0(DSharpPlus.DiscordClient, DSharpPlus.EventArgs.ComponentInteractionCreateEventArgs) (defined in AnimeSharpBot.SearchModule+<>c__DisplayClass0_0)
DSharpPlus.Exceptions.NotFoundException: Not found: 404
   at DSharpPlus.Net.DiscordApiClient.CreateInteractionResponseAsync(UInt64 interaction_id, String interaction_token, InteractionResponseType type, DiscordInteractionResponseBuilder builder)
   at AnimeSharpBot.SearchModule.ButtonClick(DiscordClient sender, ComponentInteractionCreateEventArgs e, IEnumerable`1 animeDetails) in C:\Users\mrady\RiderProjects\AnimeSharpBot\SearchModule.cs:line 110
   at AnimeSharpBot.SearchModule.<>c__DisplayClass0_0.<<SearchCommand>b__0>d.MoveNext() in C:\Users\mrady\RiderProjects\AnimeSharpBot\SearchModule.cs:line 44
--- End of stack trace from previous location ---
   at DSharpPlus.AsyncEvents.AsyncEvent`2.<>c__DisplayClass7_0.<<InvokeAsync>b__0>d.MoveNext()

这让我很困惑,因为该功能可以工作,但由于某种原因出现该错误。我该如何修复它?这是我的代码:

using System.Text;
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.SlashCommands;
using AniListNet;
using AniListNet.Objects;
using AniListNet.Parameters;
using DSharpPlus.EventArgs;

namespace AnimeSharpBot;

public class SearchModule : ApplicationCommandModule
{
    [SlashCommand("search", "Search for anime, manga, staff, character, or studio")]
    public async Task SearchCommand(InteractionContext ctx,
        [Option("category", "Category to search for")]
        [Choice("Anime", "anime")]
        [Choice("Manga", "manga")]
        [Choice("Staff", "staff")]
        [Choice("Character", "character")]
        [Choice("Studio", "studio")]
        string category,
        [Option("query", "Search query")]
        string query)
    {
        var (resultMessage, animeDetails) = await SearchAsync(category, query);

        var row = new DiscordComponent[]
        {
            new DiscordButtonComponent(ButtonStyle.Primary, "option_1", "1"),
            new DiscordButtonComponent(ButtonStyle.Primary, "option_2", "2"),
            new DiscordButtonComponent(ButtonStyle.Primary, "option_3", "3"),
            new DiscordButtonComponent(ButtonStyle.Primary, "option_4", "4"),
            new DiscordButtonComponent(ButtonStyle.Primary, "option_5", "5"),
        };

        var message = new DiscordMessageBuilder()
            .WithContent(resultMessage)
            .AddComponents(row)
            .SendAsync(ctx.Channel);

        var client = ctx.Client;
        client.ComponentInteractionCreated += async (sender, e) =>
            await ButtonClick(sender, e, animeDetails);
    }

    private async Task<(string ResultMessage, IEnumerable<Media> AnimeDetails)> SearchAsync(string category, string query)
    {
        var resultMessage = new StringBuilder();
        var client = new AniClient();
        IEnumerable<Media> animeDetails = null;

        if (category.Equals("anime", StringComparison.OrdinalIgnoreCase))
        {
            var results = await client.SearchMediaAsync(new SearchMediaFilter
            {
                Query = query,
                Type = MediaType.Anime,
                Sort = MediaSort.Popularity,
                Format = new Dictionary<MediaFormat, bool>
                {
                    { MediaFormat.TV, true },
                    { MediaFormat.Movie, true },
                    { MediaFormat.TVShort, true }
                }
            });

            for (int i = 0; i < Math.Min(results.Data.Length, 5); i++)
            {
                var animeTitle = results.Data[i].Title.EnglishTitle;
                resultMessage.AppendLine($"Result {i + 1}: {animeTitle}");
            }
            
            animeDetails = results.Data;
        }
        else if (category.Equals("manga", StringComparison.OrdinalIgnoreCase))
        {
            
        }
        else if (category.Equals("staff", StringComparison.OrdinalIgnoreCase))
        {
            
        }
        else if (category.Equals("character", StringComparison.OrdinalIgnoreCase))
        {
            
        }
        else if (category.Equals("studio", StringComparison.OrdinalIgnoreCase))
        {
            
        }
        else
        {
            return ("Please choose a valid category (anime, manga, staff, character, studio).", null);
        }

        return (resultMessage.ToString(), animeDetails);
    }

    private async Task ButtonClick(DiscordClient sender, ComponentInteractionCreateEventArgs e, IEnumerable<Media> animeDetails)
    {
        int selectedOption = int.Parse(e.Id.Substring("option_".Length));
        
        var selectedAnime = animeDetails.ElementAtOrDefault(selectedOption - 1);

        if (selectedAnime != null)
        {
            await e.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage,
                new DiscordInteractionResponseBuilder().WithContent($"You selected option {selectedOption}! Here are the details:\n{selectedAnime.Title.EnglishTitle} (ID: {selectedAnime.Id})\n{selectedAnime.Description}"));
        }
    }
}

如果确实有问题,您可以提出除修复之外的任何建议。

c# discord bots dsharp+
1个回答
0
投票

你的错误根源可以在这里的代码中找到,我在引起错误的地方和问题根源处进行了评论

    private async Task ButtonClick(DiscordClient sender, ComponentInteractionCreateEventArgs e,
        IEnumerable<Media> animeDetails) //404 caused in second arg
    {
        int selectedOption = int.Parse(e.Id.Substring("option_".Length));
        
        var selectedAnime = animeDetails.ElementAtOrDefault(selectedOption - 1);

        if (selectedAnime != null)
        {
            await e.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, //404 source, I set the 3 second countdown right here
                new DiscordInteractionResponseBuilder().WithContent($"You selected option {selectedOption}! Here are the details:\n{selectedAnime.Title.EnglishTitle} (ID: {selectedAnime.Id})\n{selectedAnime.Description}"));
        }
    }

当您在第一个

ComponentInteractionCreated
事件触发后超过 3 秒获取
ComponentInteractionCreateEventArgs
来调用
ComponentInteractionCreated
事件时,就会出现此问题。您可以通过使用
DeferredMessageUpdate
而不是
UpdateMessage
来触发后续消息来解决此问题。 DeferredMessageUpdate API 信息可以在这里找到DiscordFollowUpMessageBuilder 可以在这里找到

您可以直接从 DSharpPlus 找到讨论此问题的示例

解决此问题的另一种方法是删除机器人发送的原始消息,并在发生交互时重新发送具有相同内容和按钮的相同消息,但这会造成更多卡顿,并且适用于 API 实际上不同意的用例你在做什么。

© www.soinside.com 2019 - 2024. All rights reserved.