telegrinder 0.1.dev170__py3-none-any.whl → 0.2.0__py3-none-any.whl
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/__init__.py +2 -2
- telegrinder/api/__init__.py +1 -2
- telegrinder/api/api.py +15 -6
- telegrinder/api/error.py +2 -1
- telegrinder/api/token.py +36 -0
- telegrinder/bot/__init__.py +12 -6
- telegrinder/bot/bot.py +18 -6
- telegrinder/bot/cute_types/__init__.py +7 -7
- telegrinder/bot/cute_types/base.py +122 -20
- telegrinder/bot/cute_types/callback_query.py +10 -6
- telegrinder/bot/cute_types/chat_join_request.py +4 -5
- telegrinder/bot/cute_types/chat_member_updated.py +4 -6
- telegrinder/bot/cute_types/inline_query.py +3 -4
- telegrinder/bot/cute_types/message.py +32 -21
- telegrinder/bot/cute_types/update.py +51 -4
- telegrinder/bot/cute_types/utils.py +3 -466
- telegrinder/bot/dispatch/__init__.py +10 -11
- telegrinder/bot/dispatch/abc.py +8 -5
- telegrinder/bot/dispatch/context.py +17 -8
- telegrinder/bot/dispatch/dispatch.py +71 -48
- telegrinder/bot/dispatch/handler/__init__.py +3 -3
- telegrinder/bot/dispatch/handler/abc.py +4 -4
- telegrinder/bot/dispatch/handler/func.py +46 -22
- telegrinder/bot/dispatch/handler/message_reply.py +6 -7
- telegrinder/bot/dispatch/middleware/__init__.py +1 -1
- telegrinder/bot/dispatch/middleware/abc.py +2 -2
- telegrinder/bot/dispatch/process.py +38 -19
- telegrinder/bot/dispatch/return_manager/__init__.py +4 -4
- telegrinder/bot/dispatch/return_manager/abc.py +3 -3
- telegrinder/bot/dispatch/return_manager/callback_query.py +1 -2
- telegrinder/bot/dispatch/return_manager/inline_query.py +1 -2
- telegrinder/bot/dispatch/return_manager/message.py +1 -2
- telegrinder/bot/dispatch/view/__init__.py +8 -8
- telegrinder/bot/dispatch/view/abc.py +18 -16
- telegrinder/bot/dispatch/view/box.py +75 -64
- telegrinder/bot/dispatch/view/callback_query.py +1 -2
- telegrinder/bot/dispatch/view/chat_join_request.py +1 -2
- telegrinder/bot/dispatch/view/chat_member.py +16 -2
- telegrinder/bot/dispatch/view/inline_query.py +1 -2
- telegrinder/bot/dispatch/view/message.py +12 -5
- telegrinder/bot/dispatch/view/raw.py +9 -8
- telegrinder/bot/dispatch/waiter_machine/__init__.py +3 -3
- telegrinder/bot/dispatch/waiter_machine/machine.py +12 -8
- telegrinder/bot/dispatch/waiter_machine/middleware.py +1 -1
- telegrinder/bot/dispatch/waiter_machine/short_state.py +4 -3
- telegrinder/bot/polling/abc.py +1 -1
- telegrinder/bot/polling/polling.py +6 -6
- telegrinder/bot/rules/__init__.py +20 -20
- telegrinder/bot/rules/abc.py +57 -43
- telegrinder/bot/rules/adapter/__init__.py +5 -5
- telegrinder/bot/rules/adapter/abc.py +6 -3
- telegrinder/bot/rules/adapter/errors.py +2 -1
- telegrinder/bot/rules/adapter/event.py +28 -13
- telegrinder/bot/rules/adapter/node.py +28 -22
- telegrinder/bot/rules/adapter/raw_update.py +13 -5
- telegrinder/bot/rules/callback_data.py +4 -4
- telegrinder/bot/rules/chat_join.py +4 -4
- telegrinder/bot/rules/command.py +5 -7
- telegrinder/bot/rules/func.py +2 -2
- telegrinder/bot/rules/fuzzy.py +1 -1
- telegrinder/bot/rules/inline.py +3 -3
- telegrinder/bot/rules/integer.py +1 -2
- telegrinder/bot/rules/markup.py +5 -3
- telegrinder/bot/rules/message_entities.py +2 -2
- telegrinder/bot/rules/node.py +2 -2
- telegrinder/bot/rules/regex.py +1 -1
- telegrinder/bot/rules/rule_enum.py +1 -1
- telegrinder/bot/rules/text.py +1 -2
- telegrinder/bot/rules/update.py +1 -2
- telegrinder/bot/scenario/abc.py +2 -2
- telegrinder/bot/scenario/checkbox.py +3 -4
- telegrinder/bot/scenario/choice.py +1 -2
- telegrinder/model.py +89 -45
- telegrinder/modules.py +3 -3
- telegrinder/msgspec_utils.py +85 -57
- telegrinder/node/__init__.py +17 -10
- telegrinder/node/attachment.py +19 -16
- telegrinder/node/base.py +46 -22
- telegrinder/node/callback_query.py +5 -9
- telegrinder/node/command.py +6 -2
- telegrinder/node/composer.py +102 -77
- telegrinder/node/container.py +3 -3
- telegrinder/node/event.py +68 -0
- telegrinder/node/me.py +3 -0
- telegrinder/node/message.py +6 -10
- telegrinder/node/polymorphic.py +15 -10
- telegrinder/node/rule.py +20 -6
- telegrinder/node/scope.py +9 -1
- telegrinder/node/source.py +21 -11
- telegrinder/node/text.py +4 -4
- telegrinder/node/update.py +7 -4
- telegrinder/py.typed +0 -0
- telegrinder/rules.py +59 -0
- telegrinder/tools/__init__.py +2 -2
- telegrinder/tools/buttons.py +5 -10
- telegrinder/tools/error_handler/abc.py +2 -2
- telegrinder/tools/error_handler/error.py +2 -0
- telegrinder/tools/error_handler/error_handler.py +6 -6
- telegrinder/tools/formatting/spec_html_formats.py +10 -10
- telegrinder/tools/global_context/__init__.py +2 -2
- telegrinder/tools/global_context/global_context.py +3 -3
- telegrinder/tools/global_context/telegrinder_ctx.py +4 -4
- telegrinder/tools/keyboard.py +3 -3
- telegrinder/tools/loop_wrapper/loop_wrapper.py +47 -13
- telegrinder/tools/magic.py +96 -18
- telegrinder/types/__init__.py +1 -0
- telegrinder/types/enums.py +2 -0
- telegrinder/types/methods.py +91 -15
- telegrinder/types/objects.py +49 -24
- telegrinder/verification_utils.py +1 -3
- {telegrinder-0.1.dev170.dist-info → telegrinder-0.2.0.dist-info}/METADATA +2 -2
- telegrinder-0.2.0.dist-info/RECORD +145 -0
- telegrinder/api/abc.py +0 -73
- telegrinder-0.1.dev170.dist-info/RECORD +0 -143
- {telegrinder-0.1.dev170.dist-info → telegrinder-0.2.0.dist-info}/LICENSE +0 -0
- {telegrinder-0.1.dev170.dist-info → telegrinder-0.2.0.dist-info}/WHEEL +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
from .abc import ABCDispatch
|
|
2
|
-
from .context import Context
|
|
3
|
-
from .dispatch import
|
|
4
|
-
from .handler import ABCHandler, FuncHandler, MessageReplyHandler
|
|
5
|
-
from .middleware import ABCMiddleware
|
|
6
|
-
from .process import check_rule, process_inner
|
|
7
|
-
from .return_manager import (
|
|
1
|
+
from telegrinder.bot.dispatch.abc import ABCDispatch
|
|
2
|
+
from telegrinder.bot.dispatch.context import Context
|
|
3
|
+
from telegrinder.bot.dispatch.dispatch import Dispatch, TelegrinderContext
|
|
4
|
+
from telegrinder.bot.dispatch.handler import ABCHandler, FuncHandler, MessageReplyHandler
|
|
5
|
+
from telegrinder.bot.dispatch.middleware import ABCMiddleware
|
|
6
|
+
from telegrinder.bot.dispatch.process import check_rule, process_inner
|
|
7
|
+
from telegrinder.bot.dispatch.return_manager import (
|
|
8
8
|
ABCReturnManager,
|
|
9
9
|
BaseReturnManager,
|
|
10
10
|
CallbackQueryReturnManager,
|
|
@@ -13,7 +13,7 @@ from .return_manager import (
|
|
|
13
13
|
MessageReturnManager,
|
|
14
14
|
register_manager,
|
|
15
15
|
)
|
|
16
|
-
from .view import (
|
|
16
|
+
from telegrinder.bot.dispatch.view import (
|
|
17
17
|
ABCStateView,
|
|
18
18
|
ABCView,
|
|
19
19
|
BaseStateView,
|
|
@@ -26,14 +26,13 @@ from .view import (
|
|
|
26
26
|
RawEventView,
|
|
27
27
|
ViewBox,
|
|
28
28
|
)
|
|
29
|
-
from .waiter_machine import ShortState, WaiterMachine, clear_wm_storage_worker
|
|
29
|
+
from telegrinder.bot.dispatch.waiter_machine import ShortState, WaiterMachine, clear_wm_storage_worker
|
|
30
30
|
|
|
31
31
|
__all__ = (
|
|
32
32
|
"ABCDispatch",
|
|
33
33
|
"ABCHandler",
|
|
34
34
|
"ABCMiddleware",
|
|
35
35
|
"ABCReturnManager",
|
|
36
|
-
"ABCRule",
|
|
37
36
|
"ABCStateView",
|
|
38
37
|
"ABCView",
|
|
39
38
|
"BaseReturnManager",
|
|
@@ -54,7 +53,7 @@ __all__ = (
|
|
|
54
53
|
"MessageView",
|
|
55
54
|
"RawEventView",
|
|
56
55
|
"ShortState",
|
|
57
|
-
"
|
|
56
|
+
"TelegrinderContext",
|
|
58
57
|
"ViewBox",
|
|
59
58
|
"WaiterMachine",
|
|
60
59
|
"check_rule",
|
telegrinder/bot/dispatch/abc.py
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
3
|
|
|
4
|
-
from telegrinder.api
|
|
5
|
-
from telegrinder.tools.global_context import ABCGlobalContext
|
|
6
|
-
from telegrinder.types import Update
|
|
4
|
+
from telegrinder.api import API
|
|
5
|
+
from telegrinder.tools.global_context.abc import ABCGlobalContext
|
|
6
|
+
from telegrinder.types.objects import Update
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class ABCDispatch(ABC):
|
|
10
|
-
|
|
10
|
+
@property
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def global_context(self) -> ABCGlobalContext:
|
|
13
|
+
pass
|
|
11
14
|
|
|
12
15
|
@abstractmethod
|
|
13
|
-
async def feed(self, event: Update, api:
|
|
16
|
+
async def feed(self, event: Update, api: API) -> bool:
|
|
14
17
|
pass
|
|
15
18
|
|
|
16
19
|
@abstractmethod
|
|
@@ -10,15 +10,15 @@ Key: typing.TypeAlias = str | enum.Enum
|
|
|
10
10
|
AnyValue: typing.TypeAlias = typing.Any
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
@typing.dataclass_transform(kw_only_default=True, order_default=True)
|
|
14
13
|
class Context(dict[str, AnyValue]):
|
|
15
|
-
"""Context class
|
|
16
|
-
```
|
|
17
|
-
class MyRule(ABCRule[T]):
|
|
18
|
-
adapter = RawUpdateAdapter()
|
|
14
|
+
"""Context class like dict & dotdict.
|
|
19
15
|
|
|
16
|
+
For example:
|
|
17
|
+
```python
|
|
18
|
+
class MyRule(ABCRule[T]):
|
|
20
19
|
async def check(self, event: T, ctx: Context) -> bool:
|
|
21
|
-
ctx.
|
|
20
|
+
ctx.me = (await event.ctx_api.get_me()).unwrap()
|
|
21
|
+
ctx["items"] = [1, 2, 3]
|
|
22
22
|
return True
|
|
23
23
|
```
|
|
24
24
|
"""
|
|
@@ -68,13 +68,22 @@ class Context(dict[str, AnyValue]):
|
|
|
68
68
|
def set(self, key: Key, value: AnyValue) -> None:
|
|
69
69
|
self[key] = value
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
@typing.overload
|
|
72
|
+
def get(self, key: Key) -> AnyValue | None: ...
|
|
73
|
+
|
|
74
|
+
@typing.overload
|
|
75
|
+
def get(self, key: Key, default: T) -> T | AnyValue: ...
|
|
76
|
+
|
|
77
|
+
@typing.overload
|
|
78
|
+
def get(self, key: Key, default: None = None) -> AnyValue | None: ...
|
|
79
|
+
|
|
80
|
+
def get(self, key: Key, default: T | None = None) -> T | AnyValue | None:
|
|
72
81
|
return dict.get(self, key, default)
|
|
73
82
|
|
|
74
83
|
def get_or_set(self, key: Key, default: T) -> T:
|
|
75
84
|
if key not in self:
|
|
76
85
|
self.set(key, default)
|
|
77
|
-
return self.get(key)
|
|
86
|
+
return self.get(key, default)
|
|
78
87
|
|
|
79
88
|
def delete(self, key: Key) -> None:
|
|
80
89
|
del self[key]
|
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import dataclasses
|
|
3
2
|
import typing
|
|
4
3
|
|
|
5
4
|
from vbml.patcher import Patcher
|
|
6
5
|
|
|
7
|
-
from telegrinder.api
|
|
6
|
+
from telegrinder.api import API
|
|
8
7
|
from telegrinder.bot.cute_types.base import BaseCute
|
|
9
8
|
from telegrinder.bot.cute_types.update import UpdateCute
|
|
10
|
-
from telegrinder.bot.dispatch.
|
|
11
|
-
from telegrinder.bot.
|
|
12
|
-
from telegrinder.
|
|
13
|
-
from telegrinder.tools.error_handler.error_handler import ErrorHandler
|
|
14
|
-
from telegrinder.tools.global_context import TelegrinderCtx
|
|
15
|
-
from telegrinder.types import Update
|
|
16
|
-
|
|
17
|
-
from .abc import ABCDispatch
|
|
18
|
-
from .handler import ABCHandler, FuncHandler
|
|
19
|
-
from .handler.func import ErrorHandlerT
|
|
20
|
-
from .view.box import (
|
|
9
|
+
from telegrinder.bot.dispatch.abc import ABCDispatch
|
|
10
|
+
from telegrinder.bot.dispatch.handler.func import ErrorHandlerT, FuncHandler
|
|
11
|
+
from telegrinder.bot.dispatch.view.box import (
|
|
21
12
|
CallbackQueryView,
|
|
22
13
|
ChatJoinRequestView,
|
|
23
14
|
ChatMemberView,
|
|
@@ -26,10 +17,16 @@ from .view.box import (
|
|
|
26
17
|
RawEventView,
|
|
27
18
|
ViewBox,
|
|
28
19
|
)
|
|
20
|
+
from telegrinder.modules import logger
|
|
21
|
+
from telegrinder.tools.error_handler.error_handler import ErrorHandler
|
|
22
|
+
from telegrinder.tools.global_context import TelegrinderContext
|
|
23
|
+
from telegrinder.types.enums import UpdateType
|
|
24
|
+
from telegrinder.types.objects import Update
|
|
25
|
+
|
|
26
|
+
if typing.TYPE_CHECKING:
|
|
27
|
+
from telegrinder.bot.rules.abc import ABCRule
|
|
29
28
|
|
|
30
29
|
T = typing.TypeVar("T")
|
|
31
|
-
R = typing.TypeVar("R")
|
|
32
|
-
P = typing.ParamSpec("P")
|
|
33
30
|
Handler = typing.Callable[typing.Concatenate[T, ...], typing.Coroutine[typing.Any, typing.Any, typing.Any]]
|
|
34
31
|
Event = typing.TypeVar("Event", bound=BaseCute)
|
|
35
32
|
|
|
@@ -48,18 +45,18 @@ class Dispatch(
|
|
|
48
45
|
RawEventView,
|
|
49
46
|
],
|
|
50
47
|
):
|
|
51
|
-
|
|
52
|
-
init=False,
|
|
53
|
-
default_factory=lambda: TelegrinderCtx(),
|
|
54
|
-
)
|
|
55
|
-
default_handlers: list[ABCHandler] = dataclasses.field(
|
|
48
|
+
_global_context: TelegrinderContext = dataclasses.field(
|
|
56
49
|
init=False,
|
|
57
|
-
default_factory=lambda:
|
|
50
|
+
default_factory=lambda: TelegrinderContext(),
|
|
58
51
|
)
|
|
59
52
|
|
|
60
53
|
def __repr__(self) -> str:
|
|
61
54
|
return "Dispatch(%s)" % ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
|
|
62
55
|
|
|
56
|
+
@property
|
|
57
|
+
def global_context(self) -> TelegrinderContext:
|
|
58
|
+
return self._global_context
|
|
59
|
+
|
|
63
60
|
@property
|
|
64
61
|
def patcher(self) -> Patcher:
|
|
65
62
|
"""Alias `patcher` to get `vbml.Patcher` from the global context."""
|
|
@@ -69,28 +66,48 @@ class Dispatch(
|
|
|
69
66
|
@typing.overload
|
|
70
67
|
def handle(
|
|
71
68
|
self,
|
|
72
|
-
*rules: ABCRule,
|
|
69
|
+
*rules: "ABCRule",
|
|
70
|
+
is_blocking: bool = True,
|
|
71
|
+
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandler]]: ...
|
|
72
|
+
|
|
73
|
+
@typing.overload
|
|
74
|
+
def handle(
|
|
75
|
+
self,
|
|
76
|
+
*rules: "ABCRule",
|
|
77
|
+
dataclass: type[T],
|
|
78
|
+
is_blocking: bool = True,
|
|
73
79
|
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandler]]: ...
|
|
74
80
|
|
|
75
81
|
@typing.overload
|
|
76
82
|
def handle(
|
|
77
83
|
self,
|
|
78
|
-
*rules: ABCRule,
|
|
84
|
+
*rules: "ABCRule",
|
|
85
|
+
update_type: UpdateType,
|
|
79
86
|
is_blocking: bool = True,
|
|
80
87
|
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandler]]: ...
|
|
81
88
|
|
|
82
89
|
@typing.overload
|
|
83
90
|
def handle(
|
|
84
91
|
self,
|
|
85
|
-
*rules: ABCRule,
|
|
92
|
+
*rules: "ABCRule",
|
|
86
93
|
dataclass: type[T],
|
|
94
|
+
update_type: UpdateType,
|
|
87
95
|
is_blocking: bool = True,
|
|
88
96
|
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandler]]: ...
|
|
89
97
|
|
|
90
98
|
@typing.overload
|
|
91
99
|
def handle( # type: ignore
|
|
92
100
|
self,
|
|
93
|
-
*rules: ABCRule,
|
|
101
|
+
*rules: "ABCRule",
|
|
102
|
+
error_handler: ErrorHandlerT,
|
|
103
|
+
is_blocking: bool = True,
|
|
104
|
+
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandlerT]]: ...
|
|
105
|
+
|
|
106
|
+
@typing.overload
|
|
107
|
+
def handle( # type: ignore
|
|
108
|
+
self,
|
|
109
|
+
*rules: "ABCRule",
|
|
110
|
+
update_type: UpdateType,
|
|
94
111
|
error_handler: ErrorHandlerT,
|
|
95
112
|
is_blocking: bool = True,
|
|
96
113
|
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandlerT]]: ...
|
|
@@ -98,7 +115,7 @@ class Dispatch(
|
|
|
98
115
|
@typing.overload
|
|
99
116
|
def handle(
|
|
100
117
|
self,
|
|
101
|
-
*rules: ABCRule,
|
|
118
|
+
*rules: "ABCRule",
|
|
102
119
|
dataclass: type[T],
|
|
103
120
|
error_handler: ErrorHandlerT,
|
|
104
121
|
is_blocking: bool = True,
|
|
@@ -107,7 +124,18 @@ class Dispatch(
|
|
|
107
124
|
@typing.overload
|
|
108
125
|
def handle(
|
|
109
126
|
self,
|
|
110
|
-
*rules: ABCRule,
|
|
127
|
+
*rules: "ABCRule",
|
|
128
|
+
dataclass: type[T],
|
|
129
|
+
update_type: UpdateType,
|
|
130
|
+
error_handler: ErrorHandlerT,
|
|
131
|
+
is_blocking: bool = True,
|
|
132
|
+
) -> typing.Callable[[Handler[T]], FuncHandler[UpdateCute, Handler[T], ErrorHandlerT]]: ...
|
|
133
|
+
|
|
134
|
+
@typing.overload
|
|
135
|
+
def handle(
|
|
136
|
+
self,
|
|
137
|
+
*rules: "ABCRule",
|
|
138
|
+
update_type: UpdateType | None = None,
|
|
111
139
|
dataclass: type[T] = DEFAULT_DATACLASS,
|
|
112
140
|
error_handler: typing.Literal[None] = None,
|
|
113
141
|
is_blocking: bool = True,
|
|
@@ -115,7 +143,8 @@ class Dispatch(
|
|
|
115
143
|
|
|
116
144
|
def handle( # type: ignore
|
|
117
145
|
self,
|
|
118
|
-
*rules: ABCRule,
|
|
146
|
+
*rules: "ABCRule",
|
|
147
|
+
update_type: UpdateType | None = None,
|
|
119
148
|
dataclass: type[typing.Any] = DEFAULT_DATACLASS,
|
|
120
149
|
error_handler: ErrorHandlerT | None = None,
|
|
121
150
|
is_blocking: bool = True,
|
|
@@ -127,36 +156,30 @@ class Dispatch(
|
|
|
127
156
|
is_blocking=is_blocking,
|
|
128
157
|
dataclass=dataclass,
|
|
129
158
|
error_handler=error_handler or ErrorHandler(),
|
|
159
|
+
update_type=update_type,
|
|
130
160
|
)
|
|
131
|
-
self.
|
|
161
|
+
self.raw_event.handlers.append(handler)
|
|
132
162
|
return handler
|
|
133
163
|
|
|
134
164
|
return wrapper
|
|
135
165
|
|
|
136
|
-
async def feed(self, event: Update, api:
|
|
137
|
-
logger.debug(
|
|
138
|
-
|
|
139
|
-
|
|
166
|
+
async def feed(self, event: Update, api: API) -> bool:
|
|
167
|
+
logger.debug(
|
|
168
|
+
"Processing update (update_id={}, update_type={!r})",
|
|
169
|
+
event.update_id,
|
|
170
|
+
event.update_type.name,
|
|
171
|
+
)
|
|
140
172
|
for view in self.get_views().values():
|
|
141
173
|
if await view.check(event):
|
|
142
174
|
logger.debug(
|
|
143
|
-
"Update (update_id={}) matched view {!r}.",
|
|
175
|
+
"Update (update_id={}, update_type={!r}) matched view {!r}.",
|
|
144
176
|
event.update_id,
|
|
145
|
-
|
|
177
|
+
event.update_type.name,
|
|
178
|
+
view,
|
|
146
179
|
)
|
|
147
|
-
await view.process(event, api)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
ctx = Context()
|
|
151
|
-
loop = asyncio.get_running_loop()
|
|
152
|
-
found = False
|
|
153
|
-
for handler in self.default_handlers:
|
|
154
|
-
if await handler.check(api, event, ctx):
|
|
155
|
-
found = True
|
|
156
|
-
loop.create_task(handler.run(event, ctx))
|
|
157
|
-
if handler.is_blocking:
|
|
158
|
-
break
|
|
159
|
-
return found
|
|
180
|
+
if await view.process(event, api):
|
|
181
|
+
return True
|
|
182
|
+
return False
|
|
160
183
|
|
|
161
184
|
def load(self, external: typing.Self) -> None:
|
|
162
185
|
view_external = external.get_views()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from .abc import ABCHandler
|
|
2
|
-
from .func import FuncHandler
|
|
3
|
-
from .message_reply import MessageReplyHandler
|
|
1
|
+
from telegrinder.bot.dispatch.handler.abc import ABCHandler
|
|
2
|
+
from telegrinder.bot.dispatch.handler.func import FuncHandler
|
|
3
|
+
from telegrinder.bot.dispatch.handler.message_reply import MessageReplyHandler
|
|
4
4
|
|
|
5
5
|
__all__ = ("ABCHandler", "FuncHandler", "MessageReplyHandler")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
3
|
|
|
4
|
-
from telegrinder.api
|
|
4
|
+
from telegrinder.api import API
|
|
5
5
|
from telegrinder.bot.dispatch.context import Context
|
|
6
6
|
from telegrinder.model import Model
|
|
7
|
-
from telegrinder.types import Update
|
|
7
|
+
from telegrinder.types.objects import Update
|
|
8
8
|
|
|
9
9
|
T = typing.TypeVar("T", bound=Model)
|
|
10
10
|
|
|
@@ -13,11 +13,11 @@ class ABCHandler(ABC, typing.Generic[T]):
|
|
|
13
13
|
is_blocking: bool
|
|
14
14
|
|
|
15
15
|
@abstractmethod
|
|
16
|
-
async def check(self, api:
|
|
16
|
+
async def check(self, api: API, event: Update, ctx: Context | None = None) -> bool:
|
|
17
17
|
pass
|
|
18
18
|
|
|
19
19
|
@abstractmethod
|
|
20
|
-
async def run(self, event: T, ctx: Context) -> typing.Any:
|
|
20
|
+
async def run(self, api: API, event: T, ctx: Context) -> typing.Any:
|
|
21
21
|
pass
|
|
22
22
|
|
|
23
23
|
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
+
from functools import cached_property
|
|
2
3
|
|
|
3
4
|
import typing_extensions as typing
|
|
4
5
|
|
|
5
|
-
from telegrinder.api
|
|
6
|
+
from telegrinder.api import API
|
|
6
7
|
from telegrinder.bot.cute_types import BaseCute, UpdateCute
|
|
7
8
|
from telegrinder.bot.dispatch.context import Context
|
|
8
9
|
from telegrinder.bot.dispatch.process import check_rule
|
|
10
|
+
from telegrinder.model import Model
|
|
9
11
|
from telegrinder.modules import logger
|
|
10
|
-
from telegrinder.node import Node,
|
|
12
|
+
from telegrinder.node.base import Node, get_nodes
|
|
13
|
+
from telegrinder.node.composer import compose_nodes
|
|
14
|
+
from telegrinder.node.event import EVENT_NODE_KEY
|
|
11
15
|
from telegrinder.tools.error_handler import ABCErrorHandler, ErrorHandler
|
|
12
|
-
from telegrinder.tools.magic import get_annotations
|
|
13
|
-
from telegrinder.types import Update
|
|
14
16
|
from telegrinder.types.enums import UpdateType
|
|
17
|
+
from telegrinder.types.objects import Update
|
|
15
18
|
|
|
16
19
|
from .abc import ABCHandler
|
|
17
20
|
|
|
@@ -22,11 +25,11 @@ F = typing.TypeVar(
|
|
|
22
25
|
"F",
|
|
23
26
|
bound=typing.Callable[typing.Concatenate[typing.Any, ...], typing.Awaitable[typing.Any]],
|
|
24
27
|
)
|
|
25
|
-
Event = typing.TypeVar("Event", bound=
|
|
28
|
+
Event = typing.TypeVar("Event", bound=Model)
|
|
26
29
|
ErrorHandlerT = typing.TypeVar("ErrorHandlerT", bound=ABCErrorHandler, default=ErrorHandler)
|
|
27
30
|
|
|
28
31
|
|
|
29
|
-
@dataclasses.dataclass(repr=False)
|
|
32
|
+
@dataclasses.dataclass(repr=False, slots=True)
|
|
30
33
|
class FuncHandler(ABCHandler[Event], typing.Generic[Event, F, ErrorHandlerT]):
|
|
31
34
|
func: F
|
|
32
35
|
rules: list["ABCRule"]
|
|
@@ -49,48 +52,69 @@ class FuncHandler(ABCHandler[Event], typing.Generic[Event, F, ErrorHandlerT]):
|
|
|
49
52
|
self.error_handler,
|
|
50
53
|
)
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
@cached_property
|
|
56
|
+
def required_nodes(self) -> dict[str, type[Node]]:
|
|
57
|
+
return get_nodes(self.func)
|
|
54
58
|
|
|
55
|
-
async def check(self, api:
|
|
59
|
+
async def check(self, api: API, event: Update, ctx: Context | None = None) -> bool:
|
|
56
60
|
if self.update_type is not None and self.update_type != event.update_type:
|
|
57
61
|
return False
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
logger.debug("Checking handler {!r}...", self)
|
|
64
|
+
ctx = Context(raw_update=event) if ctx is None else ctx
|
|
60
65
|
temp_ctx = ctx.copy()
|
|
61
66
|
temp_ctx |= self.preset_context
|
|
62
67
|
|
|
63
|
-
nodes = self.
|
|
68
|
+
nodes = self.required_nodes
|
|
64
69
|
node_col = None
|
|
70
|
+
update = event
|
|
65
71
|
|
|
66
72
|
if nodes:
|
|
67
|
-
|
|
68
|
-
if
|
|
73
|
+
result = await compose_nodes(nodes, ctx, data={Update: event, API: api})
|
|
74
|
+
if not result:
|
|
75
|
+
logger.debug(f"Cannot compose nodes for handler. {result.error}")
|
|
69
76
|
return False
|
|
70
|
-
|
|
77
|
+
|
|
78
|
+
node_col = result.value
|
|
79
|
+
temp_ctx |= node_col.values
|
|
80
|
+
|
|
81
|
+
if EVENT_NODE_KEY in ctx:
|
|
82
|
+
for name, node in nodes.items():
|
|
83
|
+
if node is ctx[EVENT_NODE_KEY] and name in temp_ctx:
|
|
84
|
+
ctx[EVENT_NODE_KEY] = temp_ctx.pop(name)
|
|
71
85
|
|
|
72
86
|
for rule in self.rules:
|
|
73
|
-
if not await check_rule(api, rule,
|
|
87
|
+
if not await check_rule(api, rule, update, temp_ctx):
|
|
74
88
|
logger.debug("Rule {!r} failed!", rule)
|
|
75
89
|
return False
|
|
76
90
|
|
|
91
|
+
logger.debug("All checks passed for handler.")
|
|
92
|
+
|
|
77
93
|
temp_ctx["node_col"] = node_col
|
|
78
94
|
ctx |= temp_ctx
|
|
79
95
|
return True
|
|
80
96
|
|
|
81
|
-
async def run(self, event: Event, ctx: Context) -> typing.Any:
|
|
82
|
-
|
|
97
|
+
async def run(self, api: API, event: Event, ctx: Context) -> typing.Any:
|
|
98
|
+
logger.debug(f"Running func handler {self.func}")
|
|
99
|
+
dataclass_type = typing.get_origin(self.dataclass) or self.dataclass
|
|
83
100
|
|
|
84
|
-
if
|
|
85
|
-
|
|
101
|
+
if dataclass_type is Update and (event_node := ctx.pop(EVENT_NODE_KEY, None)) is not None:
|
|
102
|
+
event = event_node
|
|
103
|
+
|
|
104
|
+
elif dataclass_type is not None:
|
|
105
|
+
if self.update_type is not None and isinstance(event, Update):
|
|
86
106
|
update = event.to_dict()[self.update_type.value].unwrap()
|
|
87
107
|
event = (
|
|
88
108
|
self.dataclass.from_update(update, bound_api=api) # type: ignore
|
|
89
|
-
if issubclass(
|
|
90
|
-
else self.dataclass(**update.to_dict())
|
|
109
|
+
if issubclass(dataclass_type, BaseCute)
|
|
110
|
+
else self.dataclass(**update.to_dict()) # type: ignore
|
|
91
111
|
)
|
|
112
|
+
|
|
113
|
+
elif issubclass(dataclass_type, UpdateCute) and isinstance(event, Update):
|
|
114
|
+
event = self.dataclass.from_update(event, bound_api=api) # type: ignore
|
|
115
|
+
|
|
92
116
|
else:
|
|
93
|
-
event = self.dataclass(**event.to_dict())
|
|
117
|
+
event = self.dataclass(**event.to_dict()) # type: ignore
|
|
94
118
|
|
|
95
119
|
result = (await self.error_handler.run(self.func, event, api, ctx)).unwrap()
|
|
96
120
|
if node_col := ctx.node_col:
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
|
|
3
|
-
from telegrinder.api.
|
|
4
|
-
from telegrinder.bot.cute_types import MessageCute
|
|
3
|
+
from telegrinder.api.api import API
|
|
4
|
+
from telegrinder.bot.cute_types.message import MessageCute
|
|
5
5
|
from telegrinder.bot.dispatch.context import Context
|
|
6
|
+
from telegrinder.bot.dispatch.handler.abc import ABCHandler
|
|
6
7
|
from telegrinder.bot.dispatch.process import check_rule
|
|
7
8
|
from telegrinder.bot.rules.abc import ABCRule
|
|
8
9
|
from telegrinder.modules import logger
|
|
9
10
|
from telegrinder.types.objects import ReplyParameters, Update
|
|
10
11
|
|
|
11
|
-
from .abc import ABCHandler
|
|
12
|
-
|
|
13
12
|
|
|
14
13
|
class MessageReplyHandler(ABCHandler[MessageCute]):
|
|
15
14
|
def __init__(
|
|
@@ -36,8 +35,8 @@ class MessageReplyHandler(ABCHandler[MessageCute]):
|
|
|
36
35
|
self.text,
|
|
37
36
|
)
|
|
38
37
|
|
|
39
|
-
async def check(self, api:
|
|
40
|
-
ctx = ctx
|
|
38
|
+
async def check(self, api: API, event: Update, ctx: Context | None = None) -> bool:
|
|
39
|
+
ctx = Context(raw_update=event) if ctx is None else ctx
|
|
41
40
|
temp_ctx = ctx.copy()
|
|
42
41
|
temp_ctx |= self.preset_context
|
|
43
42
|
|
|
@@ -49,7 +48,7 @@ class MessageReplyHandler(ABCHandler[MessageCute]):
|
|
|
49
48
|
ctx |= temp_ctx
|
|
50
49
|
return True
|
|
51
50
|
|
|
52
|
-
async def run(self, event: MessageCute,
|
|
51
|
+
async def run(self, _: API, event: MessageCute, __: Context) -> typing.Any:
|
|
53
52
|
await event.answer(
|
|
54
53
|
text=self.text,
|
|
55
54
|
reply_parameters=ReplyParameters(event.message_id) if self.as_reply else None,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
from abc import ABC
|
|
3
3
|
|
|
4
|
-
from telegrinder.bot.cute_types.base import BaseCute
|
|
5
4
|
from telegrinder.bot.dispatch.context import Context
|
|
5
|
+
from telegrinder.model import Model
|
|
6
6
|
|
|
7
|
-
Event = typing.TypeVar("Event", bound=
|
|
7
|
+
Event = typing.TypeVar("Event", bound=Model)
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class ABCMiddleware(ABC, typing.Generic[Event]):
|