discord.js 的冷却系统问题

时间:2021-05-25 06:08:34

标签: javascript discord.js bots

我是编码新手,我正在制作一个不和谐的机器人,我想制作一个命令,所有成员都需要等待一段时间才能再次使用它,但其中一些不需要同时等待。

例如:角色 X 的成员等待 20 秒,角色 Y 的成员等待 10 秒。

问题是我无法让它与名为 humanize-duration 的 npm 包一起工作以腾出时间。嵌入描述未显示正确的时间戳。可能是我弄错了。

我试图解决什么问题?

我尝试阅读 discord.js 文档、humanize-duration 文档和 this post,但无法修复。另外,我没有收到任何错误。顺便说一句,我使用了一个命令处理程序。

这是我用作示例的代码(ping 命令):

const Discord = require("discord.js");
const humanizeDuration = require("humanize-duration");

let cooldown = new Set();

module.exports = {
  name: "ping",
  description: "It shows the bot latency.",
  
  execute(client, message, args) {
      
    let guild = client.guilds.cache.get("828376495969402901");

    let member = guild.members.cache.get(message.author.id);
      
    if(cooldown.has(message.author.id) && !member.roles.cache.has("830503345251680298")) {
        const remaining = humanizeDuration(cooldown.has(message.author.id) && !member.roles.cache.has("830503345251680298") - Date.now(), { units: ["s"], round: true, language: "en" });
        const cooldownEmbed = new Discord.MessageEmbed()
        .setTitle(`Slow down, bud`)
        .setDescription(`You can run \`ping\` again in **${remaining}**.\nThe default cooldown is \`20s\`, but boosters can only wait \`10s\`!`)
        .setColor(`RANDOM`);
        
       return message.channel.send(cooldownEmbed)
    }else if (cooldown.has(message.author.id) && member.roles.cache.has("830503345251680298")) {
        const remaining = humanizeDuration(cooldown.has(message.author.id) && member.roles.cache.has("830503345251680298") - Date.now(), { units: ["s"], round: true, language: "en" });
        const cooldownEmbed = new Discord.MessageEmbed()
        .setTitle(`Too fast`)
        .setDescription(`You can run this command again in **${remaining}**. (booster perk)`)
        .setColor(`RANDOM`);
        
        return message.channel.send(cooldownEmbed)
    }
    
    if(cooldown.add(message.author.id) && !member.roles.cache.has("830503345251680298")) {
    setTimeout(() => {
        cooldown.delete(message.author.id) && !member.roles.cache.has("830503345251680298")
    }, 10000)
}else if(cooldown.add(message.author.id) && member.roles.cache.has("830503345251680298")) {
    setTimeout(() => {
        cooldown.delete(message.author.id) && member.roles.cache.has("830503345251680298")
    }, 2000)
}

    message.channel.send('Pinging...').then(message => {

      const embed = new Discord.MessageEmbed()
        .setDescription(`Pong! :ping_pong: \`${Date.now() - message.createdTimestamp} ms\``)
        .setColor(`RANDOM`);

      message.edit(" ", embed);
    })
  }
}

enter image description here

非常感谢您提前提供帮助。

亲切的问候。

2 个答案:

答案 0 :(得分:1)

问题 #1:cooldown.has(message.author.id) && member.roles.cache.has("830503345251680298") 不返回数字

问题#2:看起来结果返回一个以毫秒为单位的数字,因此您需要使用正确的计算方法计算以毫秒为单位的剩余时间。您可以使用 Date.now() 代替 performance.now()

工作原理:

const {performance} = require('perf_hooks');
 
var start = performance.now();
// something happens
var end = performance.now();
var total = Math.floor(end - start) // returns time between each event

可能的解决方案:

const Discord = require("discord.js");
const humanizeDuration = require("humanize-duration");
const { performance } = require('perf_hooks');

let cooldown = new Set();

