Skip to content

Commit

Permalink
optimize asynchronous support, add quick add_command and add_default_…
Browse files Browse the repository at this point in the history
…command
  • Loading branch information
guangrei committed Jan 3, 2024
1 parent 95d4cff commit 0e3628f
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 11 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ func = chatrouter.util.get_func("group_name", "command_name")

7. object storage `chatrouter.data_user`.

8. support asynchronous.

## installation

```
Expand Down Expand Up @@ -96,5 +98,25 @@ if __name__ == '__main__':
exit(0)

```
asynchronous example
```python
#-*-coding:utf8;-*-
import asyncio
import chatrouter


chatbot = chatrouter.group("test", asynchronous=True)

@chatbot.add_command("call me {name}")
async def test(name):
return f"hello {name}!"

async def main():
user_input = "call me human"
response = await chatrouter.async_run(chatbot, user_input)
print(response)

if __name__ == '__main__':
asyncio.run(main())
```
for more complex example, please open [demo/telegram_bot](https://github.com/cirebon-dev/chatrouter/tree/main/demo/telegram_bot).
141 changes: 130 additions & 11 deletions chatrouter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""

__author__ = "guangrei"
__version__ = "v0.0.5"
__version__ = "v1.0.0"

_data: dict = {} # chatrouter storage
data_user: Any = None # data user storage
Expand All @@ -28,7 +28,7 @@ class group:
class ini digunakan untuk membuat command group
"""

def __init__(self, name: str, description: str = "no description!") -> None:
def __init__(self, name: str, description: str = "no description!", asynchronous=False) -> None:
"""
fungsi ini adalah kelas konstruktor
"""
Expand All @@ -37,11 +37,17 @@ def __init__(self, name: str, description: str = "no description!") -> None:
if name not in _data:
_data[name] = {}
_data[name]["/start"] = {}
_data[name]["/start"]["callback"] = self._start
if not asynchronous:
_data[name]["/start"]["callback"] = self._start
else:
_data[name]["/start"]["callback"] = self._async_start
_data[name]["/start"]["description"] = "start command!"
_data[name]["/start"]["strict"] = True
_data[name]["/help"] = {}
_data[name]["/help"]["callback"] = self._help
if not asynchronous:
_data[name]["/help"]["callback"] = self._help
else:
_data[name]["/help"]["callback"] = self._async_help
_data[name]["/help"]["description"] = "help command!"
_data[name]["/help"]["strict"] = True
self.id = name
Expand Down Expand Up @@ -70,6 +76,18 @@ def dec(func: Callable) -> Callable:
return func
return dec

def _start(self) -> str:
"""
fungsi ini sebagai default callback /start commands
"""
return self.start_msg

async def _async_start(self) -> str:
"""
fungsi ini sebagai default callback /start commands
"""
return self.start_msg

def _help(self) -> str:
"""
fungsi ini sebagai default callback /help commands.
Expand All @@ -83,11 +101,18 @@ def _help(self) -> str:
i = i+1
return hasil.strip()

def _start(self) -> str:
async def _async_help(self) -> str:
"""
fungsi ini sebagai default callback /start commands
fungsi ini sebagai default callback /help commands.
hanya menampilkan publik commands (command yang diawali dengan "/" dan memiliki deskripsi)
"""
return self.start_msg
hasil = _help_template_.format(group=self.id).strip()
i = 1
for k, v in _data[self.id].items():
if k.startswith("/") and len(v["description"]):
hasil = hasil + f'\n{i}. {k} - {v["description"]}'
i = i+1
return hasil.strip()


class util:
Expand All @@ -100,27 +125,27 @@ def get_func(group: str, route: str) -> Callable:
"""
route = util.compile(route)
return _data[group][route]["callback"]

def compile(string: str) -> str:
"""
fungsi ini untuk mengcompile regex pattern
"""
pattern = re.sub(r'\{([^}]+)\}', r'(.*)', string)
return pattern.strip()

def group_exists(name: str) -> bool:
"""
fungsi ini untuk mengecek group
"""
return name in _data

def command_exists(group: str, command: str) -> bool:
"""
fungsi ini untuk mengecek command
"""
command = util.compile(command)
return command in _data[group]

def remove_command(group: str, command: str) -> None:
"""
fungsi ini untuk menghapus command
Expand All @@ -141,6 +166,53 @@ def _route(pattern: str, string: str, strict: bool) -> Union[list, bool]:
else:
return False

async def async_get_func(group: str, route: str) -> Callable:
"""
fungsi utilitas ini dapat digunakan untuk mengambil callback pada group dan route tertentu
"""
route = await util.async_compile(route)
return _data[group][route]["callback"]

async def async_compile(string: str) -> str:
"""
fungsi ini untuk mengcompile regex pattern
"""
pattern = re.sub(r'\{([^}]+)\}', r'(.*)', string)
return pattern.strip()

async def async_group_exists(name: str) -> bool:
"""
fungsi ini untuk mengecek group
"""
return name in _data

async def async_command_exists(group: str, command: str) -> bool:
"""
fungsi ini untuk mengecek command
"""
command = await util.async_compile(command)
return command in _data[group]

async def async_remove_command(group: str, command: str) -> None:
"""
fungsi ini untuk menghapus command
"""
command = await util.async_compile(command)
del _data[group][command]

async def _async_route(pattern: str, string: str, strict: bool) -> Union[list, bool]:
"""
fungsi ini private dan berfungsi sebagai route
"""
if strict:
match = re.match(pattern, string.strip())
else:
match = re.match(pattern, string.strip(), re.IGNORECASE)
if match:
return list(match.groups())
else:
return False


def run(route: group, msg: str) -> Union[str, None]:
"""
Expand All @@ -158,5 +230,52 @@ def run(route: group, msg: str) -> Union[str, None]:
return f"info: no default handler for route {route.id}:{msg}"


async def async_run(route: group, msg: str) -> Union[str, None]:
"""
ini adalah versi async dari function run
"""
if len(msg):
for k, v in _data[route.id].items():
if k != "__default__":
args = await util._async_route(k, msg, v["strict"])
if args is not False:
ret = await v["callback"](*args)
return ret
if "__default__" in _data[route.id]:
ret = await _data[route.id]["__default__"]["callback"](msg)
return ret
else:
return f"info: no default handler for route {route.id}:{msg}"


def add_command(route: str, description: str = "", strict: bool = False, group_route: str = "main", asynchronous: bool = False) -> Callable:
"""
fungsi untuk menambahkan command secara cepat
"""
group(group_route, asynchronous=asynchronous)
method = util.compile(route)

def dec(func: Callable) -> Callable:
_data[group_route][method] = {}
_data[group_route][method]["callback"] = func
_data[group_route][method]["description"] = description
_data[group_route][method]["strict"] = strict
return func
return dec


def add_default_command(group_route: str = "main", asynchronous: bool = False) -> Callable:
"""
fungsi untuk menambahkan default command secara cepat
"""
group(group_route, asynchronous=asynchronous)

def dec(func: Callable) -> Callable:
_data[group_route]["__default__"] = {}
_data[group_route]["__default__"]["callback"] = func
return func
return dec


if __name__ == '__main__':
pass

0 comments on commit 0e3628f

Please sign in to comment.