当我遇到这个问题时,我正在为我的discord bot创建一个新的帮助命令:当调用两个或多个帮助命令时,只有最后一个可以正确处理按钮交互,其他所有命令都会出错。
我的帮助命令分为子菜单,用户可以使用StringSelectMenu进行选择。每个子菜单包含相同类别的命令页面。
示例
当我调用/help
命令两次并返回与第一个命令的按钮交互时,如果我到达子菜单的最后一页,“Next”和“Last”按钮应该被禁用,但在这种情况下它们没有被禁用。但是,最后一个命令仍然按其应有的方式工作。
当我在前面的命令中导航回第一页时也会发生此问题。
我的问题视频演示:
https://www.youtube.com/watch?v=aWtvcNmrX80
我认为导致此问题的原因:
我认为变量currentPage
是静态的,并且在命令之间共享。
然而,当调用第二个命令时,只有该第二个命令可以更新currentPage
的值,并且由于所有命令之间只有一个currentPage
共享,因此先前的命令将被迫使用最后一个命令的currentPage
的值,这将先前命令的页索引修改为不需要的页索引。
我希望发生的事情:
- 当用户选择新的子菜单时,“第一个”和“上一个”按钮将自动禁用。如果子菜单有多个页面,“下一页”和“最后一页”按钮将自动启用。否则,禁用所有按钮。
- 当用户到达子菜单的最后一页时,“下一页”和“最后一页”按钮自动禁用。
- 当用户到达子菜单的第一页时,“上一页”和“第一页”按钮自动禁用。
- 当用户处于既不是第一页也不是最后一页的页面中时,所有按钮都被启用。
我尝试过:
- 基于
interaction.id
为每个按钮创建唯一的ID。 - 记录页面索引
currentPage
以跟踪其更改。 - 查看按钮的更新条件。
- 寻找其他人的解决方案,但没有一个奏效。
- 创建会话,为用户提供
currentPage
的唯一示例。 - 使用立即调用的函数表达式来限制作用域。
我的当前编码:
- 命令的完整代码:https://pastebin.com/Ttv6YaY0的
- 用于处理按钮交互和更新页面索引的部分代码:
// 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,
});
}
});
字符串
任何帮助将不胜感激!谢谢你,谢谢
1条答案
按热度按时间2vuwiymt1#
多亏了其他程序员的帮助,我找到了一种处理按钮交互的替代方法。解决方案如下:
**我创建了一个函数,它将使用两个参数
currentPage
和maxPage
来更新和返回新的按钮组件。每次我需要编辑按钮组件时,我可以在interaction.editReply()
中的components
参数中传递此函数。将返回布尔值的条件在每个
ButtonBuilder()
的setDisabled
函数中传递,因此当条件满足时,按钮可以禁用自己。函数如下:
字符串