Discord.js V12中消息反应用户user.id与user.name获取失败及积分功能实现问题咨询
解决Discord.js v12中messageReactionAdd事件的
guild未定义错误及逻辑问题 核心错误原因
你的messageReactionAdd事件处理函数参数写错了!在Discord.js v12中,messageReactionAdd事件的回调参数是**(reaction, user)**,而不是(message, reaction, user)。这直接导致你函数里的message参数是undefined,后续调用reaction.message.guild自然会触发Cannot read property 'guild' of undefined错误。
其他需要修正的问题
除了参数错误,还有几个逻辑和语法问题需要调整:
1. SQLite语句语法错误
你的client.setdayCount语句里,VALUES部分的@dayCount和@guild之间缺少逗号,会导致SQL执行失败:
-- 错误写法 INSERT OR REPLACE INTO Table (id, dayCount, guild) VALUES (@id, @dayCount @guild); -- 修正后 INSERT OR REPLACE INTO Table (id, dayCount, guild) VALUES (@id, @dayCount, @guild);
2. 表情判断逻辑错误
你当前的表情判断写法完全不符合JavaScript逻辑:if (lastMessage.reactions.cache.emojis === "1️⃣" || "2️⃣"...) 永远会返回true,因为非空字符串都是真值。正确的做法是检查用户添加的反应表情是否在目标列表中:
const validEmojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"]; if (validEmojis.includes(reaction.emoji.name)) { // 后续逻辑 }
3. Member获取方式与逻辑问题
- 在v12中,获取服务器成员推荐使用
members.fetch()方法,而不是直接member(user.id); - 需要排除机器人用户,避免给机器人加分;
- 你直接给
character(member对象)添加setdayCount属性是不合理的,应该先从数据库查询用户当前积分,再计算更新后的值。
4. 消息获取逻辑优化
你当前获取固定消息的方式是取频道最后一条消息,这可能不是你要的固定消息。如果是固定消息,建议直接存储该消息的ID,通过ID直接获取会更可靠。
修正后的完整代码
const config = require('./config.json'); // 修正SQL语句,增加guild查询条件避免跨服务器数据混淆 client.getdayCount = DB.prepare("SELECT dayCount from Table WHERE id = ? AND guild = ?;"); client.setdayCount = DB.prepare("INSERT OR REPLACE INTO Table (id, dayCount, guild) VALUES (@id, @dayCount, @guild);"); // 修正事件参数 client.on('messageReactionAdd', addRole); client.on('messageReactionRemove', removeRole); async function addRole(reaction, user) { // 排除机器人用户,避免无效操作 if (user.bot) return; // 处理部分消息(未完全加载的消息) if (reaction.message.partial) { try { await reaction.message.fetch(); } catch (err) { console.error('获取消息失败:', err); return; } } // 验证反应的表情是否为指定的1-7表情 const validEmojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"]; if (!validEmojis.includes(reaction.emoji.name)) return; try { const targetChannel = client.channels.cache.get(config.channelID); if (!targetChannel) { console.error('目标频道未找到'); return; } // 这里暂时保留你取最后一条消息的逻辑,建议替换为固定消息ID直接获取 const messages = await targetChannel.messages.fetch({ limit: 1 }); const targetMessage = messages.first(); // 确保用户反应的是目标消息 if (reaction.message.id !== targetMessage.id) return; const guild = reaction.message.guild; if (!guild) { console.error('反应不在服务器内'); return; } // 获取用户的服务器成员对象 const member = await guild.members.fetch(user.id); if (!member) return; // 查询用户当前积分,不存在则默认为0 const existingRecord = client.getdayCount.get(user.id, guild.id); const newCount = existingRecord ? existingRecord.dayCount + 1 : 1; // 更新数据库 client.setdayCount.run({ id: user.id, dayCount: newCount, guild: guild.id }); console.log(`给${user.tag}增加1分,当前积分: ${newCount}`); } catch (err) { console.error('加分逻辑出错:', err); } } // 移除反应的扣分逻辑 async function removeRole(reaction, user) { if (user.bot) return; if (reaction.message.partial) { try { await reaction.message.fetch(); } catch (err) { console.error('获取消息失败:', err); return; } } const validEmojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"]; if (!validEmojis.includes(reaction.emoji.name)) return; try { const targetChannel = client.channels.cache.get(config.channelID); if (!targetChannel) return; const messages = await targetChannel.messages.fetch({ limit: 1 }); const targetMessage = messages.first(); if (reaction.message.id !== targetMessage.id) return; const guild = reaction.message.guild; if (!guild) return; // 查询用户当前积分,不存在则直接返回 const existingRecord = client.getdayCount.get(user.id, guild.id); if (!existingRecord) return; // 扣分后避免出现负数积分 const newCount = Math.max(0, existingRecord.dayCount - 1); client.setdayCount.run({ id: user.id, dayCount: newCount, guild: guild.id }); console.log(`给${user.tag}扣除1分,当前积分: ${newCount}`); } catch (err) { console.error('扣分逻辑出错:', err); } }
关键修改点总结
- 修正了
messageReactionAdd事件的回调参数,从(message, reaction, user)改为(reaction, user); - 修复了SQL语句中的语法错误,并增加了
guild查询条件避免跨服务器数据混淆; - 优化了表情判断逻辑,使用数组
includes方法验证表情; - 添加了机器人用户过滤,避免无效操作;
- 调整了数据库查询和更新逻辑,正确获取并计算用户积分;
- 增加了错误处理和日志输出,方便调试;
- 编写了完整的
removeRole逻辑,实现取消反应扣分的功能。
内容的提问来源于stack exchange,提问作者f00d
相关产品推荐
相关产品推荐

