Skip to content

Command

Command

Command()

Bases: ABC

Abstract base class for commands.

To create a command, subclass this class and implement the handle method. Then, register the command with the bot using bot.register(CommandSubclass).

Source code in src/signalbot/command.py
114
115
116
def __init__(self) -> None:
    # The bot attribute is assigned after calling bot.register(Command())
    self.bot: SignalBot | None = None

handle abstractmethod async

handle(context: Context) -> None

Abstract method to handle a command. This method must be implemented by subclasses to define the behavior of the command. Args: context: Chat context containing the received message and other information.

Source code in src/signalbot/command.py
125
126
127
128
129
130
131
132
@abstractmethod
async def handle(self, context: Context) -> None:
    """Abstract method to handle a command.
    This method must be implemented by subclasses to define the behavior of the
        command.
    Args:
        context: Chat context containing the received message and other information.
    """

setup

setup() -> None

Optional setup method that can be overridden by subclasses. This method is called after the command is registered with the bot but before any data is retrieved, so it cannot access the group ids.

Source code in src/signalbot/command.py
118
119
120
121
122
123
def setup(self) -> None:
    """Optional setup method that can be overridden by subclasses.
    This method is called after the command is registered with the bot but
    before any data is retrieved, so it cannot access the group ids.
    """
    return

reaction_triggered

reaction_triggered(
    *by: str,
) -> Callable[[Callable[P, T]], Callable[P, T]]

Decorator to trigger a command when a reaction is received.

Parameters:

Name Type Description Default
*by str

Optional emoji strings to filter on. If empty, triggers on any reaction.

()
Source code in src/signalbot/command.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def reaction_triggered(
    *by: str,
) -> Callable[[Callable[P, T]], Callable[P, T]]:
    """Decorator to trigger a command when a reaction is received.

    Args:
        *by: Optional emoji strings to filter on. If empty, triggers on any reaction.
    """

    def decorator_reaction_triggered(func: Callable[P, T]) -> Callable[P, T]:
        @functools.wraps(func)
        async def wrapper_reaction_triggered(
            *args: P.args, **kwargs: P.kwargs
        ) -> T | None:
            context: Context = args[1]
            if context.message.reaction is None:
                return None
            if by and context.message.reaction.emoji not in by:
                return None
            return await func(*args, **kwargs)

        return wrapper_reaction_triggered

    return decorator_reaction_triggered

regex_triggered

regex_triggered(
    *by: str | Pattern[str],
) -> Callable[[Callable[P, T]], Callable[P, T]]

Decorator to trigger a command if the message text matches any of the provided regex patterns.

Parameters:

Name Type Description Default
*by str | Pattern[str]

A variable number of strings or compiled regex patterns to match the message text against.

()
Source code in src/signalbot/command.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def regex_triggered(
    *by: str | re.Pattern[str],
) -> Callable[[Callable[P, T]], Callable[P, T]]:
    """Decorator to trigger a command if the message text matches any of the provided
    regex patterns.

    Args:
        *by: A variable number of strings or compiled regex patterns to match the
            message text against.
    """

    def decorator_regex_triggered(func: Callable[P, T]) -> Callable[P, T]:
        @functools.wraps(func)
        async def wrapper_regex_triggered(
            *args: P.args, **kwargs: P.kwargs
        ) -> T | None:
            context: Context = args[1]
            text = context.message.text
            if not isinstance(text, str):
                return None
            matches = [bool(re.search(pattern, text)) for pattern in by]
            if True not in matches:
                return None
            return await func(*args, **kwargs)

        return wrapper_regex_triggered

    return decorator_regex_triggered

triggered

triggered(
    *by: str, case_sensitive: bool = False
) -> Callable[[Callable[P, T]], Callable[P, T]]

Decorator to trigger a command if the message text matches any of the provided strings.

Parameters:

Name Type Description Default
*by str

A variable number of strings to match the message text against.

()
case_sensitive bool

Whether the matching should be case sensitive.

False
Source code in src/signalbot/command.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def triggered(
    *by: str, case_sensitive: bool = False
) -> Callable[[Callable[P, T]], Callable[P, T]]:
    """Decorator to trigger a command if the message text matches any of the provided
    strings.

    Args:
        *by: A variable number of strings to match the message text against.
        case_sensitive: Whether the matching should be case sensitive.
    """

    def decorator_triggered(func: Callable[P, T]) -> Callable[P, T]:
        @functools.wraps(func)
        async def wrapper_triggered(*args: P.args, **kwargs: P.kwargs) -> T | None:
            context: Context = args[1]
            text = context.message.text
            if not isinstance(text, str):
                return None

            by_words = by
            if not case_sensitive:
                text = text.lower()
                by_words = [t.lower() for t in by_words]
            if text not in by_words:
                return None

            return await func(*args, **kwargs)

        return wrapper_triggered

    return decorator_triggered