telegrinder 0.3.4__py3-none-any.whl → 0.3.4.post1__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 (165) hide show
  1. telegrinder/__init__.py +144 -144
  2. telegrinder/api/__init__.py +8 -8
  3. telegrinder/api/api.py +93 -93
  4. telegrinder/api/error.py +16 -16
  5. telegrinder/api/response.py +20 -20
  6. telegrinder/api/token.py +36 -36
  7. telegrinder/bot/__init__.py +66 -66
  8. telegrinder/bot/bot.py +76 -76
  9. telegrinder/bot/cute_types/__init__.py +17 -17
  10. telegrinder/bot/cute_types/base.py +258 -258
  11. telegrinder/bot/cute_types/callback_query.py +385 -385
  12. telegrinder/bot/cute_types/chat_join_request.py +61 -61
  13. telegrinder/bot/cute_types/chat_member_updated.py +160 -160
  14. telegrinder/bot/cute_types/inline_query.py +43 -43
  15. telegrinder/bot/cute_types/message.py +2637 -2637
  16. telegrinder/bot/cute_types/update.py +104 -104
  17. telegrinder/bot/cute_types/utils.py +95 -95
  18. telegrinder/bot/dispatch/__init__.py +55 -55
  19. telegrinder/bot/dispatch/abc.py +77 -77
  20. telegrinder/bot/dispatch/context.py +98 -98
  21. telegrinder/bot/dispatch/dispatch.py +202 -202
  22. telegrinder/bot/dispatch/handler/__init__.py +13 -13
  23. telegrinder/bot/dispatch/handler/abc.py +24 -24
  24. telegrinder/bot/dispatch/handler/audio_reply.py +44 -44
  25. telegrinder/bot/dispatch/handler/base.py +57 -57
  26. telegrinder/bot/dispatch/handler/document_reply.py +44 -44
  27. telegrinder/bot/dispatch/handler/func.py +135 -135
  28. telegrinder/bot/dispatch/handler/media_group_reply.py +43 -43
  29. telegrinder/bot/dispatch/handler/message_reply.py +36 -36
  30. telegrinder/bot/dispatch/handler/photo_reply.py +44 -44
  31. telegrinder/bot/dispatch/handler/sticker_reply.py +37 -37
  32. telegrinder/bot/dispatch/handler/video_reply.py +44 -44
  33. telegrinder/bot/dispatch/middleware/__init__.py +3 -3
  34. telegrinder/bot/dispatch/middleware/abc.py +22 -22
  35. telegrinder/bot/dispatch/process.py +157 -157
  36. telegrinder/bot/dispatch/return_manager/__init__.py +13 -13
  37. telegrinder/bot/dispatch/return_manager/abc.py +108 -108
  38. telegrinder/bot/dispatch/return_manager/callback_query.py +20 -20
  39. telegrinder/bot/dispatch/return_manager/inline_query.py +15 -15
  40. telegrinder/bot/dispatch/return_manager/message.py +36 -36
  41. telegrinder/bot/dispatch/view/__init__.py +13 -13
  42. telegrinder/bot/dispatch/view/abc.py +41 -41
  43. telegrinder/bot/dispatch/view/base.py +200 -200
  44. telegrinder/bot/dispatch/view/box.py +129 -129
  45. telegrinder/bot/dispatch/view/callback_query.py +17 -17
  46. telegrinder/bot/dispatch/view/chat_join_request.py +16 -16
  47. telegrinder/bot/dispatch/view/chat_member.py +39 -39
  48. telegrinder/bot/dispatch/view/inline_query.py +17 -17
  49. telegrinder/bot/dispatch/view/message.py +44 -44
  50. telegrinder/bot/dispatch/view/raw.py +114 -114
  51. telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
  52. telegrinder/bot/dispatch/waiter_machine/actions.py +13 -13
  53. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
  54. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +55 -55
  55. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +57 -57
  56. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +51 -51
  57. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +19 -19
  58. telegrinder/bot/dispatch/waiter_machine/machine.py +172 -172
  59. telegrinder/bot/dispatch/waiter_machine/middleware.py +89 -89
  60. telegrinder/bot/dispatch/waiter_machine/short_state.py +68 -68
  61. telegrinder/bot/polling/__init__.py +4 -4
  62. telegrinder/bot/polling/abc.py +25 -25
  63. telegrinder/bot/polling/polling.py +131 -131
  64. telegrinder/bot/rules/__init__.py +62 -62
  65. telegrinder/bot/rules/abc.py +206 -206
  66. telegrinder/bot/rules/adapter/__init__.py +17 -17
  67. telegrinder/bot/rules/adapter/abc.py +31 -31
  68. telegrinder/bot/rules/adapter/errors.py +5 -5
  69. telegrinder/bot/rules/adapter/event.py +65 -65
  70. telegrinder/bot/rules/adapter/node.py +48 -48
  71. telegrinder/bot/rules/adapter/raw_event.py +27 -27
  72. telegrinder/bot/rules/adapter/raw_update.py +30 -30
  73. telegrinder/bot/rules/callback_data.py +163 -163
  74. telegrinder/bot/rules/chat_join.py +43 -43
  75. telegrinder/bot/rules/command.py +126 -126
  76. telegrinder/bot/rules/enum_text.py +36 -36
  77. telegrinder/bot/rules/func.py +26 -26
  78. telegrinder/bot/rules/fuzzy.py +24 -24
  79. telegrinder/bot/rules/inline.py +56 -56
  80. telegrinder/bot/rules/integer.py +20 -20
  81. telegrinder/bot/rules/is_from.py +127 -127
  82. telegrinder/bot/rules/markup.py +43 -43
  83. telegrinder/bot/rules/mention.py +14 -14
  84. telegrinder/bot/rules/message.py +17 -17
  85. telegrinder/bot/rules/message_entities.py +35 -35
  86. telegrinder/bot/rules/node.py +27 -27
  87. telegrinder/bot/rules/regex.py +37 -37
  88. telegrinder/bot/rules/rule_enum.py +72 -72
  89. telegrinder/bot/rules/start.py +42 -42
  90. telegrinder/bot/rules/state.py +37 -37
  91. telegrinder/bot/rules/text.py +33 -33
  92. telegrinder/bot/rules/update.py +15 -15
  93. telegrinder/bot/scenario/__init__.py +5 -5
  94. telegrinder/bot/scenario/abc.py +19 -19
  95. telegrinder/bot/scenario/checkbox.py +176 -176
  96. telegrinder/bot/scenario/choice.py +51 -51
  97. telegrinder/client/__init__.py +4 -4
  98. telegrinder/client/abc.py +75 -75
  99. telegrinder/client/aiohttp.py +130 -130
  100. telegrinder/model.py +313 -313
  101. telegrinder/modules.py +237 -237
  102. telegrinder/msgspec_json.py +14 -14
  103. telegrinder/msgspec_utils.py +410 -410
  104. telegrinder/node/__init__.py +20 -20
  105. telegrinder/node/attachment.py +87 -87
  106. telegrinder/node/base.py +157 -157
  107. telegrinder/node/callback_query.py +53 -53
  108. telegrinder/node/command.py +33 -33
  109. telegrinder/node/composer.py +198 -198
  110. telegrinder/node/container.py +27 -27
  111. telegrinder/node/event.py +65 -65
  112. telegrinder/node/me.py +16 -16
  113. telegrinder/node/message.py +14 -14
  114. telegrinder/node/polymorphic.py +48 -48
  115. telegrinder/node/rule.py +76 -76
  116. telegrinder/node/scope.py +38 -38
  117. telegrinder/node/source.py +71 -71
  118. telegrinder/node/text.py +41 -41
  119. telegrinder/node/tools/__init__.py +3 -3
  120. telegrinder/node/tools/generator.py +40 -40
  121. telegrinder/node/update.py +15 -15
  122. telegrinder/rules.py +5 -5
  123. telegrinder/tools/__init__.py +74 -74
  124. telegrinder/tools/buttons.py +79 -79
  125. telegrinder/tools/error_handler/__init__.py +7 -7
  126. telegrinder/tools/error_handler/abc.py +33 -33
  127. telegrinder/tools/error_handler/error.py +9 -9
  128. telegrinder/tools/error_handler/error_handler.py +193 -193
  129. telegrinder/tools/formatting/__init__.py +46 -46
  130. telegrinder/tools/formatting/html.py +283 -283
  131. telegrinder/tools/formatting/links.py +33 -33
  132. telegrinder/tools/formatting/spec_html_formats.py +111 -111
  133. telegrinder/tools/functional.py +12 -12
  134. telegrinder/tools/global_context/__init__.py +7 -7
  135. telegrinder/tools/global_context/abc.py +63 -63
  136. telegrinder/tools/global_context/global_context.py +412 -412
  137. telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
  138. telegrinder/tools/i18n/__init__.py +7 -7
  139. telegrinder/tools/i18n/abc.py +30 -30
  140. telegrinder/tools/i18n/middleware/__init__.py +3 -3
  141. telegrinder/tools/i18n/middleware/abc.py +25 -25
  142. telegrinder/tools/i18n/simple.py +43 -43
  143. telegrinder/tools/kb_set/__init__.py +4 -4
  144. telegrinder/tools/kb_set/base.py +15 -15
  145. telegrinder/tools/kb_set/yaml.py +63 -63
  146. telegrinder/tools/keyboard.py +128 -128
  147. telegrinder/tools/limited_dict.py +37 -37
  148. telegrinder/tools/loop_wrapper/__init__.py +4 -4
  149. telegrinder/tools/loop_wrapper/abc.py +15 -15
  150. telegrinder/tools/loop_wrapper/loop_wrapper.py +224 -224
  151. telegrinder/tools/magic.py +157 -157
  152. telegrinder/tools/parse_mode.py +6 -6
  153. telegrinder/tools/state_storage/__init__.py +4 -4
  154. telegrinder/tools/state_storage/abc.py +35 -35
  155. telegrinder/tools/state_storage/memory.py +25 -25
  156. telegrinder/types/__init__.py +260 -260
  157. telegrinder/types/enums.py +701 -701
  158. telegrinder/types/methods.py +4633 -4633
  159. telegrinder/types/objects.py +6950 -6950
  160. telegrinder/verification_utils.py +32 -32
  161. {telegrinder-0.3.4.dist-info → telegrinder-0.3.4.post1.dist-info}/LICENSE +22 -22
  162. {telegrinder-0.3.4.dist-info → telegrinder-0.3.4.post1.dist-info}/METADATA +1 -1
  163. telegrinder-0.3.4.post1.dist-info/RECORD +165 -0
  164. telegrinder-0.3.4.dist-info/RECORD +0 -165
  165. {telegrinder-0.3.4.dist-info → telegrinder-0.3.4.post1.dist-info}/WHEEL +0 -0
