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

Discord.js命令冷却到期后如何自动删除数据库过期记录

Discord 机器人命令冷却记录自动删除实现方案

现有代码核心问题

  • 查到数据库存在冷却记录时,没有先校验记录的过期时间,哪怕冷却已经结束,仍会向用户返回冷却中提示
  • 重复调用两次findOne查询同一条冷却记录,属于冗余操作,第一次查询返回的data对象就是目标记录,无需二次查询
  • 你编写的过期记录删除片段逻辑本身正确,但原有代码分支没有给过期记录预留处理入口,查到记录就默认判定为冷却中直接返回,因此找不到合适的插入位置

修正后逻辑说明

你写的删除代码需要放在查询到冷却记录的分支最开头,优先判断记录是否过期:

  1. 如果记录已过期:先删除旧的过期记录,再正常执行命令、写入新的冷却记录
  2. 如果记录未过期:再计算剩余冷却时间,向用户返回冷却提示

修正后的完整可运行代码如下:

const cmd = client.commands.get(command) || client.commands.find(a => a.aliases && a.aliases.includes(command)) 
if(cmd) {
    if(cmd.cooldown) {
        const cools = require("./Schema/cooldown");
        cools.findOne({
            guildID: message.guild.id,
            userID: message.author.id,
            command: cmd.name
        }, async(err, data) => {
            if(data) {
                const timeLeft = data.coolDown - Date.now();
                // 冷却已过期,删除旧记录后正常执行命令
                if(timeLeft <= 0) {
                    await cools.findOneAndRemove({
                        guildID: message.guild.id,
                        userID: message.author.id,
                        command: cmd.name
                    })
                    cmd.execute(client, message, args, prefix)
                    new cools({
                        guildID: message.guild.id, 
                        userID: message.author.id,
                        coolDown: Date.now() + cmd.cooldown,
                        command: cmd.name
                    }).save();
                    return
                }
                // 冷却未过期,返回提示
                const remainingTime = ms(timeLeft, {long: true})
                const embed = new MessageEmbed()
                .setDescription(`You already used ${cmd.name} command.`)
                .addField("Cooldown Time:", `${remainingTime}`)
                .setColor('RANDOM')
                .setTimestamp()

                return message.channel.send({embeds: [embed]}) 
            } else {
                // 无冷却记录,直接执行命令并写入冷却
                cmd.execute(client, message, args, prefix)
                new cools({
                        guildID: message.guild.id, 
                        userID: message.author.id,
                        coolDown: Date.now() + cmd.cooldown,
                        command: cmd.name
                }).save();
            }
        })
    } 
}

优化建议

  • 上述实现属于懒删除机制,只有用户触发对应命令时才会检查并删除过期记录,不需要额外维护定时器,内存开销极低,是Discord机器人冷却功能的主流实现方式
  • 如果担心长期运行后数据库堆积大量无人触发的过期记录,可以在机器人的ready事件中添加定时批量清理任务,每小时清理一次全库过期记录即可:
// 写入机器人ready事件回调中
setInterval(async () => {
    const cools = require("./Schema/cooldown");
    // 批量删除所有到期的冷却记录
    await cools.deleteMany({ coolDown: { $lt: Date.now() } })
}, 3600000) // 间隔1小时,单位毫秒
  • 不要为每条冷却记录单独创建setTimeout做定时删除:机器人重启时所有内存中的定时器会全部失效,且用户量级较大时会占用大量内存,极易引发内存泄漏。

内容的提问来源于stack exchange,提问作者エース

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:24:28