discord.js角色差异化命令冷却下humanize-duration时间显示异常问题
核心问题原因
- 存储结构选型错误:你使用
Set存储处于冷却的用户ID,仅能记录「用户是否在冷却中」,无法存储用户触发命令的时间戳,导致剩余冷却时间计算逻辑完全错误。 - 计算逻辑错误:你在计算
remaining时,直接拿返回布尔值的判断表达式cooldown.has(xxx) && xxx做减法运算,布尔值在数值运算中会被隐式转换为1(true)或0(false),最终得到的是负数时间戳,humanize-duration处理这类非法输入自然无法输出正确结果。 - 冷却时长配置写反:需求是普通用户冷却20秒、特权角色冷却10秒,你代码里普通用户的
setTimeout设了10000ms(10秒)、特权角色设了2000ms(2秒),完全不符合需求。 - 冗余无效逻辑:
setTimeout内的cooldown.delete(xxx) && 权限判断逻辑完全无效,Set.delete()返回布尔值,后续的表达式不会产生任何实际作用。
修正后的代码
const Discord = require("discord.js"); const humanizeDuration = require("humanize-duration"); // 改用Map存储,key为用户ID,value为用户触发命令的时间戳 const cooldown = new Map(); // 提前定义配置项,后续修改更方便 const BOOSTER_ROLE_ID = "830503345251680298"; const DEFAULT_COOLDOWN = 20 * 1000; // 普通用户20秒 const BOOSTER_COOLDOWN = 10 * 1000; // 特权用户10秒 const GUILD_ID = "828376495969402901"; module.exports = { name: "ping", description: "It shows the bot latency.", execute(client, message, args) { const guild = client.guilds.cache.get(GUILD_ID); const member = guild.members.cache.get(message.author.id); const isBooster = member.roles.cache.has(BOOSTER_ROLE_ID); const userCooldown = isBooster ? BOOSTER_COOLDOWN : DEFAULT_COOLDOWN; // 判断用户是否在冷却中 if (cooldown.has(message.author.id)) { const useTime = cooldown.get(message.author.id); const remaining = useTime + userCooldown - Date.now(); // 剩余时间大于0才返回冷却提示 if (remaining > 0) { const remainingText = humanizeDuration(remaining, { units: ["s"], round: true, language: "en" }); const cooldownEmbed = new Discord.MessageEmbed() .setTitle(isBooster ? `Too fast` : `Slow down, bud`) .setDescription(isBooster ? `You can run this command again in **${remainingText}**. (booster perk)` : `You can run \`ping\` again in **${remainingText}**.\nThe default cooldown is \`20s\`, but boosters can only wait \`10s\`!` ) .setColor(`RANDOM`); return message.channel.send(cooldownEmbed); } } // 记录用户当前触发命令的时间 cooldown.set(message.author.id, Date.now()); // 到时间后清除冷却记录 setTimeout(() => { cooldown.delete(message.author.id); }, userCooldown); // 原有ping逻辑不变,修改变量名避免冲突 message.channel.send('Pinging...').then(sentMsg => { const embed = new Discord.MessageEmbed() .setDescription(`Pong! :ping_pong: \`${Date.now() - sentMsg.createdTimestamp} ms\``) .setColor(`RANDOM`); sentMsg.edit(" ", embed); }) } }
额外优化点
- 把固定配置项统一提取到代码顶部,后续修改不需要改动业务逻辑
- 冗余的重复判断逻辑合并,代码可读性更高
- 增加剩余时间合法性判断,避免输出异常数值
- 修复了回调函数内变量名和外层变量冲突的潜在问题
内容的提问来源于stack exchange,提问作者Kingstar
相关产品推荐
相关产品推荐

