telegrinder 0.3.4.post1__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 (169) hide show
  1. telegrinder/__init__.py +30 -31
  2. telegrinder/api/__init__.py +2 -1
  3. telegrinder/api/api.py +28 -20
  4. telegrinder/api/error.py +8 -4
  5. telegrinder/api/response.py +2 -2
  6. telegrinder/api/token.py +2 -2
  7. telegrinder/bot/__init__.py +6 -0
  8. telegrinder/bot/bot.py +38 -31
  9. telegrinder/bot/cute_types/__init__.py +2 -0
  10. telegrinder/bot/cute_types/base.py +54 -128
  11. telegrinder/bot/cute_types/callback_query.py +76 -61
  12. telegrinder/bot/cute_types/chat_join_request.py +4 -3
  13. telegrinder/bot/cute_types/chat_member_updated.py +28 -31
  14. telegrinder/bot/cute_types/inline_query.py +5 -4
  15. telegrinder/bot/cute_types/message.py +555 -602
  16. telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
  17. telegrinder/bot/cute_types/update.py +20 -12
  18. telegrinder/bot/cute_types/utils.py +3 -36
  19. telegrinder/bot/dispatch/__init__.py +4 -0
  20. telegrinder/bot/dispatch/abc.py +8 -9
  21. telegrinder/bot/dispatch/context.py +5 -7
  22. telegrinder/bot/dispatch/dispatch.py +85 -33
  23. telegrinder/bot/dispatch/handler/abc.py +5 -6
  24. telegrinder/bot/dispatch/handler/audio_reply.py +2 -2
  25. telegrinder/bot/dispatch/handler/base.py +3 -3
  26. telegrinder/bot/dispatch/handler/document_reply.py +2 -2
  27. telegrinder/bot/dispatch/handler/func.py +36 -42
  28. telegrinder/bot/dispatch/handler/media_group_reply.py +5 -4
  29. telegrinder/bot/dispatch/handler/message_reply.py +2 -2
  30. telegrinder/bot/dispatch/handler/photo_reply.py +2 -2
  31. telegrinder/bot/dispatch/handler/sticker_reply.py +2 -2
  32. telegrinder/bot/dispatch/handler/video_reply.py +2 -2
  33. telegrinder/bot/dispatch/middleware/abc.py +83 -8
  34. telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
  35. telegrinder/bot/dispatch/process.py +44 -50
  36. telegrinder/bot/dispatch/return_manager/__init__.py +2 -0
  37. telegrinder/bot/dispatch/return_manager/abc.py +6 -10
  38. telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +20 -0
  39. telegrinder/bot/dispatch/view/__init__.py +2 -0
  40. telegrinder/bot/dispatch/view/abc.py +10 -6
  41. telegrinder/bot/dispatch/view/base.py +81 -50
  42. telegrinder/bot/dispatch/view/box.py +20 -9
  43. telegrinder/bot/dispatch/view/callback_query.py +3 -4
  44. telegrinder/bot/dispatch/view/chat_join_request.py +2 -7
  45. telegrinder/bot/dispatch/view/chat_member.py +3 -5
  46. telegrinder/bot/dispatch/view/inline_query.py +3 -4
  47. telegrinder/bot/dispatch/view/message.py +3 -4
  48. telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
  49. telegrinder/bot/dispatch/view/raw.py +42 -40
  50. telegrinder/bot/dispatch/waiter_machine/actions.py +5 -4
  51. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +0 -0
  52. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +0 -0
  53. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +9 -7
  54. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +0 -0
  55. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +3 -2
  56. telegrinder/bot/dispatch/waiter_machine/machine.py +113 -34
  57. telegrinder/bot/dispatch/waiter_machine/middleware.py +15 -10
  58. telegrinder/bot/dispatch/waiter_machine/short_state.py +7 -18
  59. telegrinder/bot/polling/polling.py +62 -54
  60. telegrinder/bot/rules/__init__.py +24 -1
  61. telegrinder/bot/rules/abc.py +17 -10
  62. telegrinder/bot/rules/callback_data.py +20 -61
  63. telegrinder/bot/rules/chat_join.py +6 -4
  64. telegrinder/bot/rules/command.py +4 -4
  65. telegrinder/bot/rules/enum_text.py +1 -4
  66. telegrinder/bot/rules/func.py +5 -3
  67. telegrinder/bot/rules/fuzzy.py +1 -1
  68. telegrinder/bot/rules/id.py +24 -0
  69. telegrinder/bot/rules/inline.py +6 -4
  70. telegrinder/bot/rules/integer.py +2 -1
  71. telegrinder/bot/rules/logic.py +18 -0
  72. telegrinder/bot/rules/markup.py +5 -6
  73. telegrinder/bot/rules/message.py +2 -4
  74. telegrinder/bot/rules/message_entities.py +1 -3
  75. telegrinder/bot/rules/node.py +15 -9
  76. telegrinder/bot/rules/payload.py +81 -0
  77. telegrinder/bot/rules/payment_invoice.py +29 -0
  78. telegrinder/bot/rules/regex.py +5 -6
  79. telegrinder/bot/rules/state.py +1 -3
  80. telegrinder/bot/rules/text.py +10 -5
  81. telegrinder/bot/rules/update.py +0 -0
  82. telegrinder/bot/scenario/abc.py +2 -4
  83. telegrinder/bot/scenario/checkbox.py +12 -14
  84. telegrinder/bot/scenario/choice.py +6 -9
  85. telegrinder/client/__init__.py +9 -1
  86. telegrinder/client/abc.py +35 -10
  87. telegrinder/client/aiohttp.py +28 -24
  88. telegrinder/client/form_data.py +31 -0
  89. telegrinder/client/sonic.py +212 -0
  90. telegrinder/model.py +38 -145
  91. telegrinder/modules.py +3 -1
  92. telegrinder/msgspec_utils.py +136 -68
  93. telegrinder/node/__init__.py +74 -13
  94. telegrinder/node/attachment.py +92 -16
  95. telegrinder/node/base.py +196 -68
  96. telegrinder/node/callback_query.py +17 -16
  97. telegrinder/node/command.py +3 -2
  98. telegrinder/node/composer.py +40 -75
  99. telegrinder/node/container.py +13 -7
  100. telegrinder/node/either.py +82 -0
  101. telegrinder/node/event.py +20 -31
  102. telegrinder/node/file.py +51 -0
  103. telegrinder/node/me.py +4 -5
  104. telegrinder/node/payload.py +78 -0
  105. telegrinder/node/polymorphic.py +27 -8
  106. telegrinder/node/rule.py +2 -6
  107. telegrinder/node/scope.py +4 -6
  108. telegrinder/node/source.py +37 -21
  109. telegrinder/node/text.py +20 -8
  110. telegrinder/node/tools/generator.py +7 -11
  111. telegrinder/py.typed +0 -0
  112. telegrinder/rules.py +0 -61
  113. telegrinder/tools/__init__.py +97 -38
  114. telegrinder/tools/adapter/__init__.py +19 -0
  115. telegrinder/tools/adapter/abc.py +49 -0
  116. telegrinder/tools/adapter/dataclass.py +56 -0
  117. telegrinder/{bot/rules → tools}/adapter/event.py +8 -10
  118. telegrinder/{bot/rules → tools}/adapter/node.py +8 -10
  119. telegrinder/{bot/rules → tools}/adapter/raw_event.py +2 -2
  120. telegrinder/{bot/rules → tools}/adapter/raw_update.py +2 -2
  121. telegrinder/tools/buttons.py +52 -26
  122. telegrinder/tools/callback_data_serilization/__init__.py +5 -0
  123. telegrinder/tools/callback_data_serilization/abc.py +51 -0
  124. telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
  125. telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
  126. telegrinder/tools/error_handler/abc.py +4 -7
  127. telegrinder/tools/error_handler/error.py +0 -0
  128. telegrinder/tools/error_handler/error_handler.py +34 -48
  129. telegrinder/tools/formatting/__init__.py +57 -37
  130. telegrinder/tools/formatting/deep_links.py +541 -0
  131. telegrinder/tools/formatting/{html.py → html_formatter.py} +51 -79
  132. telegrinder/tools/formatting/spec_html_formats.py +14 -60
  133. telegrinder/tools/functional.py +1 -5
  134. telegrinder/tools/global_context/global_context.py +26 -51
  135. telegrinder/tools/global_context/telegrinder_ctx.py +3 -3
  136. telegrinder/tools/i18n/abc.py +0 -0
  137. telegrinder/tools/i18n/middleware/abc.py +3 -6
  138. telegrinder/tools/input_file_directory.py +30 -0
  139. telegrinder/tools/keyboard.py +9 -9
  140. telegrinder/tools/lifespan.py +105 -0
  141. telegrinder/tools/limited_dict.py +5 -10
  142. telegrinder/tools/loop_wrapper/abc.py +7 -2
  143. telegrinder/tools/loop_wrapper/loop_wrapper.py +40 -95
  144. telegrinder/tools/magic.py +184 -34
  145. telegrinder/tools/state_storage/__init__.py +0 -0
  146. telegrinder/tools/state_storage/abc.py +5 -9
  147. telegrinder/tools/state_storage/memory.py +1 -1
  148. telegrinder/tools/strings.py +13 -0
  149. telegrinder/types/__init__.py +8 -0
  150. telegrinder/types/enums.py +31 -21
  151. telegrinder/types/input_file.py +51 -0
  152. telegrinder/types/methods.py +531 -109
  153. telegrinder/types/objects.py +934 -826
  154. telegrinder/verification_utils.py +0 -2
  155. {telegrinder-0.3.4.post1.dist-info → telegrinder-0.4.0.dist-info}/LICENSE +2 -2
  156. telegrinder-0.4.0.dist-info/METADATA +144 -0
  157. telegrinder-0.4.0.dist-info/RECORD +182 -0
  158. {telegrinder-0.3.4.post1.dist-info → telegrinder-0.4.0.dist-info}/WHEEL +1 -1
  159. telegrinder/bot/rules/adapter/__init__.py +0 -17
  160. telegrinder/bot/rules/adapter/abc.py +0 -31
  161. telegrinder/node/message.py +0 -14
  162. telegrinder/node/update.py +0 -15
  163. telegrinder/tools/formatting/links.py +0 -38
  164. telegrinder/tools/kb_set/__init__.py +0 -4
  165. telegrinder/tools/kb_set/base.py +0 -15
  166. telegrinder/tools/kb_set/yaml.py +0 -63
  167. telegrinder-0.3.4.post1.dist-info/METADATA +0 -110
  168. telegrinder-0.3.4.post1.dist-info/RECORD +0 -165
  169. /telegrinder/{bot/rules → tools}/adapter/errors.py +0 -0
