使用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
相关产品推荐
相关产品推荐

