telegrinder 0.1.dev163__py3-none-any.whl → 0.1.dev164__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 (29) hide show
  1. telegrinder/bot/dispatch/abc.py +1 -1
  2. telegrinder/bot/dispatch/composition.py +15 -1
  3. telegrinder/bot/dispatch/context.py +8 -0
  4. telegrinder/bot/dispatch/dispatch.py +65 -28
  5. telegrinder/bot/dispatch/handler/abc.py +2 -4
  6. telegrinder/bot/dispatch/handler/func.py +31 -25
  7. telegrinder/bot/dispatch/handler/message_reply.py +21 -9
  8. telegrinder/bot/dispatch/middleware/abc.py +1 -1
  9. telegrinder/bot/dispatch/process.py +5 -3
  10. telegrinder/bot/dispatch/return_manager/callback_query.py +3 -1
  11. telegrinder/bot/dispatch/return_manager/inline_query.py +3 -1
  12. telegrinder/bot/dispatch/return_manager/message.py +9 -1
  13. telegrinder/bot/dispatch/view/abc.py +31 -5
  14. telegrinder/bot/dispatch/view/box.py +2 -1
  15. telegrinder/bot/dispatch/view/inline_query.py +1 -1
  16. telegrinder/bot/dispatch/view/message.py +1 -1
  17. telegrinder/bot/dispatch/waiter_machine/machine.py +14 -8
  18. telegrinder/bot/dispatch/waiter_machine/middleware.py +9 -7
  19. telegrinder/bot/dispatch/waiter_machine/short_state.py +17 -18
  20. telegrinder/bot/rules/text.py +1 -1
  21. telegrinder/bot/scenario/checkbox.py +16 -0
  22. telegrinder/node/base.py +1 -1
  23. telegrinder/node/composer.py +1 -1
  24. telegrinder/tools/error_handler/abc.py +3 -3
  25. telegrinder/tools/error_handler/error_handler.py +21 -21
  26. {telegrinder-0.1.dev163.dist-info → telegrinder-0.1.dev164.dist-info}/METADATA +1 -1
  27. {telegrinder-0.1.dev163.dist-info → telegrinder-0.1.dev164.dist-info}/RECORD +29 -29
  28. {telegrinder-0.1.dev163.dist-info → telegrinder-0.1.dev164.dist-info}/WHEEL +1 -1
  29. {telegrinder-0.1.dev163.dist-info → telegrinder-0.1.dev164.dist-info}/LICENSE +0 -0
@@ -14,7 +14,7 @@ class ABCDispatch(ABC):
14
14
  pass
15
15
 
16
16
  @abstractmethod
17
- def load(self, external: typing.Self):
17
+ def load(self, external: typing.Self) -> None:
18
18
  pass
19
19
 
20
20
 
@@ -27,12 +27,20 @@ class Composition:
27
27
  }
28
28
  self.is_blocking = is_blocking
29
29
 
30
+ def __repr__(self) -> str:
31
+ return "<{}: for function={!r} with nodes={}>".format(
32
+ ("blocking " if self.is_blocking else "")
33
+ + self.__class__.__name__,
34
+ self.func.__name__,
35
+ self.nodes,
36
+ )
37
+
30
38
  async def compose_nodes(self, update: UpdateCute) -> NodeCollection | None:
31
39
  nodes: dict[str, NodeSession] = {}
32
40
  for name, node_t in self.nodes.items():
33
41
  try:
34
42
  nodes[name] = await compose_node(node_t, update)
35
- except ComposeError as err:
43
+ except ComposeError:
36
44
  await NodeCollection(nodes).close_all()
37
45
  return None
38
46
  return NodeCollection(nodes)
@@ -45,6 +53,12 @@ class CompositionDispatch(ABCDispatch):
45
53
  def __init__(self) -> None:
46
54
  self.compositions: list[Composition] = []
47
55
 
56
+ def __repr__(self) -> str:
57
+ return "<{}: with compositions={!r}>".format(
58
+ self.__class__.__name__,
59
+ self.compositions,
60
+ )
61
+
48
62
  async def feed(self, event: Update, api: ABCAPI) -> bool:
49
63
  update = UpdateCute(**event.to_dict(), api=api)
50
64
  is_found = False
@@ -1,5 +1,6 @@
1
1
  import enum
2
2
  import typing
3
+ from reprlib import recursive_repr
3
4
 
4
5
  from telegrinder.types import Update
5
6
 
@@ -33,6 +34,13 @@ class Context(dict[str, AnyValue]):
33
34
  delattr(self.__class__, k)
34
35
  dict.__init__(self, **defaults | kwargs)
35
36
 
37
+ @recursive_repr()
38
+ def __repr__(self) -> str:
39
+ return "{}({})".format(
40
+ self.__class__.__name__,
41
+ ", ".join(f"{k}={v!r}" for k, v in self.items())
42
+ )
43
+
36
44
  def __setitem__(self, __key: Key, __value: AnyValue) -> None:
37
45
  dict.__setitem__(self, self.key_to_str(__key), __value)
38
46
 
@@ -6,8 +6,10 @@ from vbml.patcher import Patcher
6
6
 
7
7
  from telegrinder.api.abc import ABCAPI
8
8
  from telegrinder.bot.cute_types.base import BaseCute
9
+ from telegrinder.bot.dispatch.context import Context
9
10
  from telegrinder.bot.rules import ABCRule
10
11
  from telegrinder.modules import logger
12
+ from telegrinder.tools.error_handler.error_handler import ErrorHandler
11
13
  from telegrinder.tools.global_context import TelegrinderCtx
12
14
  from telegrinder.types import Update
13
15
 
@@ -19,6 +21,7 @@ from .view.box import CallbackQueryViewT, InlineQueryViewT, MessageViewT, ViewBo
19
21
  T = typing.TypeVar("T")
20
22
  R = typing.TypeVar("R")
21
23
  P = typing.ParamSpec("P")
24
+ Handler = typing.Callable[typing.Concatenate[T, ...], typing.Coroutine[typing.Any, typing.Any, typing.Any]]
22
25
  Event = typing.TypeVar("Event", bound=BaseCute)
23
26
 
24
27
  DEFAULT_DATACLASS: typing.Final[type[Update]] = Update
