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,157 +1,151 @@
1
- import inspect
2
- import typing
3
-
4
- from fntypes.option import Nothing, Option, Some
5
- from fntypes.result import Error, Ok
6
-
7
- from telegrinder.api.api import API
8
- from telegrinder.bot.cute_types.update import UpdateCute
9
- from telegrinder.bot.dispatch.context import Context
10
- from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
11
- from telegrinder.bot.dispatch.return_manager.abc import ABCReturnManager
12
- from telegrinder.model import Model
13
- from telegrinder.modules import logger
14
- from telegrinder.node.composer import CONTEXT_STORE_NODES_KEY, NodeScope, compose_nodes
15
- from telegrinder.tools.i18n.abc import I18nEnum
16
- from telegrinder.types.objects import Update
17
-
18
- if typing.TYPE_CHECKING:
19
- from telegrinder.bot.dispatch.handler.abc import ABCHandler
20
- from telegrinder.bot.rules.abc import ABCRule
21
- from telegrinder.bot.rules.adapter.abc import ABCAdapter
22
-
23
- T = typing.TypeVar("T")
24
- Event = typing.TypeVar("Event", bound=Model)
25
-
26
-
27
- async def run_adapter(
28
- adapter: "ABCAdapter[Update, T]",
29
- api: API,
30
- update: Update,
31
- context: Context,
32
- ) -> Option[T]:
33
- adapt_result = adapter.adapt(api, update, context)
34
- match await adapt_result if inspect.isawaitable(adapt_result) else adapt_result:
35
- case Ok(value):
36
- return Some(value)
37
- case Error(err):
38
- logger.debug("Adapter failed with error message: {!r}", str(err))
39
- return Nothing()
40
-
41
-
42
- async def process_inner(
43
- api: API,
44
- event: Event,
45
- raw_event: Update,
46
- middlewares: list[ABCMiddleware[Event]],
47
- handlers: list["ABCHandler[Event]"],
48
- return_manager: ABCReturnManager[Event] | None = None,
49
- ) -> bool:
50
- logger.debug("Processing {!r}...", event.__class__.__name__)
51
- ctx = Context(raw_update=raw_event)
52
- ctx[CONTEXT_STORE_NODES_KEY] = {} # For per-event shared nodes
53
-
54
- logger.debug("Run pre middlewares...")
55
- for middleware in middlewares:
56
- if middleware.adapter is not None:
57
- match await run_adapter(middleware.adapter, api, raw_event, ctx):
58
- case Some(val):
59
- event = val
60
- case Nothing():
61
- return False
62
-
63
- middleware_result = await middleware.pre(event, ctx)
64
- logger.debug("Middleware {!r} returned: {!r}", middleware.__class__.__qualname__, middleware_result)
65
- if middleware_result is False:
66
- return False
67
-
68
- found = False
69
- responses = []
70
- ctx_copy = ctx.copy()
71
-
72
- for handler in handlers:
73
- if await handler.check(api, raw_event, ctx):
74
- logger.debug("Handler {!r} matched, run...", handler)
75
- found = True
76
- response = await handler.run(api, event, ctx)
77
- logger.debug("Handler {!r} returned: {!r}", handler, response)
78
- responses.append(response)
79
- if return_manager is not None:
80
- await return_manager.run(response, event, ctx)
81
- if handler.is_blocking:
82
- break
83
-
84
- ctx = ctx_copy
85
-
86
- logger.debug("Run post middlewares...")
87
- for middleware in middlewares:
88
- logger.debug("Run post middleware {!r}", middleware.__class__.__qualname__)
89
- await middleware.post(event, responses, ctx)
90
-
91
- for session in ctx.get(CONTEXT_STORE_NODES_KEY, {}).values():
92
- await session.close(scopes=(NodeScope.PER_EVENT,))
93
-
94
- logger.debug(
95
- "{} handlers, returns {!r}",
96
- "No found" if not found else "Found",
97
- found,
98
- )
99
- return found
100
-
101
-
102
- async def check_rule(
103
- api: API,
104
- rule: "ABCRule",
105
- update: Update,
106
- ctx: Context,
107
- ) -> bool:
108
- """Checks requirements, adapts update.
109
- Returns check result."""
110
-
111
- # Running adapter
112
- match await run_adapter(rule.adapter, api, update, ctx):
113
- case Some(val):
114
- adapted_value = val
115
- case Nothing():
116
- return False
117
-
118
- # Preparing update
119
- if isinstance(adapted_val := ctx.get(rule.adapter.ADAPTED_VALUE_KEY or ""), UpdateCute):
120
- update = adapted_val
121
- elif isinstance(adapted_value, UpdateCute):
122
- update = adapted_value
123
- else:
124
- update = UpdateCute.from_update(update, bound_api=api)
125
-
126
- # Running subrules to fetch requirements
127
- ctx_copy = ctx.copy()
128
- for requirement in rule.requires:
129
- if not await check_rule(api, requirement, update, ctx_copy):
130
- return False
131
-
132
- # Translating translatable rules
133
- if I18nEnum.I18N in ctx:
134
- rule = await rule.translate(ctx[I18nEnum.I18N])
135
-
136
- ctx |= ctx_copy
137
-
138
- # Composing required nodes
139
- nodes = rule.required_nodes
140
- node_col = None
141
- if nodes:
142
- result = await compose_nodes(nodes, ctx, data={Update: update, API: api})
143
- if not result:
144
- return False
145
- node_col = result.value
146
-
147
- # Running check
148
- result = await rule.bounding_check(adapted_value, ctx, node_col=node_col)
149
-
150
- # Closing node sessions if there are any
151
- if node_col is not None:
152
- await node_col.close_all()
153
-
154
- return result
155
-
156
-
157
- __all__ = ("check_rule", "process_inner")
1
+ import typing
2
+
3
+ from fntypes.option import Nothing, Some
4
+
5
+ from telegrinder.api.api import API
6
+ from telegrinder.bot.cute_types.update import UpdateCute
7
+ from telegrinder.bot.dispatch.context import Context
8
+ from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware, run_middleware
9
+ from telegrinder.bot.dispatch.return_manager.abc import ABCReturnManager
10
+ from telegrinder.model import Model
11
+ from telegrinder.modules import logger
12
+ from telegrinder.node.composer import CONTEXT_STORE_NODES_KEY, NodeScope, compose_nodes
13
+ from telegrinder.tools.adapter.abc import run_adapter
14
+ from telegrinder.tools.i18n.abc import I18nEnum
15
+ from telegrinder.types.objects import Update
16
+
17
+ if typing.TYPE_CHECKING:
18
+ from telegrinder.bot.dispatch.handler.abc import ABCHandler
19
+ from telegrinder.bot.rules.abc import ABCRule
20
+
21
+
22
+ async def process_inner[Event: Model](
23
+ api: API,
24
+ event: Event,
25
+ raw_event: Update,
26
+ ctx: Context,
27
+ middlewares: list[ABCMiddleware[Event]],
28
+ handlers: list["ABCHandler[Event]"],
29
+ return_manager: ABCReturnManager[Event] | None = None,
30
+ ) -> bool:
31
+ logger.debug("Processing {!r}...", event.__class__.__name__)
32
+ ctx[CONTEXT_STORE_NODES_KEY] = {} # For per-event shared nodes
33
+
34
+ logger.debug("Run pre middlewares...")
35
+ for m in middlewares:
36
+ result = await run_middleware(m.pre, api, event, raw_event=raw_event, ctx=ctx, adapter=m.adapter)
37
+ logger.debug("Middleware {!r} returned: {!r}", m, result)
38
+ if result is False:
39
+ return False
40
+
41
+ found = False
42
+ responses = []
43
+ ctx_copy = ctx.copy()
44
+
45
+ for handler in handlers:
46
+ adapted_event = event
47
+
48
+ if await handler.check(api, raw_event, ctx):
49
+ if handler.adapter is not None:
50
+ match await run_adapter(handler.adapter, api, raw_event, ctx):
51
+ case Some(value):
52
+ adapted_event = value
53
+ case Nothing():
54
+ continue
55
+
56
+ found = True
57
+ logger.debug("Handler {!r} matched, run...", handler)
58
+ response = await handler.run(api, adapted_event, ctx)
59
+ logger.debug("Handler {!r} returned: {!r}", handler, response)
60
+ responses.append(response)
61
+
62
+ if return_manager is not None:
63
+ await return_manager.run(response, event, ctx)
64
+ if handler.final:
65
+ break
66
+
67
+ ctx = ctx_copy
68
+
69
+ logger.debug("Run post middlewares...")
70
+ ctx.set("responses", responses)
71
+
72
+ for m in middlewares:
73
+ await run_middleware(
74
+ m.post,
75
+ api,
76
+ event,
77
+ raw_event=raw_event,
78
+ ctx=ctx,
79
+ adapter=m.adapter,
80
+ )
81
+
82
+ for session in ctx.get(CONTEXT_STORE_NODES_KEY, {}).values():
83
+ await session.close(scopes=(NodeScope.PER_EVENT,))
84
+
85
+ logger.debug(
86
+ "{} handlers, returns {!r}",
87
+ "No found" if not found else "Found",
88
+ found,
89
+ )
90
+ return found
91
+
92
+
93
+ async def check_rule(
94
+ api: API,
95
+ rule: "ABCRule",
96
+ update: Update,
97
+ ctx: Context,
98
+ ) -> bool:
99
+ """Checks requirements, adapts update.
100
+ Returns check result.
101
+ """
102
+ update_cute = None if not isinstance(update, UpdateCute) else update
103
+
104
+ # Running adapter
105
+ match await run_adapter(rule.adapter, api, update, ctx):
106
+ case Some(val):
107
+ adapted_value = val
108
+ case Nothing():
109
+ return False
110
+
111
+ # Preparing update
112
+ if isinstance(adapted_value, UpdateCute):
113
+ update_cute = adapted_value
114
+ elif isinstance(adapted_val := ctx.get(rule.adapter.ADAPTED_VALUE_KEY or ""), UpdateCute):
115
+ update_cute = adapted_val
116
+ else:
117
+ update_cute = UpdateCute.from_update(update, bound_api=api)
118
+
119
+ # Running subrules to fetch requirements
120
+ ctx_copy = ctx.copy()
121
+ for requirement in rule.requires:
122
+ if not await check_rule(api, requirement, update_cute, ctx_copy):
123
+ return False
124
+
125
+ # Translating translatable rules
126
+ if I18nEnum.I18N in ctx:
127
+ rule = await rule.translate(ctx[I18nEnum.I18N])
128
+
129
+ ctx |= ctx_copy
130
+
131
+ # Composing required nodes
132
+ nodes = rule.required_nodes
133
+ node_col = None
134
+ if nodes:
135
+ result = await compose_nodes(nodes, ctx, data={Update: update, API: api})
136
+ if not result:
137
+ logger.debug(f"Cannot compose nodes for rule, error: {str(result.error)}")
138
+ return False
139
+ node_col = result.value
140
+
141
+ # Running check
142
+ result = await rule.bounding_check(ctx, adapted_value=adapted_value, node_col=node_col)
143
+
144
+ # Closing node sessions if there are any
145
+ if node_col is not None:
146
+ await node_col.close_all()
147
+
148
+ return result
149
+
150
+
151
+ __all__ = ("check_rule", "process_inner")
@@ -1,19 +1,21 @@
1
- from telegrinder.bot.dispatch.return_manager.abc import (
2
- ABCReturnManager,
3
- BaseReturnManager,
4
- Manager,
5
- register_manager,
6
- )
7
- from telegrinder.bot.dispatch.return_manager.callback_query import CallbackQueryReturnManager
8
- from telegrinder.bot.dispatch.return_manager.inline_query import InlineQueryReturnManager
9
- from telegrinder.bot.dispatch.return_manager.message import MessageReturnManager
10
-
11
- __all__ = (
1
+ from telegrinder.bot.dispatch.return_manager.abc import (
2
+ ABCReturnManager,
3
+ BaseReturnManager,
4
+ Manager,
5
+ register_manager,
6
+ )
7
+ from telegrinder.bot.dispatch.return_manager.callback_query import CallbackQueryReturnManager
8
+ from telegrinder.bot.dispatch.return_manager.inline_query import InlineQueryReturnManager
9
+ from telegrinder.bot.dispatch.return_manager.message import MessageReturnManager
10
+ from telegrinder.bot.dispatch.return_manager.pre_checkout_query import PreCheckoutQueryManager
11
+
12
+ __all__ = (
12
13
  "ABCReturnManager",
13
14
  "BaseReturnManager",
14
15
  "CallbackQueryReturnManager",
15
16
  "InlineQueryReturnManager",
16
17
  "Manager",
17
18
  "MessageReturnManager",
18
- "register_manager",
19
- )
19
+ "PreCheckoutQueryManager",
20
+ "register_manager",
21
+ )
@@ -1,112 +1,108 @@
1
- import dataclasses
2
- import types
3
- import typing
4
- from abc import ABC, abstractmethod
5
-
6
- from telegrinder.bot.dispatch.context import Context
7
- from telegrinder.model import Model
8
- from telegrinder.modules import logger
9
-
10
- T = typing.TypeVar("T")
11
- Event = typing.TypeVar("Event", bound=Model, contravariant=True)
12
-
13
-
14
- def get_union_types(t: types.UnionType) -> tuple[type, ...] | None:
15
- if type(t) in (types.UnionType, typing._UnionGenericAlias): # type: ignore
16
- return tuple(typing.get_origin(x) or x for x in typing.get_args(t))
17
- return None
18
-
19
-
20
- def register_manager(return_type: type[typing.Any] | types.UnionType):
21
- def wrapper(func: typing.Callable[..., typing.Awaitable[typing.Any]]):
22
- return Manager(get_union_types(return_type) or (return_type,), func) # type: ignore
23
-
24
- return wrapper
25
-
26
-
27
- @dataclasses.dataclass(frozen=True, slots=True)
28
- class Manager:
29
- types: tuple[type, ...]
30
- callback: typing.Callable[..., typing.Awaitable[typing.Any]]
31
-
32
- async def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> None:
33
- await self.callback(*args, **kwargs)
34
-
35
-
36
- class ABCReturnManager(ABC, typing.Generic[Event]):
37
- @abstractmethod
38
- async def run(self, response: typing.Any, event: Event, ctx: Context) -> None:
39
- pass
40
-
41
-
42
- class BaseReturnManager(ABCReturnManager[Event]):
43
- def __repr__(self) -> str:
44
- return "<{}: {}>".format(
45
- self.__class__.__name__,
46
- ", ".join(x.callback.__name__ + "=" + repr(x) for x in self.managers),
47
- )
48
-
49
- @property
50
- def managers(self) -> list[Manager]:
51
- managers = self.__dict__.get("managers")
52
- if managers is not None:
53
- return managers
54
- managers_lst = [
55
- manager
56
- for manager in (vars(BaseReturnManager) | vars(self.__class__)).values()
57
- if isinstance(manager, Manager)
58
- ]
59
- self.__dict__["managers"] = managers_lst
60
- return managers_lst
61
-
62
- @register_manager(Context)
63
- @staticmethod
64
- async def ctx_manager(value: Context, event: Event, ctx: Context) -> None:
65
- """Basic manager for returning context from handler."""
66
-
67
- ctx.update(value)
68
-
69
- async def run(self, response: typing.Any, event: Event, ctx: Context) -> None:
70
- logger.debug("Run return manager for response: {!r}", response)
71
- for manager in self.managers:
72
- if typing.Any in manager.types or any(type(response) is x for x in manager.types):
73
- logger.debug("Run manager {!r}...", manager.callback.__name__)
74
- await manager(response, event, ctx)
75
-
76
- @typing.overload
77
- def register_manager(
78
- self,
79
- return_type: type[T],
80
- ) -> typing.Callable[[typing.Callable[[T, Event, Context], typing.Awaitable[typing.Any]]], Manager]: ...
81
-
82
- @typing.overload
83
- def register_manager(
84
- self,
85
- return_type: tuple[type[T], ...],
86
- ) -> typing.Callable[
87
- [typing.Callable[[tuple[T, ...], Event, Context], typing.Awaitable[typing.Any]]],
88
- Manager,
89
- ]: ...
90
-
91
- def register_manager(
92
- self,
93
- return_type: type[T] | tuple[type[T], ...],
94
- ) -> typing.Callable[
95
- [typing.Callable[[T | tuple[T, ...], Event, Context], typing.Awaitable[typing.Any]]],
96
- Manager,
97
- ]:
98
- def wrapper(func: typing.Callable[[T, Event, Context], typing.Awaitable]) -> Manager:
99
- manager = Manager(get_union_types(return_type) or (return_type,), func) # type: ignore
100
- self.managers.append(manager)
101
- return manager
102
-
103
- return wrapper
104
-
105
-
106
- __all__ = (
1
+ import dataclasses
2
+ import types
3
+ import typing
4
+ from abc import ABC, abstractmethod
5
+
6
+ from telegrinder.bot.dispatch.context import Context
7
+ from telegrinder.model import Model
8
+ from telegrinder.modules import logger
9
+
10
+
11
+ def get_union_types(t: types.UnionType | typing.Any) -> tuple[type[typing.Any], ...] | None:
12
+ if type(t) in (types.UnionType, typing._UnionGenericAlias): # type: ignore
13
+ return tuple(typing.get_origin(x) or x for x in typing.get_args(t))
14
+ return None
15
+
16
+
17
+ def register_manager(return_type: type[typing.Any] | types.UnionType):
18
+ def wrapper(func: typing.Callable[..., typing.Awaitable[typing.Any]]):
19
+ return Manager(get_union_types(return_type) or (return_type,), func) # type: ignore
20
+
21
+ return wrapper
22
+
23
+
24
+ @dataclasses.dataclass(frozen=True, slots=True)
25
+ class Manager:
26
+ types: tuple[type, ...]
27
+ callback: typing.Callable[..., typing.Awaitable[typing.Any]]
28
+
29
+ async def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> None:
30
+ await self.callback(*args, **kwargs)
31
+
32
+
33
+ class ABCReturnManager[Event: Model](ABC):
34
+ @abstractmethod
35
+ async def run(self, response: typing.Any, event: Event, ctx: Context) -> None:
36
+ pass
37
+
38
+
39
+ class BaseReturnManager[Event: Model](ABCReturnManager[Event]):
40
+ def __repr__(self) -> str:
41
+ return "<{}: {}>".format(
42
+ self.__class__.__name__,
43
+ ", ".join(x.callback.__name__ + "=" + repr(x) for x in self.managers),
44
+ )
45
+
46
+ @property
47
+ def managers(self) -> list[Manager]:
48
+ managers = self.__dict__.get("managers")
49
+ if managers is not None:
50
+ return managers
51
+ managers_lst = [
52
+ manager
53
+ for manager in (vars(BaseReturnManager) | vars(self.__class__)).values()
54
+ if isinstance(manager, Manager)
55
+ ]
56
+ self.__dict__["managers"] = managers_lst
57
+ return managers_lst
58
+
59
+ @register_manager(Context)
60
+ @staticmethod
61
+ async def ctx_manager(value: Context, event: Event, ctx: Context) -> None:
62
+ """Basic manager for returning context from handler."""
63
+ ctx.update(value)
64
+
65
+ async def run(self, response: typing.Any, event: Event, ctx: Context) -> None:
66
+ logger.debug("Run return manager for response: {!r}", response)
67
+ for manager in self.managers:
68
+ if typing.Any in manager.types or any(type(response) is x for x in manager.types):
69
+ logger.debug("Run manager {!r}...", manager.callback.__name__)
70
+ await manager(response, event, ctx)
71
+
72
+ @typing.overload
73
+ def register_manager[T](
74
+ self,
75
+ return_type: type[T],
76
+ ) -> typing.Callable[[typing.Callable[[T, Event, Context], typing.Awaitable[typing.Any]]], Manager]: ...
77
+
78
+ @typing.overload
79
+ def register_manager[T](
80
+ self,
81
+ return_type: tuple[type[T], ...],
82
+ ) -> typing.Callable[
83
+ [typing.Callable[[tuple[T, ...], Event, Context], typing.Awaitable[typing.Any]]],
84
+ Manager,
85
+ ]: ...
86
+
87
+ def register_manager[T](
88
+ self,
89
+ return_type: type[T] | tuple[type[T], ...],
90
+ ) -> typing.Callable[
91
+ [typing.Callable[[T | tuple[T, ...], Event, Context], typing.Awaitable[typing.Any]]],
92
+ Manager,
93
+ ]:
94
+ def wrapper(func: typing.Callable[[T, Event, Context], typing.Awaitable]) -> Manager:
95
+ manager = Manager(get_union_types(return_type) or (return_type,), func) # type: ignore
96
+ self.managers.append(manager)
97
+ return manager
98
+
99
+ return wrapper
100
+
101
+
102
+ __all__ = (
107
103
  "ABCReturnManager",
108
104
  "BaseReturnManager",
109
105
  "Manager",
110
106
  "get_union_types",
111
- "register_manager",
112
- )
107
+ "register_manager",
108
+ )
@@ -1,20 +1,20 @@
1
- import typing
2
-
3
- from telegrinder.bot.cute_types.callback_query import CallbackQueryCute
4
- from telegrinder.bot.dispatch.context import Context
5
- from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
-
7
-
8
- class CallbackQueryReturnManager(BaseReturnManager[CallbackQueryCute]):
9
- @register_manager(str)
10
- @staticmethod
11
- async def str_manager(value: str, event: CallbackQueryCute, 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: CallbackQueryCute, ctx: Context) -> None:
17
- await event.answer(**value)
18
-
19
-
20
- __all__ = ("CallbackQueryReturnManager",)
1
+ import typing
2
+
3
+ from telegrinder.bot.cute_types.callback_query import CallbackQueryCute
4
+ from telegrinder.bot.dispatch.context import Context
5
+ from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
+
7
+
8
+ class CallbackQueryReturnManager(BaseReturnManager[CallbackQueryCute]):
9
+ @register_manager(str)
10
+ @staticmethod
11
+ async def str_manager(value: str, event: CallbackQueryCute, 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: CallbackQueryCute, ctx: Context) -> None:
17
+ await event.answer(**value)
18
+
19
+
20
+ __all__ = ("CallbackQueryReturnManager",)
@@ -1,15 +1,15 @@
1
- import typing
2
-
3
- from telegrinder.bot.cute_types.inline_query import InlineQueryCute
4
- from telegrinder.bot.dispatch.context import Context
5
- from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
-
7
-
8
- class InlineQueryReturnManager(BaseReturnManager[InlineQueryCute]):
9
- @register_manager(dict[str, typing.Any])
10
- @staticmethod
11
- async def dict_manager(value: dict[str, typing.Any], event: InlineQueryCute, ctx: Context) -> None:
12
- await event.answer(**value)
13
-
14
-
15
- __all__ = ("InlineQueryReturnManager",)
1
+ import typing
2
+
3
+ from telegrinder.bot.cute_types.inline_query import InlineQueryCute
4
+ from telegrinder.bot.dispatch.context import Context
5
+ from telegrinder.bot.dispatch.return_manager.abc import BaseReturnManager, register_manager
6
+
7
+
8
+ class InlineQueryReturnManager(BaseReturnManager[InlineQueryCute]):
9
+ @register_manager(dict[str, typing.Any])
10
+ @staticmethod
11
+ async def dict_manager(value: dict[str, typing.Any], event: InlineQueryCute, ctx: Context) -> None:
12
+ await event.answer(**value)
13
+
14
+
15
+ __all__ = ("InlineQueryReturnManager",)