Cooldowns

This module allows you to rate limit users with a sliding window rate limit.

The crescent.ext.cooldowns module provides a hook.

  • capacity is the amount of times the command can be used in a timeframe.
  • period is the length of this timeframe.
import crescent
import datetime
from crescent.ext import cooldowns

@client.include
# This command be used 3 times in 20 seconds.
@crescent.hook(cooldowns.cooldown(capacity=3, period=datetime.timedelta(seconds=20)))
@crescent.command
async def cooldowned(ctx: crescent.Context):
    print("Doing expensive operation...")
    await ctx.respond("Hello!")

Rate Limited Hook

Callbacks can be set to run when a user is ratelimited.

async def on_rate_limited(ctx: crescent.Context, time_remaining: datetime.timedelta) -> None:
    await ctx.respond(f"You are ratelimited for {time_remaining.total_seconds()}s.")

@client.include
@crescent.hook(
    cooldowns.cooldown(1, datetime.timedelta(minutes=1), callback=on_rate_limited),
)
@crescent.command
async def cooldowned(ctx: crescent.Context) -> None:
    print("Doing expensive operation...")
    await ctx.respond("Hello!")

Custom Bucket

The default bucket uses user IDs to separate users.

This is how the default bucket is implemented:

import typing
import crescent

def default_bucket(ctx: crescent.Context) -> typing.Any:
    return ctx.user.id

This is a bucket that rate limits users based on ID and guild ID:

import crescent
import typing

def custom_bucket(ctx: crescent.Context) -> typing.Any:
    return f"{ctx.guild_id}{ctx.user.id}"

To use a custom bucket, pass it into the bucket kwarg.

@client.include
@crescent.hook(cooldowns.cooldown(3, datetime.timedelta(seconds=20), bucket=custom_bucket))
@crescent.command
async def cooldowned(ctx: crescent.Context):
    print("Doing expensive operation...")
    await ctx.respond("Hello!")