如何检查用户是否正在与 select 菜单交互并在 discord.js v13 中禁用它
How do I check if the user is interacting with select menu and disable it in discord.js v13
我希望当用户与 select 菜单交互时,它应该可以工作,然后在用户停止与之交互几秒钟后将其禁用。
这就是 Dank Memer bot Help 命令的工作原理。
我的命令在做什么:
该命令用作帮助命令,获取命令文件夹子文件夹中的所有文件,并给出命令的用法、名称和描述。当用户 select 在 select 菜单中有一个选项并且该选项是命令文件夹的子文件夹时,它会编辑嵌入。
到目前为止,我一直这样做:
const { MessageEmbed, Message, MessageActionRow, MessageSelectMenu, MessageButton } = require("discord.js");
const fs = require("fs");
const prefix = require("../../config.json").PREFIX;
module.exports = {
name: "help",
description: "Get All The Commands!",
usage: "help",
cooldown: 1000 * 5,
category: "Help Commands!",
/**
* @param {Message} message
*
*/
run: async (client, message, args) => {
const sizeOfCat = fs.readdirSync("./Commands - Staff/");
const OldEmbed = new MessageEmbed()
.setAuthor({
name: "Commands! =>",
iconURL: `${message.guild.iconURL({ dynamic: true })}`
})
.setThumbnail(`${message.guild.iconURL({ dynamic: true })}`)
.setTitle(" Need help? Select The Category You Want To =>")
.setDescription(
`
**\`Hello Dear ${message.member.user.username}, Please Select Your Category According To Your Choice!\`**
**How To Use =>**
\`1) Click The Select Menu Down Below.\`
\`2) You Will See Many Categories, Click Your Category You Want To View.\`
\`3) The Embed Will Be Edited And You Can See Your Commands According To Category.\`
*Note => The Select Menu And The Button Will Be Disabled Automatically After 6 Seconds!*
**Total Categories Are: ${sizeOfCat.length}**
`
)
.setColor("BLURPLE")
.setTimestamp()
.setFooter({
text: `Requested by ${message.author.tag}`,
iconURL: message.author.displayAvatarURL({ dynamic: true })
})
const homeButton = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId("Home")
.setLabel("Back To Home!")
.setStyle("PRIMARY")
.setEmoji("️")
)
const EmojisCat = {
"Other Commands!": "",
"Help Commands!": "",
"Moderation Commands!": "⚒️",
"Owner Commands!": ""
};
const selectMenu = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId("Help-Menu")
.setPlaceholder(`Click To View The Categories Of The Commands!`)
.addOptions([
client.categoriesCommands.map((cat) => {
return {
label: `${cat[0].toUpperCase() + cat.slice(1)}`,
value: cat,
emoji: EmojisCat[cat],
description: `Click To View The Commands Of This Categories!`,
}
})
])
);
await message.reply({
content: "**There You Go, Check The List Of Categories!**",
embeds: [OldEmbed],
components: [selectMenu, homeButton]
})
.then(async (msg) => {
let filter = i => i.member.id === message.member.id;
let colletor = msg.createMessageComponentCollector({ filter: filter });
let timeout = null;
colletor.on("collect", async (i) => {
if (!i.member.id === message.member.id) {
await msg.reply({
content: `**Its Not Your Turn Of Using The Command Menu Or The Command (\`${prefix}help\`) Is Not Runned By You! Dum Dum.**`,
ephemeral: true,
});
} else {
if (i.isButton()) {
await i.deferUpdate();
if (i.customId === "Home") {
msg.edit({ embeds: [OldEmbed] })
}
}
if (i.isSelectMenu()) {
if (i.customId === "Help-Menu") {
await i.deferUpdate();
let [ directory ] = i.values;
let totalCdms = client.categoriesCommands.filter(cmd => cmd.category === directory).map(cmd => cmd.size);
let command = client.categoriesCommands.filter(cmd => cmd.category === directory).map(cmd => cmd.length) + 1;
const embed = new MessageEmbed()
.setAuthor({
name: "AwesomeSMP Commands! =>",
iconURL: `${message.guild.iconURL({ dynamic: true })}`
})
.setThumbnail(`${message.guild.iconURL({ dynamic: true })}`)
.setTitle(` Need help? Here Are All Of My ${directory} Commands:`)
.setDescription(
`
**\`Here Are One Of My [${directory} Category] Commands =>\`**
**Total Commands In ${directory} Are: ${totalCdms}**
`
)
.setColor("BLURPLE")
.setTimestamp()
.setFooter({
text: `Requested by ${message.author.tag}`,
iconURL: message.author.displayAvatarURL({ dynamic: true })
})
client.commands.filter((cmd) => cmd.category === directory)
.map((cmd) => {
embed.addField(
`\n**\nCommmand-${command++}** =>\n\`${prefix}${cmd.name}\``,
` **Description:** *${cmd.description.toUpperCase() || "*None*"}*\n **Usage:** *${prefix} ${cmd.usage || "None"}*\n`
,true
);
})
await msg.edit({
embeds: [embed]
});
if (!i.message.member.id === i.isSelectMenu()) {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(async () => {
selectMenu.components[0].setDisabled(true);
homeButton.components[0].setDisabled(true);
await msg.edit({
embeds: [OldEmbed],
components: [selectMenu, homeButton]
});
}, 6000);
}
}
}
}
});
});
}
}
到目前为止没有错误。
正如我在评论中提到的,看起来你想要做的就是在你的收集器之前声明一个空变量(例如,命名为 timeout
),每次收集器收集你做的事情clearTimeout(timeout)
如果定义了 timeout
,然后你设置 timeout
等于你当前的 setTimeout()
语句。也就是说,如果我正确理解你的问题。忽略我最初关于将超时完全移到收集器之外的评论,因为这可能不是您要寻找的问题(我相信我最初误解了您的问题——但是,如果这个答案仍然不是您要找的,我最初的评论可能正是您要找的)。
现在回答你的问题。这是我在上面和评论中描述的过程中谈论的示例。我将只展示代码的相关部分,以便您了解一切发生的位置,而不必筛选几十行代码来查找我的更改(并且请注意,以后请只包含您的代码部分与您的问题相关 - 即在这种情况下只是您的收集器和 collector.on("collect")
处理程序)。
async function disableAll() {
selectMenu.components[0].setDisabled(true);
homeButton.components[0].setDisabled(true);
await msg.edit({
embeds: [OldEmbed],
components: [selectMenu, homeButton]
});
}
let timeout = setTimeout(disableAll, 6000);
colletor.on("collect", async (i) => {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(disableAll, 6000);
});
这是这段代码的作用,一步一步。每次用户与 select 菜单交互时:
- 检查
timeout
是否已经启动。如果是这样,请清除它。 (如果尚未创建超时,则不需要清除超时)。
- 使用
setTimeout()
创建一个新的 timeout
。新超时将在 6 秒后禁用 select 菜单。
- 如果用户在 6 秒结束之前再次与 select 菜单交互,则该过程从步骤 1 重新开始。上一步中创建的超时将被清除,另一个将在它的位置,时间重置为 6 秒。
- 如果在 6 秒结束之前没有用户再次与 select 菜单交互,则一旦时间用完,select 菜单就会被禁用。这意味着菜单只会在用户最后一次与菜单交互后 6 秒禁用。
为了回应你对我在评论中试图告诉你的内容表示困惑的评论,我希望这个 step-by-step 解释能澄清我的意思。
编辑
删除了检查大小写 !i.message.member.id === i.isSelectMenu()
的 if
语句。正如我在评论中解释的那样,!i.message.member.id
在这里总是 false
,而 i.isSelectMenu()
在这里总是 true
,所以删除的 if
语句正在检查是否 false === true
(这显然是一个总是错误的陈述)。
编辑 2
正如我在对这个问题的第一条评论中提到的,即 OP 感到困惑的最初评论,最初的超时功能在收集器内部。这意味着所有禁用 select 菜单和按钮的代码只会在菜单中的值最初被 selected 后执行。换句话说,菜单不会在 6 秒无交互后自行禁用;它只会在最后一次交互后 6 秒后自行禁用。如果用户根本没有使用 select 菜单,则 6 秒后不会发生禁用。这就是我最初评论的意思。我修改了答案以将初始超时移到收集器之外。现在,如果用户出现以下情况,它将在 6 秒后禁用:a) 根本没有交互;或 b) 最后一次互动是在 6 秒前。
我希望当用户与 select 菜单交互时,它应该可以工作,然后在用户停止与之交互几秒钟后将其禁用。
这就是 Dank Memer bot Help 命令的工作原理。
我的命令在做什么: 该命令用作帮助命令,获取命令文件夹子文件夹中的所有文件,并给出命令的用法、名称和描述。当用户 select 在 select 菜单中有一个选项并且该选项是命令文件夹的子文件夹时,它会编辑嵌入。
到目前为止,我一直这样做:
const { MessageEmbed, Message, MessageActionRow, MessageSelectMenu, MessageButton } = require("discord.js");
const fs = require("fs");
const prefix = require("../../config.json").PREFIX;
module.exports = {
name: "help",
description: "Get All The Commands!",
usage: "help",
cooldown: 1000 * 5,
category: "Help Commands!",
/**
* @param {Message} message
*
*/
run: async (client, message, args) => {
const sizeOfCat = fs.readdirSync("./Commands - Staff/");
const OldEmbed = new MessageEmbed()
.setAuthor({
name: "Commands! =>",
iconURL: `${message.guild.iconURL({ dynamic: true })}`
})
.setThumbnail(`${message.guild.iconURL({ dynamic: true })}`)
.setTitle(" Need help? Select The Category You Want To =>")
.setDescription(
`
**\`Hello Dear ${message.member.user.username}, Please Select Your Category According To Your Choice!\`**
**How To Use =>**
\`1) Click The Select Menu Down Below.\`
\`2) You Will See Many Categories, Click Your Category You Want To View.\`
\`3) The Embed Will Be Edited And You Can See Your Commands According To Category.\`
*Note => The Select Menu And The Button Will Be Disabled Automatically After 6 Seconds!*
**Total Categories Are: ${sizeOfCat.length}**
`
)
.setColor("BLURPLE")
.setTimestamp()
.setFooter({
text: `Requested by ${message.author.tag}`,
iconURL: message.author.displayAvatarURL({ dynamic: true })
})
const homeButton = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId("Home")
.setLabel("Back To Home!")
.setStyle("PRIMARY")
.setEmoji("️")
)
const EmojisCat = {
"Other Commands!": "",
"Help Commands!": "",
"Moderation Commands!": "⚒️",
"Owner Commands!": ""
};
const selectMenu = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId("Help-Menu")
.setPlaceholder(`Click To View The Categories Of The Commands!`)
.addOptions([
client.categoriesCommands.map((cat) => {
return {
label: `${cat[0].toUpperCase() + cat.slice(1)}`,
value: cat,
emoji: EmojisCat[cat],
description: `Click To View The Commands Of This Categories!`,
}
})
])
);
await message.reply({
content: "**There You Go, Check The List Of Categories!**",
embeds: [OldEmbed],
components: [selectMenu, homeButton]
})
.then(async (msg) => {
let filter = i => i.member.id === message.member.id;
let colletor = msg.createMessageComponentCollector({ filter: filter });
let timeout = null;
colletor.on("collect", async (i) => {
if (!i.member.id === message.member.id) {
await msg.reply({
content: `**Its Not Your Turn Of Using The Command Menu Or The Command (\`${prefix}help\`) Is Not Runned By You! Dum Dum.**`,
ephemeral: true,
});
} else {
if (i.isButton()) {
await i.deferUpdate();
if (i.customId === "Home") {
msg.edit({ embeds: [OldEmbed] })
}
}
if (i.isSelectMenu()) {
if (i.customId === "Help-Menu") {
await i.deferUpdate();
let [ directory ] = i.values;
let totalCdms = client.categoriesCommands.filter(cmd => cmd.category === directory).map(cmd => cmd.size);
let command = client.categoriesCommands.filter(cmd => cmd.category === directory).map(cmd => cmd.length) + 1;
const embed = new MessageEmbed()
.setAuthor({
name: "AwesomeSMP Commands! =>",
iconURL: `${message.guild.iconURL({ dynamic: true })}`
})
.setThumbnail(`${message.guild.iconURL({ dynamic: true })}`)
.setTitle(` Need help? Here Are All Of My ${directory} Commands:`)
.setDescription(
`
**\`Here Are One Of My [${directory} Category] Commands =>\`**
**Total Commands In ${directory} Are: ${totalCdms}**
`
)
.setColor("BLURPLE")
.setTimestamp()
.setFooter({
text: `Requested by ${message.author.tag}`,
iconURL: message.author.displayAvatarURL({ dynamic: true })
})
client.commands.filter((cmd) => cmd.category === directory)
.map((cmd) => {
embed.addField(
`\n**\nCommmand-${command++}** =>\n\`${prefix}${cmd.name}\``,
` **Description:** *${cmd.description.toUpperCase() || "*None*"}*\n **Usage:** *${prefix} ${cmd.usage || "None"}*\n`
,true
);
})
await msg.edit({
embeds: [embed]
});
if (!i.message.member.id === i.isSelectMenu()) {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(async () => {
selectMenu.components[0].setDisabled(true);
homeButton.components[0].setDisabled(true);
await msg.edit({
embeds: [OldEmbed],
components: [selectMenu, homeButton]
});
}, 6000);
}
}
}
}
});
});
}
}
到目前为止没有错误。
正如我在评论中提到的,看起来你想要做的就是在你的收集器之前声明一个空变量(例如,命名为 timeout
),每次收集器收集你做的事情clearTimeout(timeout)
如果定义了 timeout
,然后你设置 timeout
等于你当前的 setTimeout()
语句。也就是说,如果我正确理解你的问题。忽略我最初关于将超时完全移到收集器之外的评论,因为这可能不是您要寻找的问题(我相信我最初误解了您的问题——但是,如果这个答案仍然不是您要找的,我最初的评论可能正是您要找的)。
现在回答你的问题。这是我在上面和评论中描述的过程中谈论的示例。我将只展示代码的相关部分,以便您了解一切发生的位置,而不必筛选几十行代码来查找我的更改(并且请注意,以后请只包含您的代码部分与您的问题相关 - 即在这种情况下只是您的收集器和 collector.on("collect")
处理程序)。
async function disableAll() {
selectMenu.components[0].setDisabled(true);
homeButton.components[0].setDisabled(true);
await msg.edit({
embeds: [OldEmbed],
components: [selectMenu, homeButton]
});
}
let timeout = setTimeout(disableAll, 6000);
colletor.on("collect", async (i) => {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(disableAll, 6000);
});
这是这段代码的作用,一步一步。每次用户与 select 菜单交互时:
- 检查
timeout
是否已经启动。如果是这样,请清除它。 (如果尚未创建超时,则不需要清除超时)。 - 使用
setTimeout()
创建一个新的timeout
。新超时将在 6 秒后禁用 select 菜单。 - 如果用户在 6 秒结束之前再次与 select 菜单交互,则该过程从步骤 1 重新开始。上一步中创建的超时将被清除,另一个将在它的位置,时间重置为 6 秒。
- 如果在 6 秒结束之前没有用户再次与 select 菜单交互,则一旦时间用完,select 菜单就会被禁用。这意味着菜单只会在用户最后一次与菜单交互后 6 秒禁用。
为了回应你对我在评论中试图告诉你的内容表示困惑的评论,我希望这个 step-by-step 解释能澄清我的意思。
编辑
删除了检查大小写 !i.message.member.id === i.isSelectMenu()
的 if
语句。正如我在评论中解释的那样,!i.message.member.id
在这里总是 false
,而 i.isSelectMenu()
在这里总是 true
,所以删除的 if
语句正在检查是否 false === true
(这显然是一个总是错误的陈述)。
编辑 2
正如我在对这个问题的第一条评论中提到的,即 OP 感到困惑的最初评论,最初的超时功能在收集器内部。这意味着所有禁用 select 菜单和按钮的代码只会在菜单中的值最初被 selected 后执行。换句话说,菜单不会在 6 秒无交互后自行禁用;它只会在最后一次交互后 6 秒后自行禁用。如果用户根本没有使用 select 菜单,则 6 秒后不会发生禁用。这就是我最初评论的意思。我修改了答案以将初始超时移到收集器之外。现在,如果用户出现以下情况,它将在 6 秒后禁用:a) 根本没有交互;或 b) 最后一次互动是在 6 秒前。