telegrinder 0.3.1__py3-none-any.whl → 0.3.3__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 (164) 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 -234
  11. telegrinder/bot/cute_types/callback_query.py +385 -382
  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 -53
  15. telegrinder/bot/cute_types/message.py +2637 -2631
  16. telegrinder/bot/cute_types/update.py +109 -75
  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 -92
  21. telegrinder/bot/dispatch/dispatch.py +202 -201
  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 -123
  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 +16 -16
  35. telegrinder/bot/dispatch/process.py +132 -132
  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 -211
  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 -118
  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 +167 -170
  59. telegrinder/bot/dispatch/waiter_machine/middleware.py +89 -89
  60. telegrinder/bot/dispatch/waiter_machine/short_state.py +68 -65
  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 +213 -238
  66. telegrinder/bot/rules/adapter/__init__.py +9 -9
  67. telegrinder/bot/rules/adapter/abc.py +29 -29
  68. telegrinder/bot/rules/adapter/errors.py +5 -5
  69. telegrinder/bot/rules/adapter/event.py +67 -76
  70. telegrinder/bot/rules/adapter/node.py +48 -48
  71. telegrinder/bot/rules/adapter/raw_update.py +30 -30
  72. telegrinder/bot/rules/callback_data.py +170 -171
  73. telegrinder/bot/rules/chat_join.py +46 -48
  74. telegrinder/bot/rules/command.py +126 -126
  75. telegrinder/bot/rules/enum_text.py +36 -36
  76. telegrinder/bot/rules/func.py +26 -26
  77. telegrinder/bot/rules/fuzzy.py +24 -24
  78. telegrinder/bot/rules/inline.py +60 -60
  79. telegrinder/bot/rules/integer.py +20 -20
  80. telegrinder/bot/rules/is_from.py +127 -127
  81. telegrinder/bot/rules/markup.py +43 -43
  82. telegrinder/bot/rules/mention.py +14 -14
  83. telegrinder/bot/rules/message.py +17 -17
  84. telegrinder/bot/rules/message_entities.py +35 -35
  85. telegrinder/bot/rules/node.py +27 -27
  86. telegrinder/bot/rules/regex.py +37 -37
  87. telegrinder/bot/rules/rule_enum.py +72 -72
  88. telegrinder/bot/rules/start.py +42 -42
  89. telegrinder/bot/rules/state.py +37 -37
  90. telegrinder/bot/rules/text.py +33 -33
  91. telegrinder/bot/rules/update.py +15 -15
  92. telegrinder/bot/scenario/__init__.py +5 -5
  93. telegrinder/bot/scenario/abc.py +19 -19
  94. telegrinder/bot/scenario/checkbox.py +167 -147
  95. telegrinder/bot/scenario/choice.py +46 -44
  96. telegrinder/client/__init__.py +4 -4
  97. telegrinder/client/abc.py +75 -75
  98. telegrinder/client/aiohttp.py +130 -130
  99. telegrinder/model.py +295 -244
  100. telegrinder/modules.py +237 -237
  101. telegrinder/msgspec_json.py +14 -14
  102. telegrinder/msgspec_utils.py +410 -410
  103. telegrinder/node/__init__.py +7 -3
  104. telegrinder/node/attachment.py +87 -87
  105. telegrinder/node/base.py +166 -144
  106. telegrinder/node/callback_query.py +53 -14
  107. telegrinder/node/command.py +33 -33
  108. telegrinder/node/composer.py +198 -184
  109. telegrinder/node/container.py +27 -27
  110. telegrinder/node/event.py +65 -73
  111. telegrinder/node/me.py +16 -16
  112. telegrinder/node/message.py +14 -14
  113. telegrinder/node/polymorphic.py +48 -52
  114. telegrinder/node/rule.py +76 -76
  115. telegrinder/node/scope.py +38 -38
  116. telegrinder/node/source.py +71 -71
  117. telegrinder/node/text.py +41 -21
  118. telegrinder/node/tools/__init__.py +3 -3
  119. telegrinder/node/tools/generator.py +40 -40
  120. telegrinder/node/update.py +15 -15
  121. telegrinder/rules.py +0 -0
  122. telegrinder/tools/__init__.py +74 -74
  123. telegrinder/tools/buttons.py +79 -79
  124. telegrinder/tools/error_handler/__init__.py +7 -7
  125. telegrinder/tools/error_handler/abc.py +33 -33
  126. telegrinder/tools/error_handler/error.py +9 -9
  127. telegrinder/tools/error_handler/error_handler.py +193 -193
  128. telegrinder/tools/formatting/__init__.py +46 -46
  129. telegrinder/tools/formatting/html.py +283 -283
  130. telegrinder/tools/formatting/links.py +33 -33
  131. telegrinder/tools/formatting/spec_html_formats.py +111 -111
  132. telegrinder/tools/functional.py +12 -12
  133. telegrinder/tools/global_context/__init__.py +7 -7
  134. telegrinder/tools/global_context/abc.py +63 -63
  135. telegrinder/tools/global_context/global_context.py +412 -412
  136. telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
  137. telegrinder/tools/i18n/__init__.py +7 -7
  138. telegrinder/tools/i18n/abc.py +30 -30
  139. telegrinder/tools/i18n/middleware/__init__.py +3 -3
  140. telegrinder/tools/i18n/middleware/abc.py +25 -25
  141. telegrinder/tools/i18n/simple.py +43 -43
  142. telegrinder/tools/kb_set/__init__.py +4 -4
  143. telegrinder/tools/kb_set/base.py +15 -15
  144. telegrinder/tools/kb_set/yaml.py +63 -63
  145. telegrinder/tools/keyboard.py +132 -132
  146. telegrinder/tools/limited_dict.py +37 -37
  147. telegrinder/tools/loop_wrapper/__init__.py +4 -4
  148. telegrinder/tools/loop_wrapper/abc.py +15 -15
  149. telegrinder/tools/loop_wrapper/loop_wrapper.py +224 -216
  150. telegrinder/tools/magic.py +157 -157
  151. telegrinder/tools/parse_mode.py +6 -6
  152. telegrinder/tools/state_storage/__init__.py +4 -4
  153. telegrinder/tools/state_storage/abc.py +35 -35
  154. telegrinder/tools/state_storage/memory.py +25 -25
  155. telegrinder/types/__init__.py +260 -260
  156. telegrinder/types/enums.py +701 -701
  157. telegrinder/types/methods.py +4633 -4633
  158. telegrinder/types/objects.py +8561 -6541
  159. telegrinder/verification_utils.py +32 -32
  160. {telegrinder-0.3.1.dist-info → telegrinder-0.3.3.dist-info}/LICENSE +22 -22
  161. {telegrinder-0.3.1.dist-info → telegrinder-0.3.3.dist-info}/METADATA +1 -1
  162. telegrinder-0.3.3.dist-info/RECORD +164 -0
  163. telegrinder-0.3.1.dist-info/RECORD +0 -164
  164. {telegrinder-0.3.1.dist-info → telegrinder-0.3.3.dist-info}/WHEEL +0 -0
