javascript discord.js:bot无法正确处理带有按钮的多个命令

2nbm6dog  于 2023-08-02  发布在  Java
关注(0)|答案(1)|浏览(96)

当我遇到这个问题时,我正在为我的discord bot创建一个新的帮助命令:当调用两个或多个帮助命令时,只有最后一个可以正确处理按钮交互,其他所有命令都会出错。
我的帮助命令分为子菜单,用户可以使用StringSelectMenu进行选择。每个子菜单包含相同类别的命令页面。

示例

当我调用/help命令两次并返回与第一个命令的按钮交互时,如果我到达子菜单的最后一页,“Next”和“Last”按钮应该被禁用,但在这种情况下它们没有被禁用。但是,最后一个命令仍然按其应有的方式工作。
当我在前面的命令中导航回第一页时也会发生此问题。

我的问题视频演示:

https://www.youtube.com/watch?v=aWtvcNmrX80

我认为导致此问题的原因:

我认为变量currentPage是静态的,并且在命令之间共享。
然而,当调用第二个命令时,只有该第二个命令可以更新currentPage的值,并且由于所有命令之间只有一个currentPage共享,因此先前的命令将被迫使用最后一个命令的currentPage的值,这将先前命令的页索引修改为不需要的页索引。

我希望发生的事情:

  • 当用户选择新的子菜单时,“第一个”和“上一个”按钮将自动禁用。如果子菜单有多个页面,“下一页”和“最后一页”按钮将自动启用。否则,禁用所有按钮。
  • 当用户到达子菜单的最后一页时,“下一页”和“最后一页”按钮自动禁用。
  • 当用户到达子菜单的第一页时,“上一页”和“第一页”按钮自动禁用。
  • 当用户处于既不是第一页也不是最后一页的页面中时,所有按钮都被启用。

我尝试过:

  • 基于interaction.id为每个按钮创建唯一的ID。
  • 记录页面索引currentPage以跟踪其更改。
  • 查看按钮的更新条件。
  • 寻找其他人的解决方案,但没有一个奏效。
  • 创建会话,为用户提供currentPage的唯一示例。
  • 使用立即调用的函数表达式来限制作用域。

我的当前编码:

// Handling received interactions from the collector
            collector.on("collect", async (i) => {
                if (i.user.id == interaction.user.id) {
                    // If the interaction received is not from the buttons nor from the select menu, do nothing.
                    if (!i.isButton() && !i.isStringSelectMenu()) return;
                    // Defer the reply since the command takes longer time than usual to complete
                    await i.deferUpdate();
                    // Button handling starts here
                    if (i.isButton()) {
                        // If the user is still on the starting menu, disable all the buttons
                        if (currentCategory == menu.init) {
                            for (const i of buttons) {
                                await i.setDisabled(true);
                            }
                            // User is not on the starting menu
                        } else {
                            // Update the page according to the interaction of the user
                            switch (i.customId) {
                                case "previous":
                                    currentPage -= 1;
                                    break;
                                case "next":
                                    currentPage += 1;
                                    break;
                                case "first":
                                    currentPage = 0;
                                    break;
                                case "last":
                                    currentPage = currentCategory.length - 1;
                                    break;
                                default:
                                    handleError(
                                        i,
                                        "Unknown button interaction."
                                    );
                            }

                            // Disabled and enable certain buttons to avoid errors
                            // First page
                            if (currentPage == 0) {
                                await previousBtn.setDisabled(true);
                                await firstBtn.setDisabled(true);
                                // Re-enable in case disabled
                                await nextBtn.setDisabled(false);
                                await lastBtn.setDisabled(false);
                                // Last page
                            } else if (
                                currentPage ==
                                currentCategory.length - 1
                            ) {
                                await nextBtn.setDisabled(true);
                                await lastBtn.setDisabled(true);
                                // Re-enable in case disabled
                                await previousBtn.setDisabled(false);
                                await firstBtn.setDisabled(false);
                                // Middle pages
                            } else {
                                // Reenable all buttons in case disabled
                                for (const button of buttons) {
                                    await button.setDisabled(false);
                                }
                            }

                            console.log("BTN:", currentPage);

                            // Update the embed message;
                            await i.editReply({
                                embeds: [currentCategory[currentPage]],
                                components: [selectMenuRow, buttonsRow],
                            });
                        }
                        // Select Menu Handling
                    } else if (i.isStringSelectMenu()) {
                        // i.values[0] is the command category that the user had chosen
                        switch (i.values[0]) {
                            case "fun":
                                currentCategory = menu.fun;
                                break;
                            case "utils":
                                currentCategory = menu.utilities;
                                break;
                            case "welcomebye":
                                currentCategory = menu.welcome_goodbye;
                                break;
                            default:
                                currentCategory = menu.init;
                                break;
                        }
                        currentPage = 0; // Reset the page number
                        // Disable the previous and next buttons to avoid unexpected interactions
                        await firstBtn.setDisabled(true);
                        await previousBtn.setDisabled(true);
                        // If there are more than one page of help in that category, allow the user to move on the next pages
                        if (currentCategory.length > 1) {
                            await nextBtn.setDisabled(false);
                            await lastBtn.setDisabled(false);
                            // If there is only one page of help, disable all the buttons to prevent causing errors
                        } else {
                            await nextBtn.setDisabled(true);
                            await lastBtn.setDisabled(true);
                        }
                        await interaction.editReply({
                            embeds: [currentCategory[currentPage]],
                            components: [selectMenuRow, buttonsRow],
                        });
                    }
                    // A non-command-caller user tries to interact with the command
                } else {
                    await i.deferUpdate();
                    await i.followUp({
                        content: `This is not for you.`,
                        ephemeral: true,
                    });
                }
            });

字符串
任何帮助将不胜感激!谢谢你,谢谢

2vuwiymt

2vuwiymt1#

多亏了其他程序员的帮助,我找到了一种处理按钮交互的替代方法。解决方案如下:

**我创建了一个函数,它将使用两个参数currentPagemaxPage来更新和返回新的按钮组件。每次我需要编辑按钮组件时,我可以在interaction.editReply()中的components参数中传递此函数。

将返回布尔值的条件在每个ButtonBuilder()setDisabled函数中传递,因此当条件满足时,按钮可以禁用自己。
函数如下:

// A function used to update the buttons function
getButtons(currentPage, maxPage) {
    const components = new ActionRowBuilder().addComponents(
        new ButtonBuilder()
            .setCustomId("first")
            .setLabel("First Page")
            .setStyle(ButtonStyle.Primary)
            .setDisabled(!(currentPage > 0)), // Disable if user on first page
        new ButtonBuilder()
            .setCustomId("previous")
            .setLabel("⬅️")
            .setStyle(ButtonStyle.Primary)
            .setDisabled(!(currentPage > 0)), // Disable if user on first page
        new ButtonBuilder()
            .setCustomId("next")
            .setLabel("➡️")
            .setStyle(ButtonStyle.Primary)
            .setDisabled(currentPage == maxPage), // Disable if user on last page
        new ButtonBuilder()
            .setCustomId("last")
            .setLabel("Last Page")
            .setStyle(ButtonStyle.Primary)
            .setDisabled(currentPage == maxPage) // Disable if user on last page
    );

    return components;

}

字符串

相关问题