You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:52:49