Discord.js 如何为Button按钮添加冷却机制避免触发速率限制
以下是两种生产可用的实现方案,可直接解决恶意点击按钮导致的bot触发Discord速率限制问题:
方案1:内存级冷却(适合中小型单实例bot)
基于Discord.js内置的Collection实现,自带过期自动清理能力,无需额外依赖:
- 初始化冷却存储,在bot启动时挂载全局冷却集合
- 在
interactionCreate事件中对Button交互做前置校验,通过用户ID+按钮customId生成唯一冷却标识,判断两次点击的时间差是否小于设置的冷却阈值 - 冷却期内的点击直接返回仅用户可见的提示,不执行业务逻辑
完整示例代码:
const { Client, GatewayIntentBits, Collection } = require('discord.js'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); // 全局默认冷却时长,单位毫秒,可根据不同按钮自定义 const DEFAULT_COOLDOWN = 3000; // 初始化冷却存储集合 client.buttonCooldowns = new Collection(); client.on('interactionCreate', async interaction => { // 只处理按钮交互 if (!interaction.isButton()) return; const cooldownKey = `${interaction.user.id}-${interaction.customId}`; const lastClickTime = client.buttonCooldowns.get(cooldownKey); // 校验是否处于冷却期 if (lastClickTime && Date.now() - lastClickTime < DEFAULT_COOLDOWN) { const waitTime = Math.ceil((DEFAULT_COOLDOWN - (Date.now() - lastClickTime)) / 1000); return interaction.reply({ content: `操作太频繁,请${waitTime}秒后再试`, ephemeral: true }); } // 写入冷却记录,到期自动删除释放内存 client.buttonCooldowns.set(cooldownKey, Date.now(), DEFAULT_COOLDOWN); // 此处写入正常按钮业务逻辑 // ... });
方案2:持久化冷却(适合集群/多实例bot,重启保留冷却)
如果你的bot使用多实例集群部署,或者希望重启后冷却规则仍然生效,可以使用Redis实现冷却,Redis自带原子操作和TTL过期能力,不会出现竞态问题:
const { Client, GatewayIntentBits } = require('discord.js'); const Redis = require('ioredis'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); const redis = new Redis(); // 自行配置Redis连接参数 const DEFAULT_COOLDOWN = 3000; client.on('interactionCreate', async interaction => { if (!interaction.isButton()) return; const cooldownKey = `btn_cooldown:${interaction.user.id}:${interaction.customId}`; const isInCooldown = await redis.get(cooldownKey); if (isInCooldown) { return interaction.reply({ content: "操作太频繁,请稍后再试", ephemeral: true }); } // NX参数保证只有key不存在时才写入,避免并发点击的竞态问题 await redis.set(cooldownKey, 1, 'PX', DEFAULT_COOLDOWN, 'NX'); // 此处写入正常按钮业务逻辑 // ... });
优化建议
- 冷却提示统一使用*ephemeral(仅用户可见)*属性,不会占用公开频道消息配额,也不会额外触发消息发送的速率限制
- 可根据按钮的业务属性自定义冷却时长,比如敏感操作(删除配置、触发额度消耗操作)可设置10秒以上冷却,普通查询类操作设置1-2秒即可
- 若有需要可单独配置全局黑名单,对频繁触发冷却的用户做临时全局限制,进一步降低风险
内容的提问来源于stack exchange,提问作者user16752914
相关产品推荐
相关产品推荐

