# Checks

> Cooldowns, permission checks, role and channel rules, and custom error messages.

A check stops the command when a rule is not met. The person sees an error message, and nothing else runs.

Put checks at the **top** of the pre-hook, before any work.

These functions work in slash commands, text commands and component handlers. You do not need to write `await` in front of them.

> **Tip:** You do not need `if` around a check. Each one stops the command by itself, with a good message.

## cooldown

Makes a member wait before using the command again.

```python
cooldown(time, key=None, error_message=None, count=1)
```

| Argument | What it does |
|---|---|
| `time` | How long to wait, in words: `"30 seconds"`, `"1 hour"`, `"1 day"`. |
| `key` | Who shares the cooldown. Default is the member who ran it. |
| `error_message` | Your own message. It can use the placeholders below. |
| `count` | How many uses are allowed before the wait starts. |

```python
cooldown("1 day", error_message="You already claimed today. Come back %relative%.")
coins = int(member_var("coins", 0)) + 100
update_member_var("coins", coins)
set_content(f"You got 100 coins! You now have {coins}.")
```

**Placeholders** for `error_message`:

| Placeholder | Becomes | Shows in Discord as |
|---|---|---|
| `%time%` | `5 minutes` | plain text |
| `%relative%` | a Discord time tag | **in 5 minutes**, counting down by itself |
| `%at%` | a Discord time tag | **9:46 PM**, in each reader's time zone |
| `%timestamp%` | `1788731206` | the raw number of seconds |

Use `%time%` for "try again after %time%". Use `%relative%` for "try again %relative%".

**Who shares the cooldown**

| `key` | Effect |
|---|---|
| not set | Each member has their own cooldown. |
| `server.id` | One cooldown for the whole server. |
| `channel.id` | One cooldown per channel. |
| `[user.id, channel.id]` | One per member, per channel. |

> **In a component handler:** In a component handler, `cooldown(time, key=None)` does not stop the script. It returns `False` when the click may go on, or the time left as text when it must wait.
> 
> ```python
> left = cooldown("10 seconds")
> if left:
>     set_error(f"Slow down. Try again in {left}.")
> ```

## require_permission

Lets the command run only for members with **all** these Discord permissions. Administrators always pass.

```python
require_permission(*permissions, error_message=None)
```

```python
require_permission("ban_members")
```

Write permission names in lowercase with `_`. Common ones:

`administrator`, `manage_server`, `manage_roles`, `manage_channels`, `manage_messages`, `kick_members`, `ban_members`, `timeout_members`, `mention_roles`, `send_messages`, `view_channel`.

A wrong name stops the script and lists every valid name.

## allowed_roles

Lets the command run only for members with **at least one** of these roles.

```python
allowed_roles(*roles, error_message=None)
```

```python
allowed_roles("Staff", "Moderator", error_message="Only staff can use this.")
```

Roles can be role objects, role IDs or exact role names.

## banned_roles

Stops members with **any** of these roles from running the command.

```python
banned_roles(*roles, error_message=None)
```

```python
banned_roles("Muted")
```

## allowed_channels

Lets the command run only in these channels.

```python
allowed_channels(*channels, error_message=None)
```

```python
allowed_channels("bot-commands", error_message="Use this in #bot-commands.")
```

## banned_channels

Stops the command in these channels.

```python
banned_channels(*channels, error_message=None)
```

## set_error

Stops the script at once and shows your message as an error.

```python
set_error(message)
```

```python
amount = int(amount)
if amount <= 0:
    set_error("The amount must be more than 0.")
```

`set_error` works everywhere, including events. In a command, the message is the reply.

> **Tip:** You can also set some rules on the dashboard, with no code. Open a command and pick **Allowed roles** and **Allowed channels**.
