telegrinder 0.1.dev167__tar.gz → 0.1.dev168__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of telegrinder might be problematic. Click here for more details.
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/PKG-INFO +5 -5
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/pyproject.toml +13 -5
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/readme.md +4 -4
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/callback_query.py +1 -1
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/dispatch.py +4 -3
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/handler/func.py +1 -1
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/abc.py +53 -2
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/waiter_machine/machine.py +14 -20
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/waiter_machine/short_state.py +10 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/callback_data.py +9 -11
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/scenario/checkbox.py +5 -5
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/scenario/choice.py +4 -3
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/limited_dict.py +12 -2
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/types/methods.py +20 -89
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/types/objects.py +12 -41
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/LICENSE +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/api/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/api/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/api/api.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/api/error.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/api/response.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/bot.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/base.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/chat_join_request.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/chat_member_updated.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/inline_query.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/message.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/update.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/utils.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/composition.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/context.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/handler/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/handler/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/handler/message_reply.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/middleware/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/middleware/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/process.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/return_manager/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/return_manager/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/return_manager/callback_query.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/return_manager/inline_query.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/return_manager/message.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/box.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/callback_query.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/chat_join_request.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/chat_member.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/inline_query.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/message.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/view/raw.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/waiter_machine/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/waiter_machine/middleware.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/polling/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/polling/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/polling/polling.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/adapter/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/adapter/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/adapter/errors.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/adapter/event.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/adapter/raw_update.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/chat_join.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/command.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/enum_text.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/func.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/fuzzy.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/inline.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/integer.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/is_from.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/markup.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/mention.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/message.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/message_entities.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/regex.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/rule_enum.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/start.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/text.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/rules/update.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/scenario/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/scenario/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/client/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/client/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/client/aiohttp.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/model.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/modules.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/msgspec_json.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/msgspec_utils.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/attachment.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/base.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/composer.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/container.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/message.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/rule.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/source.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/text.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/tools/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/tools/generator.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/node/update.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/rules.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/__init__.py +1 -1
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/buttons.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/error_handler/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/error_handler/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/error_handler/error.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/error_handler/error_handler.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/formatting/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/formatting/html.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/formatting/links.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/formatting/spec_html_formats.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/global_context/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/global_context/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/global_context/global_context.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/global_context/telegrinder_ctx.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/i18n/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/i18n/base.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/i18n/middleware/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/i18n/middleware/base.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/i18n/simple.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/kb_set/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/kb_set/base.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/kb_set/yaml.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/keyboard.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/loop_wrapper/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/loop_wrapper/abc.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/loop_wrapper/loop_wrapper.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/magic.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/tools/parse_mode.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/types/__init__.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/types/enums.py +0 -0
- {telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/verification_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: telegrinder
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.dev168
|
|
4
4
|
Summary: Framework for effective and reliable async telegram bot building.
|
|
5
5
|
Home-page: https://github.com/timoniq/telegrinder
|
|
6
6
|
License: MIT
|
|
@@ -49,23 +49,23 @@ Still in development.
|
|
|
49
49
|
|
|
50
50
|
Install using pip:
|
|
51
51
|
|
|
52
|
-
```
|
|
52
|
+
```console
|
|
53
53
|
pip install telegrinder
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Using poetry:
|
|
57
57
|
|
|
58
|
-
```
|
|
58
|
+
```console
|
|
59
59
|
poetry add telegrinder
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Install from github:
|
|
63
63
|
|
|
64
|
-
```
|
|
64
|
+
```console
|
|
65
65
|
pip install -U https://github.com/timoniq/telegrinder/archive/dev.zip
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
```
|
|
68
|
+
```console
|
|
69
69
|
poetry add git+https://github.com/timoniq/telegrinder.git#dev
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "telegrinder"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.dev168"
|
|
4
4
|
description = "Framework for effective and reliable async telegram bot building."
|
|
5
5
|
authors = ["timoniq <tesseradecades@mail.ru>"]
|
|
6
6
|
maintainers = ["luwqz1 <howluwqz1@gmail.com>"]
|
|
@@ -46,6 +46,11 @@ typing-extensions = "^4.10.0"
|
|
|
46
46
|
fntypes = "^0.1.2.post1"
|
|
47
47
|
|
|
48
48
|
[tool.poetry.group.dev.dependencies]
|
|
49
|
+
ruff = "^0.4.4"
|
|
50
|
+
basedpyright = "^1.12.1"
|
|
51
|
+
isort = "5.13.2"
|
|
52
|
+
sort-all = "1.2.0"
|
|
53
|
+
black = "^24.4.2"
|
|
49
54
|
pytest = "^8.0.0"
|
|
50
55
|
pytest-asyncio = "^0.23.5"
|
|
51
56
|
pytest-cov = "^4.0.0"
|
|
@@ -58,7 +63,7 @@ requires = ["poetry-core>=1.0.0"]
|
|
|
58
63
|
build-backend = "poetry.core.masonry.api"
|
|
59
64
|
|
|
60
65
|
[tool.ruff]
|
|
61
|
-
line-length =
|
|
66
|
+
line-length = 110
|
|
62
67
|
target-version = "py311"
|
|
63
68
|
lint.select = ["I", "N", "ANN", "COM", "YTT", "TCH", "SIM"]
|
|
64
69
|
lint.ignore = [
|
|
@@ -67,8 +72,8 @@ lint.ignore = [
|
|
|
67
72
|
]
|
|
68
73
|
|
|
69
74
|
[tool.black]
|
|
70
|
-
line-length =
|
|
71
|
-
target-version = ["py311"]
|
|
75
|
+
line-length = 110
|
|
76
|
+
target-version = ["py311", "py312"]
|
|
72
77
|
|
|
73
78
|
[tool.pytest.ini_options]
|
|
74
79
|
asyncio_mode = "auto"
|
|
@@ -77,4 +82,7 @@ asyncio_mode = "auto"
|
|
|
77
82
|
"__init__.py" = ["F401", "F403"]
|
|
78
83
|
|
|
79
84
|
[tool.ruff.lint.flake8-quotes]
|
|
80
|
-
docstring-quotes = "double"
|
|
85
|
+
docstring-quotes = "double"
|
|
86
|
+
|
|
87
|
+
[tool.basedpyright]
|
|
88
|
+
typeCheckingMode = "basic"
|
|
@@ -14,23 +14,23 @@ Still in development.
|
|
|
14
14
|
|
|
15
15
|
Install using pip:
|
|
16
16
|
|
|
17
|
-
```
|
|
17
|
+
```console
|
|
18
18
|
pip install telegrinder
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Using poetry:
|
|
22
22
|
|
|
23
|
-
```
|
|
23
|
+
```console
|
|
24
24
|
poetry add telegrinder
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
Install from github:
|
|
28
28
|
|
|
29
|
-
```
|
|
29
|
+
```console
|
|
30
30
|
pip install -U https://github.com/timoniq/telegrinder/archive/dev.zip
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
```
|
|
33
|
+
```console
|
|
34
34
|
poetry add git+https://github.com/timoniq/telegrinder.git#dev
|
|
35
35
|
```
|
|
36
36
|
|
{telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/cute_types/callback_query.py
RENAMED
|
@@ -217,7 +217,7 @@ class CallbackQueryCute(BaseCute[CallbackQuery], CallbackQuery, kw_only=True, di
|
|
|
217
217
|
)
|
|
218
218
|
async def edit_text(
|
|
219
219
|
self,
|
|
220
|
-
text: str
|
|
220
|
+
text: str,
|
|
221
221
|
inline_message_id: int | None = None,
|
|
222
222
|
chat_id: int | str | None = None,
|
|
223
223
|
message_id: int | None = None,
|
|
@@ -135,7 +135,9 @@ class Dispatch(
|
|
|
135
135
|
|
|
136
136
|
async def feed(self, event: Update, api: ABCAPI) -> bool:
|
|
137
137
|
logger.debug("Processing update (update_id={})", event.update_id)
|
|
138
|
-
|
|
138
|
+
loop = asyncio.get_running_loop()
|
|
139
|
+
loop.create_task(self.raw_event.process(event, api))
|
|
140
|
+
|
|
139
141
|
for view in self.get_views().values():
|
|
140
142
|
if await view.check(event):
|
|
141
143
|
logger.debug(
|
|
@@ -143,10 +145,9 @@ class Dispatch(
|
|
|
143
145
|
event.update_id,
|
|
144
146
|
view.__class__.__name__,
|
|
145
147
|
)
|
|
146
|
-
|
|
148
|
+
loop.create_task(view.process(event, api))
|
|
147
149
|
return True
|
|
148
150
|
|
|
149
|
-
loop = asyncio.get_running_loop()
|
|
150
151
|
ctx = Context()
|
|
151
152
|
found = False
|
|
152
153
|
for handler in self.default_handlers:
|
|
@@ -46,7 +46,7 @@ class FuncHandler(ABCHandler[EventT], typing.Generic[EventT, F, ErrorHandlerT]):
|
|
|
46
46
|
self.dataclass,
|
|
47
47
|
self.error_handler,
|
|
48
48
|
)
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
|
|
51
51
|
if self.update_type is not None and self.update_type != event.update_type.unwrap_or_none():
|
|
52
52
|
return False
|
|
@@ -67,13 +67,64 @@ class BaseView(ABCView, typing.Generic[EventType]):
|
|
|
67
67
|
return Some(generic_type)
|
|
68
68
|
return Nothing()
|
|
69
69
|
|
|
70
|
-
@
|
|
71
|
-
def get_raw_event(
|
|
70
|
+
@staticmethod
|
|
71
|
+
def get_raw_event(update: Update) -> Option[Model]:
|
|
72
72
|
match update.update_type:
|
|
73
73
|
case Some(update_type):
|
|
74
74
|
return getattr(update, update_type.value)
|
|
75
75
|
case _:
|
|
76
76
|
return Nothing()
|
|
77
|
+
|
|
78
|
+
@typing.overload
|
|
79
|
+
@classmethod
|
|
80
|
+
def to_handler(
|
|
81
|
+
cls,
|
|
82
|
+
*rules: ABCRule[EventType],
|
|
83
|
+
) -> typing.Callable[
|
|
84
|
+
[FuncType[EventType]],
|
|
85
|
+
FuncHandler[EventType, FuncType[EventType], ErrorHandler[EventType]],
|
|
86
|
+
]: ...
|
|
87
|
+
|
|
88
|
+
@typing.overload
|
|
89
|
+
@classmethod
|
|
90
|
+
def to_handler(
|
|
91
|
+
cls,
|
|
92
|
+
*rules: ABCRule[EventType],
|
|
93
|
+
error_handler: ErrorHandlerT,
|
|
94
|
+
is_blocking: bool = True,
|
|
95
|
+
) -> typing.Callable[
|
|
96
|
+
[FuncType[EventType]], FuncHandler[EventType, FuncType[EventType], ErrorHandlerT]
|
|
97
|
+
]: ...
|
|
98
|
+
|
|
99
|
+
@typing.overload
|
|
100
|
+
@classmethod
|
|
101
|
+
def to_handler(
|
|
102
|
+
cls,
|
|
103
|
+
*rules: ABCRule[EventType],
|
|
104
|
+
error_handler: typing.Literal[None] = None,
|
|
105
|
+
is_blocking: bool = True,
|
|
106
|
+
) -> typing.Callable[
|
|
107
|
+
[FuncType[EventType]],
|
|
108
|
+
FuncHandler[EventType, FuncType[EventType], ErrorHandler[EventType]],
|
|
109
|
+
]: ...
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def to_handler( # type: ignore
|
|
113
|
+
cls,
|
|
114
|
+
*rules: ABCRule[EventType],
|
|
115
|
+
error_handler: ABCErrorHandler | None = None,
|
|
116
|
+
is_blocking: bool = True,
|
|
117
|
+
):
|
|
118
|
+
def wrapper(func: FuncType[EventType]):
|
|
119
|
+
return FuncHandler(
|
|
120
|
+
func,
|
|
121
|
+
list(rules),
|
|
122
|
+
is_blocking=is_blocking,
|
|
123
|
+
dataclass=None,
|
|
124
|
+
error_handler=error_handler or ErrorHandler(),
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return wrapper
|
|
77
128
|
|
|
78
129
|
@typing.overload
|
|
79
130
|
def __call__(
|
{telegrinder-0.1.dev167 → telegrinder-0.1.dev168}/telegrinder/bot/dispatch/waiter_machine/machine.py
RENAMED
|
@@ -39,7 +39,7 @@ class WaiterMachine:
|
|
|
39
39
|
) -> None:
|
|
40
40
|
view_name = state_view.__class__.__name__
|
|
41
41
|
if view_name not in self.storage:
|
|
42
|
-
raise LookupError("No record of view {!r} found".format(view_name))
|
|
42
|
+
raise LookupError("No record of view {!r} found.".format(view_name))
|
|
43
43
|
|
|
44
44
|
short_state = self.storage[view_name].pop(id, None)
|
|
45
45
|
if short_state is None:
|
|
@@ -49,13 +49,7 @@ class WaiterMachine:
|
|
|
49
49
|
)
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
typing.Iterable[asyncio.Future[typing.Any]],
|
|
54
|
-
short_state.event._waiters, # type: ignore
|
|
55
|
-
)
|
|
56
|
-
for future in waiters:
|
|
57
|
-
future.cancel()
|
|
58
|
-
|
|
52
|
+
short_state.cancel()
|
|
59
53
|
await self.call_behaviour(
|
|
60
54
|
state_view,
|
|
61
55
|
short_state.event,
|
|
@@ -69,9 +63,9 @@ class WaiterMachine:
|
|
|
69
63
|
state_view: "BaseStateView[EventModel]",
|
|
70
64
|
linked: EventModel | tuple[ABCAPI, Identificator],
|
|
71
65
|
*rules: ABCRule[EventModel],
|
|
72
|
-
default: Behaviour = None,
|
|
73
|
-
on_drop: Behaviour = None,
|
|
74
|
-
expiration: datetime.timedelta |
|
|
66
|
+
default: Behaviour[EventModel] | None = None,
|
|
67
|
+
on_drop: Behaviour[EventModel] | None = None,
|
|
68
|
+
expiration: datetime.timedelta | float | None = None,
|
|
75
69
|
) -> tuple[EventModel, Context]:
|
|
76
70
|
if isinstance(expiration, int | float):
|
|
77
71
|
expiration = datetime.timedelta(seconds=expiration)
|
|
@@ -86,6 +80,7 @@ class WaiterMachine:
|
|
|
86
80
|
if not key:
|
|
87
81
|
raise RuntimeError("Unable to get state key.")
|
|
88
82
|
|
|
83
|
+
view_name = state_view.__class__.__name__
|
|
89
84
|
event = asyncio.Event()
|
|
90
85
|
short_state = ShortState(
|
|
91
86
|
key,
|
|
@@ -96,17 +91,17 @@ class WaiterMachine:
|
|
|
96
91
|
default_behaviour=default,
|
|
97
92
|
on_drop_behaviour=on_drop,
|
|
98
93
|
)
|
|
99
|
-
|
|
94
|
+
|
|
100
95
|
if view_name not in self.storage:
|
|
101
96
|
state_view.middlewares.insert(0, WaiterMiddleware(self, state_view))
|
|
102
97
|
self.storage[view_name] = LimitedDict()
|
|
103
98
|
|
|
104
|
-
self.storage[view_name]
|
|
99
|
+
if (deleted_short_state := self.storage[view_name].set(key, short_state)) is not None:
|
|
100
|
+
deleted_short_state.cancel()
|
|
101
|
+
|
|
105
102
|
await event.wait()
|
|
106
|
-
|
|
107
|
-
e, ctx = getattr(event, "context")
|
|
108
103
|
self.storage[view_name].pop(key, None)
|
|
109
|
-
return
|
|
104
|
+
return getattr(event, "context")
|
|
110
105
|
|
|
111
106
|
async def call_behaviour(
|
|
112
107
|
self,
|
|
@@ -118,8 +113,10 @@ class WaiterMachine:
|
|
|
118
113
|
) -> None:
|
|
119
114
|
# TODO: support param view as a behaviour
|
|
120
115
|
|
|
121
|
-
|
|
116
|
+
if behaviour is None:
|
|
117
|
+
return
|
|
122
118
|
|
|
119
|
+
ctx = Context(**context)
|
|
123
120
|
if isinstance(event, asyncio.Event):
|
|
124
121
|
event, preset_ctx = typing.cast(
|
|
125
122
|
tuple[EventModel, Context],
|
|
@@ -127,9 +124,6 @@ class WaiterMachine:
|
|
|
127
124
|
)
|
|
128
125
|
ctx.update(preset_ctx)
|
|
129
126
|
|
|
130
|
-
if behaviour is None:
|
|
131
|
-
return
|
|
132
|
-
|
|
133
127
|
if await behaviour.check(event.api, update, ctx):
|
|
134
128
|
await behaviour.run(event, ctx)
|
|
135
129
|
|
|
@@ -34,6 +34,16 @@ class ShortState(typing.Generic[EventModel]):
|
|
|
34
34
|
|
|
35
35
|
def __post_init__(self, expiration: datetime.timedelta | None = None) -> None:
|
|
36
36
|
self.expiration_date = (datetime.datetime.now() - expiration) if expiration is not None else None
|
|
37
|
+
|
|
38
|
+
def cancel(self) -> None:
|
|
39
|
+
"""Cancel schedule waiters."""
|
|
40
|
+
|
|
41
|
+
waiters = typing.cast(
|
|
42
|
+
typing.Iterable[asyncio.Future[typing.Any]],
|
|
43
|
+
self.event._waiters, # type: ignore
|
|
44
|
+
)
|
|
45
|
+
for future in waiters:
|
|
46
|
+
future.cancel()
|
|
37
47
|
|
|
38
48
|
|
|
39
49
|
__all__ = ("ShortState",)
|
|
@@ -16,10 +16,8 @@ from .markup import Markup, PatternLike, check_string
|
|
|
16
16
|
|
|
17
17
|
CallbackQuery: typing.TypeAlias = CallbackQueryCute
|
|
18
18
|
Validator: typing.TypeAlias = typing.Callable[[typing.Any], bool | typing.Awaitable[bool]]
|
|
19
|
-
MapDict: typing.TypeAlias = dict[
|
|
20
|
-
|
|
21
|
-
]
|
|
22
|
-
CallbackMap: typing.TypeAlias = list[tuple[str, "typing.Any | type | Validator | CallbackMap"]]
|
|
19
|
+
MapDict: typing.TypeAlias = dict[str, "typing.Any | type[typing.Any] | Validator | list[MapDict] | MapDict"]
|
|
20
|
+
CallbackMap: typing.TypeAlias = list[tuple[str, "typing.Any | type[typing.Any] | Validator | CallbackMap"]]
|
|
23
21
|
CallbackMapStrict: typing.TypeAlias = list[tuple[str, "Validator | CallbackMapStrict"]]
|
|
24
22
|
|
|
25
23
|
|
|
@@ -41,7 +39,7 @@ class CallbackQueryDataRule(CallbackQueryRule, abc.ABC, requires=[HasData()]):
|
|
|
41
39
|
|
|
42
40
|
|
|
43
41
|
class CallbackDataMap(CallbackQueryDataRule):
|
|
44
|
-
def __init__(self, mapping: MapDict) -> None:
|
|
42
|
+
def __init__(self, mapping: MapDict, /) -> None:
|
|
45
43
|
self.mapping = self.transform_to_callbacks(
|
|
46
44
|
self.transform_to_map(mapping),
|
|
47
45
|
)
|
|
@@ -86,12 +84,12 @@ class CallbackDataMap(CallbackQueryDataRule):
|
|
|
86
84
|
result = validator(value)
|
|
87
85
|
if inspect.isawaitable(result):
|
|
88
86
|
result = await result
|
|
89
|
-
return result
|
|
87
|
+
return result
|
|
90
88
|
|
|
91
89
|
return False
|
|
92
90
|
|
|
93
91
|
@classmethod
|
|
94
|
-
async def match(cls, callback_data: dict, callback_map: CallbackMapStrict) -> bool:
|
|
92
|
+
async def match(cls, callback_data: dict[str, typing.Any], callback_map: CallbackMapStrict) -> bool:
|
|
95
93
|
"""Matches callback_data with callback_map recursively."""
|
|
96
94
|
|
|
97
95
|
for key, validator in callback_map:
|
|
@@ -121,7 +119,7 @@ class CallbackDataMap(CallbackQueryDataRule):
|
|
|
121
119
|
|
|
122
120
|
|
|
123
121
|
class CallbackDataEq(CallbackQueryDataRule):
|
|
124
|
-
def __init__(self, value: str):
|
|
122
|
+
def __init__(self, value: str, /) -> None:
|
|
125
123
|
self.value = value
|
|
126
124
|
|
|
127
125
|
async def check(self, event: CallbackQuery, ctx: Context) -> bool:
|
|
@@ -129,7 +127,7 @@ class CallbackDataEq(CallbackQueryDataRule):
|
|
|
129
127
|
|
|
130
128
|
|
|
131
129
|
class CallbackDataJsonEq(CallbackQueryDataRule):
|
|
132
|
-
def __init__(self, d: dict[str, typing.Any]):
|
|
130
|
+
def __init__(self, d: dict[str, typing.Any], /) -> None:
|
|
133
131
|
self.d = d
|
|
134
132
|
|
|
135
133
|
async def check(self, event: CallbackQuery, ctx: Context) -> bool:
|
|
@@ -137,7 +135,7 @@ class CallbackDataJsonEq(CallbackQueryDataRule):
|
|
|
137
135
|
|
|
138
136
|
|
|
139
137
|
class CallbackDataJsonModel(CallbackQueryDataRule):
|
|
140
|
-
def __init__(self, model: type[msgspec.Struct] | type[DataclassInstance]):
|
|
138
|
+
def __init__(self, model: type[msgspec.Struct] | type[DataclassInstance], /) -> None:
|
|
141
139
|
self.model = model
|
|
142
140
|
|
|
143
141
|
async def check(self, event: CallbackQuery, ctx: Context) -> bool:
|
|
@@ -148,7 +146,7 @@ class CallbackDataJsonModel(CallbackQueryDataRule):
|
|
|
148
146
|
|
|
149
147
|
|
|
150
148
|
class CallbackDataMarkup(CallbackQueryDataRule):
|
|
151
|
-
def __init__(self, patterns: PatternLike | list[PatternLike]):
|
|
149
|
+
def __init__(self, patterns: PatternLike | list[PatternLike], /) -> None:
|
|
152
150
|
self.patterns = Markup(patterns).patterns
|
|
153
151
|
|
|
154
152
|
async def check(self, event: CallbackQuery, ctx: Context) -> bool:
|
|
@@ -33,13 +33,13 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
|
33
33
|
self,
|
|
34
34
|
waiter_machine: WaiterMachine,
|
|
35
35
|
chat_id: int,
|
|
36
|
-
|
|
36
|
+
message: str,
|
|
37
37
|
*,
|
|
38
38
|
ready_text: str = "Ready",
|
|
39
39
|
max_in_row: int = 3,
|
|
40
40
|
) -> None:
|
|
41
41
|
self.chat_id = chat_id
|
|
42
|
-
self.
|
|
42
|
+
self.message = message
|
|
43
43
|
self.choices: list[Choice] = []
|
|
44
44
|
self.ready = ready_text
|
|
45
45
|
self.max_in_row = max_in_row
|
|
@@ -58,7 +58,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
|
58
58
|
self.waiter_machine,
|
|
59
59
|
self.ready,
|
|
60
60
|
self.chat_id,
|
|
61
|
-
self.
|
|
61
|
+
self.message,
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
def get_markup(self) -> InlineKeyboardMarkup:
|
|
@@ -101,7 +101,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
|
101
101
|
# Toggle choice
|
|
102
102
|
self.choices[i].is_picked = not self.choices[i].is_picked
|
|
103
103
|
await cb.edit_text(
|
|
104
|
-
text=self.
|
|
104
|
+
text=self.message,
|
|
105
105
|
parse_mode=self.PARSE_MODE,
|
|
106
106
|
reply_markup=self.get_markup(),
|
|
107
107
|
)
|
|
@@ -118,7 +118,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
|
|
|
118
118
|
message = (
|
|
119
119
|
await api.send_message(
|
|
120
120
|
chat_id=self.chat_id,
|
|
121
|
-
text=self.
|
|
121
|
+
text=self.message,
|
|
122
122
|
parse_mode=self.PARSE_MODE,
|
|
123
123
|
reply_markup=self.get_markup(),
|
|
124
124
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
|
|
3
3
|
from telegrinder.bot.cute_types import CallbackQueryCute
|
|
4
|
+
from telegrinder.bot.dispatch.waiter_machine import WaiterMachine
|
|
4
5
|
|
|
5
6
|
from .checkbox import Checkbox
|
|
6
7
|
|
|
@@ -22,9 +23,9 @@ class SingleChoice(Checkbox):
|
|
|
22
23
|
if choice.code == code:
|
|
23
24
|
self.choices[i].is_picked = True
|
|
24
25
|
await cb.ctx_api.edit_message_text(
|
|
26
|
+
text=self.message,
|
|
25
27
|
chat_id=cb.message.unwrap().v.chat.id,
|
|
26
28
|
message_id=cb.message.unwrap().v.message_id,
|
|
27
|
-
text=self.msg,
|
|
28
29
|
parse_mode=self.PARSE_MODE,
|
|
29
30
|
reply_markup=self.get_markup(),
|
|
30
31
|
)
|
|
@@ -36,10 +37,10 @@ class SingleChoice(Checkbox):
|
|
|
36
37
|
api: "API",
|
|
37
38
|
view: "BaseStateView[CallbackQueryCute]",
|
|
38
39
|
) -> tuple[str, int]:
|
|
39
|
-
if len(
|
|
40
|
+
if len(tuple(choice for choice in self.choices if choice.is_picked)) != 1:
|
|
40
41
|
raise ValueError("Exactly one choice must be picked")
|
|
41
42
|
choices, m_id = await super().wait(api, view)
|
|
42
|
-
return
|
|
43
|
+
return tuple(choices.keys())[tuple(choices.values()).index(True)], m_id
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
__all__ = ("SingleChoice",)
|
|
@@ -11,12 +11,22 @@ class LimitedDict(UserDict[KT, VT]):
|
|
|
11
11
|
self.maxlimit = maxlimit
|
|
12
12
|
self.queue: deque[KT] = deque(maxlen=maxlimit)
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def set(self, key: KT, value: VT, /) -> VT | None:
|
|
15
|
+
"""Set item in the dictionary.
|
|
16
|
+
Returns a value that was deleted when the limit in the dictionary
|
|
17
|
+
was reached, otherwise None.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
deleted_item = None
|
|
15
21
|
if len(self.queue) >= self.maxlimit:
|
|
16
|
-
self.pop(self.queue.popleft(), None)
|
|
22
|
+
deleted_item = self.pop(self.queue.popleft(), None)
|
|
17
23
|
if key not in self.queue:
|
|
18
24
|
self.queue.append(key)
|
|
19
25
|
super().__setitem__(key, value)
|
|
26
|
+
return deleted_item
|
|
27
|
+
|
|
28
|
+
def __setitem__(self, key: KT, value: VT, /) -> None:
|
|
29
|
+
self.set(key, value)
|
|
20
30
|
|
|
21
31
|
def __delitem__(self, key: KT) -> None:
|
|
22
32
|
if key in self.queue:
|