You need to enable JavaScript to run this app. Discord Bot如何设置指令全局冷却:一人触发后全用户需等30分钟使用
优惠活动
大模型
产品
解决方案
定价
更多

Discord Bot如何设置指令全局冷却:一人触发后全用户需等30分钟使用

全局冷却实现核心逻辑

全局冷却与单用户冷却的本质区别仅在于冷却校验的键维度:

  • 单用户冷却以「用户ID + 指令名」为键,为每个用户单独维护冷却状态
  • 全局冷却不需要区分触发用户,直接用固定的指令标识作为唯一键,存储该指令最近一次有效执行的冷却截止时间戳,所有用户调用时统一校验该时间戳即可,无需为单个用户单独记录冷却信息
分步实现方案
  • 初始化全局冷却存储:在全局作用域下维护一个冷却状态存储对象,单进程部署场景直接使用原生JS对象即可,存储指令对应的冷却截止时间戳
  • 前置校验拦截:在指令触发逻辑的最开头,先读取对应指令的冷却截止时间戳:
    • 如果截止时间戳大于当前系统时间,说明冷却仍在生效,直接计算剩余冷却时长给用户返回提示,中断后续所有逻辑
    • 如果冷却已过期,再走原本的Embed确认弹窗、等待用户30秒内回复yes/no的流程
  • 精准写入冷却:只有在用户确认执行(即回复yes、完成职员角色@通知发送)之后,才更新全局冷却的截止时间,不要在用户刚触发指令的阶段就写入冷却,避免用户取消操作、超时的场景无意义占用冷却时长
参考代码实现

首先在全局作用域初始化配置与存储:

const Discord = require('discord.js');
const client = new Discord.Client();

// 全局冷却存储结构:键为指令标识,值为冷却截止时间戳
const globalCooldowns = {
  'call-all-staff': null // 初始状态无冷却
};
// 全局冷却时长:30分钟 = 30 * 60 * 1000 毫秒
const GLOBAL_COOLDOWN_MS = 30 * 60 * 1000;

指令触发与逻辑处理:

client.on('messageCreate', async (message) => {
  // 匹配call all staff的触发规则
  if (message.content === '!callallstaff') {
    // 第一步:全局冷却前置校验
    const cooldownEnd = globalCooldowns['call-all-staff'];
    const currentTime = Date.now();
    if (cooldownEnd && cooldownEnd > currentTime) {
      // 计算剩余冷却时间
      const remainingSec = Math.ceil((cooldownEnd - currentTime) / 1000);
      const remainingMin = Math.ceil(remainingSec / 60);
      return message.reply(`呼叫全体职员功能处于全局冷却中,请${remainingMin}分钟后再尝试使用。`);
    }

    // 冷却校验通过,弹出确认Embed
    const confirmEmbed = new Discord.MessageEmbed()
      .setTitle('紧急呼叫操作确认')
      .setDescription('该操作将@全体服务器职员,仅可在紧急场景使用,滥用将受到处罚。\n请在30秒内回复`yes`确认执行,回复`no`取消操作。');
    await message.channel.send({ embeds: [confirmEmbed] });

    // 收集发起者的回复
    const filter = (msg) => msg.author.id === message.author.id;
    const userReply = await message.channel.awaitMessages({
      filter,
      max: 1,
      time: 30 * 1000,
      errors: ['time']
    }).catch(() => null);

    // 超时处理
    if (!userReply) {
      return message.reply('操作超时,已取消呼叫请求。');
    }

    const replyContent = userReply.first().content.trim().toLowerCase();
    // 用户取消处理
    if (replyContent === 'no') {
      return message.reply('已取消呼叫全体职员操作。');
    }

    // 无效回复处理
    if (replyContent !== 'yes') {
      return message.reply('回复内容无效,已取消操作。');
    }

    // 用户确认yes,执行真正的通知逻辑
    const staffRole = message.guild.roles.cache.get('你的职员角色ID');
    await message.channel.send(`【紧急通知】${staffRole} 收到服务器紧急呼叫,请相关成员及时响应。`);

    // 通知发送成功后,才写入全局冷却
    globalCooldowns['call-all-staff'] = Date.now() + GLOBAL_COOLDOWN_MS;
  }
});

client.login('你的机器人Token');
常见踩坑提醒
  • 冷却写入时机偏差:不要在用户刚触发指令、弹出确认框的时候就写入冷却,否则用户选择取消、超时无回复的场景,也会让所有用户等30分钟冷却,完全违背功能设计的初衷
  • 多进程部署适配:如果机器人采用多进程/集群模式部署,不同进程的内存数据不互通,此时需要把全局冷却存储替换为共享缓存(如Redis),所有进程读取同一份冷却时间戳,否则会出现不同进程下的用户绕过冷却的问题
  • 冷却计时锚点偏移:冷却的计时起点要选在通知真正发送成功的时刻,不要从用户触发指令的时刻开始算,否则会因为用户确认回复的几十秒延迟,导致实际冷却时长不足30分钟

内容的提问来源于stack exchange,提问作者Sasco X

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.11 07:45:10