@@ -47,17 +50,74 @@ class Dispatch(
47
50
  def patcher(self) -> Patcher:
48
51
  """Alias `patcher` to get `vbml.Patcher` from the global context"""
49
52
  return self.global_context.vbml_patcher
53
+
54
+ @typing.overload
55
+ def handle(
56
+ self,
57
+ *rules: ABCRule[Event],
58
+ ) -> typing.Callable[[Handler[T]], FuncHandler[Event, Handler[T], ErrorHandler]]:
59
+ ...
50
60
 
61
+ @typing.overload
51
62
  def handle(
52
63
  self,
53
- *rules: ABCRule,
64
+ *rules: ABCRule[Event],
65
+ is_blocking: bool = True,
66
+ ) -> typing.Callable[[Handler[T]], FuncHandler[Event, Handler[T], ErrorHandler]]:
67
+ ...
68
+
69
+ @typing.overload
70
+ def handle(
71
+ self,
72
+ *rules: ABCRule[Event],
73
+ dataclass: type[T],
74
+ is_blocking: bool = True,
75
+ ) -> typing.Callable[[Handler[T]], FuncHandler[Event, Handler[T], ErrorHandler]]:
76
+ ...
77
+
78
+ @typing.overload
79
+ def handle( # type: ignore
80
+ self,
81
+ *rules: ABCRule[Event],
82
+ error_handler: ErrorHandlerT,
83
+ is_blocking: bool = True,
84
+ ) -> typing.Callable[[Handler[T]], FuncHandler[Event, Handler[T], ErrorHandlerT]]:
85
+ ...
86
+
87
+ @typing.overload
88
+ def handle(
89
+ self,
90
+ *rules: ABCRule[Event],
91
+ dataclass: type[T],
92
+ error_handler: ErrorHandlerT,
93
+ is_blocking: bool = True,
94
+ ) -> typing.Callable[[Handler[T]], FuncHandler[Event, Handler[T], ErrorHandlerT]]:
95
+ ...
96
+
97
+ @typing.overload
98
+ def handle(
99
+ self,
100
+ *rules: ABCRule[Event],
101
+ dataclass: type[T] = DEFAULT_DATACLASS,
102
+ error_handler: typing.Literal[None] = None,
54
103
  is_blocking: bool = True,
104
+ ) -> typing.Callable[[Handler[T]], FuncHandler[Event, Handler[T], ErrorHandler]]:
105
+ ...
106
+
107
+ def handle( # type: ignore
108
+ self,
109
+ *rules: ABCRule,
55
110
  dataclass: type[typing.Any] = DEFAULT_DATACLASS,
56
111
  error_handler: ErrorHandlerT | None = None,
112
+ is_blocking: bool = True,
57
113
  ):
58
114
  def wrapper(func: typing.Callable):
59
115
  handler = FuncHandler(
60
- func, list(rules), is_blocking, dataclass, error_handler,
116
+ func,
117
+ list(rules),
118
+ is_blocking=is_blocking,
119
+ dataclass=dataclass,
120
+ error_handler=error_handler or ErrorHandler(),
61
121
  )
62
122
  self.default_handlers.append(handler)
63
123
  return handler
@@ -77,11 +137,12 @@ class Dispatch(
77
137
  return True
78
138
 
79
139
  loop = asyncio.get_running_loop()
140
+ ctx = Context()
80
141
  found = False
81
142
  for handler in self.default_handlers:
82
- if await handler.check(api, event):
143
+ if await handler.check(api, event, ctx):
83
144
  found = True
84
- loop.create_task(handler.run(event))
145
+ loop.create_task(handler.run(event, ctx))
85
146
  if handler.is_blocking:
86
147
  break
87
148
  return found
@@ -94,30 +155,6 @@ class Dispatch(
94
155
  ), f"View {name!r} is undefined in external dispatch."
95
156
  view.load(view_external[name])
96
157
  setattr(external, name, view)
97
-
98
- @classmethod
99
- def to_handler(
100
- cls,
101
- *rules: ABCRule[BaseCute],
102
- is_blocking: bool = True,
103
- error_handler: ErrorHandlerT | None = None,
104
- ):
105
- def wrapper(
106
- func: typing.Callable[typing.Concatenate[T, P], typing.Awaitable[R]]
107
- ) -> FuncHandler[
108
- BaseCute,
109
- typing.Callable[typing.Concatenate[T, P], typing.Awaitable[R]],
110
- ErrorHandlerT,
111
- ]:
112
- return FuncHandler(
113
- func,
114
- list(rules),
115
- is_blocking=is_blocking,
116
- dataclass=None,
117
- error_handler=error_handler,
118
- )
119
-
120
- return wrapper
121
158
 
122
159
 
123
160
  __all__ = ("Dispatch",)
@@ -11,15 +11,13 @@ T = typing.TypeVar("T", bound=Model)
11
11
 
12
12
  class ABCHandler(ABC, typing.Generic[T]):
13
13
  is_blocking: bool
14
- ctx: Context
15
14
 
16
15
  @abstractmethod
17
- async def run(self, event: T) -> typing.Any:
16
+ async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
18
17
  pass
19
18
 
20
19
  @abstractmethod
21
- async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
20
+ async def run(self, event: T, ctx: Context) -> typing.Any:
22
21
  pass
23
22
 
24
-
25
23
  __all__ = ("ABCHandler",)
@@ -1,3 +1,5 @@
1
+ import dataclasses
2
+
1
3
  import typing_extensions as typing
2
4
 
3
5
  from telegrinder.api.abc import ABCAPI
@@ -13,46 +15,50 @@ from .abc import ABCHandler
13
15
  if typing.TYPE_CHECKING:
14
16
  from telegrinder.bot.rules import ABCRule
15
17
 
16
- F = typing.TypeVar("F", bound=typing.Callable[typing.Concatenate[typing.Any, ...], typing.Awaitable])
18
+ F = typing.TypeVar("F", bound=typing.Callable[typing.Concatenate[typing.Any, ...], typing.Awaitable[typing.Any]])
17
19
  EventT = typing.TypeVar("EventT", bound=BaseCute)
18
20
  ErrorHandlerT = typing.TypeVar("ErrorHandlerT", bound=ABCErrorHandler, default=ErrorHandler)
19
21
 
20
22
 
23
+ @dataclasses.dataclass(repr=False)
21
24
  class FuncHandler(ABCHandler[EventT], typing.Generic[EventT, F, ErrorHandlerT]):
22
- def __init__(
23
- self,
24
- func: F,
25
- rules: list["ABCRule[EventT]"],
26
- is_blocking: bool = True,
27
- dataclass: type[typing.Any] | None = dict,
28
- error_handler: ErrorHandlerT | None = None,
29
- ):
30
- self.func = func
31
- self.is_blocking = is_blocking
32
- self.rules = rules
33
- self.dataclass = dataclass
34
- self.error_handler: ErrorHandlerT = error_handler or ErrorHandler() # type: ignore
35
- self.ctx = Context()
36
-
37
- @property
38
- def on_error(self):
39
- return self.error_handler.register_catcher
25
+ func: F
26
+ rules: list["ABCRule[EventT]"]
27
+ _: dataclasses.KW_ONLY
28
+ is_blocking: bool = dataclasses.field(default=True)
29
+ dataclass: type[typing.Any] | None = dataclasses.field(default=dict)
30
+ error_handler: ErrorHandlerT = dataclasses.field(
31
+ default_factory=lambda: typing.cast(ErrorHandlerT, ErrorHandler()),
32
+ )
33
+ preset_context: Context = dataclasses.field(default_factory=lambda: Context())
34
+
35
+ def __repr__(self) -> str:
36
+ return "<{}: {}={!r} with rules={!r}, dataclass={!r}, error_handler={!r}>".format(
37
+ self.__class__.__name__,
38
+ "blocking function" if self.is_blocking else "function",
39
+ self.func.__name__,
40
+ self.rules,
41
+ self.dataclass,
42
+ self.error_handler,
43
+ )
40
44
 
41
45
  async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
42
46
  ctx = ctx or Context()
43
- preset_ctx = self.ctx.copy()
44
- self.ctx |= ctx
47
+ temp_ctx = ctx.copy()
48
+ temp_ctx |= self.preset_context
49
+
45
50
  for rule in self.rules:
46
- if not await check_rule(api, rule, event, self.ctx):
51
+ if not await check_rule(api, rule, event, temp_ctx):
47
52
  logger.debug("Rule {!r} failed!", rule)
48
- self.ctx = preset_ctx
49
53
  return False
54
+
55
+ ctx |= temp_ctx
50
56
  return True
51
57
 
52
- async def run(self, event: EventT) -> typing.Any:
58
+ async def run(self, event: EventT, ctx: Context) -> typing.Any:
53
59
  if self.dataclass is not None:
54
60
  event = self.dataclass(**event.to_dict())
55
- return (await self.error_handler.run(self.func, event, event.api, self.ctx)).unwrap()
61
+ return (await self.error_handler.run(self.func, event, event.api, ctx)).unwrap()
56
62
 
57
63
 
58
64
  __all__ = ("FuncHandler",)
@@ -7,7 +7,7 @@ from telegrinder.bot.dispatch.process import check_rule
7
7
  from telegrinder.bot.rules.abc import ABCRule
8
8
  from telegrinder.modules import logger
9
9
  from telegrinder.msgspec_utils import Nothing
10
- from telegrinder.types.objects import Update
10
+ from telegrinder.types.objects import ReplyParameters, Update
11
11
 
12
12
  from .abc import ABCHandler
13
13
 
@@ -17,29 +17,41 @@ class MessageReplyHandler(ABCHandler[MessageCute]):
17
17
  self,
18
18
  text: str,
19
19
  *rules: ABCRule[MessageCute],
20
- as_reply: bool = False,
21
20
  is_blocking: bool = True,
22
- ):
21
+ as_reply: bool = False,
22
+ ) -> None:
23
23
  self.text = text
