Custom Commands homeCustom Commands
  • Blog
  • Privacy
  • Premium
  • Templates
  • Support
Back to blog
// blog

Conditional cooldown for debugging custom commands

Want to have different cooldown for different user groups?

Md Shahriyar Alam

2 years ago

·4 min read

A fixed cooldown treats everyone the same. That's rarely what you want: the moderator running a cleanup command shouldn't wait as long as the member spamming a meme command.

With the has_permission and has_any_permission helpers, cooldowns become conditional — different limits for different people, decided at runtime.


Quick Answer: How Do You Set Different Cooldowns Per Role?

Call cooldown() inside a condition. Whichever branch runs decides the limit:

py
if has_permission(user, "administrator"):
    cooldown("10 seconds", user.id)
else:
    cooldown("1 minutes", user.id)

Drop that in a command's pre hook. Admins can now re-run the command every 10 seconds; everyone else waits a minute.

That's the whole idea — the rest of this guide is what you can do with it.


Skipping the Cooldown Entirely

Often you don't want a shorter limit for staff — you want none. Because the cooldown only applies when cooldown() actually runs, you skip it by not calling it:

py
if not has_permission(user, "administrator"):
    cooldown("1 minutes", user.id)

Regular members get a one-minute cooldown. Administrators get no cooldown at all, because for them that line never executes.

This is the pattern worth internalising: a cooldown that isn't called doesn't exist. Every conditional cooldown is just deciding whether — and with what duration — to make that call.


How the Pieces Work

has_permission(user, "administrator")

Returns True if the member has every permission you list:

py
has_permission(user, "manage_messages", "kick_members")  # needs both

has_any_permission(user, ...)

Returns True if they have at least one:

py
has_any_permission(user, "manage_messages", "kick_members")  # either is enough

Use has_any_permission when several roles should qualify — most staff checks are naturally "any of these", not "all of these".

cooldown(time, key)

Starts a cooldown for the given duration. The key decides who it applies to:

  • user.id → per user. Everyone has their own timer.
  • channel_id → per channel. One person's use blocks the whole channel.
  • A fixed string → server-wide. One timer for everybody.

Durations are plain English: "10 seconds", "1 minutes", "2 hours", "1 days".


Patterns Worth Stealing

Three tiers instead of two:

py
if has_permission(user, "administrator"):
    pass  # no cooldown
elif has_any_permission(user, "manage_messages", "kick_members"):
    cooldown("10 seconds", user.id)
else:
    cooldown("1 minutes", user.id)

Role-based rather than permission-based — useful for boosters or supporters, who have no special Discord permissions:

py
if not has_any_role(user, "Server Booster", "Supporter"):
    cooldown("2 minutes", user.id)

Per-channel cooldown so one busy channel doesn't get flooded, while other channels stay usable:

py
cooldown("30 seconds", channel_id)

A shared, server-wide cooldown for something genuinely expensive:

py
cooldown("1 hours", "global_announcement")

A custom message instead of the default rejection:

py
cooldown("1 minutes", user.id, error_message="Slow down — try again in a minute.")

Allow a few uses before the limit bites — count sets how many runs are permitted inside the window:

py
cooldown("1 minutes", user.id, count=3)

Three uses per minute, then they wait.


Where to Put It

Cooldowns belong in the pre hook, before any real work. That's the point: reject early, before the command has queried a database, called an API, or posted anything.

Put it at the very top, above your other logic:

py
if not has_permission(user, "administrator"):
    cooldown("1 minutes", user.id)

# ...the rest of your command

Troubleshooting

SymptomCauseFix
Everyone shares one cooldownNo key passed, or a fixed keyPass user.id as the key for per-user limits
Cooldown never triggerscooldown() sits in an unreached branchCheck your condition — an inverted if skips it silently
Admins still rate-limitedPermission name typoUse exact names: administrator, manage_messages, kick_members
Cooldown applies after the workCalled too late in the hookMove the cooldown() call to the top of pre code

Frequently Asked Questions

Can I give admins no cooldown in Discord?

Yes — wrap the call in a negative check so it never runs for them: if not has_permission(user, "administrator"): cooldown("1 minutes", user.id).

What's the difference between has_permission and has_any_permission?

has_permission requires all the permissions you list. has_any_permission requires at least one. For staff checks, has_any_permission is usually what you want.

Can cooldowns be per channel instead of per user?

Yes. The second argument is the key — pass channel_id for a per-channel cooldown, user.id for per-user, or any fixed string for a server-wide one.

Can I allow a few uses before the cooldown starts?

Yes. cooldown("1 minutes", user.id, count=3) permits three runs inside the window before blocking further use.

Can I base cooldowns on roles rather than permissions?

Yes — use has_any_role(user, "Booster", "Supporter"). Handy for members who deserve a shorter wait without holding any moderation permissions.

Do cooldowns survive a bot restart?

Yes. Cooldowns are persisted, so nobody bypasses one by waiting for a restart.


The Bigger Point

Conditional cooldowns are a small example of something larger: because these are your commands, every rule is a decision you make rather than a setting you're given.

Different limits per role, per channel, per time of day, or based on a member variable you track yourself — it's all the same if.

Possibilities are endless. You just have to think. 🚀

Loading comments…

{}

Need help?

Have a question, a suggestion, or stuck on something? Reach out — we're happy to help.

Join support server
Custom CommandsCustom Commands

The #1 custom commands Discord bot — build commands, events and databases with zero boilerplate.

Links

HomeBlogPrivacySupport

Contact

[email protected]

2 Frederick StreetLondon, WC1X 0ND

{ / } custom commands

© WEiRDSOFT LTD. All rights reserved.