如何为 discord.py 中的命令设置 double/advanced 冷却时间?
How do I set a double/advanced cooldown for a command in discord.py?
这是一个有基本冷却时间的基本命令:
@client.command()
@commands.cooldown(5, 57600, commands.BucketType.user)
async def ping(ctx)
await ctx.send("pong")
所以基本上,当用户使用命令的前缀(例如'!k')然后键入“ping”时,机器人将发送“pong!”到聊天。这是一个非常基本的命令,然后是冷却装饰器。来自冷却时间:
@commands.cooldown(5, 57600, commands.BucketType.user)
我们可以看出该命令可以在 57600 秒(16 小时)之间使用 5 次,但是如果我希望命令每 16 小时仅使用 5 次并且每次使用该命令之间还有另一个冷却时间怎么办?让我解释一下...
您每 16 小时可以使用该命令 5 次
但是当你使用该命令时,你必须等待1小时才能再次使用它
这样一来,您将无法在一分钟内立即使用该命令 5 次
把它想象成一棵每小时长一个苹果但每天只长 5 个苹果的树...我怎样才能防止用户立即使用该命令 5 次?谢谢-
Discord.py 不允许每个命令进行多次冷却检查,因此您必须使用自定义冷却处理程序。
class CooldownManager:
def __init__(self, executions_allowed: int, cooldown_time: float):
self.state = {}
self.executions_allowed = executions_allowed
self.cooldown_time = cooldown_time
def time_left(self, key) -> float:
"""Attempt to execute. Return 0 if ready, or the number of seconds until you're allowed to execute again."""
if key not in self.state.keys():
self.state[key] = []
if len(self.state[key]) > 0:
# Clean up executions that have aged away
# self.state[key] is sorted with the newest first
for i in range(len(self.state[key])-1, -1, -1):
if self.state[key][i] + self.cooldown_time < time.time():
del self.state[key][i]
if len(self.state[key]) < self.executions_allowed:
self.state[key].append(time.time())
return 0
next_available_execution = self.state[key][len(self.state)-1] + self.cooldown_time
return next_available_execution - time.time()
else:
self.state[key].append(time.time())
return 0
def assert_cooldown(self, data):
"""Run this at the beginning of the command."""
time_left = self.time_left(data)
if time_left > 0:
raise commands.CommandOnCooldown('', retry_after=time_left)
cm1 = CooldownManager(1, 4.0) # execute once every 4 seconds
cm2 = CooldownManager(3, 120.0) # execute up to 3x every 2 minutes
@client.command(name='test')
async def multicooldown(ctx):
# Check both cooldowns. This raises `CommandOnCooldown` just like the vanilla cooldown handler, so you can catch that later in your command error check.
cm1.assert_cooldown(ctx.author.id) # This is basically the bucket type. You can use things like ctx.author.id, ctx.guild.id, etc
cm2.assert_cooldown(ctx.author.id)
# Do whatever you want here
await ctx.send('test')
这是一个有基本冷却时间的基本命令:
@client.command()
@commands.cooldown(5, 57600, commands.BucketType.user)
async def ping(ctx)
await ctx.send("pong")
所以基本上,当用户使用命令的前缀(例如'!k')然后键入“ping”时,机器人将发送“pong!”到聊天。这是一个非常基本的命令,然后是冷却装饰器。来自冷却时间:
@commands.cooldown(5, 57600, commands.BucketType.user)
我们可以看出该命令可以在 57600 秒(16 小时)之间使用 5 次,但是如果我希望命令每 16 小时仅使用 5 次并且每次使用该命令之间还有另一个冷却时间怎么办?让我解释一下...
您每 16 小时可以使用该命令 5 次
但是当你使用该命令时,你必须等待1小时才能再次使用它
这样一来,您将无法在一分钟内立即使用该命令 5 次
把它想象成一棵每小时长一个苹果但每天只长 5 个苹果的树...我怎样才能防止用户立即使用该命令 5 次?谢谢-
Discord.py 不允许每个命令进行多次冷却检查,因此您必须使用自定义冷却处理程序。
class CooldownManager:
def __init__(self, executions_allowed: int, cooldown_time: float):
self.state = {}
self.executions_allowed = executions_allowed
self.cooldown_time = cooldown_time
def time_left(self, key) -> float:
"""Attempt to execute. Return 0 if ready, or the number of seconds until you're allowed to execute again."""
if key not in self.state.keys():
self.state[key] = []
if len(self.state[key]) > 0:
# Clean up executions that have aged away
# self.state[key] is sorted with the newest first
for i in range(len(self.state[key])-1, -1, -1):
if self.state[key][i] + self.cooldown_time < time.time():
del self.state[key][i]
if len(self.state[key]) < self.executions_allowed:
self.state[key].append(time.time())
return 0
next_available_execution = self.state[key][len(self.state)-1] + self.cooldown_time
return next_available_execution - time.time()
else:
self.state[key].append(time.time())
return 0
def assert_cooldown(self, data):
"""Run this at the beginning of the command."""
time_left = self.time_left(data)
if time_left > 0:
raise commands.CommandOnCooldown('', retry_after=time_left)
cm1 = CooldownManager(1, 4.0) # execute once every 4 seconds
cm2 = CooldownManager(3, 120.0) # execute up to 3x every 2 minutes
@client.command(name='test')
async def multicooldown(ctx):
# Check both cooldowns. This raises `CommandOnCooldown` just like the vanilla cooldown handler, so you can catch that later in your command error check.
cm1.assert_cooldown(ctx.author.id) # This is basically the bucket type. You can use things like ctx.author.id, ctx.guild.id, etc
cm2.assert_cooldown(ctx.author.id)
# Do whatever you want here
await ctx.send('test')