talkomatic.py 0.1.2
An easy-to-use Python versatile wrapper for the Talkomatic Bot interface ensuring best practices for making bots, and handling the REST API.
 
Loading...
Searching...
No Matches
command.py
Go to the documentation of this file.
1from talkomatic.dataclasses import User
2
3import argparse
4from shlex import split as split_args
5from typing import Callable, Awaitable, Any, Type, Union
6
7
8
9class _ArgumentParser(argparse.ArgumentParser):
10 """
11 A private class that is identical to argparse.ArgumentParser, the
12 only change being that error messages are not printed.
13 """
14
15 def error(self, message: str) -> None:
16 pass
17
19 """
20 A class that represents a parameter for a command.
21
22 Args:
23 name (str): The name of the parameter.
24 description (str): The description of the parameter.
25 data_type (object): The type of the parameter.
26 aliases (list[str]): The aliases of the parameter.
27 required (bool): Whether the parameter is required.
28 number_of_args (int): The number of arguments the parameter can take. (INFINITE_ARGS for infinite)
29 """
30
31 name: str
32 description: str
33 data_type: Type[Union[int, float, str, bool]]
34 aliases: list[str]
35 positional: bool
36 required: bool
37 number_of_args: int
38
39 def __init__(self, name: str, description: str, data_type: Type[Union[int, float, str, bool]], positional: bool = False, aliases: list[str] = [], required: bool = True, number_of_args: int = 1) -> None:
40 if data_type not in (int, float, str, bool):
41 raise ValueError("Invalid data type")
42
43 self.name = name
44 self.description = description
45 self.data_type = data_type
46 self.positional = positional
47 self.aliases = aliases
48 self.required = required
49 self.number_of_args = number_of_args
50
51class Command:
52 function: Callable[..., Awaitable[Any]]
53 _parser: argparse.ArgumentParser
54 name: str
55 description: str
56 aliases: list[str]
57 parameters: list[CommandParameter]
58 hidden: bool
59
60 def __init__(self, name: str, description: str, aliases: list[str] = [], hidden: bool = False) -> None:
61 self.name = name
62 self.description = description
63 self.aliases = aliases
64 self.hidden = hidden
65 self._parser = _ArgumentParser(prog = name, description = description, add_help = False)
66
67 def add_argument(self, names: list[str], description: str, data_type: Type[Union[int, float, str, bool]], positional: bool = False, required: bool = True, number_of_args: int = 1) -> None:
68 required_args = {}
69 if positional:
70 if required:
71 if number_of_args == INFINITE_ARGS:
72 required_args["nargs"] = "+"
73 else:
74 required_args["nargs"] = number_of_args
75 elif number_of_args == INFINITE_ARGS:
76 required_args["nargs"] = "*"
77 else:
78 required_args["nargs"] = "?"
79 else:
80 if required:
81 required_args["required"] = True
82 self._parser.add_argument(*[f"{'--' if not positional else ''}{name}" for name in names], help = description, type = data_type, **required_args)
83
84 async def execute(self, user: User, args: str) -> str:
85 try:
86 try:
87 namespace = self._parser.parse_args(split_args(args))
88 except SystemExit:
89 return ""
90
91 await self.function(user, **vars(namespace))
92 return ""
93 except Exception as e:
94 return f"Internal bot error: {str(e)}"
95
96INFINITE_ARGS = -1
97
98__all__ = ["Command", "CommandParameter", "INFINITE_ARGS"]
str execute(self, User user, str args)
Definition command.py:84
None __init__(self, str name, str description, list[str] aliases=[], bool hidden=False)
Definition command.py:60
None add_argument(self, list[str] names, str description, Type[Union[int, float, str, bool]] data_type, bool positional=False, bool required=True, int number_of_args=1)
Definition command.py:67
None __init__(self, str name, str description, Type[Union[int, float, str, bool]] data_type, bool positional=False, list[str] aliases=[], bool required=True, int number_of_args=1)
Definition command.py:39