telegrinder 0.1.dev164__py3-none-any.whl → 0.1.dev166__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 (93) hide show
  1. telegrinder/__init__.py +58 -0
  2. telegrinder/api/abc.py +1 -1
  3. telegrinder/api/api.py +8 -6
  4. telegrinder/api/error.py +2 -3
  5. telegrinder/bot/__init__.py +14 -0
  6. telegrinder/bot/bot.py +13 -2
  7. telegrinder/bot/cute_types/__init__.py +4 -0
  8. telegrinder/bot/cute_types/base.py +22 -13
  9. telegrinder/bot/cute_types/chat_join_request.py +63 -0
  10. telegrinder/bot/cute_types/chat_member_updated.py +244 -0
  11. telegrinder/bot/cute_types/message.py +33 -6
  12. telegrinder/bot/cute_types/update.py +5 -4
  13. telegrinder/bot/cute_types/utils.py +39 -17
  14. telegrinder/bot/dispatch/__init__.py +9 -1
  15. telegrinder/bot/dispatch/composition.py +10 -8
  16. telegrinder/bot/dispatch/context.py +9 -10
  17. telegrinder/bot/dispatch/dispatch.py +29 -19
  18. telegrinder/bot/dispatch/handler/abc.py +1 -0
  19. telegrinder/bot/dispatch/handler/func.py +29 -6
  20. telegrinder/bot/dispatch/handler/message_reply.py +2 -3
  21. telegrinder/bot/dispatch/middleware/abc.py +2 -4
  22. telegrinder/bot/dispatch/process.py +4 -3
  23. telegrinder/bot/dispatch/return_manager/__init__.py +1 -1
  24. telegrinder/bot/dispatch/return_manager/abc.py +39 -21
  25. telegrinder/bot/dispatch/return_manager/callback_query.py +4 -2
  26. telegrinder/bot/dispatch/return_manager/inline_query.py +4 -2
  27. telegrinder/bot/dispatch/return_manager/message.py +12 -6
  28. telegrinder/bot/dispatch/view/__init__.py +8 -2
  29. telegrinder/bot/dispatch/view/abc.py +26 -20
  30. telegrinder/bot/dispatch/view/box.py +72 -1
  31. telegrinder/bot/dispatch/view/callback_query.py +1 -3
  32. telegrinder/bot/dispatch/view/chat_join_request.py +17 -0
  33. telegrinder/bot/dispatch/view/chat_member.py +26 -0
  34. telegrinder/bot/dispatch/view/message.py +23 -1
  35. telegrinder/bot/dispatch/view/raw.py +116 -0
  36. telegrinder/bot/dispatch/waiter_machine/__init__.py +2 -1
  37. telegrinder/bot/dispatch/waiter_machine/machine.py +73 -19
  38. telegrinder/bot/dispatch/waiter_machine/middleware.py +3 -3
  39. telegrinder/bot/dispatch/waiter_machine/short_state.py +6 -3
  40. telegrinder/bot/polling/polling.py +17 -1
  41. telegrinder/bot/rules/__init__.py +20 -12
  42. telegrinder/bot/rules/abc.py +0 -9
  43. telegrinder/bot/rules/adapter/event.py +31 -22
  44. telegrinder/bot/rules/callback_data.py +15 -20
  45. telegrinder/bot/rules/chat_join.py +47 -0
  46. telegrinder/bot/rules/enum_text.py +7 -2
  47. telegrinder/bot/rules/inline.py +3 -3
  48. telegrinder/bot/rules/is_from.py +36 -50
  49. telegrinder/bot/rules/markup.py +1 -1
  50. telegrinder/bot/rules/message.py +17 -0
  51. telegrinder/bot/rules/message_entities.py +1 -1
  52. telegrinder/bot/rules/start.py +6 -4
  53. telegrinder/bot/rules/text.py +2 -1
  54. telegrinder/bot/rules/update.py +16 -0
  55. telegrinder/bot/scenario/checkbox.py +9 -7
  56. telegrinder/client/aiohttp.py +4 -4
  57. telegrinder/model.py +43 -19
  58. telegrinder/modules.py +16 -32
  59. telegrinder/msgspec_utils.py +48 -36
  60. telegrinder/node/__init__.py +12 -12
  61. telegrinder/node/attachment.py +15 -5
  62. telegrinder/node/base.py +24 -16
  63. telegrinder/node/composer.py +8 -6
  64. telegrinder/node/container.py +1 -1
  65. telegrinder/node/rule.py +4 -4
  66. telegrinder/node/source.py +4 -2
  67. telegrinder/node/tools/generator.py +1 -1
  68. telegrinder/tools/__init__.py +2 -1
  69. telegrinder/tools/error_handler/abc.py +4 -3
  70. telegrinder/tools/error_handler/error_handler.py +22 -16
  71. telegrinder/tools/formatting/html.py +20 -18
  72. telegrinder/tools/formatting/links.py +12 -6
  73. telegrinder/tools/formatting/spec_html_formats.py +5 -6
  74. telegrinder/tools/global_context/abc.py +5 -1
  75. telegrinder/tools/global_context/global_context.py +2 -2
  76. telegrinder/tools/global_context/telegrinder_ctx.py +1 -1
  77. telegrinder/tools/i18n/base.py +4 -3
  78. telegrinder/tools/i18n/simple.py +1 -3
  79. telegrinder/tools/keyboard.py +1 -1
  80. telegrinder/tools/loop_wrapper/__init__.py +2 -2
  81. telegrinder/tools/loop_wrapper/abc.py +1 -4
  82. telegrinder/tools/loop_wrapper/loop_wrapper.py +90 -36
  83. telegrinder/tools/magic.py +1 -1
  84. telegrinder/types/__init__.py +206 -0
  85. telegrinder/types/enums.py +34 -0
  86. telegrinder/types/methods.py +52 -47
  87. telegrinder/types/objects.py +531 -88
  88. telegrinder/verification_utils.py +33 -0
  89. {telegrinder-0.1.dev164.dist-info → telegrinder-0.1.dev166.dist-info}/METADATA +1 -1
  90. telegrinder-0.1.dev166.dist-info/RECORD +136 -0
  91. telegrinder-0.1.dev164.dist-info/RECORD +0 -127
  92. {telegrinder-0.1.dev164.dist-info → telegrinder-0.1.dev166.dist-info}/LICENSE +0 -0
  93. {telegrinder-0.1.dev164.dist-info → telegrinder-0.1.dev166.dist-info}/WHEEL +0 -0
