地图项每次 node.js 都会被替换

Map items gets replaced every time node.js

我正在尝试为我的 Discord 机器人中的命令处理程序实施冷却,但我被卡住了。

冷却时间本身有效,但是当我尝试使用与我之前执行的命令不同的命令时,该冷却时间会被最后一个替换。这是代码:

const cooldowns = new Map();

       try {
    
            const cooldown = cooldowns.get(interaction.user.id);
    
            if (cooldown && cooldowns.get("command") == command.data.name) {
    
                const remaining = ms(cooldown - Date.now(), {till: "second"});
    
                return interaction.reply({ content: `Please wait until cooldown expires! Remaining: ${codeLine(remaining)}`});
            }
    
            await command.execute(client, interaction, Discord, profileData);
    
            let startTime = Date.now() + command.cooldown;
            cooldowns.set(interaction.user.id, startTime);
            cooldowns.set("command", command.data.name); 
    
            setTimeout(async () => cooldowns.delete(interaction.user.id, "command"), command.cooldown);
        }
        catch (error) {
    
            console.log(`The interaction error is ${error}`);
    
            await interaction.reply({ content: "There was an error trying to execute this command. ", ephemeral: true});
        }
    }

因此,例如,当我使用命令 /hello 时,冷却时间为 30 秒,这是第一次执行,如果我尝试再次执行它,机器人会以冷却时间响应说我在冷却时间到期之前不能使用该命令,这是正确的,但是如果我使用另一个命令,例如 /world 和 0 冷却时间,该命令会正确执行,但是 /hello 命令的冷却时间被取消,它可以再次使用。

我假设 interaction.user.id"command" 项目被替换为新项目,但我找不到创建新项目的方法。

已更新

根据您的要求,我创建了如下数据结构

{
   "userA": {
      "/hello": startTime
      "/world": startTime
   },
   "userB": {
      "/hello": startTime
      "/world": startTime
   }
}

userA 是用户id

/hello/world是命令

startTime是每个命令的冷却时间

您可以通过一些评论来检查此实现



const cooldowns = {}; //similar to Map but simpler

try {

  //cannot find any user in cooldowns map
  if (!cooldowns[interaction.user.id]) {
    cooldowns[interaction.user.id] = {} //create map to keep commands
  }

  //check if the cooldown exists in the commands
  const cooldown = cooldowns[interaction.user.id][command.data.name];

  if (cooldown) {

    const remaining = ms(cooldown - Date.now(), {
      till: "second"
    });

    if (remaining > 0) {
      return interaction.reply({
        content: `Please wait until cooldown expires! Remaining: ${codeLine(remaining)}`
      });
    }

  }

  await command.execute(client, interaction, Discord, profileData);

  let startTime = Date.now() + command.cooldown;

  cooldowns[interaction.user.id][command.data.name] = startTime

  setTimeout(async () => delete cooldowns[interaction.user.id][command.data.name], command.cooldown);
} catch (error) {

  console.log(`The interaction error is ${error}`);

  await interaction.reply({
    content: "There was an error trying to execute this command. ",
    ephemeral: true
  });
}

旧答案

 if (cooldown && cooldowns.get("command") == command.data.name) {
    const remaining = ms(cooldown - Date.now(), {till: "second"});
    return interaction.reply({ content: `Please wait until cooldown expires! Remaining: ${codeLine(remaining)}`});
}

我认为这部分导致了问题cooldowns.get("command") == command.data.name。如果您的新命令与之前的命令匹配,则检查冷却时间。

但是只要你的新命令与前一个命令不匹配,你就绕过了系统不会检查剩余时间的条件。

可能的解决方法应该是

 if (cooldown) {
    const remaining = ms(cooldown - Date.now(), {till: "second"});
    return interaction.reply({ content: `Please wait until cooldown expires! Remaining: ${codeLine(remaining)}`});
}

只需要从用户id上查看cooldown,不需要查看command匹配