DiscordJS 如何根据选中的反应复制Embed消息发送到其他聊天频道
Discord.js v14 实现反应触发Embed转发的方案
前置准备
- 确保你的Bot已经开启开发者门户中
Privileged Gateway Intents下的三个开关:Server Members Intent、Message Content Intent、Guild Message Reactions Intent - 确保Bot拥有原消息所在频道的
Send Messages、Embed Links、Read Message History权限,目标转发频道的Send Messages、Embed Links权限
核心逻辑实现
1. 注册事件监听与过滤无效触发
首先监听messageReactionAdd事件,过滤掉Bot自身触发的反应、非目标三个反应的操作,避免误触发:
const { Client, GatewayIntentBits, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMembers ] }); // 配置项:替换为你实际的三个目标反应emoji、转发目标频道ID、Bot Token const TARGET_EMOJIS = ['✅', '❌', '⚠️']; const FORWARD_CHANNEL_ID = '替换为目标转发频道ID'; const BOT_TOKEN = '替换为你的Bot Token'; client.on('messageReactionAdd', async (reaction, user) => { // 忽略Bot自身触发的反应 if (user.bot) return; // 忽略非目标emoji的反应 if (!TARGET_EMOJIS.includes(reaction.emoji.name)) return; // 处理部分加载的消息/反应 if (reaction.partial) await reaction.fetch(); if (reaction.message.partial) await reaction.message.fetch(); // 忽略没有Embed的消息 if (!reaction.message.embeds.length) return; // 可选:移除用户添加的反应,避免重复触发 await reaction.users.remove(user.id);
2. 生成确认交互弹窗
用按钮组件生成确认交互,发送给触发反应的用户:
// 构造确认/取消按钮 const confirmBtn = new ButtonBuilder() .setCustomId(`confirm_forward_${reaction.message.id}_${user.id}`) .setLabel('确认转发') .setStyle(ButtonStyle.Success); const cancelBtn = new ButtonBuilder() .setCustomId(`cancel_forward_${reaction.message.id}_${user.id}`) .setLabel('取消') .setStyle(ButtonStyle.Danger); const row = new ActionRowBuilder().addComponents(confirmBtn, cancelBtn); // 给触发用户发送确认消息,只有触发用户可见 const confirmMsg = await reaction.message.reply({ content: `${user}, 确认要将该Embed转发到指定频道吗?`, components: [row], allowedMentions: { users: [user.id] }, ephemeral: true }); });
3. 监听按钮交互,执行转发逻辑
监听interactionCreate事件,判断用户点击的按钮,执行对应操作:
client.on('interactionCreate', async interaction => { if (!interaction.isButton()) return; // 匹配转发相关的按钮ID,过滤无关交互 const idParts = interaction.customId.split('_'); if (idParts.length !==4 || (idParts[0]!=='confirm' && idParts[0]!=='cancel')) return; const [action, _, msgId, triggerUserId] = idParts; // 忽略非当前触发用户的点击操作 if (interaction.user.id !== triggerUserId) { return interaction.reply({ content: '你无权操作该确认', ephemeral: true }); } if (action === 'confirm') { // 获取原消息的Embed内容 const originalMsg = await interaction.channel.messages.fetch(msgId); const targetEmbeds = originalMsg.embeds; // 获取转发目标频道 const forwardChannel = await client.channels.fetch(FORWARD_CHANNEL_ID); // 发送Embed到目标频道 await forwardChannel.send({ embeds: targetEmbeds }); // 更新确认消息,移除按钮 await interaction.update({ content: '✅ 已成功转发Embed', components: [] }); } else if (action === 'cancel') { // 取消操作,更新确认消息移除按钮 await interaction.update({ content: '❌ 已取消转发操作', components: [] }); } }); // 登录Bot client.login(BOT_TOKEN);
注意事项
- 如果你的反应是自定义emoji,需要把
TARGET_EMOJIS里的内容替换为自定义emoji的ID - 如果需要区分不同反应转发到不同频道,可以把
TARGET_EMOJIS修改为键值对映射,根据触发的emoji匹配对应的转发频道ID - 生产环境建议添加
try/catch异常捕获,避免消息/频道不存在等报错导致Bot崩溃
内容的提问来源于stack exchange,提问作者User57
相关产品推荐
相关产品推荐