@@ -7,11 +7,8 @@ from telegrinder.bot.dispatch.context import Context
7
7
  from telegrinder.model import Model
8
8
  from telegrinder.modules import logger
9
9
 
10
- T = typing.TypeVar("T")
11
- Event = typing.TypeVar("Event", bound=Model, contravariant=True)
12
10
 
13
-
14
- def get_union_types(t: types.UnionType) -> tuple[type, ...] | None:
11
+ def get_union_types(t: types.UnionType | typing.Any) -> tuple[type[typing.Any], ...] | None:
15
12
  if type(t) in (types.UnionType, typing._UnionGenericAlias): # type: ignore
16
13
  return tuple(typing.get_origin(x) or x for x in typing.get_args(t))
17
14
  return None
@@ -33,13 +30,13 @@ class Manager:
33
30
  await self.callback(*args, **kwargs)
34
31
 
35
32
 
36
- class ABCReturnManager(ABC, typing.Generic[Event]):
33
+ class ABCReturnManager[Event: Model](ABC):
37
34
  @abstractmethod
38
35
  async def run(self, response: typing.Any, event: Event, ctx: Context) -> None:
39
36
  pass
40
37
 
41
38
 
42
- class BaseReturnManager(ABCReturnManager[Event]):
39
+ class BaseReturnManager[Event: Model](ABCReturnManager[Event]):
43
40
  def __repr__(self) -> str:
