Discord.js 特定角色分配后无法发送通知消息问题求解
职位成就通知功能实现方案
现有代码失效原因
- 触发事件选型错误:当前绑定的
messageCreate事件仅在用户发送消息时触发,无法监听用户获得职位角色的动作,用户拿到角色时如果没有发消息,逻辑完全不会执行。 - 角色发放逻辑错误:代码里的
member.roles.cache.get()仅会从本地缓存读取角色对象,没有执行实际的添加角色操作,Discord.js中给成员加角色需要调用member.roles.add()方法。 - 逻辑判断反向:现有判断是「用户没有目标角色时执行逻辑」,和需求里「用户获得角色时触发成就通知」的触发条件完全不符。
- 冗余无效代码:定义了公告频道变量
canal、引入了wait延迟方法,但全程没有调用,属于无效代码。 - API调用错误:
messageCreate事件中获取发消息用户应该用message.author,原代码写的message.user是不存在的属性,运行会直接报错。
正确实现代码
核心逻辑改用guildMemberUpdate事件监听成员角色变更,精准捕捉用户获得职位的时机,再触发通知逻辑,代码如下:
const client = require("../index.js"); // 监听服务器成员信息变更(角色增减、昵称修改等操作都会触发该事件) client.on('guildMemberUpdate', async (oldMember, newMember) => { // 配置参数,替换为你服务器实际的ID值 const TARGET_PS_ROLE_ID = "980553630782464068"; // PlayStation职位对应的角色ID const ACHIEVEMENT_CHANNEL_ID = "980553632116269080"; // 成就公告频道ID // 校验是否为刚获得目标角色的场景:更新前无角色,更新后有角色 const hadRole = oldMember.roles.cache.has(TARGET_PS_ROLE_ID); const gotRole = newMember.roles.cache.has(TARGET_PS_ROLE_ID); if (hadRole || !gotRole) return; try { // 给用户发私信解锁通知 await newMember.send(`${client.emoji.success} 恭喜你解锁PlayStation职位成就,对应身份组已自动到账!`); // 需要在频道发全服成就公告就放开下面的注释 // const announceChannel = newMember.guild.channels.cache.get(ACHIEVEMENT_CHANNEL_ID); // if (announceChannel) { // await announceChannel.send(`🎉 恭喜 ${newMember.user.tag} 成功解锁PlayStation职位成就!`); // } } catch (error) { // 捕获用户关闭私信等异常,避免程序崩溃 console.log(`向用户${newMember.user.tag}发送成就通知失败:`, error); } }); // 可选兜底逻辑:用户发消息时自动检测资格补发角色,不需要可以删除 client.on('messageCreate', async message => { // 跳过机器人消息、非服务器消息 if (message.author.bot || !message.guild) return; const TARGET_PS_ROLE_ID = "980553630782464068"; // 强制拉取最新的成员信息,避免缓存导致判断不准 const member = await message.guild.members.fetch({ user: message.author.id, force: true }); // 替换成你自己的资格判断规则,比如积分达标、完成指定任务等 const matchRoleRequirement = true; if (matchRoleRequirement && !member.roles.cache.has(TARGET_PS_ROLE_ID)) { await member.roles.add(TARGET_PS_ROLE_ID); // 角色发放成功后,上面的角色更新监听会自动触发成就通知逻辑,这里不用重复发 } })
部署注意事项
- 需要给机器人账号开启「管理角色」权限,且机器人在服务器的最高角色层级,必须高于你要发放的职位角色,否则会出现加角色无权限的报错。
- 如果要做多个职位对应多个成就的逻辑,只需要把角色ID、成就名称、通知内容做成键值对映射表遍历判断即可,不需要为每个职位单独写监听逻辑。
- 参考的卡片式成就通知效果,可以用Discord.js的MessageEmbed嵌入消息实现,搭配成就封面图、解锁条件、奖励说明字段,就能做出和参考样式一致的通知卡片。
内容的提问来源于stack exchange,提问作者Alguém Top
相关产品推荐
相关产品推荐

