telegrinder 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of telegrinder might be problematic. Click here for more details.

Files changed (85) hide show
  1. telegrinder/__init__.py +45 -12
  2. telegrinder/bot/__init__.py +32 -4
  3. telegrinder/bot/cute_types/callback_query.py +60 -146
  4. telegrinder/bot/cute_types/chat_join_request.py +12 -16
  5. telegrinder/bot/cute_types/chat_member_updated.py +15 -105
  6. telegrinder/bot/cute_types/inline_query.py +5 -14
  7. telegrinder/bot/cute_types/message.py +623 -1238
  8. telegrinder/bot/dispatch/__init__.py +40 -3
  9. telegrinder/bot/dispatch/abc.py +8 -1
  10. telegrinder/bot/dispatch/context.py +2 -2
  11. telegrinder/bot/dispatch/dispatch.py +8 -1
  12. telegrinder/bot/dispatch/handler/__init__.py +17 -1
  13. telegrinder/bot/dispatch/handler/audio_reply.py +44 -0
  14. telegrinder/bot/dispatch/handler/base.py +57 -0
  15. telegrinder/bot/dispatch/handler/document_reply.py +44 -0
  16. telegrinder/bot/dispatch/handler/func.py +3 -3
  17. telegrinder/bot/dispatch/handler/media_group_reply.py +43 -0
  18. telegrinder/bot/dispatch/handler/message_reply.py +12 -35
  19. telegrinder/bot/dispatch/handler/photo_reply.py +44 -0
  20. telegrinder/bot/dispatch/handler/sticker_reply.py +37 -0
  21. telegrinder/bot/dispatch/handler/video_reply.py +44 -0
  22. telegrinder/bot/dispatch/process.py +2 -2
  23. telegrinder/bot/dispatch/return_manager/abc.py +11 -8
  24. telegrinder/bot/dispatch/return_manager/callback_query.py +2 -2
  25. telegrinder/bot/dispatch/return_manager/inline_query.py +2 -2
  26. telegrinder/bot/dispatch/return_manager/message.py +3 -3
  27. telegrinder/bot/dispatch/view/__init__.py +2 -1
  28. telegrinder/bot/dispatch/view/abc.py +2 -181
  29. telegrinder/bot/dispatch/view/base.py +200 -0
  30. telegrinder/bot/dispatch/view/callback_query.py +3 -3
  31. telegrinder/bot/dispatch/view/chat_join_request.py +2 -2
  32. telegrinder/bot/dispatch/view/chat_member.py +2 -3
  33. telegrinder/bot/dispatch/view/inline_query.py +2 -2
  34. telegrinder/bot/dispatch/view/message.py +5 -4
  35. telegrinder/bot/dispatch/view/raw.py +4 -3
  36. telegrinder/bot/dispatch/waiter_machine/__init__.py +18 -0
  37. telegrinder/bot/dispatch/waiter_machine/actions.py +10 -0
  38. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +15 -0
  39. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +60 -0
  40. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +49 -0
  41. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +54 -0
  42. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +19 -0
  43. telegrinder/bot/dispatch/waiter_machine/machine.py +88 -101
  44. telegrinder/bot/dispatch/waiter_machine/middleware.py +23 -41
  45. telegrinder/bot/dispatch/waiter_machine/short_state.py +9 -9
  46. telegrinder/bot/polling/polling.py +5 -2
  47. telegrinder/bot/rules/__init__.py +3 -3
  48. telegrinder/bot/rules/abc.py +6 -5
  49. telegrinder/bot/rules/adapter/__init__.py +1 -1
  50. telegrinder/bot/rules/integer.py +1 -1
  51. telegrinder/bot/rules/is_from.py +19 -0
  52. telegrinder/bot/rules/state.py +9 -6
  53. telegrinder/bot/scenario/checkbox.py +5 -5
  54. telegrinder/bot/scenario/choice.py +2 -2
  55. telegrinder/client/aiohttp.py +5 -7
  56. telegrinder/model.py +6 -11
  57. telegrinder/modules.py +16 -25
  58. telegrinder/msgspec_json.py +1 -1
  59. telegrinder/msgspec_utils.py +56 -5
  60. telegrinder/node/base.py +2 -2
  61. telegrinder/node/composer.py +5 -9
  62. telegrinder/node/container.py +6 -1
  63. telegrinder/node/event.py +2 -0
  64. telegrinder/node/polymorphic.py +7 -7
  65. telegrinder/node/rule.py +6 -4
  66. telegrinder/node/scope.py +3 -3
  67. telegrinder/node/source.py +4 -2
  68. telegrinder/node/tools/generator.py +7 -6
  69. telegrinder/rules.py +2 -2
  70. telegrinder/tools/__init__.py +10 -10
  71. telegrinder/tools/functional.py +9 -0
  72. telegrinder/tools/keyboard.py +6 -1
  73. telegrinder/tools/loop_wrapper/loop_wrapper.py +4 -5
  74. telegrinder/tools/magic.py +17 -19
  75. telegrinder/tools/state_storage/__init__.py +3 -3
  76. telegrinder/tools/state_storage/abc.py +12 -10
  77. telegrinder/tools/state_storage/memory.py +9 -6
  78. telegrinder/types/__init__.py +1 -0
  79. telegrinder/types/methods.py +10 -2
  80. telegrinder/types/objects.py +47 -5
  81. {telegrinder-0.2.1.dist-info → telegrinder-0.3.0.dist-info}/METADATA +4 -5
  82. telegrinder-0.3.0.dist-info/RECORD +164 -0
  83. telegrinder-0.2.1.dist-info/RECORD +0 -149
  84. {telegrinder-0.2.1.dist-info → telegrinder-0.3.0.dist-info}/LICENSE +0 -0
  85. {telegrinder-0.2.1.dist-info → telegrinder-0.3.0.dist-info}/WHEEL +0 -0
