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

使用discord.js与commando开发冻结命令时遇DiscordAPIError: Unknown Message错误求助

解决Discord.js Commando冻结命令的"Unknown Message"错误

这个错误的根源很清晰:你在代码最开头就执行了message.delete(),但之后仍然尝试通过message.say()和message.delete(5000)来操作这条已经被Discord服务器移除的消息——API找不到这条消息,自然就抛出了Unknown Message错误。

让我们一步步修复这个问题,同时优化代码里的其他潜在问题:

核心问题修复思路

首先,把message.delete()的调用移到所有需要使用原消息对象的操作之后,或者改用message.channel.send()来发送通知(因为即使原消息被删除,频道对象依然有效)。另外,原代码的逻辑结构有些混乱,比如创建角色后的通知和添加角色操作位置不当,可能导致重复执行或逻辑错误。

修改后的完整代码

async run(message, { user }) {
  // 先检查执行者权限
  if (!message.member.hasPermission("MUTE_MEMBERS")) {
    return message.channel.send("Sorry, but you do not have the Mute Members Permission! If you believe this is an error, contact an owner.");
  }
  
  // 检查目标用户是否存在
  if (!user) {
    return message.channel.send(`Cannot find user!`);
  }

  const member = message.guild.member(user);
  // 检查目标用户是否在服务器内
  if (!member) {
    return message.channel.send(`User is not in this server!`);
  }

  // 检查目标用户权限是否高于执行者
  if (member.hasPermission("MUTE_MEMBERS")) {
    return message.channel.send("The user you are trying to freeze is either the same, or higher role than you.");
  }

  let muterole = message.guild.roles.find(role => role.name === "Frozen");
  
  // 检查用户是否已被冻结
  if (muterole && member.roles.has(muterole.id)) {
    return message.channel.send(`${user.username} is already frozen!`);
  }

  // 如果冻结角色不存在,创建角色并批量设置频道权限
  if (!muterole) {
    try {
      muterole = await message.guild.createRole({
        name: "Frozen",
        color: "#000000",
        permissions: []
      });

      // 用Promise.all替代forEach,确保所有频道权限设置完成后再继续
      await Promise.all(message.guild.channels.map(async channel => {
        await channel.overwritePermissions(muterole, {
          SEND_MESSAGES: false,
          ADD_REACTIONS: false,
          SPEAK: false
        });
      }));
    } catch (e) {
      console.error(e.stack);
      return message.channel.send("Failed to create the Frozen role!");
    }
  }

  // 为用户添加冻结角色
  await member.addRole(muterole);
  // 发送成功通知并定时删除该通知
  const successMsg = await message.channel.send(`**${user.username} has been frozen! To unfreeze them, use the unfreeze command!**`);
  
  // 最后删除原命令消息和成功通知
  message.delete();
  setTimeout(() => successMsg.delete(), 5000);
}

关键修改点说明

  • 移除了开头的message.delete(),改为在所有通知发送完成后再删除原消息,避免后续操作依赖已删除的消息对象
  • 改用message.channel.send()替代message.say(),彻底摆脱对原消息对象的依赖
  • 用Promise.all替代forEach处理频道权限设置,确保所有异步操作完成后再继续(forEach不会等待内部的async函数执行完毕,可能导致角色未创建完成就去设置权限)
  • 调整了逻辑结构,确保添加角色和发送成功通知的操作只执行一次
  • 添加了对member是否存在的检查,避免用户输入不存在的服务器成员时出错
  • 修复了拼写错误(beleive改为believe,error前补充an)

这样修改后,你就不会再遇到Unknown Message的错误,同时代码的稳定性和可读性也得到了提升。

内容的提问来源于stack exchange,提问作者swoods

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:52:46