discord.js:按钮交互时如何获取斜杠命令的字符串选项?
Discord.js中按钮交互时如何获取原斜杠命令的字符串选项?
我用discord.js开发了一个斜杠命令,它接收字符串选项,调用API查询数据后以Embed形式返回结果,回复里还附带了一个刷新按钮用来更新数据。现在的问题是,用户点击按钮触发交互时,我怎么获取当初斜杠命令使用的那个字符串选项?
我试过把字符串选项通过ActionRow Builder传递、设为按钮的customId、甚至放到Embed里,但要么没法正常工作,要么感觉很不规范。想知道能不能通过交互ID拿到对应的原交互实例,进而获取那个字符串选项?
相关代码如下:
async execute(interaction) { const search = interaction.options.getString("search"); const pairs = await getQuery(search); const refreshButton = new ButtonBuilder() .setCustomId(search) .setLabel("Refresh") .setStyle(ButtonStyle.Secondary); const row = new ActionRowBuilder().addComponents([refreshButton]); const embed = makeEmbed(pairs[0]); if (pairs.length > 0) { interaction.reply({ embeds: [embed], components: [row], }); } else { interaction.reply( `No results for search term ${search}. Please check your query and try again.` ); } }, // NEED ACCESS TO THE STRING OPTION search IN THIS FUNCTION async refresh(interaction) { const pairs = await getQuery(interaction.customId); const embed = makeEmbed(pairs[0]); console.log(interaction.customId); if (pairs.length > 0) { interaction.update({ embeds: [embed] }); } else { interaction.update( `No results for search term ${search}. Please check your query and try again.` ); } }
解决方案
首先明确:Discord不会保存原斜杠命令的交互选项数据,无法直接通过交互ID获取原交互实例的选项。以下是几种规范可行的实现方式:
1. 结构化Custom ID(最简便规范)
直接将搜索词作为customId存在风险(特殊字符、长度限制),可以给customId加前缀并编码,避免冲突和格式问题:
修改execute中的按钮构建代码:
const refreshButton = new ButtonBuilder() // 加前缀区分刷新按钮,对搜索词编码处理特殊字符 .setCustomId(`refresh_${encodeURIComponent(search)}`) .setLabel("Refresh") .setStyle(ButtonStyle.Secondary);
在refresh函数中解析提取搜索词:
async refresh(interaction) { const [prefix, encodedSearch] = interaction.customId.split('_'); // 校验确保是目标刷新按钮 if (prefix !== 'refresh') return; const search = decodeURIComponent(encodedSearch); const pairs = await getQuery(search); const embed = makeEmbed(pairs[0]); if (pairs.length > 0) { interaction.update({ embeds: [embed] }); } else { interaction.update( `No results for search term ${search}. Please check your query and try again.` ); } }
2. 从原消息Embed中提取隐藏信息
如果不想将搜索词暴露在customId中,可以把搜索词存入Embed的隐藏区域(比如footer):
修改execute中的Embed构建:
const embed = makeEmbed(pairs[0]) // 将搜索词存入footer,用户不会注意到 .setFooter({ text: `search:${search}` });
在refresh函数中获取原消息并解析:
async refresh(interaction) { // 获取原回复消息 const originalMessage = await interaction.fetchReply(); const originalEmbed = originalMessage.embeds[0]; // 从footer提取搜索词 const search = originalEmbed.footer.text.split(':')[1]; const pairs = await getQuery(search); const embed = makeEmbed(pairs[0]) .setFooter({ text: `search:${search}` }); // 更新后保留标识 if (pairs.length > 0) { interaction.update({ embeds: [embed] }); } else { interaction.update( `No results for search term ${search}. Please check your query and try again.` ); } }
3. 缓存/数据库存储关联数据
如果搜索词过长或需要长期关联,可以用缓存(如Redis)或数据库存储原交互ID与搜索词的映射:
修改execute函数:
async execute(interaction) { const search = interaction.options.getString("search"); // 将原交互ID与搜索词存入缓存,设置过期时间(示例为1小时) await cache.set(`interaction_${interaction.id}`, search, 3600); // 按钮用固定customId即可 const refreshButton = new ButtonBuilder() .setCustomId('refresh_button') .setLabel("Refresh") .setStyle(ButtonStyle.Secondary); // 其余回复代码不变 }
在refresh函数中查询缓存:
async refresh(interaction) { // 获取原斜杠命令的交互ID const originalInteractionId = interaction.message.interaction.id; // 从缓存取出搜索词 const search = await cache.get(`interaction_${originalInteractionId}`); if (!search) { return interaction.update({ content: "该查询已过期,请重新发起搜索。", components: [] }); } const pairs = await getQuery(search); const embed = makeEmbed(pairs[0]); if (pairs.length > 0) { interaction.update({ embeds: [embed] }); } else { interaction.update( `No results for search term ${search}. Please check your query and try again.` ); } }
内容的提问来源于stack exchange,提问作者gooltoe
相关产品推荐
相关产品推荐