@@ -49,7 +49,9 @@ class StringFormatter(string.Formatter):
49
49
  )
50
50
  return fmt
51
51
 
52
- def get_spec_formatter(self, value: SpecialFormat) -> typing.Callable[..., "TagFormat"]:
52
+ def get_spec_formatter(
53
+ self, value: SpecialFormat
54
+ ) -> typing.Callable[..., "TagFormat"]:
53
55
  return globals()[value.__formatter_name__]
54
56
 
55
57
  def check_formats(self, value: typing.Any, fmts: list[str]) -> "TagFormat":
@@ -78,11 +80,15 @@ class StringFormatter(string.Formatter):
78
80
  with suppress(ValueError):
79
81
  return HTMLFormatter(
80
82
  format(
81
- value.formatting()
82
- if isinstance(value, TagFormat)
83
- else self.get_spec_formatter(value)(**value.__dict__).formatting()
84
- if is_spec_format(value)
85
- else value,
83
+ (
84
+ value.formatting()
85
+ if isinstance(value, TagFormat)
86
+ else (
87
+ self.get_spec_formatter(value)(**value.__dict__).formatting()
88
+ if is_spec_format(value)
89
+ else value
90
+ )
91
+ ),
86
92
  fmt,
87
93
  )
88
94
  )
@@ -200,11 +206,8 @@ def bold(string: str) -> TagFormat:
200
206
  return TagFormat(string, tag="b")
201
207
 
202
208
 
203
- def channel_boost_link(channel_username: str, string: str | None = None):
204
- return link(
205
- get_channel_boost_link(channel_username),
206
- string or f"t.me/{channel_username}?boost",
207
- )
209
+ def channel_boost_link(channel_id: str | int, string: str | None = None):
210
+ return link(get_channel_boost_link(channel_id), string)
208
211
 
209
212
 
210
213
  def code_inline(string: str) -> TagFormat:
@@ -234,15 +237,14 @@ def spoiler(string: str) -> TagFormat:
234
237
  return TagFormat(string, tag="tg-spoiler")
235
238
 
236
239
 