@@ -74,6 +74,7 @@ __all__ = (
74
74
  "ABCGlobalContext",
75
75
  "ABCI18n",
76
76
  "ABCLoopWrapper",
77
+ "ABCStateStorage",
77
78
  "ABCTranslator",
78
79
  "ABCTranslatorMiddleware",
79
80
  "AnyMarkup",
@@ -101,6 +102,7 @@ __all__ = (
101
102
  "LimitedDict",
102
103
  "Link",
103
104
  "LoopWrapper",
105
+ "MemoryStateStorage",
104
106
  "Mention",
105
107
  "ParseMode",
106
108
  "PreCode",
@@ -111,8 +113,14 @@ __all__ = (
111
113
  "SpecialFormat",
112
114
  "StartBotLink",
113
115
  "StartGroupLink",
116
+ "StateData",
114
117
  "TelegrinderContext",
115
118
  "TgEmoji",
119
+ "block_quote",
120
+ "bold",
121
+ "channel_boost_link",
122
+ "code_inline",
123
+ "ctx_var",
116
124
  "escape",
117
125
  "get_channel_boost_link",
118
126
  "get_invite_chat_link",
@@ -120,12 +128,14 @@ __all__ = (
120
128
  "get_resolve_domain_link",
121
129
  "get_start_bot_link",
122
130
  "get_start_group_link",
131
+ "impl",
123
132
  "invite_chat_link",
124
133
  "italic",
125
134
  "link",
126
135
  "magic_bundle",
127
136
  "mention",
128
137
  "pre_code",
138
+ "resolve_arg_names",
129
139
  "resolve_domain",
130
140
  "spoiler",
131
141
  "start_bot_link",
@@ -133,14 +143,4 @@ __all__ = (
133
143
  "strike",
134
144
  "tg_emoji",
135
145
  "underline",
136
- "bold",
137
- "channel_boost_link",
138
- "code_inline",
139
- "ctx_var",
140
- "block_quote",
141
- "impl",
142
- "resolve_arg_names",
143
- "ABCStateStorage",
144
- "MemoryStateStorage",
145
- "StateData",
146
146
  )
@@ -0,0 +1,9 @@
1
+ import typing
2
+
3
+ from fntypes import Nothing, Option, Some
4
+
5
+ T = typing.TypeVar("T")
6
+
7
+
8
+ def from_optional(value: T | None) -> Option[T]:
9
+ return Some(value) if value is not None else Nothing()
@@ -26,6 +26,11 @@ class KeyboardModel:
26
26
  keyboard: list[list[DictStrAny]]
27
27
 
28
28
 
29
+
30
+ def copy_keyboard(keyboard: list[list[DictStrAny]]) -> list[list[DictStrAny]]:
31
+ return [row.copy() for row in keyboard]
32
+
33
+
29
34
  class ABCMarkup(ABC, typing.Generic[ButtonT]):
30
35
  BUTTON: type[ButtonT]
31
36
  keyboard: list[list[DictStrAny]]
@@ -73,7 +78,7 @@ class ABCMarkup(ABC, typing.Generic[ButtonT]):
73
78
  return copy_keyboard
74
79
 
75
80
  def merge(self, other: typing.Self) -> typing.Self:
76
- self.keyboard.extend(other.keyboard)
81
+ self.keyboard.extend(copy_keyboard(other.keyboard))
77
82
  return self
78
83
 
79
84
 
@@ -44,17 +44,16 @@ class DelayedTask(typing.Generic[CoroFunc]):
44
44
  def is_cancelled(self) -> bool:
45
45
  return self._cancelled
46
46
 
47
- async def __call__(self, *args, **kwargs) -> None:
47
+ async def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> None:
48
48
  while not self.is_cancelled:
49
49
  await asyncio.sleep(self.seconds)
50
50
  if self.is_cancelled:
51
51
  break
52
52
  try:
53
53
  await self.handler(*args, **kwargs)
54
- except Exception as e:
55
- logger.exception("Error in delayed task: {}", str(e))
56
- if not self.repeat:
57
- break
54
+ finally:
55
+ if not self.repeat:
56
+ break
58
57
 
59
58
  def cancel(self) -> None:
60
59
  if not self._cancelled:
@@ -6,7 +6,7 @@ from functools import wraps
6
6
 
7
7
  if typing.TYPE_CHECKING:
8
8
  from telegrinder.bot.rules.abc import ABCRule
9
- from telegrinder.node.base import Node
9
+ from telegrinder.node.polymorphic import Polymorphic
10
10
 
11
11
  T = typing.TypeVar("T", bound=ABCRule)
12
12
  F = typing.TypeVar(
@@ -23,7 +23,6 @@ IMPL_MARK: typing.Final[str] = "_is_impl"
23
23
 
24
24
  def cache_magic_value(mark_key: str, /):
25
25
  def inner(func: "F") -> "F":
26
-
27
26
  @wraps(func)
28
27
  def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Any:
29
28
  if mark_key not in args[0].__dict__:
@@ -31,6 +30,7 @@ def cache_magic_value(mark_key: str, /):
31
30
  return args[0].__dict__[mark_key]
32
31
 
33
32
  return wrapper # type: ignore
33
+
34
34
  return inner
35
35
 
36
36
 
@@ -43,13 +43,13 @@ def get_default_args(func: FuncType) -> dict[str, typing.Any]:
43
43
  fspec = inspect.getfullargspec(func)
44
44
  if not fspec.defaults:
45
45
  return {}
46
- return dict(zip(fspec.args[-len(fspec.defaults):], fspec.defaults))
46
+ return dict(zip(fspec.args[-len(fspec.defaults) :], fspec.defaults))
47
47
 
48
48
 
49
49
  def get_annotations(func: FuncType, *, return_type: bool = False) -> dict[str, typing.Any]:
50
50
  annotations = func.__annotations__
51
51
  if not return_type and "return" in func.__annotations__:
52
- annotations.pop("return")
52
+ annotations.pop("return")
53
53
  return annotations
54
54
 
55
55
 
@@ -60,13 +60,11 @@ def to_str(s: str | enum.Enum) -> str:
60
60
 
61
61
 
62
62
  @typing.overload
63
- def magic_bundle(handler: FuncType, kw: dict[str, typing.Any]) -> dict[str, typing.Any]:
64
- ...
63
+ def magic_bundle(handler: FuncType, kw: dict[str, typing.Any]) -> dict[str, typing.Any]: ...
65
64
 
66
65
 
67
66
  @typing.overload
68
- def magic_bundle(handler: FuncType, kw: dict[enum.Enum, typing.Any]) -> dict[str, typing.Any]:
69
- ...
67
+ def magic_bundle(handler: FuncType, kw: dict[enum.Enum, typing.Any]) -> dict[str, typing.Any]: ...
70
68
 
71
69
 
72
70
  @typing.overload
@@ -76,8 +74,7 @@ def magic_bundle(
76
74
  *,
77
75
  start_idx: int = 1,
78
76
  bundle_ctx: bool = True,
79
- ) -> dict[str, typing.Any]:
80
- ...
77
+ ) -> dict[str, typing.Any]: ...
81
78
 
82
79
 
83
80
  @typing.overload
@@ -87,8 +84,7 @@ def magic_bundle(
87
84
  *,
88
85
  start_idx: int = 1,
89
86
  bundle_ctx: bool = True,
90
- ) -> dict[str, typing.Any]:
91
- ...
87
+ ) -> dict[str, typing.Any]: ...
92
88
 
93
89
 
94
90
  @typing.overload
@@ -97,8 +93,7 @@ def magic_bundle(
97
93
  kw: dict[type, typing.Any],
98
94
  *,
99
95
  typebundle: typing.Literal[True] = True,
100
- ) -> dict[str, typing.Any]:
101
- ...
96
+ ) -> dict[str, typing.Any]: ...
102
97
 
103
98
 
104
99
  def magic_bundle(
@@ -109,7 +104,6 @@ def magic_bundle(
109
104
  bundle_ctx: bool = True,
110
105
  typebundle: bool = False,
111
106
  ) -> dict[str, typing.Any]:
112
-
113
107
  if typebundle:
114
108
  types = get_annotations(handler, return_type=False)
115
109
  bundle: dict[str, typing.Any] = {}
@@ -141,13 +135,17 @@ def impl(method: typing.Callable[..., typing.Any]):
141
135
  return classmethod(method)
142
136
 
143
137
 
144
- def get_impls(cls: type["Node"]) -> list[typing.Callable[..., typing.Any]]:
145
- return [
138
+ def get_impls(cls: type["Polymorphic"]) -> list[typing.Callable[..., typing.Any]]:
139
+ moprh_impls = getattr(cls, "__morph_impls__", None)
140
+ if moprh_impls is not None:
141
+ return moprh_impls
142
+ impls = [
146
143
  func.__func__
147
144
  for func in vars(cls).values()
148
145
  if isinstance(func, classmethod) and getattr(func.__func__, IMPL_MARK, False)
149
146
  ]
150
-
147
+ setattr(cls, "__morph_impls__", impls)
148
+ return impls
151
149
 
152
150
 
153
151
  __all__ = (
@@ -158,8 +156,8 @@ __all__ = (
158
156
  "get_cached_translation",
159
157
  "get_default_args",
160
158
  "get_default_args",
161
- "impl",
162
159
  "get_impls",
160
+ "impl",
163
161
  "magic_bundle",
164
162
  "resolve_arg_names",
165
163
  "to_str",
@@ -1,4 +1,4 @@
1
- from .abc import ABCStateStorage, StateData
2
- from .memory import MemoryStateStorage
1
+ from telegrinder.tools.state_storage.abc import ABCStateStorage, StateData
2
+ from telegrinder.tools.state_storage.memory import MemoryStateStorage
3
3
 
4
- __all__ = ("ABCStateStorage", "StateData", "MemoryStateStorage")
4
+ __all__ = ("ABCStateStorage", "MemoryStateStorage", "StateData")
@@ -1,4 +1,5 @@
1
1
  import abc
2
+ import enum
2
3
  import typing
3
4
  from dataclasses import dataclass
4
5
 
@@ -9,25 +10,26 @@ from telegrinder.bot.rules.state import State, StateMeta
9
10
  Payload = typing.TypeVar("Payload")
10
11
 
11
12
 
12
- @dataclass
13
+ @dataclass(frozen=True, slots=True)
13
14
  class StateData(typing.Generic[Payload]):
14
- key: str
15
+ key: str | enum.Enum
15
16
  payload: Payload
16
17
 
17
18
 
18
19
  class ABCStateStorage(abc.ABC, typing.Generic[Payload]):
19
20
  @abc.abstractmethod
20
- async def get(self, user_id: int) -> Option[StateData[Payload]]:
21
- ...
21
+ async def get(self, user_id: int) -> Option[StateData[Payload]]: ...
22
22
 
23
23
  @abc.abstractmethod
24
- async def delete(self, user_id: int) -> None:
25
- ...
24
+ async def delete(self, user_id: int) -> None: ...
26
25
 
27
26
  @abc.abstractmethod
28
- async def set(self, user_id: int, key: str, payload: Payload) -> None:
29
- ...
27
+ async def set(self, user_id: int, key: str | enum.Enum, payload: Payload) -> None: ...
28
+
29
+ def State(self, key: str | StateMeta | enum.Enum = StateMeta.ANY, /) -> State[Payload]: # noqa: N802
30
+ """Can be used as a shortcut to get a state rule dependant on current storage."""
30
31
 
31
- def State(self, key: str | StateMeta = StateMeta.ANY) -> State: # noqa: N802
32
- """Can be used as a shortcut to get a state rule dependant on current storage"""
33
32
  return State(storage=self, key=key)
33
+
34
+
35
+ __all__ = ("ABCStateStorage", "StateData")
@@ -1,22 +1,25 @@
1
1
  import typing
2
2
 
3
- from fntypes import Nothing, Option, Some
3
+ from fntypes.option import Option
4
4
 
5
- from .abc import ABCStateStorage, StateData
5
+ from telegrinder.tools.functional import from_optional
6
+ from telegrinder.tools.state_storage.abc import ABCStateStorage, StateData
6
7
 
7
- Payload = dict[str, typing.Any]
8
+ Payload: typing.TypeAlias = dict[str, typing.Any]
8
9
 
9
10
 
10
11
  class MemoryStateStorage(ABCStateStorage[Payload]):
11
- def __init__(self):
12
+ def __init__(self) -> None:
12
13
  self.storage: dict[int, StateData[Payload]] = {}
13
14
 
14
15
  async def get(self, user_id: int) -> Option[StateData[Payload]]:
15
- state = self.storage.get(user_id)
16
- return Some(state) if state is not None else Nothing()
16
+ return from_optional(self.storage.get(user_id))
17
17
 
18
18
  async def set(self, user_id: int, key: str, payload: Payload) -> None:
19
19
  self.storage[user_id] = StateData(key, payload)
20
20
 
21
21
  async def delete(self, user_id: int) -> None:
22
22
  self.storage.pop(user_id)
23
+
24
+
25
+ __all__ = ("MemoryStateStorage",)
@@ -178,6 +178,7 @@ __all__ = (
178
178
  "PaidMediaInfo",
179
179
  "PaidMediaPhoto",
180
180
  "PaidMediaPreview",
181
+ "PaidMediaPurchased",
181
182
  "PaidMediaVideo",
182
183
  "PassportData",
183
184
  "PassportElementError",
@@ -13,7 +13,7 @@ if typing.TYPE_CHECKING:
13
13
 
14
14
 
15
15
  class APIMethods:
16
- """Telegram Bot API 7.9 methods, released `August 14, 2024`."""
16
+ """Telegram Bot API methods version 7.10, released `September 6, 2024`."""
17
17
 
18
18
  default_params = ProxiedDict(
19
19
  typing.TypedDict(
@@ -1054,6 +1054,7 @@ class APIMethods:
1054
1054
  star_count: int,
1055
1055
  media: list[InputPaidMedia],
1056
1056
  business_connection_id: str | None = None,
1057
+ payload: str | None = None,
1057
1058
  caption: str | None = None,
1058
1059
  parse_mode: str | None = default_params["parse_mode"],
1059
1060
  caption_entities: list[MessageEntity] | None = None,
@@ -1080,10 +1081,14 @@ class APIMethods:
1080
1081
  Star proceeds from this media will be credited to the chat's balance. Otherwise, \
1081
1082
  they will be credited to the bot's balance.
1082
1083
 
1083
- :param star_count: The number of Telegram Stars that must be paid to buy access to the media. \
1084
+ :param star_count: The number of Telegram Stars that must be paid to buy access to the media; \
1085
+ 1-2500.
1084
1086
 
1085
1087
  :param media: A JSON-serialized array describing the media to be sent; up to 10 items. \
1086
1088
 
1089
+ :param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed \
1090
+ to the user, use it for your internal processes.
1091
+
1087
1092
  :param caption: Media caption, 0-1024 characters after entities parsing.
1088
1093
 
1089
1094
  :param parse_mode: Mode for parsing entities in the media caption. See formatting options \
@@ -4623,3 +4628,6 @@ class APIMethods:
4623
4628
  get_params(locals()),
4624
4629
  )
4625
4630
  return full_result(method_response, list[GameHighScore])
4631
+
4632
+
4633
+ __all__ = ("APIMethods",)
@@ -292,6 +292,10 @@ class Update(Model):
292
292
  """Optional. New incoming pre-checkout query. Contains full information
293
293
  about checkout."""
294
294
 
295
+ purchased_paid_media: Option["PaidMediaPurchased"] = Nothing
296
+ """Optional. A user purchased paid media with a non-empty payload sent by the
297
+ bot in a non-channel chat."""
298
+
295
299
  poll: Option["Poll"] = Nothing
296
300
  """Optional. New poll state. Bots receive only updates about manually stopped
297
301
  polls and polls, which are sent by the bot."""
@@ -2179,9 +2183,13 @@ class VideoChatParticipantsInvited(Model):
2179
2183
  class GiveawayCreated(Model):
2180
2184
  """Object `GiveawayCreated`, see the [documentation](https://core.telegram.org/bots/api#giveawaycreated).
2181
2185
 
2182
- This object represents a service message about the creation of a scheduled giveaway. Currently holds no information.
2186
+ This object represents a service message about the creation of a scheduled giveaway.
2183
2187
  """
2184
2188
 
2189
+ prize_star_count: Option[int] = Nothing
2190
+ """Optional. The number of Telegram Stars to be split between giveaway winners;
2191
+ for Telegram Star giveaways only."""
2192
+
2185
2193
 
2186
2194
  class Giveaway(Model):
2187
2195
  """Object `Giveaway`, see the [documentation](https://core.telegram.org/bots/api#giveaway).
@@ -2214,9 +2222,13 @@ class Giveaway(Model):
2214
2222
  then all users can participate in the giveaway. Users with a phone number
2215
2223
  that was bought on Fragment can always participate in giveaways."""
2216
2224
 
2225
+ prize_star_count: Option[int] = Nothing
2226
+ """Optional. The number of Telegram Stars to be split between giveaway winners;
2227
+ for Telegram Star giveaways only."""
2228
+
2217
2229
  premium_subscription_month_count: Option[int] = Nothing
2218
2230
  """Optional. The number of months the Telegram Premium subscription won from
2219
- the giveaway will be active for."""
2231
+ the giveaway will be active for; for Telegram Premium giveaways only."""
2220
2232
 
2221
2233
 
2222
2234
  class GiveawayWinners(Model):
@@ -2244,9 +2256,13 @@ class GiveawayWinners(Model):
2244
2256
  """Optional. The number of other chats the user had to join in order to be eligible
2245
2257
  for the giveaway."""
2246
2258
 
2259
+ prize_star_count: Option[int] = Nothing
2260
+ """Optional. The number of Telegram Stars that were split between giveaway
2261
+ winners; for Telegram Star giveaways only."""
2262
+
2247
2263
  premium_subscription_month_count: Option[int] = Nothing
2248
2264
  """Optional. The number of months the Telegram Premium subscription won from
2249
- the giveaway will be active for."""
2265
+ the giveaway will be active for; for Telegram Premium giveaways only."""
2250
2266
 
2251
2267
  unclaimed_prize_count: Option[int] = Nothing
2252
2268
  """Optional. Number of undistributed prizes."""
@@ -2278,6 +2294,10 @@ class GiveawayCompleted(Model):
2278
2294
  giveaway_message: Option["Message"] = Nothing
2279
2295
  """Optional. Message with the giveaway that was completed, if it wasn't deleted."""
2280
2296
 
2297
+ is_star_giveaway: Option[bool] = Nothing
2298
+ """Optional. True, if the giveaway is a Telegram Star giveaway. Otherwise,
2299
+ currently, the giveaway is a Telegram Premium giveaway."""
2300
+
2281
2301
 
2282
2302
  class LinkPreviewOptions(Model):
2283
2303
  """Object `LinkPreviewOptions`, see the [documentation](https://core.telegram.org/bots/api#linkpreviewoptions).
@@ -3634,7 +3654,7 @@ class ChatBoostSourceGiftCode(ChatBoostSource):
3634
3654
  class ChatBoostSourceGiveaway(ChatBoostSource):
3635
3655
  """Object `ChatBoostSourceGiveaway`, see the [documentation](https://core.telegram.org/bots/api#chatboostsourcegiveaway).
3636
3656
 
3637
- The boost was obtained by the creation of a Telegram Premium giveaway. This boosts the chat 4 times for the duration of the corresponding Telegram Premium subscription.
3657
+ The boost was obtained by the creation of a Telegram Premium or a Telegram Star giveaway. This boosts the chat 4 times for the duration of the corresponding Telegram Premium subscription for Telegram Premium giveaways and prize_star_count / 500 times for one year for Telegram Star giveaways.
3638
3658
  """
3639
3659
 
3640
3660
  source: typing.Literal["giveaway"]
@@ -3645,7 +3665,12 @@ class ChatBoostSourceGiveaway(ChatBoostSource):
3645
3665
  have been deleted already. May be 0 if the message isn't sent yet."""
3646
3666
 
3647
3667
  user: Option["User"] = Nothing
3648
- """Optional. User that won the prize in the giveaway if any."""
3668
+ """Optional. User that won the prize in the giveaway if any; for Telegram Premium
3669
+ giveaways only."""
3670
+
3671
+ prize_star_count: Option[int] = Nothing
3672
+ """Optional. The number of Telegram Stars to be split between giveaway winners;
3673
+ for Telegram Star giveaways only."""
3649
3674
 
3650
3675
  is_unclaimed: Option[bool] = Nothing
3651
3676
  """Optional. True, if the giveaway was completed, but there was no user to win
@@ -5725,6 +5750,19 @@ class PreCheckoutQuery(Model):
5725
5750
  """Optional. Order information provided by the user."""
5726
5751
 
5727
5752
 
5753
+ class PaidMediaPurchased(Model):
5754
+ """Object `PaidMediaPurchased`, see the [documentation](https://core.telegram.org/bots/api#paidmediapurchased).
5755
+
5756
+ This object contains information about a paid media purchase.
5757
+ """
5758
+
5759
+ from_: "User"
5760
+ """User who purchased the media."""
5761
+
5762
+ paid_media_payload: str
5763
+ """Bot-specified paid media payload."""
5764
+
5765
+
5728
5766
  class RevenueWithdrawalStatePending(RevenueWithdrawalState):
5729
5767
  """Object `RevenueWithdrawalStatePending`, see the [documentation](https://core.telegram.org/bots/api#revenuewithdrawalstatepending).
5730
5768
 
@@ -5779,6 +5817,9 @@ class TransactionPartnerUser(TransactionPartner):
5779
5817
  paid_media: Option[list[Variative["PaidMediaPreview", "PaidMediaPhoto", "PaidMediaVideo"]]] = Nothing
5780
5818
  """Optional. Information about the paid media bought by the user."""
5781
5819
 
5820
+ paid_media_payload: Option[str] = Nothing
5821
+ """Optional. Bot-specified paid media payload."""
5822
+
5782
5823
 
5783
5824
  class TransactionPartnerFragment(TransactionPartner):
5784
5825
  """Object `TransactionPartnerFragment`, see the [documentation](https://core.telegram.org/bots/api#transactionpartnerfragment).
@@ -6428,6 +6469,7 @@ __all__ = (
6428
6469
  "PaidMediaInfo",
6429
6470
  "PaidMediaPhoto",
6430
6471
  "PaidMediaPreview",
6472
+ "PaidMediaPurchased",
6431
6473
  "PaidMediaVideo",
6432
6474
  "PassportData",
6433
6475
  "PassportElementError",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: telegrinder
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Modern visionary telegram bot framework.
5
5
  Home-page: https://github.com/timoniq/telegrinder
6
6
  License: MIT
@@ -43,8 +43,9 @@ Still in development.
43
43
  * Type hinted
44
44
  * Customizable and extensible
45
45
  * Ready to use scenarios and rules
46
- * Fast models built on msgspec
46
+ * Fast models built on [msgspec](https://github.com/jcrist/msgspec)
47
47
  * Both low-level and high-level API
48
+ * Support [optional dependecies](https://github.com/timoniq/telegrinder/blob/dev/docs/guide/optional_dependencies.md)
48
49
 
49
50
  # Getting started
50
51
 
@@ -85,9 +86,7 @@ logger.set_level("INFO")
85
86
  @bot.on.message(Text("/start"))
86
87
  async def start(message: Message):
87
88
  me = (await api.get_me()).unwrap()
88
- await message.answer(
89
- f"Hello, {message.from_user.full_name}! I'm {me.full_name}."
90
- )
89
+ await message.answer(f"Hello, {message.from_user.full_name}! I'm {me.full_name}.")
91
90
 
92
91
 
93
92
  bot.run_forever()