Discord.js v14中如何隐藏Embed并点击按钮后显示?
解决方案:让Embed默认隐藏,仅点击按钮时展示
问题背景
我在命令执行函数中创建了一个Embed,希望仅在点击按钮时显示它。当前功能仅实现一半,问题是Embed默认会显示,且点击按钮时会再次重复显示。想实现Embed默认隐藏,直到按钮被点击才展示;同时由于数据来自API响应且未保存,无法将Embed创建逻辑移至index.js,也不想用数据库。
修改方案
核心思路是不直接发送Embed到消息中,而是将生成Embed所需的API数据(或Embed本身的序列化数据)存入按钮的自定义ID中,点击按钮时再解析数据生成并展示Embed。
1. 修改command.js:不发送Embed,将数据存入按钮
// Call API let data = await response.json(); // 序列化API返回的关键数据(用encodeURIComponent避免字符冲突) const serializedInfo = encodeURIComponent(JSON.stringify(data.images.info)); // 创建按钮,自定义ID中加入序列化数据,用|分隔标识与数据 const getGenerationDataButton = new ButtonBuilder() .setCustomId(`get_image_generation_data|${serializedInfo}`) .setLabel("Get Image Generation Data") .setStyle(ButtonStyle.Primary); const actionRow = new ActionRowBuilder().addComponents(getGenerationDataButton); // 仅发送文件和按钮,不包含Embed await interaction.editReply({ files: files, components: [actionRow], });
2. 修改index.js:解析按钮数据,生成并发送Embed
if (interaction.isButton()) { // 拆分自定义ID,分离标识和序列化数据 const [customId, serializedInfo] = interaction.customId.split('|'); if (customId === "get_image_generation_data") { // 解析数据 const info = JSON.parse(decodeURIComponent(serializedInfo)); const fields = Object.entries(info); // 重新构建Embed const embed = new EmbedBuilder() .setColor(0x0099ff) .setTitle("txt2img") .addFields(fields) .setTimestamp(); // 以临时消息形式发送Embed await interaction.reply({ embeds: [embed], ephemeral: true, }); } }
替代方案(复用Embed配置)
如果不想在index.js中重复编写Embed构建逻辑,可以直接序列化整个Embed的配置:
修改command.js
// Call API let data = await response.json(); const fields = Object.entries(JSON.parse(data.images.info)) // 创建Embed const embed = new EmbedBuilder() .setColor(0x0099ff) .setTitle("txt2img") .addFields(fields) .setTimestamp(); // 序列化Embed为JSON并编码 const serializedEmbed = encodeURIComponent(JSON.stringify(embed.toJSON())); // 创建按钮 const getGenerationDataButton = new ButtonBuilder() .setCustomId(`get_image_generation_data|${serializedEmbed}`) .setLabel("Get Image Generation Data") .setStyle(ButtonStyle.Primary); const actionRow = new ActionRowBuilder().addComponents(getGenerationDataButton); // 仅发送文件和按钮 await interaction.editReply({ files: files, components: [actionRow], });
修改index.js
if (interaction.isButton()) { const [customId, serializedEmbed] = interaction.customId.split('|'); if (customId === "get_image_generation_data") { // 解析并还原Embed const embedData = JSON.parse(decodeURIComponent(serializedEmbed)); const embed = EmbedBuilder.from(embedData); await interaction.reply({ embeds: [embed], ephemeral: true, }); } }
注意事项
- Discord按钮的自定义ID长度限制为100字符,若序列化后的数据过长,建议优先选择仅序列化API返回的关键数据(而非整个Embed)来缩短长度。
- 使用
encodeURIComponent和decodeURIComponent避免JSON中的特殊字符破坏自定义ID格式。
内容的提问来源于stack exchange,提问作者billyjean
相关产品推荐
相关产品推荐

