You need to enable JavaScript to run this app. 如何在discord.py中为机器人特定指令添加冷却效果并适配现有代码
优惠活动
大模型
产品
解决方案
定价
更多

如何在discord.py中为机器人特定指令添加冷却效果并适配现有代码

你无法集成@commands.cooldown的核心原因
  • 当前代码基于discord.Client的原生on_message事件手写指令触发逻辑,并未接入commands.Bot的指令注册体系,而@commands.cooldown是专为commands框架注册的指令设计的配套装饰器,核心的冷却计数、维度分桶、冷却重置逻辑都绑定在框架的指令执行流程上,脱离框架手写的消息判断逻辑根本无法触发该装饰器的生效链路。
  • 现有逻辑没有内置的冷却状态存储、用户维度的调用记录能力,硬把装饰器加在普通消息判断分支上不会产生任何效果。

推荐实现方案:迁移到commands.Bot框架(完美适配现有cooldown装饰器)

  • 把初始化的原生客户端替换为commands.Bot实例,指定你的指令前缀为#,自动加载指令解析、冷却管理的整套内置能力
  • 将原来自写的#help、#gamble触发逻辑,改为用@client.command()装饰的独立指令函数,此时就可以直接叠加@commands.cooldown(rate=1, per=5, bucket=commands.BucketType.user)装饰器实现单用户维度的5秒1次的冷却规则
  • 必须在重写的on_message事件中加入await client.process_commands(message),否则Bot不会识别、执行所有注册的指令
  • 改造后的完整参考代码:
import discord
import random
from pathlib import Path
from discord.ext import commands

# 替换原生Client为带指令框架的Bot,匹配你原来的#前缀
client = commands.Bot(command_prefix='#')

@client.event
async def on_ready():
    print(f'We have logged in as {client.user}')

# 带冷却规则的gamble指令:每个用户每5秒最多调用1次
@client.command()
@commands.cooldown(rate=1, per=5, bucket=commands.BucketType.user)
async def gamble(ctx):
    # 原#gamble的业务逻辑写在这里,ctx.send()可以直接向指令所在频道发消息
    *command goes here*

@client.command()
async def help(ctx):
    # 原#help的业务逻辑写在这里
    *command goes here*

# 捕获冷却触发的异常,给用户友好提示
@client.event
async def on_command_error(ctx, error):
    if isinstance(error, commands.CommandOnCooldown):
        wait_seconds = round(error.retry_after, 1)
        await ctx.send(f'操作太快啦,这个指令还要等{wait_seconds}秒才能再次使用')

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    # 必须加这行调用,否则框架不会处理注册的指令
    await client.process_commands(message)

client.run('TOKEN')

备选实现方案:不迁移框架,手动实现冷却逻辑

如果不想改动现有整体指令结构,可以自己维护冷却记录字典,手动判断触发间隔:

  • 新建字典存储每个用户对不同指令的上次调用时间戳,每次触发指令时对比当前时间和上次调用的时间差,不足冷却时长就直接拦截返回
  • 核心参考逻辑:
import time
# 冷却记录表:{指令名: {用户ID: 上次调用时间戳}}
cooldown_store = {
    "gamble": {}
}
# 配置gamble指令的冷却时长为5秒
COOLDOWN_CONFIG = {
    "gamble": 5
}

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    now = time.time()
    user_id = message.author.id

    if message.content.startswith('#gamble'):
        # 获取当前用户上次调用gamble的时间
        last_call = cooldown_store["gamble"].get(user_id, 0)
        # 判断是否在冷却期
        if now - last_call < COOLDOWN_CONFIG["gamble"]:
            wait = round(COOLDOWN_CONFIG["gamble"] - (now - last_call), 1)
            await message.channel.send(f'操作太快啦,还要等{wait}秒才能用这个指令')
            return
        # 更新调用时间戳
        cooldown_store["gamble"][user_id] = now
        # 原gamble业务逻辑写在这里
        *command goes here*

    if message.content.startswith('#help'):
        # 原help业务逻辑写在这里
        *command goes here*

内容的提问来源于stack exchange,提问作者Luke Timmons

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 02:06:01