237
- def start_bot_link(bot_username: str, data: str, string: str | None = None) -> TagFormat:
238
- return link(
239
- get_start_bot_link(bot_username, data),
240
- string or f"t.me/{bot_username}?start={data}"
241
- )
240
+ def start_bot_link(bot_id: str | int, data: str, string: str | None = None) -> TagFormat:
241
+ return link(get_start_bot_link(bot_id, data), string)
242
242
 
243
243
 
244
- def start_group_link(bot_username: str, data: str, string: str | None = None) -> TagFormat:
245
- return link(get_start_group_link(bot_username, data), string)
244
+ def start_group_link(
245
+ bot_id: str | int, data: str, string: str | None = None
246
+ ) -> TagFormat:
247
+ return link(get_start_group_link(bot_id, data), string)
246
248
 
247
249
 
248
250
  def strike(string: str) -> TagFormat:
@@ -6,16 +6,22 @@ def get_resolve_domain_link(username: str) -> str:
6
6
  return f"tg://resolve?domain={username}"
7
7
 
8
8
 
9
- def get_start_bot_link(bot_username: str, data: str) -> str:
10
- return get_resolve_domain_link(bot_username) + f"&start={data}"
9
+ def get_start_bot_link(bot_id: str | int, data: str) -> str:
10
+ if isinstance(bot_id, int):
11
+ return get_mention_link(bot_id) + f"&start={data}"
12
+ return get_resolve_domain_link(bot_id) + f"&start={data}"
11
13
 
12
14
 
13
- def get_start_group_link(bot_username: str, data: str) -> str:
14
- return get_resolve_domain_link(bot_username) + f"&startgroup={data}"
15
+ def get_start_group_link(bot_id: str | int, data: str) -> str:
16
+ if isinstance(bot_id, int):
17
+ return get_mention_link(bot_id) + f"&startgroup={data}"
18
+ return get_resolve_domain_link(bot_id) + f"&startgroup={data}"
15
19
 
16
20
 
17
- def get_channel_boost_link(channel_username: str) -> str:
18
- return get_resolve_domain_link(channel_username) + "&boost"
21
+ def get_channel_boost_link(channel_id: str | int) -> str:
22
+ if isinstance(channel_id, int):
23
+ return get_mention_link(channel_id) + "&boost"
24
+ return get_resolve_domain_link(channel_id) + "&boost"
19
25
 
20
26
 
21
27
  def get_invite_chat_link(invite_link: str) -> str:
@@ -3,14 +3,13 @@ import typing
3
3
 
4
4
  from telegrinder.types.enums import ProgrammingLanguage
5
5
 
