Discord.js机器人警告系统无法发送DM的问题求助
解决Discord.js警告机器人无法发送DM的问题
让我们一步步拆解你的问题,先揪出核心代码里的几个隐藏坑:
1. 先修复明显的变量错误
你代码里有一行a.splice(0, 2),但a这个变量根本没定义,应该是grad.splice(0, 2)——这行如果没改,运行到这里会直接抛出ReferenceError,你说无报错可能是没触发到这个分支?先把这个低级bug修了再说。
2. 别依赖缓存获取成员
msg.guild.members.cache.find()只能找到已经在机器人本地缓存里的成员,如果目标用户很久没发言、刚进服务器,或者机器人重启过,缓存里可能没有他的信息,自然找不到人也发不了DM。正确做法是用members.fetch()方法,它会直接从Discord API拉取成员数据,不管缓存里有没有:
// 替换原来的成员查找逻辑 const targetMember = await msg.guild.members.fetch({ query: linesplit[1], limit: 1 }) .then(members => members.first()) .catch(err => { msg.reply(`查找用户时出错:${err}`); return null; }); if (!targetMember) { msg.reply(`找不到用户 ${linesplit[1]}`); return; }
注意:fetch是异步方法,所以你需要把message事件的回调改成async:
mod.on('message', async msg => { // 给回调加async关键字 // ... 剩下的代码 })
3. 给DM发送加上错误处理
很多时候DM发不出去不是代码逻辑错了,而是用户关闭了服务器DM、把机器人拉黑了,或者机器人没有相关权限——但你原来的代码没加.catch(),失败了也看不到错误信息,自然不知道问题出在哪。一定要加上错误捕获:
targetMember.send(`__***Warned by: ${msg.author.tag}***__\n警告原因:\n${gradon}`) .then(() => { msg.reply(`已成功给 ${targetMember.user.tag} 发送警告DM`); }) .catch(err => { msg.reply(`无法给用户发送DM,错误原因:${err.message}`); // 可选:如果DM发不出去,在服务器频道公开警告用户 msg.channel.send(`⚠️ ${targetMember},你被 ${msg.author} 警告:\n${gradon}`); });
4. 优化用户匹配逻辑
用user.tag匹配虽然可行,但有时候用户可能输入时打错了大小写,或者改了用户名(不过discriminator还是原来的)——可以改成大小写不敏感的匹配:
// 如果还是想用缓存查找,改成小写匹配避免大小写问题 const targetMember = msg.guild.members.cache.find(member => member.user.tag.toLowerCase() === linesplit[1].toLowerCase() );
完整修改后的核心代码片段
把这些点整合起来,你的警告命令部分应该改成这样:
if(msg.content.startsWith('*warn')){ if(msg.member.hasPermission('ADMINISTRATOR') || msg.member.roles.cache.has('724326097306779699')){ const linesplit = msg.content.split('\n'); if(linesplit.length < 3){ msg.channel.send(`格式错误!正确格式:\n*warn\n目标用户tag\n警告原因`); return; } // 异步获取目标成员 const targetMember = await msg.guild.members.fetch({ query: linesplit[1], limit: 1 }) .then(members => members.first()) .catch(err => { msg.reply(`查找用户失败:${err}`); return null; }); if(!targetMember){ msg.reply(`找不到用户 ${linesplit[1]}`); return; } // 检查是否是管理员/版主 if(targetMember.hasPermission('ADMINISTRATOR') || targetMember.roles.cache.has('724326097306779699')){ msg.reply(`你不能警告管理员或版主`); return; } // 处理警告原因 const grad = [...linesplit]; // 复制数组避免修改原数据 grad.splice(0, 2); // 移除前两行(*warn和用户tag) const gradon = grad.join('\n'); // 发送DM并处理错误 targetMember.send(`__***Warned by: ${msg.author.tag}***__\n警告原因:\n${gradon}`) .then(() => { msg.reply(`已成功向 ${targetMember.user.tag} 发送警告通知`); }) .catch(err => { msg.reply(`无法发送DM给用户,错误信息:${err.message}`); // 可选:在服务器频道公开警告 msg.channel.send(`⚠️ ${targetMember},你被 ${msg.author} 警告:\n${gradon}`); }); } else { msg.reply('你没有权限使用这个命令'); } }
额外小建议
- 把固定的角色ID改成常量,比如
const MOD_ROLE_ID = '724326097306779699',后续修改更方便。 - 考虑用
MessageEmbed来发送警告,格式更美观专业。 - 把警告记录到数据库或者本地文件里,方便后续追溯查看。
内容的提问来源于stack exchange,提问作者mataldin
相关产品推荐
相关产品推荐