module.exports = {
    name: "ping",
    description: "It shows the bot latency.",

    execute(client, message, args) {

        let guild = client.guilds.cache.get("828376495969402901");
        var start = performance.now();
        let member = guild.members.cache.get(message.author.id);

        if (cooldown.has(message.author.id) && !member.roles.cache.has("830503345251680298")) {
            var end = performance.now();
            var total = Math.floor(end - start)
            const remaining = humanizeDuration(total, { units: ["s"], round: true, language: "en" });
            const cooldownEmbed = new Discord.MessageEmbed()
                .setTitle(`Slow down, bud`)
                .setDescription(`You can run \`ping\` again in **${remaining}**.\nThe default cooldown is \`20s\`, but boosters can only wait \`10s\`!`)
                .setColor(`RANDOM`);

            return message.channel.send(cooldownEmbed)
        }
    }
}

message.channel.send('Pinging...').then(message => {

    const embed = new Discord.MessageEmbed()
        .setDescription(`Pong! :ping_pong: \`${Date.now() - message.createdTimestamp} ms\``)
        .setColor(`RANDOM`);

    message.edit(" ", embed);
})

答案 1 :(得分:1)

有几个错误。首先,cooldown.has(message.author.id)member.roles.cache.has("830503345251680298") 都返回一个布尔值。你不能用它来衡量剩余时间。

图像上显示的错误是由于您试图从布尔值 (Date.now()) 中减去日期 (!member.roles.cache.has("830503345251680298")),因此它返回自时代。检查以下代码段:

console.log(true - Date.now())
console.log(false - Date.now())

要解决此问题,您需要将到期日期存储在某处。我建议您将这些冷却时间到期时间与成员 ID 的键一起存储在不和谐 collection 中。然后,检查两件事;如果成员具有助推器角色 (memberHasBooster) 并且成员必须等待冷却时间到期 (memberHasCooldown)。

如果memberHasCooldown,您可以通过从到期日期(new Date())中减去当前日期(cooldowns.get(message.author.id))来计算剩余时间。它以毫秒为单位返回剩余时间。请注意,我使用了 cooldowns.get,而不是 cooldowns.hasCollection#get 返回存储的实际值,Collection#has 仅返回布尔值。

然后,您可以将剩余时间格式化,并在嵌入中发送。

如果成员没有冷却时间,您可以使用 Collection#set 添加一个新成员。键是会员 ID,值是到期日。您可以通过将 10000/20000 毫秒 (timeout) 添加到当前时间来计算到期日期。您还需要添加具有相同 setTimeouttimeout 并从集合中删除冷却时间。

添加冷却时间后,您可以发送实际消息。我在这里使用了异步/等待。不要忘记为实际发送的消息使用不同的名称(sentMessage 而不是 message)。

查看下面的完整代码:

let Discord = require('discord.js');
let humanizeDuration = require('humanize-duration');

let cooldowns = new Discord.Collection();

module.exports = {
  name: 'ping',
  description: 'It shows the bot latency.',
  async execute(client, message, args) {
      let guild = client.guilds.cache.get('828376495969402901');
      let member = guild.members.cache.get(message.author.id);
      let memberHasBooster = member.roles.cache.has('830503345251680298');
      let memberHasCooldown = cooldowns.has(message.author.id);

      if (memberHasCooldown) {
        let remaining = cooldowns.get(message.author.id) - new Date.now();
        let remainingFormatted = humanizeDuration(remaining, {
          language: 'en',
          round: true,
          units: ['s'],
        });
        let embed = new Discord.MessageEmbed()
          .setColor(`RANDOM`)
          .setTitle(`Slow down, bud`)
          .setDescription(
            `You can run \`ping\` again in **${remainingFormatted}**. ${
              memberHasBooster
                ? '(booster perk)'
                : '\nThe default cooldown is `20s`, but boosters can only wait `10s`!'
            }`,
          );

        return message.channel.send(embed);
      }

      // add cooldown
      const timeout = memberHasBooster ? 10 * 1000 : 20 * 1000;
      cooldowns.set(message.author.id, new Date() + timeout);

      setTimeout(() => cooldowns.delete(message.author.id), timeout);

      const sentMessage = await message.channel.send('Pinging...');

      const embed = new Discord.MessageEmbed()
        .setDescription(
          `Pong! :ping_pong: \`${
            Date.now() - sentMessage.createdTimestamp
          } ms\``,
        )
        .setColor(`RANDOM`);

      sentMessage.edit(' ', embed);
  },
};