telegrinder 0.3.4__py3-none-any.whl → 0.4.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.

Files changed (192) hide show
  1. telegrinder/__init__.py +148 -149
  2. telegrinder/api/__init__.py +9 -8
  3. telegrinder/api/api.py +101 -93
  4. telegrinder/api/error.py +20 -16
  5. telegrinder/api/response.py +20 -20
  6. telegrinder/api/token.py +36 -36
  7. telegrinder/bot/__init__.py +72 -66
  8. telegrinder/bot/bot.py +83 -76
  9. telegrinder/bot/cute_types/__init__.py +19 -17
  10. telegrinder/bot/cute_types/base.py +184 -258
  11. telegrinder/bot/cute_types/callback_query.py +400 -385
  12. telegrinder/bot/cute_types/chat_join_request.py +62 -61
  13. telegrinder/bot/cute_types/chat_member_updated.py +157 -160
  14. telegrinder/bot/cute_types/inline_query.py +44 -43
  15. telegrinder/bot/cute_types/message.py +2590 -2637
  16. telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
  17. telegrinder/bot/cute_types/update.py +112 -104
  18. telegrinder/bot/cute_types/utils.py +62 -95
  19. telegrinder/bot/dispatch/__init__.py +59 -55
  20. telegrinder/bot/dispatch/abc.py +76 -77
  21. telegrinder/bot/dispatch/context.py +96 -98
  22. telegrinder/bot/dispatch/dispatch.py +254 -202
  23. telegrinder/bot/dispatch/handler/__init__.py +13 -13
  24. telegrinder/bot/dispatch/handler/abc.py +23 -24
  25. telegrinder/bot/dispatch/handler/audio_reply.py +44 -44
  26. telegrinder/bot/dispatch/handler/base.py +57 -57
  27. telegrinder/bot/dispatch/handler/document_reply.py +44 -44
  28. telegrinder/bot/dispatch/handler/func.py +129 -135
  29. telegrinder/bot/dispatch/handler/media_group_reply.py +44 -43
  30. telegrinder/bot/dispatch/handler/message_reply.py +36 -36
  31. telegrinder/bot/dispatch/handler/photo_reply.py +44 -44
  32. telegrinder/bot/dispatch/handler/sticker_reply.py +37 -37
  33. telegrinder/bot/dispatch/handler/video_reply.py +44 -44
  34. telegrinder/bot/dispatch/middleware/__init__.py +3 -3
  35. telegrinder/bot/dispatch/middleware/abc.py +97 -22
  36. telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
  37. telegrinder/bot/dispatch/process.py +151 -157
  38. telegrinder/bot/dispatch/return_manager/__init__.py +15 -13
  39. telegrinder/bot/dispatch/return_manager/abc.py +104 -108
  40. telegrinder/bot/dispatch/return_manager/callback_query.py +20 -20
  41. telegrinder/bot/dispatch/return_manager/inline_query.py +15 -15
  42. telegrinder/bot/dispatch/return_manager/message.py +36 -36
  43. telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +20 -0
  44. telegrinder/bot/dispatch/view/__init__.py +15 -13
  45. telegrinder/bot/dispatch/view/abc.py +45 -41
  46. telegrinder/bot/dispatch/view/base.py +231 -200
  47. telegrinder/bot/dispatch/view/box.py +140 -129
  48. telegrinder/bot/dispatch/view/callback_query.py +16 -17
  49. telegrinder/bot/dispatch/view/chat_join_request.py +11 -16
  50. telegrinder/bot/dispatch/view/chat_member.py +37 -39
  51. telegrinder/bot/dispatch/view/inline_query.py +16 -17
  52. telegrinder/bot/dispatch/view/message.py +43 -44
  53. telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
  54. telegrinder/bot/dispatch/view/raw.py +116 -114
  55. telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
  56. telegrinder/bot/dispatch/waiter_machine/actions.py +14 -13
  57. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
  58. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +55 -55
  59. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +59 -57
  60. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +51 -51
  61. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +20 -19
  62. telegrinder/bot/dispatch/waiter_machine/machine.py +251 -172
  63. telegrinder/bot/dispatch/waiter_machine/middleware.py +94 -89
  64. telegrinder/bot/dispatch/waiter_machine/short_state.py +57 -68
  65. telegrinder/bot/polling/__init__.py +4 -4
  66. telegrinder/bot/polling/abc.py +25 -25
  67. telegrinder/bot/polling/polling.py +139 -131
  68. telegrinder/bot/rules/__init__.py +85 -62
  69. telegrinder/bot/rules/abc.py +213 -206
  70. telegrinder/bot/rules/callback_data.py +122 -163
  71. telegrinder/bot/rules/chat_join.py +45 -43
  72. telegrinder/bot/rules/command.py +126 -126
  73. telegrinder/bot/rules/enum_text.py +33 -36
  74. telegrinder/bot/rules/func.py +28 -26
  75. telegrinder/bot/rules/fuzzy.py +24 -24
  76. telegrinder/bot/rules/id.py +24 -0
  77. telegrinder/bot/rules/inline.py +58 -56
  78. telegrinder/bot/rules/integer.py +21 -20
  79. telegrinder/bot/rules/is_from.py +127 -127
  80. telegrinder/bot/rules/logic.py +18 -0
  81. telegrinder/bot/rules/markup.py +42 -43
  82. telegrinder/bot/rules/mention.py +14 -14
  83. telegrinder/bot/rules/message.py +15 -17
  84. telegrinder/bot/rules/message_entities.py +33 -35
  85. telegrinder/bot/rules/node.py +33 -27
  86. telegrinder/bot/rules/payload.py +81 -0
  87. telegrinder/bot/rules/payment_invoice.py +29 -0
  88. telegrinder/bot/rules/regex.py +36 -37
  89. telegrinder/bot/rules/rule_enum.py +72 -72
  90. telegrinder/bot/rules/start.py +42 -42
  91. telegrinder/bot/rules/state.py +35 -37
  92. telegrinder/bot/rules/text.py +38 -33
  93. telegrinder/bot/rules/update.py +15 -15
  94. telegrinder/bot/scenario/__init__.py +5 -5
  95. telegrinder/bot/scenario/abc.py +17 -19
  96. telegrinder/bot/scenario/checkbox.py +174 -176
  97. telegrinder/bot/scenario/choice.py +48 -51
  98. telegrinder/client/__init__.py +12 -4
  99. telegrinder/client/abc.py +100 -75
  100. telegrinder/client/aiohttp.py +134 -130
  101. telegrinder/client/form_data.py +31 -0
  102. telegrinder/client/sonic.py +212 -0
  103. telegrinder/model.py +208 -315
  104. telegrinder/modules.py +239 -237
  105. telegrinder/msgspec_json.py +14 -14
  106. telegrinder/msgspec_utils.py +478 -410
  107. telegrinder/node/__init__.py +86 -25
  108. telegrinder/node/attachment.py +163 -87
  109. telegrinder/node/base.py +288 -160
  110. telegrinder/node/callback_query.py +54 -53
  111. telegrinder/node/command.py +34 -33
  112. telegrinder/node/composer.py +163 -198
  113. telegrinder/node/container.py +33 -27
  114. telegrinder/node/either.py +82 -0
  115. telegrinder/node/event.py +54 -65
  116. telegrinder/node/file.py +51 -0
  117. telegrinder/node/me.py +15 -16
  118. telegrinder/node/payload.py +78 -0
  119. telegrinder/node/polymorphic.py +67 -48
  120. telegrinder/node/rule.py +72 -76
  121. telegrinder/node/scope.py +36 -38
  122. telegrinder/node/source.py +87 -71
  123. telegrinder/node/text.py +53 -41
  124. telegrinder/node/tools/__init__.py +3 -3
  125. telegrinder/node/tools/generator.py +36 -40
  126. telegrinder/py.typed +0 -0
  127. telegrinder/rules.py +1 -62
  128. telegrinder/tools/__init__.py +152 -93
  129. telegrinder/tools/adapter/__init__.py +19 -0
  130. telegrinder/tools/adapter/abc.py +49 -0
  131. telegrinder/tools/adapter/dataclass.py +56 -0
  132. telegrinder/{bot/rules → tools}/adapter/errors.py +5 -5
  133. telegrinder/{bot/rules → tools}/adapter/event.py +63 -65
  134. telegrinder/{bot/rules → tools}/adapter/node.py +46 -48
  135. telegrinder/{bot/rules → tools}/adapter/raw_event.py +27 -27
  136. telegrinder/{bot/rules → tools}/adapter/raw_update.py +30 -30
  137. telegrinder/tools/buttons.py +106 -80
  138. telegrinder/tools/callback_data_serilization/__init__.py +5 -0
  139. telegrinder/tools/callback_data_serilization/abc.py +51 -0
  140. telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
  141. telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
  142. telegrinder/tools/error_handler/__init__.py +7 -7
  143. telegrinder/tools/error_handler/abc.py +30 -33
  144. telegrinder/tools/error_handler/error.py +9 -9
  145. telegrinder/tools/error_handler/error_handler.py +179 -193
  146. telegrinder/tools/formatting/__init__.py +83 -63
  147. telegrinder/tools/formatting/deep_links.py +541 -0
  148. telegrinder/tools/formatting/{html.py → html_formatter.py} +266 -294
  149. telegrinder/tools/formatting/spec_html_formats.py +71 -117
  150. telegrinder/tools/functional.py +8 -12
  151. telegrinder/tools/global_context/__init__.py +7 -7
  152. telegrinder/tools/global_context/abc.py +63 -63
  153. telegrinder/tools/global_context/global_context.py +387 -412
  154. telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
  155. telegrinder/tools/i18n/__init__.py +7 -7
  156. telegrinder/tools/i18n/abc.py +30 -30
  157. telegrinder/tools/i18n/middleware/__init__.py +3 -3
  158. telegrinder/tools/i18n/middleware/abc.py +22 -25
  159. telegrinder/tools/i18n/simple.py +43 -43
  160. telegrinder/tools/input_file_directory.py +30 -0
  161. telegrinder/tools/keyboard.py +128 -128
  162. telegrinder/tools/lifespan.py +105 -0
  163. telegrinder/tools/limited_dict.py +32 -37
  164. telegrinder/tools/loop_wrapper/__init__.py +4 -4
  165. telegrinder/tools/loop_wrapper/abc.py +20 -15
  166. telegrinder/tools/loop_wrapper/loop_wrapper.py +169 -224
  167. telegrinder/tools/magic.py +307 -157
  168. telegrinder/tools/parse_mode.py +6 -6
  169. telegrinder/tools/state_storage/__init__.py +4 -4
  170. telegrinder/tools/state_storage/abc.py +31 -35
  171. telegrinder/tools/state_storage/memory.py +25 -25
  172. telegrinder/tools/strings.py +13 -0
  173. telegrinder/types/__init__.py +268 -260
  174. telegrinder/types/enums.py +711 -701
  175. telegrinder/types/input_file.py +51 -0
  176. telegrinder/types/methods.py +5055 -4633
  177. telegrinder/types/objects.py +7058 -6950
  178. telegrinder/verification_utils.py +30 -32
  179. {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/LICENSE +22 -22
  180. telegrinder-0.4.0.dist-info/METADATA +144 -0
  181. telegrinder-0.4.0.dist-info/RECORD +182 -0
  182. {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/WHEEL +1 -1
  183. telegrinder/bot/rules/adapter/__init__.py +0 -17
  184. telegrinder/bot/rules/adapter/abc.py +0 -31
  185. telegrinder/node/message.py +0 -14
  186. telegrinder/node/update.py +0 -15
  187. telegrinder/tools/formatting/links.py +0 -38
  188. telegrinder/tools/kb_set/__init__.py +0 -4
  189. telegrinder/tools/kb_set/base.py +0 -15
  190. telegrinder/tools/kb_set/yaml.py +0 -63
  191. telegrinder-0.3.4.dist-info/METADATA +0 -110
  192. telegrinder-0.3.4.dist-info/RECORD +0 -165
@@ -1,36 +1,36 @@
1
- import typing
2
-
3
- from telegrinder.bot.cute_types.message import MessageCute
4
- from telegrinder.bot.dispatch.context import Context
5
- from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
- from telegrinder.tools.formatting import HTMLFormatter
7
-
8
-
9
- class MessageReturnManager(BaseReturnManager[MessageCute]):
10
- @register_manager(str)
11
- @staticmethod
12
- async def str_manager(value: str, event: MessageCute, ctx: Context) -> None:
13
- await event.answer(value)
14
-
15
- @register_manager(list[str] | tuple[str, ...])
16
- @staticmethod
17
- async def seq_manager(
18
- value: list[str] | tuple[str, ...],
19
- event: MessageCute,
20
- ctx: Context,
21
- ) -> None:
22
- for message in value:
23
- await event.answer(message)
24
-
25
- @register_manager(dict[str, typing.Any])
26
- @staticmethod
27
- async def dict_manager(value: dict[str, typing.Any], event: MessageCute, ctx: Context) -> None:
28
- await event.answer(**value)
29
-
30
- @register_manager(HTMLFormatter)
31
- @staticmethod
32
- async def htmlformatter_manager(value: HTMLFormatter, event: MessageCute, ctx: Context) -> None:
33
- await event.answer(value, parse_mode=HTMLFormatter.PARSE_MODE)
34
-
35
-
36
- __all__ = ("MessageReturnManager",)
1
+ import typing
2
+
3
+ from telegrinder.bot.cute_types.message import MessageCute
4
+ from telegrinder.bot.dispatch.context import Context
5
+ from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
+ from telegrinder.tools.formatting import HTMLFormatter
7
+
8
+
9
+ class MessageReturnManager(BaseReturnManager[MessageCute]):
10
+ @register_manager(str)
11
+ @staticmethod
12
+ async def str_manager(value: str, event: MessageCute, ctx: Context) -> None:
13
+ await event.answer(value)
14
+
15
+ @register_manager(list[str] | tuple[str, ...])
16
+ @staticmethod
17
+ async def seq_manager(
18
+ value: list[str] | tuple[str, ...],
19
+ event: MessageCute,
20
+ ctx: Context,
21
+ ) -> None:
22
+ for message in value:
23
+ await event.answer(message)
24
+
25
+ @register_manager(dict[str, typing.Any])
26
+ @staticmethod
27
+ async def dict_manager(value: dict[str, typing.Any], event: MessageCute, ctx: Context) -> None:
28
+ await event.answer(**value)
29
+
30
+ @register_manager(HTMLFormatter)
31
+ @staticmethod
32
+ async def htmlformatter_manager(value: HTMLFormatter, event: MessageCute, ctx: Context) -> None:
33
+ await event.answer(value, parse_mode=HTMLFormatter.PARSE_MODE)
34
+
35
+
36
+ __all__ = ("MessageReturnManager",)
@@ -0,0 +1,20 @@
1
+ import typing
2
+
3
+ from telegrinder.bot.cute_types.pre_checkout_query import PreCheckoutQueryCute
4
+ from telegrinder.bot.dispatch.context import Context
5
+ from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
+
7
+
8
+ class PreCheckoutQueryManager(BaseReturnManager[PreCheckoutQueryCute]):
9
+ @register_manager(bool)
10
+ @staticmethod
11
+ async def bool_manager(value: bool, event: PreCheckoutQueryCute, ctx: Context) -> None:
12
+ await event.answer(value)
13
+
14
+ @register_manager(dict[str, typing.Any])
15
+ @staticmethod
16
+ async def dict_manager(value: dict[str, typing.Any], event: PreCheckoutQueryCute, ctx: Context) -> None:
17
+ await event.answer(**value)
18
+
19
+
20
+ __all__ = ("PreCheckoutQueryManager",)
@@ -1,14 +1,15 @@
1
- from telegrinder.bot.dispatch.view.abc import ABCStateView, ABCView
2
- from telegrinder.bot.dispatch.view.base import BaseStateView, BaseView
3
- from telegrinder.bot.dispatch.view.box import ViewBox
4
- from telegrinder.bot.dispatch.view.callback_query import CallbackQueryView
5
- from telegrinder.bot.dispatch.view.chat_join_request import ChatJoinRequestView
6
- from telegrinder.bot.dispatch.view.chat_member import ChatMemberView
7
- from telegrinder.bot.dispatch.view.inline_query import InlineQueryView
8
- from telegrinder.bot.dispatch.view.message import MessageView
9
- from telegrinder.bot.dispatch.view.raw import RawEventView
10
-
11
- __all__ = (
1
+ from telegrinder.bot.dispatch.view.abc import ABCStateView, ABCView
2
+ from telegrinder.bot.dispatch.view.base import BaseStateView, BaseView
3
+ from telegrinder.bot.dispatch.view.box import ViewBox
4
+ from telegrinder.bot.dispatch.view.callback_query import CallbackQueryView
5
+ from telegrinder.bot.dispatch.view.chat_join_request import ChatJoinRequestView
6
+ from telegrinder.bot.dispatch.view.chat_member import ChatMemberView
7
+ from telegrinder.bot.dispatch.view.inline_query import InlineQueryView
8
+ from telegrinder.bot.dispatch.view.message import MessageView
9
+ from telegrinder.bot.dispatch.view.pre_checkout_query import PreCheckoutQueryView
10
+ from telegrinder.bot.dispatch.view.raw import RawEventView
11
+
12
+ __all__ = (
12
13
  "ABCStateView",
13
14
  "ABCView",
14
15
  "BaseStateView",
@@ -18,6 +19,7 @@ __all__ = (
18
19
  "ChatMemberView",
19
20
  "InlineQueryView",
20
21
  "MessageView",
22
+ "PreCheckoutQueryView",
21
23
  "RawEventView",
22
- "ViewBox",
23
- )
24
+ "ViewBox",
25
+ )
@@ -1,43 +1,47 @@
1
- import typing
2
- from abc import ABC, abstractmethod
3
-
4
- from telegrinder.api.api import API
5
- from telegrinder.bot.cute_types.base import BaseCute
6
- from telegrinder.bot.dispatch.handler.abc import ABCHandler
7
- from telegrinder.types.objects import Update
8
-
9
- Event = typing.TypeVar("Event", bound=BaseCute)
10
-
11
-
12
- class ABCView(ABC):
13
- def __repr__(self) -> str:
14
- return "<{}>".format(self.__class__.__name__)
15
-
16
- @abstractmethod
17
- async def check(self, event: Update) -> bool:
18
- pass
19
-
20
- @abstractmethod
21
- async def process(self, event: Update, api: API) -> bool:
22
- pass
23
-
24
- @abstractmethod
25
- def load(self, external: typing.Self) -> None:
26
- pass
27
-
28
-
29
- class ABCEventRawView(ABCView, ABC, typing.Generic[Event]):
30
- handlers: list[ABCHandler[Event]]
31
-
32
-
33
- class ABCStateView(ABCView, typing.Generic[Event]):
34
- @abstractmethod
35
- def get_state_key(self, event: Event) -> int | None:
36
- pass
37
-
38
-
39
- __all__ = (
1
+ import typing
2
+ from abc import ABC, abstractmethod
3
+
4
+ from telegrinder.api.api import API
5
+ from telegrinder.bot.cute_types.base import BaseCute
6
+ from telegrinder.bot.dispatch.context import Context
7
+ from telegrinder.bot.dispatch.handler.abc import ABCHandler
8
+ from telegrinder.types.objects import Update
9
+
10
+
11
+ class ABCView(ABC):
12
+ def __repr__(self) -> str:
13
+ return "<{}>".format(self.__class__.__name__)
14
+
15
+ @abstractmethod
16
+ async def check(self, event: Update) -> bool:
17
+ pass
18
+
19
+ @abstractmethod
20
+ async def process(
21
+ self,
22
+ event: Update,
23
+ api: API[typing.Any],
24
+ context: Context,
25
+ ) -> bool:
26
+ pass
27
+
28
+ @abstractmethod
29
+ def load(self, external: typing.Self, /) -> None:
30
+ pass
31
+
32
+
33
+ class ABCEventRawView[Event: BaseCute](ABCView, ABC):
34
+ handlers: list[ABCHandler[Event]]
35
+
36
+
37
+ class ABCStateView[Event: BaseCute](ABCView):
38
+ @abstractmethod
39
+ def get_state_key(self, event: Event) -> int | None:
40
+ pass
41
+
42
+
43
+ __all__ = (
40
44
  "ABCEventRawView",
41
45
  "ABCStateView",
42
- "ABCView",
43
- )
46
+ "ABCView",
47
+ )
@@ -1,200 +1,231 @@
1
- import typing
2
- from abc import ABC, abstractmethod
3
- from functools import cached_property
4
-
5
- from fntypes.option import Nothing, Some
6
-
7
- from telegrinder.api.api import API
8
- from telegrinder.bot.cute_types.base import BaseCute
9
- from telegrinder.bot.dispatch.handler.abc import ABCHandler
10
- from telegrinder.bot.dispatch.handler.func import Func, FuncHandler
11
- from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
12
- from telegrinder.bot.dispatch.process import process_inner
13
- from telegrinder.bot.dispatch.return_manager.abc import ABCReturnManager
14
- from telegrinder.bot.dispatch.view.abc import ABCStateView, ABCView
15
- from telegrinder.bot.rules.abc import ABCRule
16
- from telegrinder.model import Model
17
- from telegrinder.msgspec_utils import Option
18
- from telegrinder.tools.error_handler.error_handler import ABCErrorHandler, ErrorHandler
19
- from telegrinder.types.objects import Update
20
-
21
- P = typing.ParamSpec("P")
22
- R = typing.TypeVar("R", covariant=True)
23
- Event = typing.TypeVar("Event", bound=BaseCute)
24
- ErrorHandlerT = typing.TypeVar("ErrorHandlerT", bound=ABCErrorHandler)
25
- MiddlewareT = typing.TypeVar("MiddlewareT", bound=ABCMiddleware)
26
-
27
-
28
- def get_event_model_class(view: "BaseView[Event]") -> Option[type[Event]]:
29
- for base in view.__class__.__bases__ + (view.__class__,):
30
- if "__orig_bases__" not in base.__dict__:
31
- continue
32
-
33
- for orig_base in base.__dict__["__orig_bases__"]:
34
- origin_base = typing.get_origin(orig_base) or orig_base
35
- if not isinstance(origin_base, type) and not issubclass(origin_base, object):
36
- continue
37
-
38
- for generic_type in typing.get_args(orig_base):
39
- orig_generic_type = typing.get_origin(generic_type) or generic_type
40
- if isinstance(orig_generic_type, type) and issubclass(orig_generic_type, BaseCute):
41
- return Some(generic_type)
42
-
43
- return Nothing()
44
-
45
-
46
- class BaseView(ABCView, typing.Generic[Event]):
47
- auto_rules: list[ABCRule]
48
- handlers: list[ABCHandler[Event]]
49
- middlewares: list[ABCMiddleware[Event]]
50
- return_manager: ABCReturnManager[Event] | None = None
51
-
52
- @staticmethod
53
- def get_raw_event(update: Update) -> Option[Model]:
54
- return getattr(update, update.update_type.value)
55
-
56
- @cached_property
57
- def event_model_class(self) -> Option[type[Event]]:
58
- return get_event_model_class(self)
59
-
60
- @typing.overload
61
- @classmethod
62
- def to_handler(
63
- cls,
64
- *rules: ABCRule,
65
- ) -> typing.Callable[
66
- [Func[P, R]],
67
- FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
68
- ]: ...
69
-
70
- @typing.overload
71
- @classmethod
72
- def to_handler(
73
- cls,
74
- *rules: ABCRule,
75
- error_handler: ErrorHandlerT,
76
- is_blocking: bool = True,
77
- ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
78
-
79
- @typing.overload
80
- @classmethod
81
- def to_handler(
82
- cls,
83
- *rules: ABCRule,
84
- error_handler: typing.Literal[None] = None,
85
- is_blocking: bool = True,
86
- ) -> typing.Callable[
87
- [Func[P, R]],
88
- FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
89
- ]: ...
90
-
91
- @classmethod
92
- def to_handler(
93
- cls,
94
- *rules: ABCRule,
95
- error_handler: ABCErrorHandler | None = None,
96
- is_blocking: bool = True,
97
- ) -> typing.Callable[..., typing.Any]:
98
- def wrapper(func):
99
- return FuncHandler(
100
- func,
101
- list(rules),
102
- is_blocking=is_blocking,
103
- dataclass=None,
104
- error_handler=error_handler or ErrorHandler(),
105
- )
106
-
107
- return wrapper
108
-
109
- @typing.overload
110
- def __call__(
111
- self,
112
- *rules: ABCRule,
113
- ) -> typing.Callable[
114
- [Func[P, R]],
115
- FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
116
- ]: ...
117
-
118
- @typing.overload
119
- def __call__( # type: ignore
120
- self,
121
- *rules: ABCRule,
122
- error_handler: ErrorHandlerT,
123
- is_blocking: bool = True,
124
- ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
125
-
126
- @typing.overload
127
- def __call__(
128
- self,
129
- *rules: ABCRule,
130
- error_handler: typing.Literal[None] = None,
131
- is_blocking: bool = True,
132
- ) -> typing.Callable[
133
- [Func[P, R]],
134
- FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
135
- ]: ...
136
-
137
- def __call__(
138
- self,
139
- *rules: ABCRule,
140
- error_handler: ABCErrorHandler | None = None,
141
- is_blocking: bool = True,
142
- ) -> typing.Callable[..., typing.Any]:
143
- def wrapper(func):
144
- func_handler = FuncHandler(
145
- func,
146
- [*self.auto_rules, *rules],
147
- is_blocking=is_blocking,
148
- dataclass=None,
149
- error_handler=error_handler or ErrorHandler(),
150
- )
151
- self.handlers.append(func_handler)
152
- return func_handler
153
-
154
- return wrapper
155
-
156
- def register_middleware(self, *args: typing.Any, **kwargs: typing.Any):
157
- def wrapper(cls: type[MiddlewareT]) -> type[MiddlewareT]:
158
- self.middlewares.append(cls(*args, **kwargs))
159
- return cls
160
-
161
- return wrapper
162
-
163
- async def check(self, event: Update) -> bool:
164
- match self.get_raw_event(event):
165
- case Some(e) if issubclass(
166
- self.event_model_class.expect(
167
- "{!r} has no event model class in generic.".format(self.__class__.__qualname__),
168
- ),
169
- e.__class__,
170
- ) and (self.handlers or self.middlewares):
171
- return True
172
- case _:
173
- return False
174
-
175
- async def process(self, event: Update, api: API) -> bool:
176
- return await process_inner(
177
- api,
178
- self.event_model_class.unwrap().from_update(
179
- update=self.get_raw_event(event).unwrap(),
180
- bound_api=api,
181
- ),
182
- event,
183
- self.middlewares,
184
- self.handlers,
185
- self.return_manager,
186
- )
187
-
188
- def load(self, external: typing.Self) -> None:
189
- self.auto_rules.extend(external.auto_rules)
190
- self.handlers.extend(external.handlers)
191
- self.middlewares.extend(external.middlewares)
192
-
193
-
194
- class BaseStateView(ABCStateView[Event], BaseView[Event], ABC, typing.Generic[Event]):
195
- @abstractmethod
196
- def get_state_key(self, event: Event) -> int | None:
197
- pass
198
-
199
-
200
- __all__ = ("ABCStateView", "ABCView", "BaseStateView", "BaseView")
1
+ import typing
2
+ from abc import ABC, abstractmethod
3
+ from functools import cached_property
4
+
5
+ from fntypes.option import Nothing, Some
6
+
7
+ from telegrinder.api.api import API
8
+ from telegrinder.bot.cute_types.base import BaseCute
9
+ from telegrinder.bot.dispatch.context import Context
10
+ from telegrinder.bot.dispatch.handler.abc import ABCHandler
11
+ from telegrinder.bot.dispatch.handler.func import Func, FuncHandler
12
+ from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
13
+ from telegrinder.bot.dispatch.process import process_inner
14
+ from telegrinder.bot.dispatch.return_manager.abc import ABCReturnManager
15
+ from telegrinder.bot.dispatch.view.abc import ABCStateView, ABCView
16
+ from telegrinder.bot.rules.abc import ABCRule
17
+ from telegrinder.model import Model
18
+ from telegrinder.msgspec_utils import Option
19
+ from telegrinder.tools.error_handler.error_handler import ABCErrorHandler, ErrorHandler
20
+ from telegrinder.types.objects import Update
21
+
22
+
23
+ def get_event_model_class[Event: BaseCute](
24
+ view: "BaseView[Event] | type[BaseView[Event]]",
25
+ ) -> Option[type[Event]]:
26
+ view_class = view if isinstance(view, typing.Type) else view.__class__
27
+ for base in view.__class__.__bases__ + (view_class,):
28
+ if "__orig_bases__" not in base.__dict__:
29
+ continue
30
+
31
+ for orig_base in base.__dict__["__orig_bases__"]:
32
+ origin_base = typing.get_origin(orig_base) or orig_base
33
+ if not isinstance(origin_base, type) and not issubclass(origin_base, object):
34
+ continue
35
+
36
+ for generic_type in typing.get_args(orig_base):
37
+ orig_generic_type = typing.get_origin(generic_type) or generic_type
38
+ if isinstance(orig_generic_type, type) and issubclass(orig_generic_type, BaseCute):
39
+ return Some(generic_type)
40
+
41
+ return Nothing()
42
+
43
+
44
+ class BaseView[Event: BaseCute](ABCView):
45
+ def __init__(self) -> None:
46
+ self.handlers: list[ABCHandler[Event]] = []
47
+ self.middlewares: list[ABCMiddleware[Event]] = []
48
+ self.return_manager: ABCReturnManager[Event] | None = None
49
+ self._auto_rules: ABCRule | None = None
50
+
51
+ @property
52
+ def auto_rules(self) -> tuple[ABCRule] | tuple[()]:
53
+ return (self._auto_rules,) if self._auto_rules else ()
54
+
55
+ @auto_rules.setter
56
+ def auto_rules(self, value: ABCRule | None) -> None:
57
+ """Example usage:
58
+
59
+ ```python
60
+ view.auto_rules = Rule1() & Rule2() | Rule3() & Rule4()
61
+ view.auto_rules # (<OrRule>,)
62
+
63
+ view.auto_rules = None
64
+ view.auto_rules # ()
65
+ ```
66
+ """
67
+ self._auto_rules = value
68
+
69
+ @staticmethod
70
+ def get_raw_event(update: Update) -> Option[Model]:
71
+ return getattr(update, update.update_type.value)
72
+
73
+ @cached_property
74
+ def event_model_class(self) -> Option[type[Event]]:
75
+ return get_event_model_class(self)
76
+
77
+ @typing.overload
78
+ @classmethod
79
+ def to_handler[**P, R](
80
+ cls,
81
+ *rules: ABCRule,
82
+ ) -> typing.Callable[
83
+ [Func[P, R]],
84
+ FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
85
+ ]: ...
86
+
87
+ @typing.overload
88
+ @classmethod
89
+ def to_handler[**P, Dataclass, R](
90
+ cls,
91
+ *rules: ABCRule,
92
+ dataclass: type[Dataclass],
93
+ final: bool = True,
94
+ ) -> typing.Callable[
95
+ [Func[P, R]],
96
+ FuncHandler[Dataclass, Func[P, R], ErrorHandler[Dataclass]],
97
+ ]: ...
98
+
99
+ @typing.overload
100
+ @classmethod
101
+ def to_handler[**P, ErrorHandlerT: ABCErrorHandler, R](
102
+ cls,
103
+ *rules: ABCRule,
104
+ error_handler: ErrorHandlerT,
105
+ final: bool = True,
106
+ ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
107
+
108
+ @typing.overload
109
+ @classmethod
110
+ def to_handler[**P, Dataclass, ErrorHandlerT: ABCErrorHandler, R](
111
+ cls,
112
+ *rules: ABCRule,
113
+ dataclass: type[Dataclass],
114
+ error_handler: ErrorHandlerT,
115
+ final: bool = True,
116
+ ) -> typing.Callable[[Func[P, R]], FuncHandler[Dataclass, Func[P, R], ErrorHandlerT]]: ...
117
+
118
+ @classmethod
119
+ def to_handler(
120
+ cls,
121
+ *rules: ABCRule,
122
+ dataclass: type[typing.Any] | None = None,
123
+ error_handler: ABCErrorHandler | None = None,
124
+ final: bool = True,
125
+ ) -> typing.Callable[..., typing.Any]:
126
+ def wrapper(func):
127
+ return FuncHandler(
128
+ func,
129
+ list(rules),
130
+ final=final,
131
+ dataclass=dataclass,
132
+ error_handler=error_handler or ErrorHandler(),
133
+ )
134
+
135
+ return wrapper
136
+
137
+ @typing.overload
138
+ def __call__[**P, R](
139
+ self,
140
+ *rules: ABCRule,
141
+ final: bool = True,
142
+ ) -> typing.Callable[
143
+ [Func[P, R]],
144
+ FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
145
+ ]: ...
146
+
147
+ @typing.overload
148
+ def __call__[**P, Dataclass, R](
149
+ self,
150
+ *rules: ABCRule,
151
+ dataclass: type[Dataclass],
152
+ final: bool = True,
153
+ ) -> typing.Callable[
154
+ [Func[P, R]],
155
+ FuncHandler[Dataclass, Func[P, R], ErrorHandler[Dataclass]],
156
+ ]: ...
157
+
158
+ @typing.overload
159
+ def __call__[**P, ErrorHandlerT: ABCErrorHandler, R](
160
+ self,
161
+ *rules: ABCRule,
162
+ error_handler: ErrorHandlerT,
163
+ final: bool = True,
164
+ ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
165
+
166
+ def __call__[**P, R](
167
+ self,
168
+ *rules: ABCRule,
169
+ dataclass: type[typing.Any] | None = None,
170
+ error_handler: ABCErrorHandler | None = None,
171
+ final: bool = True,
172
+ ) -> typing.Callable[..., typing.Any]:
173
+ def wrapper(func: typing.Callable[..., typing.Any]):
174
+ func_handler = FuncHandler(
175
+ func,
176
+ [*self.auto_rules, *rules],
177
+ final=final,
178
+ dataclass=dataclass,
179
+ error_handler=error_handler or ErrorHandler(),
180
+ )
181
+ self.handlers.append(func_handler)
182
+ return func_handler
183
+
184
+ return wrapper
185
+
186
+ def register_middleware[Middleware: ABCMiddleware](self, *args: typing.Any, **kwargs: typing.Any):
187
+ def wrapper(cls: type[Middleware]) -> type[Middleware]:
188
+ self.middlewares.append(cls(*args, **kwargs))
189
+ return cls
190
+
191
+ return wrapper
192
+
193
+ async def check(self, event: Update) -> bool:
194
+ match self.get_raw_event(event):
195
+ case Some(e) if issubclass(
196
+ self.event_model_class.expect(
197
+ "{!r} has no event model class in generic.".format(self.__class__.__qualname__),
198
+ ),
199
+ e.__class__,
200
+ ) and (self.handlers or self.middlewares):
201
+ return True
202
+ case _:
203
+ return False
204
+
205
+ async def process(self, event: Update, api: API, context: Context) -> bool:
206
+ return await process_inner(
207
+ api,
208
+ self.event_model_class.unwrap().from_update(
209
+ update=self.get_raw_event(event).unwrap(),
210
+ bound_api=api,
211
+ ),
212
+ event,
213
+ context,
214
+ self.middlewares,
215
+ self.handlers,
216
+ self.return_manager,
217
+ )
218
+
219
+ def load(self, external: typing.Self, /) -> None:
220
+ self.handlers.extend(external.handlers)
221
+ self.middlewares.extend(external.middlewares)
222
+
223
+
224
+ class BaseStateView[Event: BaseCute](ABCStateView[Event], BaseView[Event], ABC):
225
+ @classmethod
226
+ @abstractmethod
227
+ def get_state_key(cls, event: Event) -> int | None:
228
+ pass
229
+
230
+
231
+ __all__ = ("ABCStateView", "ABCView", "BaseStateView", "BaseView")