@@ -1,68 +1,68 @@
1
- import asyncio
2
- import dataclasses
3
- import datetime
4
- import typing
5
- from contextlib import suppress
6
-
7
- from telegrinder.bot.cute_types import BaseCute
8
- from telegrinder.bot.dispatch.context import Context
9
- from telegrinder.bot.dispatch.handler.abc import ABCHandler
10
- from telegrinder.bot.rules.abc import ABCRule
11
- from telegrinder.model import Model
12
-
13
- if typing.TYPE_CHECKING:
14
- from .actions import WaiterActions
15
-
16
-
17
- T = typing.TypeVar("T", bound=Model)
18
- EventModel = typing.TypeVar("EventModel", bound=BaseCute)
19
-
20
- Behaviour: typing.TypeAlias = ABCHandler[T] | None
21
-
22
-
23
- class ShortStateContext(typing.Generic[EventModel], typing.NamedTuple):
24
- event: EventModel
25
- context: Context
26
-
27
-
28
- @dataclasses.dataclass(slots=True)
29
- class ShortState(typing.Generic[EventModel]):
30
- event: asyncio.Event
31
- actions: "WaiterActions[EventModel]"
32
-
33
- release: ABCRule | None = dataclasses.field(
34
- default=None,
35
- kw_only=True,
36
- )
37
- filter: ABCRule | None = dataclasses.field(
38
- default=None,
39
- kw_only=True,
40
- )
41
-
42
- lifetime: dataclasses.InitVar[datetime.timedelta | None] = dataclasses.field(
43
- default=None,
44
- kw_only=True,
45
- )
46
-
47
- expiration_date: datetime.datetime | None = dataclasses.field(init=False, kw_only=True)
48
- creation_date: datetime.datetime = dataclasses.field(init=False)
49
- context: ShortStateContext[EventModel] | None = dataclasses.field(default=None, init=False, kw_only=True)
50
-
51
- def __post_init__(self, expiration: datetime.timedelta | None = None) -> None:
52
- self.creation_date = datetime.datetime.now()
53
- self.expiration_date = (self.creation_date + expiration) if expiration is not None else None
54
-
55
- async def cancel(self) -> None:
56
- """Cancel schedule waiters."""
57
-
58
- waiters = typing.cast(
59
- typing.Iterable[asyncio.Future[typing.Any]],
60
- self.event._waiters, # type: ignore
61
- )
62
- for future in waiters:
63
- future.cancel()
64
- with suppress(asyncio.CancelledError):
65
- await future
66
-
67
-
68
- __all__ = ("ShortState", "ShortStateContext")
1
+ import asyncio
2
+ import dataclasses
3
+ import datetime
4
+ import typing
5
+ from contextlib import suppress
6
+
7
+ from telegrinder.bot.cute_types import BaseCute
8
+ from telegrinder.bot.dispatch.context import Context
9
+ from telegrinder.bot.dispatch.handler.abc import ABCHandler
10
+ from telegrinder.bot.rules.abc import ABCRule
11
+ from telegrinder.model import Model
12
+
13
+ if typing.TYPE_CHECKING:
14
+ from .actions import WaiterActions
15
+
16
+
17
+ T = typing.TypeVar("T", bound=Model)
18
+ EventModel = typing.TypeVar("EventModel", bound=BaseCute)
19
+
20
+ Behaviour: typing.TypeAlias = ABCHandler[T] | None
21
+
22
+
23
+ class ShortStateContext(typing.Generic[EventModel], typing.NamedTuple):
24
+ event: EventModel
25
+ context: Context
26
+
27
+
28
+ @dataclasses.dataclass(slots=True)
29
+ class ShortState(typing.Generic[EventModel]):
30
+ event: asyncio.Event
31
+ actions: "WaiterActions[EventModel]"
32
+
33
+ release: ABCRule | None = dataclasses.field(
34
+ default=None,
35
+ kw_only=True,
36
+ )
37
+ filter: ABCRule | None = dataclasses.field(
38
+ default=None,
39
+ kw_only=True,
40
+ )
41
+
42
+ lifetime: dataclasses.InitVar[datetime.timedelta | None] = dataclasses.field(
43
+ default=None,
44
+ kw_only=True,
45
+ )
46
+
47
+ expiration_date: datetime.datetime | None = dataclasses.field(init=False, kw_only=True)
48
+ creation_date: datetime.datetime = dataclasses.field(init=False)
49
+ context: ShortStateContext[EventModel] | None = dataclasses.field(default=None, init=False, kw_only=True)
50
+
51
+ def __post_init__(self, expiration: datetime.timedelta | None = None) -> None:
52
+ self.creation_date = datetime.datetime.now()
53
+ self.expiration_date = (self.creation_date + expiration) if expiration is not None else None
54
+
55
+ async def cancel(self) -> None:
56
+ """Cancel schedule waiters."""
57
+
58
+ waiters = typing.cast(
59
+ typing.Iterable[asyncio.Future[typing.Any]],
60
+ self.event._waiters, # type: ignore
61
+ )
62
+ for future in waiters:
63
+ future.cancel()
64
+ with suppress(asyncio.CancelledError):
65
+ await future
66
+
67
+
68
+ __all__ = ("ShortState", "ShortStateContext")
@@ -1,4 +1,4 @@
1
- from .abc import ABCPolling
2
- from .polling import Polling
3
-
4
- __all__ = ("ABCPolling", "Polling")
1
+ from .abc import ABCPolling
2
+ from .polling import Polling
3
+
4
+ __all__ = ("ABCPolling", "Polling")
@@ -1,25 +1,25 @@
1
- import typing
2
- from abc import ABC, abstractmethod
3
-
4
- import msgspec
5
-
6
- from telegrinder.types.objects import Update
7
-
8
-
9
- class ABCPolling(ABC):
10
- offset: int
11
-
12
- @abstractmethod
13
- async def get_updates(self) -> list[msgspec.Raw]:
14
- pass
15
-
16
- @abstractmethod
17
- async def listen(self) -> typing.AsyncGenerator[list[Update], None]:
18
- yield []
19
-
20
- @abstractmethod
21
- def stop(self) -> None:
22
- pass
23
-
24
-
25
- __all__ = ("ABCPolling",)
1
+ import typing
2
+ from abc import ABC, abstractmethod
3
+
4
+ import msgspec
5
+
6
+ from telegrinder.types.objects import Update
7
+
8
+
9
+ class ABCPolling(ABC):
10
+ offset: int
11
+
12
+ @abstractmethod
13
+ async def get_updates(self) -> list[msgspec.Raw]:
14
+ pass
15
+
16
+ @abstractmethod
17
+ async def listen(self) -> typing.AsyncGenerator[list[Update], None]:
18
+ yield []
19
+
20
+ @abstractmethod
21
+ def stop(self) -> None:
22
+ pass
23
+
24
+
25
+ __all__ = ("ABCPolling",)
@@ -1,131 +1,131 @@
1
- import asyncio
2
- import typing
3
-
4
- import aiohttp
5
- import msgspec
6
- from fntypes.result import Error, Ok
7
-
8
- from telegrinder.api.api import API
9
- from telegrinder.api.error import InvalidTokenError
10
- from telegrinder.bot.polling.abc import ABCPolling
11
- from telegrinder.modules import logger
12
- from telegrinder.msgspec_utils import decoder
13
- from telegrinder.types.objects import Update, UpdateType
14
-
15
-
16
- class Polling(ABCPolling):
17
- def __init__(
18
- self,
19
- api: API,
20
- *,
21
- offset: int = 0,
22
- reconnection_timeout: float = 5,
23
- max_reconnetions: int = 10,
24
- include_updates: set[str | UpdateType] | None = None,
25
- exclude_updates: set[str | UpdateType] | None = None,
26
- ) -> None:
27
- self.api = api
28
- self.allowed_updates = self.get_allowed_updates(
29
- include_updates=include_updates,
30
- exclude_updates=exclude_updates,
31
- )
32
- self.reconnection_timeout = 5.0 if reconnection_timeout < 0 else reconnection_timeout
33
- self.max_reconnetions = 10 if max_reconnetions < 0 else max_reconnetions
34
- self.offset = offset
35
- self._stop = False
36
-
37
- def __repr__(self) -> str:
38
- return (
39
- "<{}: with api={!r}, stopped={}, offset={}, allowed_updates={!r}, "
40
- "max_reconnetions={}, reconnection_timeout={}>"
41
- ).format(
42
- self.__class__.__name__,
43
- self.api,
44
- self._stop,
45
- self.offset,
46
- self.allowed_updates,
47
- self.max_reconnetions,
48
- self.reconnection_timeout,
49
- )
50
-
51
- @staticmethod
52
- def get_allowed_updates(
53
- *,
54
- include_updates: set[str | UpdateType] | None = None,
55
- exclude_updates: set[str | UpdateType] | None = None,
56
- ) -> list[str]:
57
- allowed_updates: list[str] = list(x.value for x in UpdateType)
58
- if not include_updates and not exclude_updates:
59
- return allowed_updates
60
-
61
- if include_updates and exclude_updates:
62
- allowed_updates = [
63
- x for x in allowed_updates if x in include_updates and x not in exclude_updates
64
- ]
65
- elif exclude_updates:
66
- allowed_updates = [x for x in allowed_updates if x not in exclude_updates]
67
- elif include_updates:
68
- allowed_updates = [x for x in allowed_updates if x in include_updates]
69
-
70
- return [x.value if isinstance(x, UpdateType) else x for x in allowed_updates]
71
-
72
- async def get_updates(self) -> msgspec.Raw | None:
73
- raw_updates = await self.api.request_raw(
74
- "getUpdates",
75
- {
76
- "offset": self.offset,
77
- "allowed_updates": self.allowed_updates,
78
- },
79
- )
80
- match raw_updates:
81
- case Ok(value):
82
- return value
83
- case Error(err) if err.code in (401, 404):
84
- raise InvalidTokenError("Token seems to be invalid")
85
-
86
- async def listen(self) -> typing.AsyncGenerator[list[Update], None]:
87
- logger.debug("Listening polling")
88
- reconn_counter = 0
89
-
90
- while not self._stop:
91
- try:
92
- updates = await self.get_updates()
93
- reconn_counter = 0
94
- if not updates:
95
- continue
96
- updates_list: list[Update] = decoder.decode(updates, type=list[Update])
97
- if updates_list:
98
- yield updates_list
99
- self.offset = updates_list[-1].update_id + 1
100
- except InvalidTokenError as e:
101
- logger.error(e)
102
- self.stop()
103
- exit(3)
104
- except asyncio.CancelledError:
105
- logger.info("Caught cancel, polling stopping...")
106
- self.stop()
107
- except (aiohttp.client.ServerConnectionError, TimeoutError):
108
- if reconn_counter > self.max_reconnetions:
109
- logger.error(
110
- "Failed to reconnect to the server after {} attempts, polling stopping.",
111
- self.max_reconnetions,
112
- )
113
- self.stop()
114
- exit(6)
115
- else:
116
- logger.warning(
117
- "Server disconnected, waiting 5 seconds to reconnect...",
118
- )
119
- reconn_counter += 1
120
- await asyncio.sleep(self.reconnection_timeout)
121
- except (aiohttp.ClientConnectorError, aiohttp.ClientOSError):
122
- logger.error("Client connection failed, attempted to reconnect...")
123
- await asyncio.sleep(self.reconnection_timeout)
124
- except BaseException as e:
125
- logger.exception(e)
126
-
127
- def stop(self) -> None:
128
- self._stop = True
129
-
130
-
131
- __all__ = ("Polling",)
1
+ import asyncio
2
+ import typing
3
+
4
+ import aiohttp
5
+ import msgspec
6
+ from fntypes.result import Error, Ok
7
+
8
+ from telegrinder.api.api import API
9
+ from telegrinder.api.error import InvalidTokenError
10
+ from telegrinder.bot.polling.abc import ABCPolling
11
+ from telegrinder.modules import logger
12
+ from telegrinder.msgspec_utils import decoder
13
+ from telegrinder.types.objects import Update, UpdateType
14
+
15
+
16
+ class Polling(ABCPolling):
17
+ def __init__(
18
+ self,
19
+ api: API,
20
+ *,
21
+ offset: int = 0,
22
+ reconnection_timeout: float = 5,
23
+ max_reconnetions: int = 10,
24
+ include_updates: set[str | UpdateType] | None = None,
25
+ exclude_updates: set[str | UpdateType] | None = None,
26
+ ) -> None:
27
+ self.api = api
28
+ self.allowed_updates = self.get_allowed_updates(
29
+ include_updates=include_updates,
30
+ exclude_updates=exclude_updates,
31
+ )
32
+ self.reconnection_timeout = 5.0 if reconnection_timeout < 0 else reconnection_timeout
33
+ self.max_reconnetions = 10 if max_reconnetions < 0 else max_reconnetions
34
+ self.offset = offset
35
+ self._stop = False
36
+
37
+ def __repr__(self) -> str:
38
+ return (
39
+ "<{}: with api={!r}, stopped={}, offset={}, allowed_updates={!r}, "
40
+ "max_reconnetions={}, reconnection_timeout={}>"
41
+ ).format(
42
+ self.__class__.__name__,
43
+ self.api,
44
+ self._stop,
45
+ self.offset,
46
+ self.allowed_updates,
47
+ self.max_reconnetions,
48
+ self.reconnection_timeout,
49
+ )
50
+
51
+ @staticmethod
52
+ def get_allowed_updates(
53
+ *,
54
+ include_updates: set[str | UpdateType] | None = None,
55
+ exclude_updates: set[str | UpdateType] | None = None,
56
+ ) -> list[str]:
57
+ allowed_updates: list[str] = list(x.value for x in UpdateType)
58
+ if not include_updates and not exclude_updates:
59
+ return allowed_updates
60
+
61
+ if include_updates and exclude_updates:
62
+ allowed_updates = [
63
+ x for x in allowed_updates if x in include_updates and x not in exclude_updates
64
+ ]
65
+ elif exclude_updates:
66
+ allowed_updates = [x for x in allowed_updates if x not in exclude_updates]
67
+ elif include_updates:
68
+ allowed_updates = [x for x in allowed_updates if x in include_updates]
69
+
70
+ return [x.value if isinstance(x, UpdateType) else x for x in allowed_updates]
71
+
72
+ async def get_updates(self) -> msgspec.Raw | None:
73
+ raw_updates = await self.api.request_raw(
74
+ "getUpdates",
75
+ {
76
+ "offset": self.offset,
77
+ "allowed_updates": self.allowed_updates,
78
+ },
79
+ )
80
+ match raw_updates:
81
+ case Ok(value):
82
+ return value
83
+ case Error(err) if err.code in (401, 404):
84
+ raise InvalidTokenError("Token seems to be invalid")
85
+
86
+ async def listen(self) -> typing.AsyncGenerator[list[Update], None]:
87
+ logger.debug("Listening polling")
88
+ reconn_counter = 0
89
+
90
+ while not self._stop:
91
+ try:
92
+ updates = await self.get_updates()
93
+ reconn_counter = 0
94
+ if not updates:
95
+ continue
96
+ updates_list: list[Update] = decoder.decode(updates, type=list[Update])
97
+ if updates_list:
98
+ yield updates_list
99
+ self.offset = updates_list[-1].update_id + 1
100
+ except InvalidTokenError as e:
101
+ logger.error(e)
102
+ self.stop()
103
+ exit(3)
104
+ except asyncio.CancelledError:
105
+ logger.info("Caught cancel, polling stopping...")
106
+ self.stop()
107
+ except (aiohttp.client.ServerConnectionError, TimeoutError):
108
+ if reconn_counter > self.max_reconnetions:
109
+ logger.error(
110
+ "Failed to reconnect to the server after {} attempts, polling stopping.",
111
+ self.max_reconnetions,
112
+ )
113
+ self.stop()
114
+ exit(6)
115
+ else:
116
+ logger.warning(
117
+ "Server disconnected, waiting 5 seconds to reconnect...",
118
+ )
119
+ reconn_counter += 1
120
+ await asyncio.sleep(self.reconnection_timeout)
121
+ except (aiohttp.ClientConnectorError, aiohttp.ClientOSError):
122
+ logger.error("Client connection failed, attempted to reconnect...")
123
+ await asyncio.sleep(self.reconnection_timeout)
124
+ except BaseException as e:
125
+ logger.exception(e)
126
+
127
+ def stop(self) -> None:
128
+ self._stop = True
129
+
130
+
131
+ __all__ = ("Polling",)
@@ -1,63 +1,63 @@
1
- from telegrinder.bot.rules.abc import ABCRule, AndRule, NotRule, OrRule
2
- from telegrinder.bot.rules.callback_data import (
3
- CallbackDataEq,
4
- CallbackDataJsonEq,
5
- CallbackDataJsonModel,
6
- CallbackDataMap,
7
- CallbackDataMarkup,
8
- CallbackQueryDataRule,
9
- CallbackQueryRule,
10
- HasData,
11
- )
12
- from telegrinder.bot.rules.chat_join import (
13
- ChatJoinRequestRule,
14
- HasInviteLink,
15
- InviteLinkByCreator,
16
- InviteLinkName,
17
- )
18
- from telegrinder.bot.rules.command import Argument, Command
19
- from telegrinder.bot.rules.enum_text import EnumTextRule
20
- from telegrinder.bot.rules.func import FuncRule
21
- from telegrinder.bot.rules.fuzzy import FuzzyText
22
- from telegrinder.bot.rules.inline import (
23
- HasLocation,
24
- InlineQueryChatType,
25
- InlineQueryMarkup,
26
- InlineQueryRule,
27
- InlineQueryText,
28
- )
29
- from telegrinder.bot.rules.integer import IntegerInRange, IsInteger
30
- from telegrinder.bot.rules.is_from import (
31
- IsBot,
32
- IsChat,
33
- IsChatId,
34
- IsDice,
35
- IsDiceEmoji,
36
- IsForum,
37
- IsForward,
38
- IsForwardType,
39
- IsGroup,
40
- IsLanguageCode,
41
- IsPremium,
42
- IsPrivate,
43
- IsReply,
44
- IsSuperGroup,
45
- IsUser,
46
- IsUserId,
47
- )
48
- from telegrinder.bot.rules.markup import Markup
49
- from telegrinder.bot.rules.mention import HasMention
50
- from telegrinder.bot.rules.message import MessageRule
51
- from telegrinder.bot.rules.message_entities import HasEntities, MessageEntities
52
- from telegrinder.bot.rules.node import NodeRule
53
- from telegrinder.bot.rules.regex import Regex
54
- from telegrinder.bot.rules.rule_enum import RuleEnum
55
- from telegrinder.bot.rules.start import StartCommand
56
- from telegrinder.bot.rules.state import State, StateMeta
57
- from telegrinder.bot.rules.text import HasText, Text
58
- from telegrinder.bot.rules.update import IsUpdateType
59
-
60
- __all__ = (
1
+ from telegrinder.bot.rules.abc import ABCRule, AndRule, NotRule, OrRule
2
+ from telegrinder.bot.rules.callback_data import (
3
+ CallbackDataEq,
4
+ CallbackDataJsonEq,
5
+ CallbackDataJsonModel,
6
+ CallbackDataMap,
7
+ CallbackDataMarkup,
8
+ CallbackQueryDataRule,
9
+ CallbackQueryRule,
10
+ HasData,
11
+ )
12
+ from telegrinder.bot.rules.chat_join import (
13
+ ChatJoinRequestRule,
14
+ HasInviteLink,
15
+ InviteLinkByCreator,
16
+ InviteLinkName,
17
+ )
18
+ from telegrinder.bot.rules.command import Argument, Command
19
+ from telegrinder.bot.rules.enum_text import EnumTextRule
20
+ from telegrinder.bot.rules.func import FuncRule
21
+ from telegrinder.bot.rules.fuzzy import FuzzyText
22
+ from telegrinder.bot.rules.inline import (
23
+ HasLocation,
24
+ InlineQueryChatType,
25
+ InlineQueryMarkup,
26
+ InlineQueryRule,
27
+ InlineQueryText,
28
+ )
29
+ from telegrinder.bot.rules.integer import IntegerInRange, IsInteger
30
+ from telegrinder.bot.rules.is_from import (
31
+ IsBot,
32
+ IsChat,
33
+ IsChatId,
34
+ IsDice,
35
+ IsDiceEmoji,
36
+ IsForum,
37
+ IsForward,
38
+ IsForwardType,
39
+ IsGroup,
40
+ IsLanguageCode,
41
+ IsPremium,
42
+ IsPrivate,
43
+ IsReply,
44
+ IsSuperGroup,
45
+ IsUser,
46
+ IsUserId,
47
+ )
48
+ from telegrinder.bot.rules.markup import Markup
49
+ from telegrinder.bot.rules.mention import HasMention
50
+ from telegrinder.bot.rules.message import MessageRule
51
+ from telegrinder.bot.rules.message_entities import HasEntities, MessageEntities
52
+ from telegrinder.bot.rules.node import NodeRule
53
+ from telegrinder.bot.rules.regex import Regex
54
+ from telegrinder.bot.rules.rule_enum import RuleEnum
55
+ from telegrinder.bot.rules.start import StartCommand
56
+ from telegrinder.bot.rules.state import State, StateMeta
57
+ from telegrinder.bot.rules.text import HasText, Text
58
+ from telegrinder.bot.rules.update import IsUpdateType
59
+
60
+ __all__ = (
61
61
  "ABCRule",
62
62
  "AndRule",
63
63
  "Argument",
@@ -115,5 +115,5 @@ __all__ = (
115
115
  "StartCommand",
116
116
  "State",
117
117
  "StateMeta",
118
- "Text",
119
- )
118
+ "Text",
119
+ )