44
41
  return "<{}: {}>".format(
45
42
  self.__class__.__name__,
@@ -63,7 +60,6 @@ class BaseReturnManager(ABCReturnManager[Event]):
63
60
  @staticmethod
64
61
  async def ctx_manager(value: Context, event: Event, ctx: Context) -> None:
65
62
  """Basic manager for returning context from handler."""
66
-
67
63
  ctx.update(value)
68
64
 
69
65
  async def run(self, response: typing.Any, event: Event, ctx: Context) -> None:
@@ -74,13 +70,13 @@ class BaseReturnManager(ABCReturnManager[Event]):
74
70
  await manager(response, event, ctx)
75
71
 
76
72
  @typing.overload
77
- def register_manager(
73
+ def register_manager[T](
78
74
  self,
79
75
  return_type: type[T],
80
76
  ) -> typing.Callable[[typing.Callable[[T, Event, Context], typing.Awaitable[typing.Any]]], Manager]: ...
81
77
 
82
78
  @typing.overload
83
- def register_manager(
79
+ def register_manager[T](
84
80
  self,
85
81
  return_type: tuple[type[T], ...],
86
82
  ) -> typing.Callable[
@@ -88,7 +84,7 @@ class BaseReturnManager(ABCReturnManager[Event]):
88
84
  Manager,
89
85
  ]: ...
90
86
 
91
- def register_manager(
87
+ def register_manager[T](
92
88
  self,
93
89
  return_type: type[T] | tuple[type[T], ...],
94
90
  ) -> typing.Callable[
@@ -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",)
@@ -6,6 +6,7 @@ from telegrinder.bot.dispatch.view.chat_join_request import ChatJoinRequestView
6
6
  from telegrinder.bot.dispatch.view.chat_member import ChatMemberView
7
7
  from telegrinder.bot.dispatch.view.inline_query import InlineQueryView
8
8
  from telegrinder.bot.dispatch.view.message import MessageView
9
+ from telegrinder.bot.dispatch.view.pre_checkout_query import PreCheckoutQueryView
9
10
  from telegrinder.bot.dispatch.view.raw import RawEventView
10
11
 
11
12
  __all__ = (
@@ -18,6 +19,7 @@ __all__ = (
18
19
  "ChatMemberView",
19
20
  "InlineQueryView",
20
21
  "MessageView",
22
+ "PreCheckoutQueryView",
21
23
  "RawEventView",
22
24
  "ViewBox",
23
25
  )
@@ -3,11 +3,10 @@ from abc import ABC, abstractmethod
3
3
 
4
4
  from telegrinder.api.api import API
5
5
  from telegrinder.bot.cute_types.base import BaseCute
6
+ from telegrinder.bot.dispatch.context import Context
6
7
  from telegrinder.bot.dispatch.handler.abc import ABCHandler
7
8
  from telegrinder.types.objects import Update
8
9
 
9
- Event = typing.TypeVar("Event", bound=BaseCute)
10
-
11
10
 
12
11
  class ABCView(ABC):
13
12
  def __repr__(self) -> str:
@@ -18,19 +17,24 @@ class ABCView(ABC):
18
17
  pass
19
18
 
20
19
  @abstractmethod
21
- async def process(self, event: Update, api: API) -> bool:
20
+ async def process(
21
+ self,
22
+ event: Update,
23
+ api: API[typing.Any],
24
+ context: Context,
25
+ ) -> bool:
22
26
  pass
23
27
 
24
28
  @abstractmethod
25
- def load(self, external: typing.Self) -> None:
29
+ def load(self, external: typing.Self, /) -> None:
26
30
  pass
27
31
 
28
32
 
29
- class ABCEventRawView(ABCView, ABC, typing.Generic[Event]):
33
+ class ABCEventRawView[Event: BaseCute](ABCView, ABC):
30
34
  handlers: list[ABCHandler[Event]]
31
35
 
32
36
 
33
- class ABCStateView(ABCView, typing.Generic[Event]):
37
+ class ABCStateView[Event: BaseCute](ABCView):
34
38
  @abstractmethod
35
39
  def get_state_key(self, event: Event) -> int | None:
36
40
  pass
@@ -6,6 +6,7 @@ from fntypes.option import Nothing, Some
6
6
 
7
7
  from telegrinder.api.api import API
8
8
  from telegrinder.bot.cute_types.base import BaseCute
9
+ from telegrinder.bot.dispatch.context import Context
9
10
  from telegrinder.bot.dispatch.handler.abc import ABCHandler
10
11
  from telegrinder.bot.dispatch.handler.func import Func, FuncHandler
11
12
  from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
@@ -18,15 +19,12 @@ from telegrinder.msgspec_utils import Option
18
19
  from telegrinder.tools.error_handler.error_handler import ABCErrorHandler, ErrorHandler
19
20
  from telegrinder.types.objects import Update
20
21
 
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
22
 
27
-
28
- def get_event_model_class(view: "BaseView[Event]") -> Option[type[Event]]:
29
- for base in view.__class__.__bases__ + (view.__class__,):
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,):
30
28
  if "__orig_bases__" not in base.__dict__:
31
29
  continue
32
30
 
@@ -43,11 +41,30 @@ def get_event_model_class(view: "BaseView[Event]") -> Option[type[Event]]:
43
41
  return Nothing()
44
42
 
45
43
 
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
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
51
68
 
52
69
  @staticmethod
53
70
  def get_raw_event(update: Update) -> Option[Model]:
@@ -59,7 +76,7 @@ class BaseView(ABCView, typing.Generic[Event]):
59
76
 
60
77
  @typing.overload
61
78
  @classmethod
62
- def to_handler(
79
+ def to_handler[**P, R](
63
80
  cls,
64
81
  *rules: ABCRule,
65
82
  ) -> typing.Callable[
@@ -69,83 +86,96 @@ class BaseView(ABCView, typing.Generic[Event]):
69
86
 
70
87
  @typing.overload
71
88
  @classmethod
72
- def to_handler(
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](
73
102
  cls,
74
103
  *rules: ABCRule,
75
104
  error_handler: ErrorHandlerT,
76
- is_blocking: bool = True,
105
+ final: bool = True,
77
106
  ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
78
107
 
79
108
  @typing.overload
80
109
  @classmethod
81
- def to_handler(
110
+ def to_handler[**P, Dataclass, ErrorHandlerT: ABCErrorHandler, R](
82
111
  cls,
83
112
  *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
- ]: ...
113
+ dataclass: type[Dataclass],
114
+ error_handler: ErrorHandlerT,
115
+ final: bool = True,
116
+ ) -> typing.Callable[[Func[P, R]], FuncHandler[Dataclass, Func[P, R], ErrorHandlerT]]: ...
90
117
 
91
118
  @classmethod
92
119
  def to_handler(
93
120
  cls,
94
121
  *rules: ABCRule,
122
+ dataclass: type[typing.Any] | None = None,
95
123
  error_handler: ABCErrorHandler | None = None,
96
- is_blocking: bool = True,
124
+ final: bool = True,
97
125
  ) -> typing.Callable[..., typing.Any]:
98
126
  def wrapper(func):
99
127
  return FuncHandler(
100
128
  func,
101
129
  list(rules),
102
- is_blocking=is_blocking,
103
- dataclass=None,
130
+ final=final,
131
+ dataclass=dataclass,
104
132
  error_handler=error_handler or ErrorHandler(),
105
133
  )
106
134
 
107
135
  return wrapper
108
136
 
109
137
  @typing.overload
110
- def __call__(
138
+ def __call__[**P, R](
111
139
  self,
112
140
  *rules: ABCRule,
141
+ final: bool = True,
113
142
  ) -> typing.Callable[
114
143
  [Func[P, R]],
115
144
  FuncHandler[Event, Func[P, R], ErrorHandler[Event]],
116
145
  ]: ...
117
146
 
118
147
  @typing.overload
119
- def __call__( # type: ignore
148
+ def __call__[**P, Dataclass, R](
120
149
  self,
121
150
  *rules: ABCRule,
122
- error_handler: ErrorHandlerT,
123
- is_blocking: bool = True,
124
- ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
151
+ dataclass: type[Dataclass],
152
+ final: bool = True,
153
+ ) -> typing.Callable[
154
+ [Func[P, R]],
155
+ FuncHandler[Dataclass, Func[P, R], ErrorHandler[Dataclass]],
156
+ ]: ...
125
157
 
126
158
  @typing.overload
127
- def __call__(
159
+ def __call__[**P, ErrorHandlerT: ABCErrorHandler, R](
128
160
  self,
129
161
  *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
- ]: ...
162
+ error_handler: ErrorHandlerT,
163
+ final: bool = True,
164
+ ) -> typing.Callable[[Func[P, R]], FuncHandler[Event, Func[P, R], ErrorHandlerT]]: ...
136
165
 
137
- def __call__(
166
+ def __call__[**P, R](
138
167
  self,
139
168
  *rules: ABCRule,
169
+ dataclass: type[typing.Any] | None = None,
140
170
  error_handler: ABCErrorHandler | None = None,
141
- is_blocking: bool = True,
171
+ final: bool = True,
142
172
  ) -> typing.Callable[..., typing.Any]:
143
- def wrapper(func):
173
+ def wrapper(func: typing.Callable[..., typing.Any]):
144
174
  func_handler = FuncHandler(
145
175
  func,
146
176
  [*self.auto_rules, *rules],
147
- is_blocking=is_blocking,
148
- dataclass=None,
177
+ final=final,
178
+ dataclass=dataclass,
149
179
  error_handler=error_handler or ErrorHandler(),
150
180
  )
151
181
  self.handlers.append(func_handler)
@@ -153,8 +183,8 @@ class BaseView(ABCView, typing.Generic[Event]):
153
183
 
154
184
  return wrapper
155
185
 
156
- def register_middleware(self, *args: typing.Any, **kwargs: typing.Any):
157
- def wrapper(cls: type[MiddlewareT]) -> type[MiddlewareT]:
186
+ def register_middleware[Middleware: ABCMiddleware](self, *args: typing.Any, **kwargs: typing.Any):
187
+ def wrapper(cls: type[Middleware]) -> type[Middleware]:
158
188
  self.middlewares.append(cls(*args, **kwargs))
159
189
  return cls
160
190
 
@@ -172,7 +202,7 @@ class BaseView(ABCView, typing.Generic[Event]):
172
202
  case _:
173
203
  return False
174
204
 
175
- async def process(self, event: Update, api: API) -> bool:
205
+ async def process(self, event: Update, api: API, context: Context) -> bool:
176
206
  return await process_inner(
177
207
  api,
178
208
  self.event_model_class.unwrap().from_update(
@@ -180,20 +210,21 @@ class BaseView(ABCView, typing.Generic[Event]):
180
210
  bound_api=api,
181
211
  ),
182
212
  event,
213
+ context,
183
214
  self.middlewares,
184
215
  self.handlers,
185
216
  self.return_manager,
186
217
  )
187
218
 
188
- def load(self, external: typing.Self) -> None:
189
- self.auto_rules.extend(external.auto_rules)
219
+ def load(self, external: typing.Self, /) -> None:
190
220
  self.handlers.extend(external.handlers)
191
221
  self.middlewares.extend(external.middlewares)
192
222
 
193
223
 
194
- class BaseStateView(ABCStateView[Event], BaseView[Event], ABC, typing.Generic[Event]):
224
+ class BaseStateView[Event: BaseCute](ABCStateView[Event], BaseView[Event], ABC):
225
+ @classmethod
195
226
  @abstractmethod
196
- def get_state_key(self, event: Event) -> int | None:
227
+ def get_state_key(cls, event: Event) -> int | None:
197
228
  pass
198
229
 
199
230
 
@@ -8,16 +8,26 @@ from telegrinder.bot.dispatch.view import (
8
8
  chat_member,
9
9
  inline_query,
10
10
  message,
11
+ pre_checkout_query,
11
12
  raw,
12
13
  )
13
14
  from telegrinder.bot.dispatch.view.abc import ABCEventRawView, ABCView
14
15
  from telegrinder.types.enums import UpdateType
15
16
 
16
17
  CallbackQueryView = typing.TypeVar(
17
- "CallbackQueryView", bound=ABCView, default=callback_query.CallbackQueryView
18
+ "CallbackQueryView",
19
+ bound=ABCView,
20
+ default=callback_query.CallbackQueryView,
21
+ )
22
+ PreCheckoutQueryView = typing.TypeVar(
23
+ "PreCheckoutQueryView",
24
+ bound=ABCView,
25
+ default=pre_checkout_query.PreCheckoutQueryView,
18
26
  )
19
27
  ChatJoinRequestView = typing.TypeVar(
20
- "ChatJoinRequestView", bound=ABCView, default=chat_join_request.ChatJoinRequestView
28
+ "ChatJoinRequestView",
29
+ bound=ABCView,
30
+ default=chat_join_request.ChatJoinRequestView,
21
31
  )
22
32
  ChatMemberView = typing.TypeVar("ChatMemberView", bound=ABCView, default=chat_member.ChatMemberView)
23
33
  InlineQueryView = typing.TypeVar("InlineQueryView", bound=ABCView, default=inline_query.InlineQueryView)
@@ -33,6 +43,7 @@ class ViewBox(
33
43
  ChatMemberView,
34
44
  InlineQueryView,
35
45
  MessageView,
46
+ PreCheckoutQueryView,
36
47
  RawEventView,
37
48
  ],
38
49
  ):
@@ -44,6 +55,7 @@ class ViewBox(
44
55
  message_view: dataclasses.InitVar[MessageView | None] = None
45
56
  business_message_view: dataclasses.InitVar[MessageView | None] = None
46
57
  channel_post_view: dataclasses.InitVar[MessageView | None] = None
58
+ pre_checkout_query_view: dataclasses.InitVar[PreCheckoutQueryView | None] = None
47
59
  edited_message_view: dataclasses.InitVar[MessageView | None] = None
48
60
  edited_business_message_view: dataclasses.InitVar[MessageView | None] = None
49
61
  edited_channel_post_view: dataclasses.InitVar[MessageView | None] = None
@@ -66,6 +78,7 @@ class ViewBox(
66
78
  edited_channel_post_view: MessageView | None = None,
67
79
  any_message_view: MessageView | None = None,
68
80
  chat_member_updated_view: ChatMemberView | None = None,
81
+ pre_checkout_query_view: PreCheckoutQueryView | None = None,
69
82
  raw_event_view: RawEventView | None = None,
70
83
  ) -> None:
71
84
  self.callback_query = typing.cast(
@@ -106,13 +119,16 @@ class ViewBox(
106
119
  )
107
120
  self.edited_business_message = typing.cast(
108
121
  MessageView,
109
- edited_business_message_view
110
- or message.MessageView(update_type=UpdateType.EDITED_BUSINESS_MESSAGE),
122
+ edited_business_message_view or message.MessageView(update_type=UpdateType.EDITED_BUSINESS_MESSAGE),
111
123
  )
112
124
  self.edited_channel_post = typing.cast(
113
125
  MessageView,
114
126
  edited_channel_post_view or message.MessageView(update_type=UpdateType.EDITED_CHANNEL_POST),
115
127
  )
128
+ self.pre_checkout_query = typing.cast(
129
+ PreCheckoutQueryView,
130
+ pre_checkout_query_view or pre_checkout_query.PreCheckoutQueryView(),
131
+ )
116
132
  self.any_message = typing.cast(MessageView, any_message_view or message.MessageView())
117
133
  self.chat_member_updated = typing.cast(
118
134
  ChatMemberView,
@@ -120,10 +136,5 @@ class ViewBox(
120
136
  )
121
137
  self.raw_event = typing.cast(RawEventView, raw_event_view or raw.RawEventView())
122
138
 
123
- def get_views(self) -> dict[str, ABCView]:
124
- """Get all views."""
125
-
126
- return {name: view for name, view in self.__dict__.items() if isinstance(view, ABCView)}
127
-
128
139
 
129
140
  __all__ = ("ViewBox",)
@@ -5,12 +5,11 @@ from telegrinder.bot.dispatch.view.base import BaseStateView
5
5
 
6
6
  class CallbackQueryView(BaseStateView[CallbackQueryCute]):
7
7
  def __init__(self) -> None:
8
- self.auto_rules = []
9
- self.handlers = []
10
- self.middlewares = []
8
+ super().__init__()
11
9
  self.return_manager = CallbackQueryReturnManager()
12
10
 
13
- def get_state_key(self, event: CallbackQueryCute) -> int | None:
11
+ @classmethod
12
+ def get_state_key(cls, event: CallbackQueryCute) -> int | None:
14
13
  return event.message_id.unwrap_or_none()
15
14
 
16
15
 
@@ -3,13 +3,8 @@ from telegrinder.bot.dispatch.view.base import BaseStateView
3
3
 
4
4
 
5
5
  class ChatJoinRequestView(BaseStateView[ChatJoinRequestCute]):
6
- def __init__(self) -> None:
7
- self.auto_rules = []
8
- self.handlers = []
9
- self.middlewares = []
10
- self.return_manager = None
11
-
12
- def get_state_key(self, event: ChatJoinRequestCute) -> int | None:
6
+ @classmethod
7
+ def get_state_key(cls, event: ChatJoinRequestCute) -> int | None:
13
8
  return event.chat_id
14
9
 
15
10
 
@@ -13,10 +13,7 @@ ChatMemberUpdateType: typing.TypeAlias = typing.Literal[
13
13
 
14
14
  class ChatMemberView(BaseStateView[ChatMemberUpdatedCute]):
15
15
  def __init__(self, *, update_type: ChatMemberUpdateType | None = None) -> None:
16
- self.auto_rules = []
17
- self.handlers = []
18
- self.middlewares = []
19
- self.return_manager = None
16
+ super().__init__()
20
17
  self.update_type = update_type
21
18
 
22
19
  def __repr__(self) -> str:
@@ -25,7 +22,8 @@ class ChatMemberView(BaseStateView[ChatMemberUpdatedCute]):
25
22
  "chat_member_updated" if self.update_type is None else self.update_type.value,
26
23
  )
27
24
 
28
- def get_state_key(self, event: ChatMemberUpdatedCute) -> int | None:
25
+ @classmethod
26
+ def get_state_key(cls, event: ChatMemberUpdatedCute) -> int | None:
29
27
  return event.chat_id
30
28
 
31
29
  async def check(self, event: Update) -> bool:
@@ -5,12 +5,11 @@ from telegrinder.bot.dispatch.view.base import BaseStateView
5
5
 
6
6
  class InlineQueryView(BaseStateView[InlineQueryCute]):
7
7
  def __init__(self) -> None:
8
- self.auto_rules = []
9
- self.handlers = []
10
- self.middlewares = []
8
+ super().__init__()
11
9
  self.return_manager = InlineQueryReturnManager()
12
10
 
13
- def get_state_key(self, event: InlineQueryCute) -> int | None:
11
+ @classmethod
12
+ def get_state_key(cls, event: InlineQueryCute) -> int | None:
14
13
  return event.from_user.id
15
14
 
16
15
 
@@ -18,10 +18,8 @@ MessageUpdateType: typing.TypeAlias = typing.Literal[
18
18
 
19
19
  class MessageView(BaseStateView[MessageCute]):
20
20
  def __init__(self, *, update_type: MessageUpdateType | None = None) -> None:
21
- self.auto_rules = []
22
- self.handlers = []
21
+ super().__init__()
23
22
  self.update_type = update_type
24
- self.middlewares = []
25
23
  self.return_manager = MessageReturnManager()
26
24
 
27
25
  def __repr__(self) -> str:
@@ -30,7 +28,8 @@ class MessageView(BaseStateView[MessageCute]):
30
28
  "any message update" if self.update_type is None else self.update_type.value,
31
29
  )
32
30
 
33
- def get_state_key(self, event: MessageCute) -> int | None:
31
+ @classmethod
32
+ def get_state_key(cls, event: MessageCute) -> int | None:
34
33
  return event.chat_id
35
34
 
36
35
  async def check(self, event: Update) -> bool:
@@ -0,0 +1,16 @@
1
+ from telegrinder.bot.cute_types.pre_checkout_query import PreCheckoutQueryCute
2
+ from telegrinder.bot.dispatch.return_manager.pre_checkout_query import PreCheckoutQueryManager
3
+ from telegrinder.bot.dispatch.view.base import BaseStateView
4
+
5
+
6
+ class PreCheckoutQueryView(BaseStateView[PreCheckoutQueryCute]):
7
+ def __init__(self) -> None:
8
+ super().__init__()
9
+ self.return_manager = PreCheckoutQueryManager()
10
+
11
+ @classmethod
12
+ def get_state_key(cls, event: PreCheckoutQueryCute) -> int | None:
13
+ return event.from_user.id
14
+
15
+
16
+ __all__ = ("PreCheckoutQueryView",)