24
24
  self.rules = list(rules)
25
25
  self.as_reply = as_reply
26
26
  self.is_blocking = is_blocking
27
- self.dataclass = MessageCute
28
- self.ctx = Context()
27
+ self.preset_context = Context()
28
+
29
+ def __repr__(self) -> str:
30
+ return "<{}: with rules={!r}, {}: {!r}>".format(
31
+ ("blocking " if self.is_blocking else "")
32
+ + self.__class__.__name__,
33
+ self.rules,
34
+ "answer text as reply" if self.as_reply else "answer text",
35
+ self.text,
36
+ )
29
37
 
30
38
  async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
31
39
  ctx = ctx or Context()
32
- self.ctx |= ctx
40
+ temp_ctx = ctx.copy()
41
+ temp_ctx |= self.preset_context
42
+
33
43
  for rule in self.rules:
34
- if not await check_rule(api, rule, event, self.ctx):
44
+ if not await check_rule(api, rule, event, ctx):
35
45
  logger.debug("Rule {!r} failed!", rule)
36
46
  return False
47
+
48
+ ctx |= temp_ctx
37
49
  return True
38
50
 
39
- async def run(self, event: MessageCute) -> typing.Any:
51
+ async def run(self, event: MessageCute, _: Context) -> typing.Any:
40
52
  await event.answer(
41
53
  text=self.text,
42
- reply_to_message_id=(event.message_id if self.as_reply else Nothing),
54
+ reply_parameters=ReplyParameters(event.message_id) if self.as_reply else None,
43
55
  )
44
56
 
45
57
 
@@ -11,7 +11,7 @@ class ABCMiddleware(ABC, typing.Generic[T]):
11
11
  async def pre(self, event: T, ctx: Context) -> bool:
12
12
  ...
13
13
 
14
- async def post(self, event: T, responses: list[typing.Any], ctx: Context):
14
+ async def post(self, event: T, responses: list[typing.Any], ctx: Context) -> None:
15
15
  ...
16
16
 
17
17
 
@@ -17,7 +17,7 @@ if typing.TYPE_CHECKING:
17
17
  from telegrinder.bot.rules.abc import ABCRule
18
18
 
19
19
  T = typing.TypeVar("T", bound=BaseCute)
20
- _ = typing.Any
20
+ _: typing.TypeAlias = typing.Any
21
21
 
22
22
 