@@ -1,65 +1,68 @@
1
- import asyncio
2
- import dataclasses
3
- import datetime
4
- import typing
5
-
6
- from telegrinder.bot.cute_types import BaseCute
7
- from telegrinder.bot.dispatch.context import Context
8
- from telegrinder.bot.dispatch.handler.abc import ABCHandler
9
- from telegrinder.bot.rules.abc import ABCRule
10
- from telegrinder.model import Model
11
-
12
- if typing.TYPE_CHECKING:
13
- from .actions import WaiterActions
14
-
15
-
16
- T = typing.TypeVar("T", bound=Model)
17
- EventModel = typing.TypeVar("EventModel", bound=BaseCute)
18
-
19
- Behaviour: typing.TypeAlias = ABCHandler[T] | None
20
-
21
-
22
- class ShortStateContext(typing.Generic[EventModel], typing.NamedTuple):
23
- event: EventModel
24
- context: Context
25
-
26
-
27
- @dataclasses.dataclass(slots=True)
28
- class ShortState(typing.Generic[EventModel]):
29
- event: asyncio.Event
30
- actions: "WaiterActions[EventModel]"
31
-
32
- release: ABCRule | None = dataclasses.field(
33
- default=None,
34
- kw_only=True,
35
- )
36
- filter: ABCRule | None = dataclasses.field(
37
- default=None,
38
- kw_only=True,
39
- )
40
-
41
- lifetime: dataclasses.InitVar[datetime.timedelta | None] = dataclasses.field(
42
- default=None,
43
- kw_only=True,
44
- )
45
-
46
- expiration_date: datetime.datetime | None = dataclasses.field(init=False, kw_only=True)
47
- creation_date: datetime.datetime = dataclasses.field(init=False)
48
- context: ShortStateContext[EventModel] | None = dataclasses.field(default=None, init=False, kw_only=True)
49
-
50
- def __post_init__(self, expiration: datetime.timedelta | None = None) -> None:
51
- self.creation_date = datetime.datetime.now()
52
- self.expiration_date = (self.creation_date + expiration) if expiration is not None else None
53
-
54
- def cancel(self) -> None:
55
- """Cancel schedule waiters."""
56
-
57
- waiters = typing.cast(
58
- typing.Iterable[asyncio.Future[typing.Any]],
59
- self.event._waiters, # type: ignore
60
- )
61
- for future in waiters:
62
- future.cancel()
63
-
64
-
65
- __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 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
+ )