These can be used on any function or method marked with async
,
Nextcord is just used for the examples here.
Rate-limits the command to 1
call per person
every 15
seconds in your main file.
import cooldowns
...
@bot.slash_command(
description="Ping command",
)
@cooldowns.cooldown(1, 15, bucket=cooldowns.SlashBucket.author)
async def ping(interaction: nextcord.Interaction):
await interaction.response.send_message("Pong!")
Rate-limits the command to 1
call per
guild every 30
seconds.
import cooldowns
...
@nextcord.slash_command(
description="Ping command",
)
@cooldowns.cooldown(1, 30, bucket=cooldowns.SlashBucket.guild)
async def ping(self, interaction: nextcord.Interaction):
await interaction.response.send_message("Pong!")
Here is an example error handler
from cooldowns import CallableOnCooldown
...
@bot.event
async def on_application_command_error(inter: nextcord.Interaction, error):
error = getattr(error, "original", error)
if isinstance(error, CallableOnCooldown):
await inter.send(
f"You are being rate-limited! Retry in `{error.retry_after}` seconds."
)
else:
raise error
from cooldowns import get_remaining_calls, cooldown, SlashBucket
@bot.slash_command()
@cooldown(2, 10, SlashBucket.command)
async def test(inter):
...
calls_left = get_remaining_calls(test, inter)
await inter.send(f"You can call this {calls_left} times before getting rate-limited")
Only resets cooldowns for the given id.
from cooldowns import cooldown, CooldownBucket, reset_cooldown
@cooldown(1, 30, CooldownBucket.all, cooldown_id="my_cooldown")
async def test(*args, **kwargs):
...
# Reset
reset_cooldown("my_cooldown")
Resets all cooldowns on the provided callable.
from cooldowns import cooldown, CooldownBucket, reset_cooldowns
@cooldown(1, 30, CooldownBucket.all)
@cooldown(1, 15, CooldownBucket.args)
async def test(*args, **kwargs):
...
# Reset
reset_cooldowns(test)
Resets only the given buckets on a cooldown.
from cooldowns import cooldown, CooldownBucket, reset_bucket
@cooldown(1, 30, CooldownBucket.all)
async def test(*args, **kwargs):
...
...
# Reset the bucket with `1` as an argument
reset_bucket(test, 1)
Here's an example check to only apply a cooldown
if the first argument is equal to 1
.
@cooldown(
1, 1, bucket=CooldownBucket.args, check=lambda *args, **kwargs: args[0] == 1
)
async def test_func(*args, **kwargs) -> (tuple, dict):
return args, kwargs
Here's one use an async check. Functionally its the same as the previous one.
async def mock_db_check(*args, **kwargs):
# You can do database calls here or anything
# since this is an async context
return args[0] == 1
@cooldown(1, 1, bucket=CooldownBucket.args, check=mock_db_check)
async def test_func(*args, **kwargs) -> (tuple, dict):
return args, kwargs
All you need is an enum with the process
method.
Heres an example which rate-limits based off of the first argument.
class CustomBucket(Enum):
first_arg = 1
def process(self, *args, **kwargs):
if self is CustomBucket.first_arg:
# This bucket is based ONLY off
# of the first argument passed
return args[0]
# Then to use
@cooldown(1, 1, bucket=CustomBucket.first_arg)
async def test_func(*args, **kwargs):
.....
Stack as many cooldown's as you want, just note Python starts from the bottom decor and works its way up.
# Can call ONCE time_period second using the same args
# Can call TWICE time_period second using the same kwargs
@cooldown(1, 1, bucket=CooldownBucket.args)
@cooldown(2, 1, bucket=CooldownBucket.kwargs)
async def test_func(*args, **kwargs) -> (tuple, dict):
return args, kwargs
This allows you to use the same cooldown on multiple callables.
from cooldowns import define_shared_cooldown, shared_cooldown, CooldownBucket
define_shared_cooldown(1, 5, CooldownBucket.all, cooldown_id="my_id")
@shared_cooldown("my_id")
async def test_1(*args, **kwargs):
return 1
@shared_cooldown("my_id")
async def test_2(*args, **kwargs):
return 2
# These now both share the same cooldown
How to use the Cooldown object without a decorator.
from cooldowns import Cooldown, CooldownBucket
cooldown = Cooldown(1, 5, CooldownBucket.args)
async with cooldown(*args, **kwargs):
# This will apply the cooldown
...
# Do things
This is useful if you want to be able to trigger a specific time_period cooldown inside the command itself.
from cooldowns import TriggerCooldown, CooldownBucket
my_trigger_cooldown = TriggerCooldown(1, 5, CooldownBucket.all)
@my_trigger_cooldown
async def test_1(*args, **kwargs):
# Your command.
# Do things..
# Apply the trigger cooldown instantly.
await my_trigger_cooldown.trigger(20)
# You can still do things..
# But command cannot be called again within 20 seconds.