Discord.js v13 如何防止机器人在尝试删除消息时崩溃?

Discord.js v13 How to prevent the bot from crashing on attempted message deletion?

我的 discord 机器人有这个 'clear' 命令,它应该像这样工作: -用户输入 !mute

  1. 机器人删除了这么多条消息(最多 100 条)
  2. 机器人发送消息说这些消息已被删除
  3. 机器人在 5 秒后删除了该消息 除最后一部分外,一切正常,您会看到在执行第 2 部分后消息是否被另一个来源删除,然后机器人找不到要删除的消息并崩溃。 代码如下:
module.exports = {
    name: 'clear',
    description: "clears messages",
    async execute(message, args)
    {   
        if(!args[0]) return message.reply("Please specify how many messages you want to clear!");
        if(isNaN(args[0])) return message.reply("Please enter a number of messages you want to clear!");
        
        if(args[0] > 100) return message.reply("You can't delete more than 100 messages!");
        if(args[0] < 1) return message.reply("You can't delete less than 1 message!");

        await message.channel.messages.fetch({limit: args[0]}).then(messages =>{
            message.channel.bulkDelete(messages).then(() => {
                message.channel.send("Deleted " + args[0] + " messages") .then(msg => {
                    let id = msg.id;
                    setTimeout(function(){
                        if(message.channel.messages.fetch(id))
                        {
                            try {
                                msg.delete()
                            }
                            catch (error) {
                                console.log(error)
                                return
                            }
                        }
                    }, 5000);
                  })
                });
            })
    }
}

我得到的错误是:

C:\Users\Miki\Desktop\discord boty\jajco bot\node_modules\discord.js\src\rest\RequestHandler.js:350
      throw new DiscordAPIError(data, res.status, request);
            ^

DiscordAPIError: Unknown Message
    at RequestHandler.execute (C:\Users\Miki\Desktop\discord boty\jajco bot\node_modules\discord.js\src\rest\RequestHandler.js:350:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async RequestHandler.push (C:\Users\Miki\Desktop\discord boty\jajco bot\node_modules\discord.js\src\rest\RequestHandler.js:51:14)
    at async MessageManager._fetchId (C:\Users\Miki\Desktop\discord boty\jajco bot\node_modules\discord.js\src\managers\MessageManager.js:219:18) {
  method: 'get',
  path: '/channels/943105549795471443/messages/946096412922368100',
  code: 10008,
  httpStatus: 404,
  requestData: { json: undefined, files: [] }
}

如您所见,我已经尝试使用 try...catch() 但它没有解决问题。关于做什么的任何想法?或者我的代码中可能存在错误,例如缺少导入或其他类似的东西?

首先让我们看一下这段代码:

try {
    msg.delete();
} catch (error) {
    return console.log(error);
}

此代码不会执行您期望的操作。 msg.delete(); 是 return 一个 Promise 的函数。如果承诺失败,try/catch 结构将不会执行任何操作。因此,要捕获错误,您必须在 Promise 上使用 catch 方法,就像您之前使用 .then() 一样,您必须使用 .catch().

所以你的新代码将是这样的:

msg.delete().catch(error => console.error(error);
// Or, even better:
msg.delete().catch(console.error);

这里完全一样:

if (message.channel.messages.fetch(id))

那将永远是 true 因为 fetch() 函数将 return 一个 Promise ans 因为它既不是 0, ''(空字符串)、NaNfalseundefinednull See here for false values

相反,您要做的是检查邮件是否包含您的 ID:

message.channel.messages.fetch(id).then(msg => {
    // Do what you want with the fetched msg
}).catch(error => {
    // Console error why it failed to fetch the id (probably because it doesn't exist or got deleted)
    message.reply('Failed to fetch the id');
});

最后这段代码还有一些问题:

message.channel.bulkDelete(messages).then(() => {

messages 是一个 Collection,不是一个数字,bulkDelete() 等待一个数字,所以改为这样做:

message.channel.bulkDelete(messages.size).then(() => {

我个人不明白你为什么要获取消息,你可以简单地这样做:

message.channel.messages.fetch({
    limit: args[0]
}).then(messages => {
    message.channel.bulkDelete(messages.size).then(() => {
        message.channel.send(`Deleted ${args[0]} messages`).then(msg => {
            setTimeout(() => msg.delete(), 5000);
        });
    });
});

您需要做的就是 await msg.delete() 在您的 try 块中。承诺必须先解决,然后才能对其进行任何错误测试。

try {
  // Add 'await'
  await msg.delete();
} catch (error) {
  return console.log(error);
}

如果您想取消错误以使函数静默失败:

msg.delete()
   .catch(() => null);

您还可以在让您的客户端尝试删除它之前检查 Message#deletable

if (msg.deletable) {
   // I'd still recommend adding your preferred error handling
   msg.delete();
}
return message.reply({ content: "Done" })
          .then(m => setTimeout(() => message.delete().catch(() => null), 2500))

像这样使用它会解决 d.js v13.6

的问题