23
23
  async def process_inner(
@@ -36,15 +36,17 @@ async def process_inner(
36
36
 
37
37
  found = False
38
38
  responses = []
39
+ ctx_copy = ctx.copy()
40
+
39
41
  for handler in handlers:
40
42
  if await handler.check(event.api, raw_event, ctx):
41
43
  found = True
42
- handler.ctx |= ctx
43
- response = await handler.run(event)
44
+ response = await handler.run(event, ctx)
44
45
  responses.append(response)
45
46
  await return_manager.run(response, event, ctx)
46
47
  if handler.is_blocking:
47
48
  break
49
+ ctx = ctx_copy
48
50
 
49
51
  for middleware in middlewares:
50
52
  await middleware.post(event, responses, ctx)
@@ -1,3 +1,5 @@
1
+ import typing
2
+
1
3
  from telegrinder.bot.cute_types import CallbackQueryCute
2
4
  from telegrinder.bot.dispatch.context import Context
3
5
 
@@ -12,7 +14,7 @@ class CallbackQueryReturnManager(BaseReturnManager[CallbackQueryCute]):
12
14
 
13
15
  @register_manager(dict)
14
16
  @staticmethod
15
- async def dict_manager(value: dict, event: CallbackQueryCute, ctx: Context) -> None:
17
+ async def dict_manager(value: dict[str, typing.Any], event: CallbackQueryCute, ctx: Context) -> None:
16
18
  await event.answer(**value)
17
19
 
18
20
 
@@ -1,3 +1,5 @@
1
+ import typing
2
+
1
3
  from telegrinder.bot.cute_types import InlineQueryCute
2
4
  from telegrinder.bot.dispatch.context import Context
3
5
 
@@ -7,7 +9,7 @@ from .abc import BaseReturnManager, register_manager
7
9
  class InlineQueryReturnManager(BaseReturnManager[InlineQueryCute]):
8
10
  @register_manager(dict)
9
11
  @staticmethod
10
- async def dict_manager(value: dict, event: InlineQueryCute, ctx: Context) -> None:
12
+ async def dict_manager(value: dict[str, typing.Any], event: InlineQueryCute, ctx: Context) -> None:
11
13
  await event.answer(**value)
12
14
 
13
15
 
@@ -1,5 +1,8 @@
1
+ import typing
2
+
1
3
  from telegrinder.bot.cute_types import MessageCute
2
4
  from telegrinder.bot.dispatch.context import Context
5
+ from telegrinder.tools.formatting import HTMLFormatter
3
6
 
4
7
  from .abc import BaseReturnManager, register_manager
5
8
 
@@ -18,8 +21,13 @@ class MessageReturnManager(BaseReturnManager[MessageCute]):
18
21
 
19
22
  @register_manager(dict)
20
23
  @staticmethod
21
- async def dict_manager(value: dict, event: MessageCute, ctx: Context) -> None:
24
+ async def dict_manager(value: dict[str, typing.Any], event: MessageCute, ctx: Context) -> None:
22
25
  await event.answer(**value)
23
26
 
27
+ @register_manager(HTMLFormatter)
28
+ @staticmethod
29
+ async def htmlformatter_manager(value: HTMLFormatter, event: MessageCute, ctx: Context) -> None:
30
+ await event.answer(value, parse_mode=HTMLFormatter.PARSE_MODE)
31
+
24
32
 
25
33
  __all__ = ("MessageReturnManager",)
@@ -6,16 +6,18 @@ from fntypes.co import Nothing, Some
6
6
  from telegrinder.api.abc import ABCAPI
7
7
  from telegrinder.bot.cute_types.base import BaseCute
8
8
  from telegrinder.bot.dispatch.handler.abc import ABCHandler
9
- from telegrinder.bot.dispatch.handler.func import ErrorHandlerT, FuncHandler
9
+ from telegrinder.bot.dispatch.handler.func import FuncHandler
10
10
  from telegrinder.bot.dispatch.middleware.abc import ABCMiddleware
11
11
  from telegrinder.bot.dispatch.process import process_inner
12
12
  from telegrinder.bot.dispatch.return_manager.abc import ABCReturnManager
13
13
  from telegrinder.bot.rules.abc import ABCRule
14
14
  from telegrinder.model import Model
15
15
  from telegrinder.msgspec_utils import Option
16
+ from telegrinder.tools.error_handler.error_handler import ABCErrorHandler, ErrorHandler
16
17
  from telegrinder.types.objects import Update
17
18
 
18
19
  EventType = typing.TypeVar("EventType", bound=BaseCute)
20
+ ErrorHandlerT = typing.TypeVar("ErrorHandlerT", bound=ABCErrorHandler)
19
21
  MiddlewareT = typing.TypeVar("MiddlewareT", bound=ABCMiddleware)
20
22
 
21
23
  FuncType: typing.TypeAlias = typing.Callable[
@@ -74,20 +76,44 @@ class BaseView(ABCView, typing.Generic[EventType]):
74
76
  return getattr(update, update_type.value)
75
77
  case _:
76
78
  return Nothing()
79
+
80
+ @typing.overload
81
+ def __call__(
82
+ self,
83
+ *rules: ABCRule[EventType],
84
+ ) -> typing.Callable[[FuncType[EventType]], FuncHandler[EventType, FuncType[EventType], ErrorHandler]]:
85
+ ...
86
+
87
+ @typing.overload
88
+ def __call__(
89
+ self,
90
+ *rules: ABCRule[EventType],
91
+ error_handler: ErrorHandlerT,
92
+ is_blocking: bool = True,
93
+ ) -> typing.Callable[[FuncType[EventType]], FuncHandler[EventType, FuncType[EventType], ErrorHandlerT]]:
94
+ ...
77
95
 
96
+ @typing.overload
78
97
  def __call__(
79
98
  self,
80
99
  *rules: ABCRule[EventType],
100
+ error_handler: typing.Literal[None] = None,
101
+ is_blocking: bool = True,
102
+ ) -> typing.Callable[[FuncType[EventType]], FuncHandler[EventType, FuncType[EventType], ErrorHandler]]:
103
+ ...
104
+
105
+ def __call__( # type: ignore
106
+ self,
107
+ *rules: ABCRule[EventType],
108
+ error_handler: ABCErrorHandler | None = None,
81
109
  is_blocking: bool = True,
82
- error_handler: ErrorHandlerT | None = None,
83
110
  ):
84
111
  def wrapper(func: FuncType[EventType]):
85
- func_handler = FuncHandler[EventType, FuncType[EventType], ErrorHandlerT](
112
+ func_handler = FuncHandler(
86
113
  func,
87
114
  [*self.auto_rules, *rules],
88
- is_blocking,
115
+ is_blocking=is_blocking,
89
116
  dataclass=None,
90
- error_handler=error_handler,
91
117
  )
92
118
  self.handlers.append(func_handler)
93
119
  return func_handler
@@ -30,7 +30,8 @@ class ViewBox(typing.Generic[CallbackQueryViewT, InlineQueryViewT, MessageViewT]
30
30
 
31
31
  def get_views(self) -> dict[str, ABCView]:
32
32
  return {
33
- name: view for name, view in self.__dict__.items()
33
+ name: view
34
+ for name, view in self.__dict__.items()
34
35
  if isinstance(view, ABCView)
35
36
  }
36
37
 
@@ -12,7 +12,7 @@ class InlineQueryView(BaseStateView[InlineQueryCute]):
12
12
  self.return_manager = InlineQueryReturnManager()
13
13
 
14
14
  def get_state_key(self, event: InlineQueryCute) -> int | None:
15
- return event.from_.id
15
+ return event.from_user.id
16
16
 
17
17
 
18
18
  __all__ = ("InlineQueryView",)
@@ -12,7 +12,7 @@ class MessageView(BaseStateView[MessageCute]):
12
12
  self.return_manager = MessageReturnManager()
13
13
 
14
14
  def get_state_key(self, event: MessageCute) -> int | None:
15
- return event.chat.id
15
+ return event.chat_id
16
16
 
17
17
 
18
18
  __all__ = ("MessageView",)
@@ -19,12 +19,18 @@ if typing.TYPE_CHECKING:
19
19
  class WaiterMachine:
20
20
  def __init__(self) -> None:
21
21
  self.storage: Storage = {}
22
+
23
+ def __repr__(self) -> str:
24
+ return "<{}: storage={!r}>".format(
25
+ self.__class__.__name__,
26
+ self.storage,
27
+ )
22
28
 
23
29
  async def drop(
24
30
  self,
25
31
  state_view: "ABCStateView[EventModel]",
26
32
  id: Identificator,
27
- **context,
33
+ **context: typing.Any,
28
34
  ) -> None:
29
35
  view_name = state_view.__class__.__name__
30
36
  if view_name not in self.storage:
@@ -60,9 +66,9 @@ class WaiterMachine:
60
66
  *rules: ABCRule[EventModel],
61
67
  default: Behaviour = None,
62
68
  on_drop: Behaviour = None,
63
- expiration: datetime.timedelta | int | None = None,
69
+ expiration: datetime.timedelta | int | float | None = None,
64
70
  ) -> tuple[EventModel, Context]:
65
- if isinstance(expiration, int):
71
+ if isinstance(expiration, int | float):
66
72
  expiration = datetime.timedelta(seconds=expiration)
67
73
 
68
74
  api: ABCAPI
@@ -77,9 +83,9 @@ class WaiterMachine:
77
83
 
78
84
  short_state = ShortState(
79
85
  key,
80
- ctx_api=api,
81
- event=event,
82
- rules=rules,
86
+ api,
87
+ event,
88
+ rules,
83
89
  expiration=expiration,
84
90
  default_behaviour=default,
85
91
  on_drop_behaviour=on_drop,
@@ -104,13 +110,13 @@ class WaiterMachine:
104
110
  view: "ABCStateView[EventModel]",
105
111
  behaviour: Behaviour,
106
112
  event: asyncio.Event | EventModel,
107
- **context,
113
+ **context: typing.Any,
108
114
  ) -> None:
109
115
  if behaviour is None:
110
116
  return
111
117
  # TODO: add behaviour check
112
118
  # TODO: support view as a behaviour
113
- await behaviour.run(event)
119
+ await behaviour.run(event, context) # type: ignore
114
120
 
115
121
 
116
122
  __all__ = ("WaiterMachine",)
@@ -38,32 +38,34 @@ class WaiterMiddleware(ABCMiddleware[EventType]):
38
38
  if key is None:
39
39
  raise RuntimeError("Unable to get state key.")
40
40
 
41
- short_state: typing.Optional["ShortState"] = self.machine.storage[view_name].get(key)
41
+ short_state: typing.Optional["ShortState[EventType]"] = self.machine.storage[view_name].get(key)
42
42
  if not short_state:
43
43
  return True
44
44
 
45
45
  if (
46
- short_state.expiration is not None
47
- and datetime.datetime.now() >= short_state.expiration
46
+ short_state.expiration_date is not None
47
+ and datetime.datetime.now() >= short_state.expiration_date
48
48
  ):
49
49
  await self.machine.drop(self.view, short_state.key)
50
50
  return True
51
51
 
52
52
  handler = FuncHandler(
53
- self.pass_runtime, list(short_state.rules), dataclass=None
53
+ self.pass_runtime,
54
+ list(short_state.rules),
55
+ dataclass=None,
54
56
  )
55
- handler.ctx.set("short_state", short_state)
57
+ handler.preset_context.set("short_state", short_state)
56
58
  result = await handler.check(event.ctx_api, ctx.raw_update, ctx)
57
59
 
58
60
  if result is True:
59
- await handler.run(event)
61
+ await handler.run(event, ctx)
60
62
 
61
63
  elif short_state.default_behaviour is not None:
62
64
  await self.machine.call_behaviour(
63
65
  self.view,
64
66
  short_state.default_behaviour,
65
67
  event,
66
- **handler.ctx,
68
+ **handler.preset_context,
67
69
  )
68
70
 
69
71
  return False
@@ -1,8 +1,9 @@
1
1
  import asyncio
2
+ import dataclasses
2
3
  import datetime
3
4
  import typing
4
5
 
5
- from telegrinder.api.abc import ABCAPI
6
+ from telegrinder.api import ABCAPI
6
7
  from telegrinder.bot.cute_types import BaseCute
7
8
  from telegrinder.bot.dispatch.handler.abc import ABCHandler
8
9
  from telegrinder.bot.rules.abc import ABCRule
@@ -14,24 +15,22 @@ EventModel = typing.TypeVar("EventModel", bound=BaseCute)
14
15
  Behaviour: typing.TypeAlias = ABCHandler | None
15
16
 
16
17
 
18
+ @dataclasses.dataclass
17
19
  class ShortState(typing.Generic[EventModel]):
18
- def __init__(
19
- self,
20
- key: "Identificator",
21
- ctx_api: ABCAPI,
22
- event: asyncio.Event,
23
- rules: tuple[ABCRule[EventModel], ...],
24
- expiration: datetime.timedelta | None = None,
25
- default_behaviour: Behaviour | None = None,
26
- on_drop_behaviour: Behaviour | None = None,
27
- ) -> None:
28
- self.key = key
29
- self.ctx_api = ctx_api
30
- self.event = event
31
- self.rules = rules
32
- self.default_behaviour = default_behaviour
33
- self.expiration = (datetime.datetime.now() + expiration) if expiration else None
34
- self.on_drop_behaviour = on_drop_behaviour
20
+ key: "Identificator"
21
+ ctx_api: ABCAPI
22
+ event: asyncio.Event
23
+ rules: tuple[ABCRule[EventModel], ...]
24
+ _: dataclasses.KW_ONLY
25
+ expiration: dataclasses.InitVar[datetime.timedelta | None] = dataclasses.field(default=None)
26
+ default_behaviour: Behaviour | None = dataclasses.field(default=None)
27
+ on_drop_behaviour: Behaviour | None = dataclasses.field(default=None)
28
+ expiration_date: datetime.datetime | None = dataclasses.field(init=False)
29
+
30
+ def __post_init__(self, expiration: datetime.timedelta | None = None) -> None:
31
+ self.expiration_date = (
32
+ datetime.datetime.now() - expiration
33
+ ) if expiration is not None else None
35
34
 
36
35
 
37
36
  __all__ = ("ShortState",)
@@ -14,7 +14,7 @@ class TextMessageRule(MessageRule, ABC, requires=[HasText()]):
14
14
 
15
15
 
16
16
  class Text(TextMessageRule):
17
- def __init__(self, texts: str | list[str], ignore_case: bool = False):
17
+ def __init__(self, texts: str | list[str], *, ignore_case: bool = False) -> None:
18
18
  if not isinstance(texts, list):
19
19
  texts = [texts]
20
20
  self.texts = texts if not ignore_case else list(map(str.lower, texts))
@@ -45,6 +45,21 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
45
45
  self.max_in_row = max_in_row
46
46
  self.random_code = secrets.token_hex(8)
47
47
  self.waiter_machine = waiter_machine
48
+
49
+ def __repr__(self) -> str:
50
+ return (
51
+ "<{}@{!r}: (choices={!r}, max_in_row={}) with waiter_machine={!r}, ready_text={!r} "
52
+ "for chat_id={} with message={!r}>"
53
+ ).format(
54
+ self.__class__.__name__,
55
+ self.random_code,
56
+ self.choices,
57
+ self.max_in_row,
58
+ self.waiter_machine,
59
+ self.ready,
60
+ self.chat_id,
61
+ self.msg,
62
+ )
48
63
 
49
64
  def get_markup(self) -> InlineKeyboardMarkup:
50
65
  kb = InlineKeyboard()
@@ -70,6 +85,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
70
85
  name: str,
71
86
  default_text: str,
72
87
  picked_text: str,
88
+ *,
73
89
  is_picked: bool = False,
74
90
  ) -> typing.Self:
75
91
  self.choices.append(
telegrinder/node/base.py CHANGED
@@ -6,7 +6,7 @@ ComposeResult: typing.TypeAlias = typing.Coroutine[typing.Any, typing.Any, typin
6
6
 
7
7
 
8
8
  class ComposeError(BaseException):
9
- pass
9
+ ...
10
10
 
11
11
 
12
12
  class Node(abc.ABC):
@@ -27,7 +27,7 @@ class NodeSession:
27
27
  self.generator = None
28
28
 
29
29
  def __repr__(self) -> str:
30
- return f"<NodeSession {self.value}" + ("ACTIVE>" if self.generator else ">")
30
+ return f"<NodeSession: {self.value}" + ("ACTIVE>" if self.generator else ">")
31
31
 
32
32
 
33
33
  class NodeCollection:
@@ -13,12 +13,12 @@ Handler = typing.Callable[typing.Concatenate[EventT, ...], typing.Awaitable[typi
13
13
 
14
14
  class ABCErrorHandler(ABC, typing.Generic[EventT]):
15
15
  @abstractmethod
16
- def register_catcher(
16
+ def __call__(
17
17
  self,
18
18
  *args: typing.Any,
19
19
  **kwargs: typing.Any,
20
20
  ) -> typing.Callable[[typing.Callable[..., typing.Any]], typing.Callable[..., typing.Any]]:
21
- ...
21
+ """Decorator for registering callback as an error handler."""
22
22
 
23
23
  @abstractmethod
24
24
  async def run(
@@ -28,7 +28,7 @@ class ABCErrorHandler(ABC, typing.Generic[EventT]):
28
28
  api: ABCAPI,
29
29
  ctx: Context,
30
30
  ) -> Result[typing.Any, typing.Any]:
31
- ...
31
+ """Run error handler."""
32
32
 
33
33
 
34
34
  __all__ = ("ABCErrorHandler",)
@@ -97,27 +97,8 @@ class ErrorHandler(ABCErrorHandler[EventT]):
97
97
  if self.catcher is not None
98
98
  else "<ErrorHandler: No catcher>"
99
99
  )
100
-
101
- async def __call__(
102
- self,
103
- handler: Handler[EventT],
104
- event: EventT,
105
- api: ABCAPI,
106
- ctx: Context,
107
- ) -> Result[typing.Any, BaseException]:
108
- assert self.catcher is not None
109
100
 
110
- try:
111
- return await self.catcher(handler, event, api, ctx)
112
- except BaseException as exc:
113
- return Error(CatcherError(
114
- exc,
115
- "Exception {!r} was occurred during the running catcher {!r}.".format(
116
- repr(exc), self.catcher.func.__name__
117
- )
118
- ))
119
-
120
- def register_catcher(
101
+ def __call__(
121
102
  self,
122
103
  *exceptions: type[BaseException] | BaseException,
123
104
  logging: bool = False,
@@ -142,6 +123,25 @@ class ErrorHandler(ABCErrorHandler[EventT]):
142
123
  return func
143
124
  return decorator
144
125
 
126
+ async def process(
127
+ self,
128
+ handler: Handler[EventT],
129
+ event: EventT,
130
+ api: ABCAPI,
131
+ ctx: Context,
132
+ ) -> Result[typing.Any, BaseException]:
133
+ assert self.catcher is not None
134
+
135
+ try:
136
+ return await self.catcher(handler, event, api, ctx)
137
+ except BaseException as exc:
138
+ return Error(CatcherError(
139
+ exc,
140
+ "Exception {!r} was occurred during the running catcher {!r}.".format(
141
+ repr(exc), self.catcher.func.__name__
142
+ )
143
+ ))
144
+
145
145
  def process_catcher_error(self, error: CatcherError) -> Result[None, str]:
146
146
  assert self.catcher is not None
147
147
 
@@ -164,7 +164,7 @@ class ErrorHandler(ABCErrorHandler[EventT]):
164
164
  if not self.catcher:
165
165
  return Ok(await handler(event, **magic_bundle(handler, ctx))) # type: ignore
166
166
 
167
- match await self(handler, event, api, ctx):
167
+ match await self.process(handler, event, api, ctx):
168
168
  case Ok(_) as ok:
169
169
  return ok
170
170
  case Error(exc) as err:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: telegrinder
3
- Version: 0.1.dev163
3
+ Version: 0.1.dev164
4
4
  Summary: Framework for effective and reliable async telegram bot building.
5
5
  Home-page: https://github.com/timoniq/telegrinder
6
6
  License: MIT
@@ -14,32 +14,32 @@ telegrinder/bot/cute_types/message.py,sha256=xYlbHfKP1kbVpUXOLed8yCuxW8v1cD7lV6N
14
14
  telegrinder/bot/cute_types/update.py,sha256=VakZ2FwapOJvpEBIyzuiT8eftHHzBS-uPXrAUROQxOg,752
15
15
  telegrinder/bot/cute_types/utils.py,sha256=Gp7zHUn5gEfxFItIYbzkaj6wxWoPNe7hM9abHkn3Jug,16349
16
16
  telegrinder/bot/dispatch/__init__.py,sha256=o10t98PY1BuIGaJcloxfbgUYp0bf5ZqAaBQScIaV3VQ,1322
17
- telegrinder/bot/dispatch/abc.py,sha256=3bOKEFJTKarwqWTDqhscVw2U5FBllJ-TyId-aUPzb7c,454
18
- telegrinder/bot/dispatch/composition.py,sha256=0UbXqTxcs0X_DGB5COR6n_9RZBIhn83O2-1UNVoZQ8E,2558
19
- telegrinder/bot/dispatch/context.py,sha256=Uk_GFN3wlLuS5BGgBaLfLxU8xBp_yB4fPJcuzEd1ti4,2093
20
- telegrinder/bot/dispatch/dispatch.py,sha256=UyzqfsYTfr-gXo12NbJcYLi6Y8ZorRYEE3H0DU1bT8s,3818
17
+ telegrinder/bot/dispatch/abc.py,sha256=YX184RfqSTMtxrt6qyNRu9uhlPHJLEJY3RKsLfBV7nw,462
18
+ telegrinder/bot/dispatch/composition.py,sha256=EcIgiFJm1v7y8uaumrvBl-43vl8pABbjYLdgVNp4M-s,2973
19
+ telegrinder/bot/dispatch/context.py,sha256=ozsL1oy5BGjXADzVT-qhe8YohMxc-ORQKfUaKNbYm-Q,2322
20
+ telegrinder/bot/dispatch/dispatch.py,sha256=NSPLNAUu2q2-73JXLPAatF5cej1ySZykeiHaQD4XFhE,5048
21
21
  telegrinder/bot/dispatch/handler/__init__.py,sha256=mzchbArrm0eoTEeVKHYrtJX4WSfW5t6T4xDU3-mtYaA,169
22
- telegrinder/bot/dispatch/handler/abc.py,sha256=ffa9zmIcaIkIuQk8JKBty2pf53woH6hzIkQb0wmqA3k,573
23
- telegrinder/bot/dispatch/handler/func.py,sha256=B2rUH5Adm5RI4bE-49cbf5FCYTxsw2M3cJ-2GMctC0o,2085
24
- telegrinder/bot/dispatch/handler/message_reply.py,sha256=pfFINSLwTsx9buHwVW1ahVRWYQZn0QKyIazkO8D5MVo,1425
22
+ telegrinder/bot/dispatch/handler/abc.py,sha256=Qi7MDVlUdvMZYqYis3HuSoSW6KF23q3nqfvQ8FM5sEw,569
23
+ telegrinder/bot/dispatch/handler/func.py,sha256=IvDWA3ybQUcxXBOeEwteKeIVKp9-Lj9EEfKf2IIVQ40,2369
24
+ telegrinder/bot/dispatch/handler/message_reply.py,sha256=rpBRDHuJ4PdCUKq0CtFWgs7jCS4PlcgYoPFr6QOYpgw,1827
25
25
  telegrinder/bot/dispatch/middleware/__init__.py,sha256=qDuTt2ZZKX9UMjPdw5xaaNZdMI-i3P4Px2T8qbYCMJw,61
26
- telegrinder/bot/dispatch/middleware/abc.py,sha256=RWmr1agbvCabsh-m1WeQORi-Lrkt1xRBidKkugzA41Y,421
27
- telegrinder/bot/dispatch/process.py,sha256=Z4iNCwqZQyBogGxFzeNK7Pbk3ldH_e0Z95AE9sm5R-0,2267
26
+ telegrinder/bot/dispatch/middleware/abc.py,sha256=mF_G22pes-qJg6wqK9Tf71sduODXSyPjWyPT1hAiDo0,429
27
+ telegrinder/bot/dispatch/process.py,sha256=J9MYuP-soXXa0eFjJ-5wE_bNEFmr4SukJzdajDSTfAw,2313
28
28
  telegrinder/bot/dispatch/return_manager/__init__.py,sha256=-4h9nU-vdyPgv7bqKi1fAlfzNOKTO9m9FtdTZOhrmuc,447
29
29
  telegrinder/bot/dispatch/return_manager/abc.py,sha256=dGPwsIUJW_6SRsNxSiWS69xOOwSOATzMP2a7FoD90sA,3150
30
- telegrinder/bot/dispatch/return_manager/callback_query.py,sha256=FV_bVdJRbtVNRvf_CvL1V5EFZqS83VqZQOWUi1x3pxk,624
31
- telegrinder/bot/dispatch/return_manager/inline_query.py,sha256=erJ54AXSG_1lACnzmP1CIQYT4RkHT4Ml5PeRD1bkHK4,452
32
- telegrinder/bot/dispatch/return_manager/message.py,sha256=eXjQEm1qBv5W9MfvdAfleytarR7UY_Ksnpv4EAaMfQY,824
30
+ telegrinder/bot/dispatch/return_manager/callback_query.py,sha256=LIkXTGGyEnAHY-L_F82sbtzQtjvOHBi2GeL2eiWsEFc,656
31
+ telegrinder/bot/dispatch/return_manager/inline_query.py,sha256=-GRnPcdnNamtKL0IbbxCynyO3Dimk9Uz-_-wegfr1h4,484
32
+ telegrinder/bot/dispatch/return_manager/message.py,sha256=MNML9jGAAkmza1bwUOQVn9l2FmFqGHP4npub6TM_vqs,1139
33
33
  telegrinder/bot/dispatch/view/__init__.py,sha256=iMReW_At2YzenjUGOgrVnOcHLVJAIQAfI9DdQElZdcM,379
34
- telegrinder/bot/dispatch/view/abc.py,sha256=YJ_FI1SkF2bMg6yFjz2JuvwE7j_Qv6_jky-Ytfe_1Ow,4685
35
- telegrinder/bot/dispatch/view/box.py,sha256=Le7HbD9Obl-P_5nnmwptKkv8VBNlBAfWmlPWFnerUos,1240
34
+ telegrinder/bot/dispatch/view/abc.py,sha256=E6fB_WRsX3y1i84_DwTYNhFyLUyOc0ougihvoxQSuFE,5564
35
+ telegrinder/bot/dispatch/view/box.py,sha256=rek4a2cxO6VTPRVXoz9KJsb0kU_rAYX2SlN-7LCZvsM,1252
36
36
  telegrinder/bot/dispatch/view/callback_query.py,sha256=iL6DbB8ucXGvlv0w8eyMeZ94S1xz181pIn2yvYK1N_8,636
37
- telegrinder/bot/dispatch/view/inline_query.py,sha256=ZcT1iCE8uRQ_PeaXGcOsXrMmIl2ow0YTTtDzuQ2kgjU,527
38
- telegrinder/bot/dispatch/view/message.py,sha256=U80vO8tFtVsMfZHMA_LU9HunLB7nw0vbgEBltyZaSzk,498
37
+ telegrinder/bot/dispatch/view/inline_query.py,sha256=hRwrgfhgS5YF0E6eUrR8FuWVHUMlnA758kG7V049lkE,531
38
+ telegrinder/bot/dispatch/view/message.py,sha256=XX-_UmVf3_12-8I4TuH7utMRKxRcVKpWknXKhnGEx44,498
39
39
  telegrinder/bot/dispatch/waiter_machine/__init__.py,sha256=RUuq-J1qZMeREL8omM8kxEfgAz3-7h3B9NhzSjLTMqA,190
40
- telegrinder/bot/dispatch/waiter_machine/machine.py,sha256=IhbbDDzRFQQFjOcq1Pzh8tSFE90o3LmxIqe0fnyMM80,3412
41
- telegrinder/bot/dispatch/waiter_machine/middleware.py,sha256=MExbbYO9Bs_fBv1UTr28mOT3iozwY-H9Yg_7Z-B4Y5U,2483
42
- telegrinder/bot/dispatch/waiter_machine/short_state.py,sha256=tmvoeJNA7c4h30khkljt3tAGp_8LUt6lONN9C3OPuSg,1124
40
+ telegrinder/bot/dispatch/waiter_machine/machine.py,sha256=RHq0x6XOl7xcT3nZICIpkaDgVibiLLIEak_mYt5jnTw,3610
41
+ telegrinder/bot/dispatch/waiter_machine/middleware.py,sha256=6i_E2VPX71wYFnjESsUoCq1PaL4T6uaSXIWTgsTu874,2556
42
+ telegrinder/bot/dispatch/waiter_machine/short_state.py,sha256=2jYjr5RM2DknakcdbTc_xvH8FCrKKvDI8tsUwG0I5Hg,1200
43
43
  telegrinder/bot/polling/__init__.py,sha256=OqfIFPS_V6UrCg-vCv9pkMFzTKdNbDP2faBfATs_TGg,94
44
44
  telegrinder/bot/polling/abc.py,sha256=-5BpX55SJfDlEJWt15yOXWCizQRrgeY5oiA5eHkm1Nw,434
45
45
  telegrinder/bot/polling/polling.py,sha256=GPXXlAhI81PZVUMGXsPd4j67GO19zozMRJaVNAgsBMg,4280
@@ -64,10 +64,10 @@ telegrinder/bot/rules/message_entities.py,sha256=_lWHCNymbV1Sv-f2Q8Ca3SOxqIPSHVy
64
64
  telegrinder/bot/rules/regex.py,sha256=wqGEEiFqe5t_RwX9KjVCtg0wRZfwqo1ktGvNBo9JaKE,1191
65
65
  telegrinder/bot/rules/rule_enum.py,sha256=BUd78f7fEa0hfu1Paa384_Q-r0lB-ZWWukqkrFXdn58,2083
66
66
  telegrinder/bot/rules/start.py,sha256=5ok581Ww56g27rE4QkrykbBZ-ER-SnATQNzMGut2PHA,1183
67
- telegrinder/bot/rules/text.py,sha256=LaY8A2KUYDZpIllYTRSXXCwWfDN6dnFFmdvXM1nCKvA,1147
67
+ telegrinder/bot/rules/text.py,sha256=FUynYklF7VCFwOXj-cFCXWOA2N5Ul9BV9Wolbi5X72c,1158
68
68
  telegrinder/bot/scenario/__init__.py,sha256=Ehe2uH-eQ-vRBPxIzdmE23B-FBOAa9YQyndmb6K8C5E,166
69
69
  telegrinder/bot/scenario/abc.py,sha256=3AZYRjZlkbDtyFbsKdZ6BefzWYlJ0DOrGwh8jI3nzv4,474
70
- telegrinder/bot/scenario/checkbox.py,sha256=H5XuhAwwvyJbMdVpRLDzCXg2VKDU029OnDbgcANB3IE,3738
70
+ telegrinder/bot/scenario/checkbox.py,sha256=IIpC6F1JTtnH3D49R9xrXXrBd7A6klWzpDRCeBHwGg8,4202
71
71
  telegrinder/bot/scenario/choice.py,sha256=-NYyzgfGI0njVuT-EY0j3jS4tPlsKOEkZaUagtns7dE,1442
72
72
  telegrinder/client/__init__.py,sha256=ZiS1Wb_l_kv3FHzEEi1oXtFLwlA_HXmWOzeN0xA3E7Y,104
73
73
  telegrinder/client/abc.py,sha256=OxsTX_PLYBEeFT9zpidFUzAbQL9BM7rQqru7zdn5DiQ,1611
@@ -78,8 +78,8 @@ telegrinder/msgspec_json.py,sha256=phfyhUvYYZUGEcI6RAyRx9lnARPK_Fqtw3Q0MEJnuUk,2
78
78
  telegrinder/msgspec_utils.py,sha256=ZA_qj36FabalE65J82j_Hp34umHhUFbNIOt8CBYbqvA,7987
79
79
  telegrinder/node/__init__.py,sha256=01XTe8GPUBp5LXayDshihTxre7ejf99NYte20d08JLM,706
80
80
  telegrinder/node/attachment.py,sha256=vMnD2tWQQQ6PFuXEIq2ZdL91xcBxiwlAkMkqJqseLlk,2587
81
- telegrinder/node/base.py,sha256=iszAnP2pD3REDpUfufbVyJmg0rkXt2-ByeG6LgmS7Zc,2221
82
- telegrinder/node/composer.py,sha256=f6l8qLjewu6lJTcxAucKyiQ4t-4d614YF6ssk9kYCZg,2225
81
+ telegrinder/node/base.py,sha256=rEYPjLQ5EqahyIvH9ktlk_iOiym2NGK2wzh9akVIs6I,2220
82
+ telegrinder/node/composer.py,sha256=OQj3WpY5EJ2UyFa5BWw70-AvXBny9jcuOVMRbrgOQWg,2226
83
83
  telegrinder/node/container.py,sha256=sECP3TyC6AaNcJqKOfrL1T7-N8fkZzP2vB84kku6Jxg,636
84
84
  telegrinder/node/message.py,sha256=2IW6DjF0KqH2_TZbZ-MXNsDioQRVPg9TUt86aQos0Kk,415
85
85
  telegrinder/node/rule.py,sha256=VGmS4lJAFCoR0hCZSLn56fonMt0FhOGyZ1BQn_1vgeg,1724
@@ -92,9 +92,9 @@ telegrinder/rules.py,sha256=BFB8RFwKKxqs9HFfo_p0RfulQNonPZAX8cHpmnG7qCU,39
92
92
  telegrinder/tools/__init__.py,sha256=EssNbs2XHkoL-tRMB_nk5pQsgdDLg2zb0nSUY8liXIM,2878
93
93
  telegrinder/tools/buttons.py,sha256=qMvtpawzkjdqopqE7o9C0k-no1dGJVy5gjFX4SiOE6A,2430
94
94
  telegrinder/tools/error_handler/__init__.py,sha256=WmYWZCNhhSk32j4lIOltEwzoYUx086TGTbOF5h3Ps7s,207
95
- telegrinder/tools/error_handler/abc.py,sha256=1w-X7dncSyO5ouv6r_LAnywFRGYz7SgA79eNfTqMG3M,881
95
+ telegrinder/tools/error_handler/abc.py,sha256=ymQGDXgnIkfjMMBsLeNcpekQ-p7lj9kSSTLFWqpZ8Ok,952
96
96
  telegrinder/tools/error_handler/error.py,sha256=jVp3J4pMkkL20QHvDtlid9hKtAc66jZIcpsecB3-f98,188
97
- telegrinder/tools/error_handler/error_handler.py,sha256=LIAQNSTb14AhKhvhddhW4EQCwBpyNjAZJZSfcy4Fsas,5993
97
+ telegrinder/tools/error_handler/error_handler.py,sha256=GpGNkEHZAv_4awk96tpJwcnm_YdI3MAfWVILS49jNQ4,5992
98
98
  telegrinder/tools/formatting/__init__.py,sha256=_oxb-4y_vyIgALlO2rfaa-azqicySpHHIcaYBrVPdSg,1609
99
99
  telegrinder/tools/formatting/html.py,sha256=-tvN1zJK_Q7evil3-XgRdvsdYsOgaG9eX2KsIQkt0m8,8718
100
100
  telegrinder/tools/formatting/links.py,sha256=ABglEz8EA6XitSM5xJt2FU78ffUdXVNbziJUjoUjKnI,1074
@@ -121,7 +121,7 @@ telegrinder/types/__init__.py,sha256=pvPKWDXq9PBiIOCW8dFcJMqgr1kAqodPhwT-u8I4kug
121
121
  telegrinder/types/enums.py,sha256=9ZYiz_KRP1o7jB5If6730YLDfLt_-wKVK8UFs5a6CVI,18330
122
122
  telegrinder/types/methods.py,sha256=CbeuZgtH5IIH1cKZlMWVkTnNAFqQLOYLw-_DeWHKKhk,186385
123
123
  telegrinder/types/objects.py,sha256=znpGLbPrFu5GCUf4j6p_XA7iCVaxYqUZN1UqBEpr5FY,214803
124
- telegrinder-0.1.dev163.dist-info/LICENSE,sha256=J9ngGsqHCNNjpm3xYPT7EnlzsnjhfqNXej5mJFjM6lw,1094
125
- telegrinder-0.1.dev163.dist-info/METADATA,sha256=Njdjq7FipuHi822K2gkEmCd2HnEh5Y624RlBtzaM0_s,2892
126
- telegrinder-0.1.dev163.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
127
- telegrinder-0.1.dev163.dist-info/RECORD,,
124
+ telegrinder-0.1.dev164.dist-info/LICENSE,sha256=J9ngGsqHCNNjpm3xYPT7EnlzsnjhfqNXej5mJFjM6lw,1094
125
+ telegrinder-0.1.dev164.dist-info/METADATA,sha256=iaWGLP29CV1O042MEqTS25vDC7FsqUSB9Zh5cE62gGc,2892
126
+ telegrinder-0.1.dev164.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
127
+ telegrinder-0.1.dev164.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any