discord.js v14 messageReactionAdd事件触发后无限发送消息问题排查
问题
使用discord.js v14开发的机器人,在messageReactionAdd事件中实现了点击指定表情后向目标频道发送通知消息的功能。该功能初期运行正常,但一段时间后,用户点击一次表情就会触发机器人无限重复发送消息。相关代码如下:
const { MessageReaction, Events, GatewayIntentBits, Partials } = require("discord.js"); const reactionConfig = { channelID: "1078339846172573778", targetChannelID: "972616312952070144", messageID: "1078355581435379723", firstEmoji: "926995541596962919", staffRoleID: "886867243076567071", normalRoleID: "886869696752803890", } module.exports = { name: "messageReactionAdd", /** * * @param {MessageReaction} reaction */ async execute(reaction) { const client = reaction.client; if (reaction.partial) { try { await reaction.fetch(); } catch (error) { console.error('Something went wrong when fetching the message:', error); return; } } const channel = client.channels.cache.get(reactionConfig.channelID) const msg = await channel.messages.fetch(reactionConfig.messageID) if(msg){ const collector = msg.createReactionCollector( 'time: 10000ms'); collector.on('collect', async (reaction, user) => { switch (reaction.emoji.id){ case reactionConfig.firstEmoji: { await client.channels.cache.get(reactionConfig.targetChannelID).send(`<@&${reactionConfig.staffRoleID}> - ${user} want to get Wookiee role. Please take action and check requirements!`) collector.stop(); break; } } }) } }
问题原因与解决方案
- 重复创建ReactionCollector导致资源堆积:每次触发
messageReactionAdd事件,代码都会为目标消息创建一个新的反应收集器。随着时间推移,大量活跃的收集器会积累下来,当用户点击表情时,所有收集器都会同时触发collect事件,导致重复发送消息。 - 未排除机器人自身反应:如果机器人对目标消息有操作(比如添加初始表情),可能会触发事件进入循环,这是潜在的触发重复的诱因。
- 冗余的消息获取逻辑:每次事件触发都重新获取目标消息,既浪费资源又没必要,直接通过
reaction.message即可判断是否为目标消息。
修正后的代码:
const { MessageReaction, Events } = require("discord.js"); const reactionConfig = { channelID: "1078339846172573778", targetChannelID: "972616312952070144", messageID: "1078355581435379723", firstEmoji: "926995541596962919", staffRoleID: "886867243076567071", normalRoleID: "886869696752803890", }; module.exports = { name: Events.MessageReactionAdd, /** * @param {MessageReaction} reaction * @param {import('discord.js').User} user */ async execute(reaction, user) { const client = reaction.client; // 排除机器人自身反应,避免循环触发 if (user.bot) return; // 处理部分反应对象,获取完整数据 if (reaction.partial) { try { await reaction.fetch(); } catch (error) { console.error('获取消息时出错:', error); return; } } // 校验当前反应是否属于目标频道和目标消息 if (reaction.message.channel.id !== reactionConfig.channelID || reaction.message.id !== reactionConfig.messageID) { return; } // 校验是否为目标表情,发送通知 if (reaction.emoji.id === reactionConfig.firstEmoji) { try { await client.channels.cache.get(reactionConfig.targetChannelID).send(`<@&${reactionConfig.staffRoleID}> - ${user} 想要获取 Wookiee 角色,请处理并检查要求!`); } catch (error) { console.error('发送通知消息时出错:', error); } } } };
内容的提问来源于stack exchange,提问作者Xhani
相关产品推荐
相关产品推荐