6
- SpecialFormat = typing.Union[
6
+ SpecialFormat: typing.TypeAlias = typing.Union[
7
7
  "ChannelBoostLink",
8
8
  "InviteChatLink",
9
9
  "Link",
10
10
  "Mention",
11
11
  "PreCode",
12
12
  "ResolveDomain",
13
- "SpecialFormat",
14
13
  "StartBotLink",
15
14
  "StartGroupLink",
16
15
  "TgEmoji",
@@ -38,7 +37,7 @@ class BaseSpecFormat:
38
37
  class ChannelBoostLink(BaseSpecFormat):
39
38
  __formatter_name__ = "channel_boost_link"
40
39
 
41
- channel_username: str
40
+ channel_id: str | int
42
41
  string: str | None = None
43
42
 
44
43
 
@@ -77,7 +76,7 @@ class PreCode(BaseSpecFormat):
77
76
  @dataclasses.dataclass(repr=False)
78
77
  class TgEmoji(BaseSpecFormat):
79
78
  __formatter_name__ = "tg_emoji"
80
-
79
+
81
80
  string: str
82
81
  emoji_id: int
83
82
 
@@ -86,7 +85,7 @@ class TgEmoji(BaseSpecFormat):
86
85
  class StartBotLink(BaseSpecFormat):
87
86
  __formatter_name__ = "start_bot_link"
88
87
 
89
- bot_username: str
88
+ bot_id: str | int
90
89
  data: str
91
90
  string: str | None
92
91
 
@@ -95,7 +94,7 @@ class StartBotLink(BaseSpecFormat):
95
94
  class StartGroupLink(BaseSpecFormat):
96
95
  __formatter_name__ = "start_group_link"
97
96
 
98
- bot_username: str
97
+ bot_id: str | int
99
98
  data: str
100
99
  string: str | None = None
101
100
 
@@ -35,7 +35,11 @@ class GlobalCtxVar(typing.Generic[T]):
35
35
 
36
36
  @classmethod
37
37
  def collect(cls, name: str, ctx_value: T | CtxVariable[T]) -> typing.Self:
38
- ctx_value = CtxVar(ctx_value) if not isinstance(ctx_value, CtxVar | GlobalCtxVar) else ctx_value
38
+ ctx_value = (
39
+ CtxVar(ctx_value)
40
+ if not isinstance(ctx_value, CtxVar | GlobalCtxVar)
41
+ else ctx_value
42
+ )
39
43
  params = ctx_value.__dict__
40
44
  params["name"] = name
41
45
  return cls(**params)
@@ -199,8 +199,8 @@ class GlobalContext(ABCGlobalContext, typing.Generic[CtxValueT], dict[str, Globa
199
199
  self.set_context_variables(variables)
200
200
 
201
201
  def __repr__(self) -> str:
202
- return "<{!r} -> ({})>".format(
203
- f"{self.__class__.__name__}@{self.ctx_name}",
202
+ return "<{} -> ({})>".format(
203
+ f"{self.__class__.__name__}@{self.ctx_name!r}",
204
204
  ", ".join(repr(var) for var in self),
205
205
  )
206
206
 
@@ -7,7 +7,7 @@ from telegrinder.tools.global_context import GlobalContext, ctx_var
7
7
 
8
8
  class TelegrinderCtx(GlobalContext):
9
9
  """Basic type-hinted telegrinder context with context name `"telegrinder"`.
10
-
10
+
11
11
  You can use this class or GlobalContext:
12
12
  ```
13
13
  from telegrinder.tools.global_context import GlobalContext, TelegrinderCtx
@@ -1,4 +1,5 @@
1
1
  import enum
2
+ import typing
2
3
  from abc import ABC, abstractmethod
3
4
 
4
5
 
@@ -9,14 +10,14 @@ class ABCI18n(ABC):
9
10
 
10
11
 
11
12
  class ABCTranslator(ABC):
12
- def __init__(self, locale: str, **kwargs):
13
+ def __init__(self, locale: str, **kwargs: typing.Any) -> None:
13
14
  self.locale = locale
14
15
 
15
16
  @abstractmethod
16
- def get(self, __key: str, *args, **kwargs) -> str:
17
+ def get(self, __key: str, *args: typing.Any, **kwargs: typing.Any) -> str:
17
18
  """This translates a key to actual human-readable string"""
18
19
 
19
- def __call__(self, __key: str, *args, **kwargs):
20
+ def __call__(self, __key: str, *args: typing.Any, **kwargs: typing.Any) -> str:
20
21
  return self.get(__key, *args, **kwargs)
21
22
 
22
23
 
@@ -20,9 +20,7 @@ class SimpleI18n(ABCI18n):
20
20
  if not os.path.isdir(os.path.join(self.folder, name)):
21
21
  continue
22
22
 
23
- mo_path = os.path.join(
24
- self.folder, name, "LC_MESSAGES", f"{self.domain}.mo"
25
- )
23
+ mo_path = os.path.join(self.folder, name, "LC_MESSAGES", f"{self.domain}.mo")
26
24
  if os.path.exists(mo_path):
27
25
  with open(mo_path, "rb") as f:
28
26
  result[name] = gettext.GNUTranslations(f)
@@ -46,7 +46,7 @@ class ABCMarkup(ABC, typing.Generic[ButtonT]):
46
46
  def add(self, row_or_button: RowButtons[ButtonT] | ButtonT) -> typing.Self:
47
47
  if not len(self.keyboard):
48
48
  self.row()
49
-
49
+
50
50
  if isinstance(row_or_button, RowButtons):
51
51
  self.keyboard[-1].extend(row_or_button.get_data())
52
52
  if row_or_button.auto_row:
@@ -1,4 +1,4 @@
1
1
  from .abc import ABCLoopWrapper
2
- from .loop_wrapper import DelayedTask, LoopWrapper
2
+ from .loop_wrapper import DelayedTask, Lifespan, LoopWrapper
3
3
 
4
- __all__ = ("ABCLoopWrapper", "DelayedTask", "LoopWrapper")
4
+ __all__ = ("ABCLoopWrapper", "DelayedTask", "Lifespan", "LoopWrapper")
@@ -1,13 +1,10 @@
1
1
  import typing
2
2
  from abc import ABC, abstractmethod
3
3
 
4
- CoroutineTask: typing.TypeAlias = typing.Coroutine[typing.Any, typing.Any, typing.Any]
5
- CoroutineFunc: typing.TypeAlias = typing.Callable[..., CoroutineTask]
6
-
7
4
 
8
5
  class ABCLoopWrapper(ABC):
9
6
  @abstractmethod
10
- def add_task(self, task: CoroutineFunc | CoroutineTask) -> None:
7
+ def add_task(self, task: typing.Any) -> None:
11
8
  pass
12
9
 
13
10
  @abstractmethod
@@ -5,12 +5,36 @@ import typing
5
5
 
6
6
  from telegrinder.modules import logger
7
7
 
8
- from .abc import ABCLoopWrapper, CoroutineFunc, CoroutineTask
8
+ from .abc import ABCLoopWrapper
9
+
10
+ T = typing.TypeVar("T")
11
+ P = typing.ParamSpec("P")
12
+ CoroFunc = typing.TypeVar("CoroFunc", bound="CoroutineFunc")
13
+
14
+ CoroutineTask: typing.TypeAlias = typing.Coroutine[typing.Any, typing.Any, T]
15
+ CoroutineFunc: typing.TypeAlias = typing.Callable[P, CoroutineTask[T]]
16
+ Task: typing.TypeAlias = typing.Union[CoroutineFunc, CoroutineTask, "DelayedTask"]
17
+
18
+
19
+ def run_tasks(
20
+ tasks: list[CoroutineTask[typing.Any]],
21
+ loop: asyncio.AbstractEventLoop,
22
+ ) -> None:
23
+ while tasks:
24
+ loop.run_until_complete(tasks.pop(0))
25
+
26
+
27
+ def to_coroutine_task(task: Task) -> CoroutineTask[typing.Any]:
28
+ if asyncio.iscoroutinefunction(task) or isinstance(task, DelayedTask):
29
+ task = task()
30
+ elif not asyncio.iscoroutine(task):
31
+ raise TypeError("Task should be coroutine or coroutine function.")
32
+ return task
9
33
 
10
34
 
11
35
  @dataclasses.dataclass
12
- class DelayedTask:
13
- handler: CoroutineFunc
36
+ class DelayedTask(typing.Generic[CoroFunc]):
37
+ handler: CoroFunc
14
38
  seconds: float
15
39
  repeat: bool = dataclasses.field(default=False, kw_only=True)
16
40
  _cancelled: bool = dataclasses.field(default=False, init=False, repr=False)
@@ -33,28 +57,64 @@ class DelayedTask:
33
57
  self._cancelled = True
34
58
 
35
59
 
60
+ @dataclasses.dataclass(kw_only=True)
61
+ class Lifespan:
62
+ startup_tasks: list[CoroutineTask[typing.Any]] = dataclasses.field(
63
+ default_factory=lambda: []
64
+ )
65
+ shutdown_tasks: list[CoroutineTask[typing.Any]] = dataclasses.field(
66
+ default_factory=lambda: []
67
+ )
68
+
69
+ def on_startup(self, task_or_func: Task) -> Task:
70
+ task_or_func = to_coroutine_task(task_or_func)
71
+ self.startup_tasks.append(task_or_func)
72
+ return task_or_func
73
+
74
+ def on_shutdown(self, task_or_func: Task) -> Task:
75
+ task_or_func = to_coroutine_task(task_or_func)
76
+ self.shutdown_tasks.append(task_or_func)
77
+ return task_or_func
78
+
79
+ def start(self, loop: asyncio.AbstractEventLoop) -> None:
80
+ run_tasks(self.startup_tasks, loop)
81
+
82
+ def shutdown(self, loop: asyncio.AbstractEventLoop) -> None:
83
+ run_tasks(self.shutdown_tasks, loop)
84
+
85
+
36
86
  class LoopWrapper(ABCLoopWrapper):
37
- def __init__(self, tasks: list[CoroutineTask] | None = None):
38
- self.on_startup: list[CoroutineTask] = []
39
- self.on_shutdown: list[CoroutineTask] = []
40
- self.tasks = tasks or []
87
+ def __init__(
88
+ self,
89
+ *,
90
+ tasks: list[CoroutineTask[typing.Any]] | None = None,
91
+ lifespan: Lifespan | None = None,
92
+ ) -> None:
93
+ self.tasks: list[CoroutineTask[typing.Any]] = tasks or []
94
+ self.lifespan = lifespan or Lifespan()
41
95
  self._loop = asyncio.new_event_loop()
42
-
96
+
97
+ def __repr__(self) -> str:
98
+ return "<{}: loop={!r} with tasks={!r}, lifespan={!r}>".format(
99
+ self.__class__.__name__,
100
+ self._loop,
101
+ self.tasks,
102
+ self.lifespan,
103
+ )
104
+
43
105
  def run_event_loop(self) -> None:
44
106
  if not self.tasks:
45
107
  logger.warning("You run loop with 0 tasks!")
46
108
 
47
- for startup_task in self.on_startup:
48
- self._loop.run_until_complete(startup_task)
49
- for task in self.tasks:
50
- self._loop.create_task(task)
51
-
52
- self.tasks.clear()
109
+ self.lifespan.start(self._loop)
110
+ while self.tasks:
111
+ self._loop.create_task(self.tasks.pop(0))
53
112
  tasks = asyncio.all_tasks(self._loop)
113
+
54
114
  try:
55
115
  while tasks:
56
116
  tasks_results, _ = self._loop.run_until_complete(
57
- asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
117
+ asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION),
58
118
  )
59
119
  for task_result in tasks_results:
60
120
  try:
@@ -64,25 +124,21 @@ class LoopWrapper(ABCLoopWrapper):
64
124
  tasks = asyncio.all_tasks(self._loop)
65
125
  except KeyboardInterrupt:
66
126
  print() # blank print for ^C
67
- logger.info("KeyboardInterrupt")
127
+ logger.info("Caught KeyboardInterrupt, cancellation...")
68
128
  self.complete_tasks(tasks)
69
129
  finally:
70
- for shutdown_task in self.on_shutdown:
71
- self._loop.run_until_complete(shutdown_task)
130
+ self.lifespan.shutdown(self._loop)
72
131
  if self._loop.is_running():
73
132
  self._loop.close()
74
-
75
- def add_task(self, task: CoroutineFunc | CoroutineTask | DelayedTask):
76
- if asyncio.iscoroutinefunction(task) or isinstance(task, DelayedTask):
77
- task = task()
78
- elif not asyncio.iscoroutine(task):
79
- raise TypeError("Task should be coroutine or coroutine function.")
133
+
134
+ def add_task(self, task: Task) -> None:
135
+ task = to_coroutine_task(task)
80
136
 
81
137
  if self._loop and self._loop.is_running():
82
138
  self._loop.create_task(task)
83
139
  else:
84
140
  self.tasks.append(task)
85
-
141
+
86
142
  def complete_tasks(self, tasks: set[asyncio.Task[typing.Any]]) -> None:
87
143
  tasks = tasks | asyncio.all_tasks(self._loop)
88
144
  task_to_cancel = asyncio.gather(*tasks, return_exceptions=True)
@@ -97,15 +153,14 @@ class LoopWrapper(ABCLoopWrapper):
97
153
  hours: int = 0,
98
154
  minutes: int = 0,
99
155
  seconds: float = 0,
100
- ) -> typing.Callable[[typing.Callable], DelayedTask]:
156
+ ):
101
157
  seconds += minutes * 60
102
158
  seconds += hours * 60 * 60
103
159
  seconds += days * 24 * 60 * 60
104
160
 
105
- def decorator(func: typing.Callable) -> DelayedTask:
106
- delayed_task = DelayedTask(func, seconds, repeat=False)
107
- self.add_task(delayed_task)
108
- return delayed_task
161
+ def decorator(func: CoroFunc) -> CoroFunc:
162
+ self.add_task(DelayedTask(func, seconds, repeat=False))
163
+ return func
109
164
 
110
165
  return decorator
111
166
 
@@ -116,17 +171,16 @@ class LoopWrapper(ABCLoopWrapper):
116
171
  hours: int = 0,
117
172
  minutes: int = 0,
118
173
  seconds: float = 0,
119
- ) -> typing.Callable[[typing.Callable], DelayedTask]:
174
+ ):
120
175
  seconds += minutes * 60
121
176
  seconds += hours * 60 * 60
122
177
  seconds += days * 24 * 60 * 60
123
178
 
124
- def decorator(func: typing.Callable) -> DelayedTask:
125
- delayed_task = DelayedTask(func, seconds, repeat=True)
126
- self.add_task(delayed_task)
127
- return delayed_task
179
+ def decorator(func: CoroFunc) -> CoroFunc:
180
+ self.add_task(DelayedTask(func, seconds, repeat=True))
181
+ return func
128
182
 
129
183
  return decorator
130
184
 
131
185
 
132
- __all__ = ("DelayedTask", "LoopWrapper")
186
+ __all__ = ("DelayedTask", "Lifespan", "LoopWrapper", "to_coroutine_task")
@@ -28,7 +28,7 @@ def to_str(s: str | enum.Enum) -> str:
28
28
 
29
29
 
30
30
  def magic_bundle(
31
- handler: FuncType,
31
+ handler: FuncType,
32
32
  kw: dict[str | enum.Enum, typing.Any],
33
33
  *,
34
34
  start_idx: int = 1,
@@ -1,2 +1,208 @@
1
1
  from telegrinder.types.enums import *
2
2
  from telegrinder.types.objects import *
3
+
4
+ __all__ = (
5
+ "Animation",
6
+ "Audio",
7
+ "BackgroundFill",
8
+ "BackgroundFillFreeformGradient",
9
+ "BackgroundFillGradient",
10
+ "BackgroundFillSolid",
11
+ "BackgroundType",
12
+ "BackgroundTypeChatTheme",
13
+ "BackgroundTypeFill",
14
+ "BackgroundTypePattern",
15
+ "BackgroundTypeWallpaper",
16
+ "Birthdate",
17
+ "BotCommand",
18
+ "BotCommandScope",
19
+ "BotCommandScopeAllChatAdministrators",
20
+ "BotCommandScopeAllGroupChats",
21
+ "BotCommandScopeAllPrivateChats",
22
+ "BotCommandScopeChat",
23
+ "BotCommandScopeChatAdministrators",
24
+ "BotCommandScopeChatMember",
25
+ "BotCommandScopeDefault",
26
+ "BotDescription",
27
+ "BotName",
28
+ "BotShortDescription",
29
+ "BusinessConnection",
30
+ "BusinessIntro",
31
+ "BusinessLocation",
32
+ "BusinessMessagesDeleted",
33
+ "BusinessOpeningHours",
34
+ "BusinessOpeningHoursInterval",
35
+ "CallbackGame",
36
+ "CallbackQuery",
37
+ "Chat",
38
+ "ChatAdministratorRights",
39
+ "ChatBackground",
40
+ "ChatBoost",
41
+ "ChatBoostAdded",
42
+ "ChatBoostRemoved",
43
+ "ChatBoostSource",
44
+ "ChatBoostSourceGiftCode",
45
+ "ChatBoostSourceGiveaway",
46
+ "ChatBoostSourcePremium",
47
+ "ChatBoostUpdated",
48
+ "ChatFullInfo",
49
+ "ChatInviteLink",
50
+ "ChatJoinRequest",
51
+ "ChatLocation",
52
+ "ChatMember",
53
+ "ChatMemberAdministrator",
54
+ "ChatMemberBanned",
55
+ "ChatMemberLeft",
56
+ "ChatMemberMember",
57
+ "ChatMemberOwner",
58
+ "ChatMemberRestricted",
59
+ "ChatMemberUpdated",
60
+ "ChatPermissions",
61
+ "ChatPhoto",
62
+ "ChatShared",
63
+ "ChosenInlineResult",
64
+ "Contact",
65
+ "Dice",
66
+ "Document",
67
+ "EncryptedCredentials",
68
+ "EncryptedPassportElement",
69
+ "ExternalReplyInfo",
70
+ "File",
71
+ "ForceReply",
72
+ "ForumTopic",
73
+ "ForumTopicClosed",
74
+ "ForumTopicCreated",
75
+ "ForumTopicEdited",
76
+ "ForumTopicReopened",
77
+ "Game",
78
+ "GameHighScore",
79
+ "GeneralForumTopicHidden",
80
+ "GeneralForumTopicUnhidden",
81
+ "Giveaway",
82
+ "GiveawayCompleted",
83
+ "GiveawayCreated",
84
+ "GiveawayWinners",
85
+ "InaccessibleMessage",
86
+ "InlineKeyboardButton",
87
+ "InlineKeyboardMarkup",
88
+ "InlineQuery",
89
+ "InlineQueryResult",
90
+ "InlineQueryResultArticle",
91
+ "InlineQueryResultAudio",
92
+ "InlineQueryResultCachedAudio",
93
+ "InlineQueryResultCachedDocument",
94
+ "InlineQueryResultCachedGif",
95
+ "InlineQueryResultCachedMpeg4Gif",
96
+ "InlineQueryResultCachedPhoto",
97
+ "InlineQueryResultCachedSticker",
98
+ "InlineQueryResultCachedVideo",
99
+ "InlineQueryResultCachedVoice",
100
+ "InlineQueryResultContact",
101
+ "InlineQueryResultDocument",
102
+ "InlineQueryResultGame",
103
+ "InlineQueryResultGif",
104
+ "InlineQueryResultLocation",
105
+ "InlineQueryResultMpeg4Gif",
106
+ "InlineQueryResultPhoto",
107
+ "InlineQueryResultVenue",
108
+ "InlineQueryResultVideo",
109
+ "InlineQueryResultVoice",
110
+ "InlineQueryResultsButton",
111
+ "InputContactMessageContent",
112
+ "InputFile",
113
+ "InputInvoiceMessageContent",
114
+ "InputLocationMessageContent",
115
+ "InputMedia",
116
+ "InputMediaAnimation",
117
+ "InputMediaAudio",
118
+ "InputMediaDocument",
119
+ "InputMediaPhoto",
120
+ "InputMediaVideo",
121
+ "InputMessageContent",
122
+ "InputPollOption",
123
+ "InputSticker",
124
+ "InputTextMessageContent",
125
+ "InputVenueMessageContent",
126
+ "Invoice",
127
+ "KeyboardButton",
128
+ "KeyboardButtonPollType",
129
+ "KeyboardButtonRequestChat",
130
+ "KeyboardButtonRequestUsers",
131
+ "LabeledPrice",
132
+ "LinkPreviewOptions",
133
+ "Location",
134
+ "LoginUrl",
135
+ "MaskPosition",
136
+ "MaybeInaccessibleMessage",
137
+ "MenuButton",
138
+ "MenuButtonCommands",
139
+ "MenuButtonDefault",
140
+ "MenuButtonWebApp",
141
+ "Message",
142
+ "MessageAutoDeleteTimerChanged",
143
+ "MessageEntity",
144
+ "MessageId",
145
+ "MessageOrigin",
146
+ "MessageOriginChannel",
147
+ "MessageOriginChat",
148
+ "MessageOriginHiddenUser",
149
+ "MessageOriginUser",
150
+ "MessageReactionCountUpdated",
151
+ "MessageReactionUpdated",
152
+ "Model",
153
+ "OrderInfo",
154
+ "PassportData",
155
+ "PassportElementError",
156
+ "PassportElementErrorDataField",
157
+ "PassportElementErrorFile",
158
+ "PassportElementErrorFiles",
159
+ "PassportElementErrorFrontSide",
160
+ "PassportElementErrorReverseSide",
161
+ "PassportElementErrorSelfie",
162
+ "PassportElementErrorTranslationFile",
163
+ "PassportElementErrorTranslationFiles",
164
+ "PassportElementErrorUnspecified",
165
+ "PassportFile",
166
+ "PhotoSize",
167
+ "Poll",
168
+ "PollAnswer",
169
+ "PollOption",
170
+ "PreCheckoutQuery",
171
+ "ProximityAlertTriggered",
172
+ "ReactionCount",
173
+ "ReactionType",
174
+ "ReactionTypeCustomEmoji",
175
+ "ReactionTypeEmoji",
176
+ "ReplyKeyboardMarkup",
177
+ "ReplyKeyboardRemove",
178
+ "ReplyParameters",
179
+ "ResponseParameters",
180
+ "SentWebAppMessage",
181
+ "SharedUser",
182
+ "ShippingAddress",
183
+ "ShippingOption",
184
+ "ShippingQuery",
185
+ "Sticker",
186
+ "StickerSet",
187
+ "Story",
188
+ "SuccessfulPayment",
189
+ "SwitchInlineQueryChosenChat",
190
+ "TextQuote",
191
+ "Update",
192
+ "User",
193
+ "UserChatBoosts",
194
+ "UserProfilePhotos",
195
+ "UsersShared",
196
+ "Venue",
197
+ "Video",
198
+ "VideoChatEnded",
199
+ "VideoChatParticipantsInvited",
200
+ "VideoChatScheduled",
201
+ "VideoChatStarted",
202
+ "VideoNote",
203
+ "Voice",
204
+ "WebAppData",
205
+ "WebAppInfo",
206
+ "WebhookInfo",
207
+ "WriteAccessAllowed",
208
+ )