Discord.js消息反应监听异常:仅响应机器人自身操作
解决Discord机器人消息反应监听无响应问题
核心问题诊断
- 缺失必要的Intents:Discord.js v13及以上版本中,监听消息反应事件必须启用
GUILD_MESSAGE_REACTIONS意图,当前代码未配置该权限。 - 未处理Partial对象:如果监听的消息是机器人启动前已存在的,或不在客户端缓存中,反应事件触发时会返回Partial对象,需启用Partial支持并处理完整数据。
具体修改步骤
1. 补充Intents并启用Partial支持(修改index.js)
修改客户端初始化代码,添加缺失的意图并开启消息、反应、用户的Partial支持:
const { Client, Intents } = require('discord.js'); const roleClaim = require('./role-claim') const client = new Client({ intents: [ Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS // 新增:监听消息反应的必要意图 ], partials: ['MESSAGE', 'REACTION', 'USER'] // 新增:处理缓存外的Partial对象 }); client.login("你的机器人Token"); const config = require("./config.json"); client.on("ready", () => { client.user.setActivity("altV: Multiplayer on FreeZone", { type: "PLAYING" }) console.log("1000-7"); roleClaim(client); })
2. 处理Partial事件并过滤机器人操作(修改role-claim.js)
在反应事件监听中先获取完整对象,并排除机器人自身的反应操作:
const firstMessage = require('./first-message') module.exports = (client) => { const channelId = '813819563703271484' const getEmoji = (emojiName) => client.emojis.cache.find((emoji) => emoji.name === emojiName) const emojis = { mercedes: 'Mercedes', ferrari: 'FERRARI', renault: 'RENAULT' } const reactions = [] let emojiText = 'Pick any team \n\n' for (const key in emojis) { const emoji = getEmoji(key) reactions.push(emoji) const role = emojis[key] emojiText += `${emoji} = ${role} \n` } firstMessage(client, channelId, emojiText, reactions); // 修改添加反应监听,处理Partial对象 client.on('messageReactionAdd', async (reaction, user) => { // 若为Partial对象,先获取完整数据 if (reaction.partial) { try { await reaction.fetch(); } catch (err) { console.error('获取反应数据失败:', err); return; } } if (user.partial) { try { await user.fetch(); } catch (err) { console.error('获取用户数据失败:', err); return; } } // 跳过机器人自身的反应 if (user.bot) return; console.log("用户添加了反应"); // 此处可添加角色分配逻辑 }) // 修改移除反应监听,处理Partial对象 client.on('messageReactionRemove', async (reaction, user) => { if (reaction.partial) { try { await reaction.fetch(); } catch (err) { console.error('获取反应数据失败:', err); return; } } if (user.partial) { try { await user.fetch(); } catch (err) { console.error('获取用户数据失败:', err); return; } } if (user.bot) return; console.log("用户移除了反应"); // 此处可添加角色移除逻辑 }) }
3. 优化消息处理逻辑(修改first-message.js)
原代码遍历频道所有消息并编辑,建议只处理目标消息,避免不必要的操作:
function addReactions(message, reactions) { message.react(reactions[0]) reactions.shift() if (reactions.length > 0) { setTimeout(() => addReactions(message, reactions), 750) } } module.exports = async (client, id, text, reactions = []) => { const channel = await client.channels.fetch(id) const messages = await channel.messages.fetch(); if (messages.size === 0) { channel.send(text).then(message => addReactions(message, reactions)) } else { // 仅处理频道内第一条消息,可根据需求调整 const targetMessage = messages.first(); await targetMessage.edit(text); // 清除现有反应后重新添加 await targetMessage.reactions.removeAll(); addReactions(targetMessage, reactions); } }
关键说明
- Intents权限:Discord API要求机器人明确声明所需权限,
GUILD_MESSAGE_REACTIONS是接收反应事件的必要条件。 - Partial对象:当消息/反应不在本地缓存时,需通过
fetch()获取完整数据才能正常操作。 - 过滤机器人:添加
user.bot判断可避免机器人自身的反应触发业务逻辑。
内容的提问来源于stack exchange,提问作者Re1zuz
相关产品推荐
相关产品推荐

