Skip to content

Checks

Checks are decorators that gate command execution. They run before the command callback and can block invocation by raising a CheckError. matrix.py ships with a built-in cooldown check; you can also write custom checks with Registry.add_check.

from matrix import Bot, Context
from matrix.checks import cooldown

bot = Bot()

@bot.command("roll")
@cooldown(rate=1, period=10.0)
async def roll(ctx: Context):
    await ctx.reply("🎲 You rolled a 6!")

matrix.checks

ADMIN_POWER_LEVEL module-attribute

ADMIN_POWER_LEVEL = 100

MODERATOR_POWER_LEVEL module-attribute

MODERATOR_POWER_LEVEL = 50

cooldown

cooldown(rate, period)

Decorator to cooldown a command.

Example
@cooldown(rate=3, period=10)
@bot.command("hello")
async def hello(ctx: Context) -> None:
    await ctx.reply("Hello!")

@hello.error(CooldownError)
async def hello_error(ctx: Context, error: CooldownError) -> None:
    await ctx.reply(f"Slow down! Try again in {error.retry:.1f}s.")
Source code in matrix/checks.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def cooldown(rate: int, period: float) -> Callable:
    """
    Decorator to cooldown a command.

    ## Example

    ```python
    @cooldown(rate=3, period=10)
    @bot.command("hello")
    async def hello(ctx: Context) -> None:
        await ctx.reply("Hello!")

    @hello.error(CooldownError)
    async def hello_error(ctx: Context, error: CooldownError) -> None:
        await ctx.reply(f"Slow down! Try again in {error.retry:.1f}s.")
    ```
    """

    def wrapper(cmd: "Command") -> "Command":
        cmd.set_cooldown(rate, period)
        return cmd

    return wrapper

is_admin

is_admin()

Decorator to restrict a command to room admins (power level >= ADMIN_POWER_LEVEL).

Example
@is_admin()
@bot.command("ban")
async def ban(ctx: Context, user_id: str) -> None:
    await ctx.room.ban_user(user_id)

@ban.error(CheckError)
async def ban_error(ctx: Context, error: CheckError) -> None:
    await ctx.reply("You must be an admin to use this command.")
Source code in matrix/checks.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def is_admin() -> Callable:
    """
    Decorator to restrict a command to room admins
    (power level >= `ADMIN_POWER_LEVEL`).

    ## Example

    ```python
    @is_admin()
    @bot.command("ban")
    async def ban(ctx: Context, user_id: str) -> None:
        await ctx.room.ban_user(user_id)

    @ban.error(CheckError)
    async def ban_error(ctx: Context, error: CheckError) -> None:
        await ctx.reply("You must be an admin to use this command.")
    ```
    """

    async def _is_admin(ctx: "Context") -> bool:
        level = ctx.room.power_levels.get_user_level(ctx.sender)
        return level >= ADMIN_POWER_LEVEL  # type: ignore[no-any-return]

    def wrapper(cmd: "Command") -> "Command":
        cmd.check(_is_admin)
        return cmd

    return wrapper

is_moderator

is_moderator()

Decorator to restrict a command to room moderators (power level >= MODERATOR_POWER_LEVEL).

Example
@is_moderator()
@bot.command("kick")
async def kick(ctx: Context, user_id: str) -> None:
    await ctx.room.kick_user(user_id)

@kick.error(CheckError)
async def kick_error(ctx: Context, error: CheckError) -> None:
    await ctx.reply("You must be a moderator to use this command.")
Source code in matrix/checks.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def is_moderator() -> Callable:
    """
    Decorator to restrict a command to room moderators
    (power level >= `MODERATOR_POWER_LEVEL`).

    ## Example

    ```python
    @is_moderator()
    @bot.command("kick")
    async def kick(ctx: Context, user_id: str) -> None:
        await ctx.room.kick_user(user_id)

    @kick.error(CheckError)
    async def kick_error(ctx: Context, error: CheckError) -> None:
        await ctx.reply("You must be a moderator to use this command.")
    ```
    """

    async def _is_moderator(ctx: "Context") -> bool:
        level = ctx.room.power_levels.get_user_level(ctx.sender)
        return level >= MODERATOR_POWER_LEVEL  # type: ignore[no-any-return]

    def wrapper(cmd: "Command") -> "Command":
        cmd.check(_is_moderator)
        return cmd

    return wrapper

is_room_encrypted

is_room_encrypted()

Decorator to restrict a command to encrypted rooms.

Example
@is_room_encrypted()
@bot.command("secret")
async def secret(ctx: Context) -> None:
    await ctx.reply("This room is encrypted!")

@secret.error(CheckError)
async def secret_error(ctx: Context, error: CheckError) -> None:
    await ctx.reply("This command can only be used in an encrypted room.")
Source code in matrix/checks.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
def is_room_encrypted() -> Callable:
    """
    Decorator to restrict a command to encrypted rooms.

    ## Example

    ```python
    @is_room_encrypted()
    @bot.command("secret")
    async def secret(ctx: Context) -> None:
        await ctx.reply("This room is encrypted!")

    @secret.error(CheckError)
    async def secret_error(ctx: Context, error: CheckError) -> None:
        await ctx.reply("This command can only be used in an encrypted room.")
    ```
    """

    async def _is_room_encrypted(ctx: "Context") -> bool:
        return ctx.room.encrypted

    def wrapper(cmd: "Command") -> "Command":
        cmd.check(_is_room_encrypted)
        return cmd

    return wrapper