telegrinder 0.3.4__py3-none-any.whl → 0.4.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 (192) hide show
  1. telegrinder/__init__.py +148 -149
  2. telegrinder/api/__init__.py +9 -8
  3. telegrinder/api/api.py +101 -93
  4. telegrinder/api/error.py +20 -16
  5. telegrinder/api/response.py +20 -20
  6. telegrinder/api/token.py +36 -36
  7. telegrinder/bot/__init__.py +72 -66
  8. telegrinder/bot/bot.py +83 -76
  9. telegrinder/bot/cute_types/__init__.py +19 -17
  10. telegrinder/bot/cute_types/base.py +184 -258
  11. telegrinder/bot/cute_types/callback_query.py +400 -385
  12. telegrinder/bot/cute_types/chat_join_request.py +62 -61
  13. telegrinder/bot/cute_types/chat_member_updated.py +157 -160
  14. telegrinder/bot/cute_types/inline_query.py +44 -43
  15. telegrinder/bot/cute_types/message.py +2590 -2637
  16. telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
  17. telegrinder/bot/cute_types/update.py +112 -104
  18. telegrinder/bot/cute_types/utils.py +62 -95
  19. telegrinder/bot/dispatch/__init__.py +59 -55
  20. telegrinder/bot/dispatch/abc.py +76 -77
  21. telegrinder/bot/dispatch/context.py +96 -98
  22. telegrinder/bot/dispatch/dispatch.py +254 -202
  23. telegrinder/bot/dispatch/handler/__init__.py +13 -13
  24. telegrinder/bot/dispatch/handler/abc.py +23 -24
  25. telegrinder/bot/dispatch/handler/audio_reply.py +44 -44
  26. telegrinder/bot/dispatch/handler/base.py +57 -57
  27. telegrinder/bot/dispatch/handler/document_reply.py +44 -44
  28. telegrinder/bot/dispatch/handler/func.py +129 -135
  29. telegrinder/bot/dispatch/handler/media_group_reply.py +44 -43
  30. telegrinder/bot/dispatch/handler/message_reply.py +36 -36
  31. telegrinder/bot/dispatch/handler/photo_reply.py +44 -44
  32. telegrinder/bot/dispatch/handler/sticker_reply.py +37 -37
  33. telegrinder/bot/dispatch/handler/video_reply.py +44 -44
  34. telegrinder/bot/dispatch/middleware/__init__.py +3 -3
  35. telegrinder/bot/dispatch/middleware/abc.py +97 -22
  36. telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
  37. telegrinder/bot/dispatch/process.py +151 -157
  38. telegrinder/bot/dispatch/return_manager/__init__.py +15 -13
  39. telegrinder/bot/dispatch/return_manager/abc.py +104 -108
  40. telegrinder/bot/dispatch/return_manager/callback_query.py +20 -20
  41. telegrinder/bot/dispatch/return_manager/inline_query.py +15 -15
  42. telegrinder/bot/dispatch/return_manager/message.py +36 -36
  43. telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +20 -0
  44. telegrinder/bot/dispatch/view/__init__.py +15 -13
  45. telegrinder/bot/dispatch/view/abc.py +45 -41
  46. telegrinder/bot/dispatch/view/base.py +231 -200
  47. telegrinder/bot/dispatch/view/box.py +140 -129
  48. telegrinder/bot/dispatch/view/callback_query.py +16 -17
  49. telegrinder/bot/dispatch/view/chat_join_request.py +11 -16
  50. telegrinder/bot/dispatch/view/chat_member.py +37 -39
  51. telegrinder/bot/dispatch/view/inline_query.py +16 -17
  52. telegrinder/bot/dispatch/view/message.py +43 -44
  53. telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
  54. telegrinder/bot/dispatch/view/raw.py +116 -114
  55. telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
  56. telegrinder/bot/dispatch/waiter_machine/actions.py +14 -13
  57. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
  58. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +55 -55
  59. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +59 -57
  60. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +51 -51
  61. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +20 -19
  62. telegrinder/bot/dispatch/waiter_machine/machine.py +251 -172
  63. telegrinder/bot/dispatch/waiter_machine/middleware.py +94 -89
  64. telegrinder/bot/dispatch/waiter_machine/short_state.py +57 -68
  65. telegrinder/bot/polling/__init__.py +4 -4
  66. telegrinder/bot/polling/abc.py +25 -25
  67. telegrinder/bot/polling/polling.py +139 -131
  68. telegrinder/bot/rules/__init__.py +85 -62
  69. telegrinder/bot/rules/abc.py +213 -206
  70. telegrinder/bot/rules/callback_data.py +122 -163
  71. telegrinder/bot/rules/chat_join.py +45 -43
  72. telegrinder/bot/rules/command.py +126 -126
  73. telegrinder/bot/rules/enum_text.py +33 -36
  74. telegrinder/bot/rules/func.py +28 -26
  75. telegrinder/bot/rules/fuzzy.py +24 -24
  76. telegrinder/bot/rules/id.py +24 -0
  77. telegrinder/bot/rules/inline.py +58 -56
  78. telegrinder/bot/rules/integer.py +21 -20
  79. telegrinder/bot/rules/is_from.py +127 -127
  80. telegrinder/bot/rules/logic.py +18 -0
  81. telegrinder/bot/rules/markup.py +42 -43
  82. telegrinder/bot/rules/mention.py +14 -14
  83. telegrinder/bot/rules/message.py +15 -17
  84. telegrinder/bot/rules/message_entities.py +33 -35
  85. telegrinder/bot/rules/node.py +33 -27
  86. telegrinder/bot/rules/payload.py +81 -0
  87. telegrinder/bot/rules/payment_invoice.py +29 -0
  88. telegrinder/bot/rules/regex.py +36 -37
  89. telegrinder/bot/rules/rule_enum.py +72 -72
  90. telegrinder/bot/rules/start.py +42 -42
  91. telegrinder/bot/rules/state.py +35 -37
  92. telegrinder/bot/rules/text.py +38 -33
  93. telegrinder/bot/rules/update.py +15 -15
  94. telegrinder/bot/scenario/__init__.py +5 -5
  95. telegrinder/bot/scenario/abc.py +17 -19
  96. telegrinder/bot/scenario/checkbox.py +174 -176
  97. telegrinder/bot/scenario/choice.py +48 -51
  98. telegrinder/client/__init__.py +12 -4
  99. telegrinder/client/abc.py +100 -75
  100. telegrinder/client/aiohttp.py +134 -130
  101. telegrinder/client/form_data.py +31 -0
  102. telegrinder/client/sonic.py +212 -0
  103. telegrinder/model.py +208 -315
  104. telegrinder/modules.py +239 -237
  105. telegrinder/msgspec_json.py +14 -14
  106. telegrinder/msgspec_utils.py +478 -410
  107. telegrinder/node/__init__.py +86 -25
  108. telegrinder/node/attachment.py +163 -87
  109. telegrinder/node/base.py +288 -160
  110. telegrinder/node/callback_query.py +54 -53
  111. telegrinder/node/command.py +34 -33
  112. telegrinder/node/composer.py +163 -198
  113. telegrinder/node/container.py +33 -27
  114. telegrinder/node/either.py +82 -0
  115. telegrinder/node/event.py +54 -65
  116. telegrinder/node/file.py +51 -0
  117. telegrinder/node/me.py +15 -16
  118. telegrinder/node/payload.py +78 -0
  119. telegrinder/node/polymorphic.py +67 -48
  120. telegrinder/node/rule.py +72 -76
  121. telegrinder/node/scope.py +36 -38
  122. telegrinder/node/source.py +87 -71
  123. telegrinder/node/text.py +53 -41
  124. telegrinder/node/tools/__init__.py +3 -3
  125. telegrinder/node/tools/generator.py +36 -40
  126. telegrinder/py.typed +0 -0
  127. telegrinder/rules.py +1 -62
  128. telegrinder/tools/__init__.py +152 -93
  129. telegrinder/tools/adapter/__init__.py +19 -0
  130. telegrinder/tools/adapter/abc.py +49 -0
  131. telegrinder/tools/adapter/dataclass.py +56 -0
  132. telegrinder/{bot/rules → tools}/adapter/errors.py +5 -5
  133. telegrinder/{bot/rules → tools}/adapter/event.py +63 -65
  134. telegrinder/{bot/rules → tools}/adapter/node.py +46 -48
  135. telegrinder/{bot/rules → tools}/adapter/raw_event.py +27 -27
  136. telegrinder/{bot/rules → tools}/adapter/raw_update.py +30 -30
  137. telegrinder/tools/buttons.py +106 -80
  138. telegrinder/tools/callback_data_serilization/__init__.py +5 -0
  139. telegrinder/tools/callback_data_serilization/abc.py +51 -0
  140. telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
  141. telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
  142. telegrinder/tools/error_handler/__init__.py +7 -7
  143. telegrinder/tools/error_handler/abc.py +30 -33
  144. telegrinder/tools/error_handler/error.py +9 -9
  145. telegrinder/tools/error_handler/error_handler.py +179 -193
  146. telegrinder/tools/formatting/__init__.py +83 -63
  147. telegrinder/tools/formatting/deep_links.py +541 -0
  148. telegrinder/tools/formatting/{html.py → html_formatter.py} +266 -294
  149. telegrinder/tools/formatting/spec_html_formats.py +71 -117
  150. telegrinder/tools/functional.py +8 -12
  151. telegrinder/tools/global_context/__init__.py +7 -7
  152. telegrinder/tools/global_context/abc.py +63 -63
  153. telegrinder/tools/global_context/global_context.py +387 -412
  154. telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
  155. telegrinder/tools/i18n/__init__.py +7 -7
  156. telegrinder/tools/i18n/abc.py +30 -30
  157. telegrinder/tools/i18n/middleware/__init__.py +3 -3
  158. telegrinder/tools/i18n/middleware/abc.py +22 -25
  159. telegrinder/tools/i18n/simple.py +43 -43
  160. telegrinder/tools/input_file_directory.py +30 -0
  161. telegrinder/tools/keyboard.py +128 -128
  162. telegrinder/tools/lifespan.py +105 -0
  163. telegrinder/tools/limited_dict.py +32 -37
  164. telegrinder/tools/loop_wrapper/__init__.py +4 -4
  165. telegrinder/tools/loop_wrapper/abc.py +20 -15
  166. telegrinder/tools/loop_wrapper/loop_wrapper.py +169 -224
  167. telegrinder/tools/magic.py +307 -157
  168. telegrinder/tools/parse_mode.py +6 -6
  169. telegrinder/tools/state_storage/__init__.py +4 -4
  170. telegrinder/tools/state_storage/abc.py +31 -35
  171. telegrinder/tools/state_storage/memory.py +25 -25
  172. telegrinder/tools/strings.py +13 -0
  173. telegrinder/types/__init__.py +268 -260
  174. telegrinder/types/enums.py +711 -701
  175. telegrinder/types/input_file.py +51 -0
  176. telegrinder/types/methods.py +5055 -4633
  177. telegrinder/types/objects.py +7058 -6950
  178. telegrinder/verification_utils.py +30 -32
  179. {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/LICENSE +22 -22
  180. telegrinder-0.4.0.dist-info/METADATA +144 -0
  181. telegrinder-0.4.0.dist-info/RECORD +182 -0
  182. {telegrinder-0.3.4.dist-info → telegrinder-0.4.0.dist-info}/WHEEL +1 -1
  183. telegrinder/bot/rules/adapter/__init__.py +0 -17
  184. telegrinder/bot/rules/adapter/abc.py +0 -31
  185. telegrinder/node/message.py +0 -14
  186. telegrinder/node/update.py +0 -15
  187. telegrinder/tools/formatting/links.py +0 -38
  188. telegrinder/tools/kb_set/__init__.py +0 -4
  189. telegrinder/tools/kb_set/base.py +0 -15
  190. telegrinder/tools/kb_set/yaml.py +0 -63
  191. telegrinder-0.3.4.dist-info/METADATA +0 -110
  192. telegrinder-0.3.4.dist-info/RECORD +0 -165
@@ -1,54 +1,113 @@
1
- from .attachment import Attachment, Audio, Photo, Video
2
- from .base import ComposeError, DataNode, Name, Node, ScalarNode, is_node
3
- from .callback_query import CallbackQueryData, CallbackQueryNode, Field
4
- from .command import CommandInfo
5
- from .composer import Composition, NodeCollection, NodeSession, compose_node, compose_nodes
6
- from .container import ContainerNode
7
- from .event import EventNode
8
- from .me import Me
9
- from .message import MessageNode
10
- from .polymorphic import Polymorphic, impl
11
- from .rule import RuleChain
12
- from .scope import GLOBAL, PER_CALL, PER_EVENT, NodeScope, global_node, per_call, per_event
13
- from .source import ChatSource, Source, UserSource
14
- from .text import Text, TextInteger, TextLiteral
15
- from .tools import generate_node
16
- from .update import UpdateNode
17
-
18
- __all__ = (
1
+ from .attachment import (
2
+ Animation,
3
+ Attachment,
4
+ Audio,
5
+ Document,
6
+ Photo,
7
+ SuccessfulPayment,
8
+ Video,
9
+ VideoNote,
10
+ Voice,
11
+ )
12
+ from .base import (
13
+ Composable,
14
+ ComposeError,
15
+ DataNode,
16
+ FactoryNode,
17
+ GlobalNode,
18
+ IsNode,
19
+ Name,
20
+ Node,
21
+ NodeComposeFunction,
22
+ NodeImpersonation,
23
+ NodeProto,
24
+ NodeType,
25
+ as_node,
26
+ is_node,
27
+ scalar_node,
28
+ unwrap_node,
29
+ )
30
+ from .callback_query import (
31
+ CallbackQueryData,
32
+ CallbackQueryDataJson,
33
+ Field,
34
+ )
35
+ from .command import CommandInfo
36
+ from .composer import NodeCollection, NodeSession, compose_node, compose_nodes
37
+ from .container import ContainerNode
38
+ from .either import Either, Optional
39
+ from .event import EventNode
40
+ from .file import File, FileId
41
+ from .me import Me
42
+ from .payload import Payload, PayloadData, PayloadSerializer
43
+ from .polymorphic import Polymorphic, impl
44
+ from .rule import RuleChain
45
+ from .scope import (
46
+ GLOBAL,
47
+ PER_CALL,
48
+ PER_EVENT,
49
+ NodeScope,
50
+ global_node,
51
+ per_call,
52
+ per_event,
53
+ )
54
+ from .source import ChatSource, Source, UserId, UserSource
55
+ from .text import Text, TextInteger, TextLiteral
56
+ from .tools import generate_node
57
+
58
+ __all__ = (
59
+ "Animation",
19
60
  "Attachment",
20
61
  "Audio",
21
62
  "CallbackQueryData",
22
- "CallbackQueryNode",
63
+ "CallbackQueryDataJson",
23
64
  "ChatSource",
24
65
  "CommandInfo",
66
+ "Composable",
25
67
  "ComposeError",
26
- "Composition",
27
68
  "ContainerNode",
28
69
  "DataNode",
70
+ "Document",
71
+ "Either",
29
72
  "EventNode",
73
+ "FactoryNode",
30
74
  "Field",
75
+ "Field",
76
+ "File",
77
+ "FileId",
31
78
  "GLOBAL",
79
+ "GlobalNode",
80
+ "IsNode",
32
81
  "Me",
33
- "MessageNode",
34
82
  "Name",
35
83
  "Node",
36
84
  "NodeCollection",
85
+ "NodeComposeFunction",
86
+ "NodeImpersonation",
87
+ "NodeProto",
37
88
  "NodeScope",
38
89
  "NodeSession",
90
+ "NodeType",
91
+ "Optional",
39
92
  "PER_CALL",
40
93
  "PER_EVENT",
94
+ "Payload",
95
+ "PayloadData",
96
+ "PayloadSerializer",
41
97
  "Photo",
42
98
  "Polymorphic",
43
99
  "RuleChain",
44
- "ScalarNode",
45
100
  "Source",
101
+ "SuccessfulPayment",
46
102
  "Text",
47
103
  "TextInteger",
48
104
  "TextLiteral",
49
- "UpdateNode",
105
+ "UserId",
50
106
  "UserSource",
51
107
  "Video",
108
+ "VideoNote",
109
+ "Voice",
110
+ "as_node",
52
111
  "compose_node",
53
112
  "compose_nodes",
54
113
  "generate_node",
@@ -56,5 +115,7 @@ __all__ = (
56
115
  "impl",
57
116
  "is_node",
58
117
  "per_call",
59
- "per_event",
60
- )
118
+ "per_event",
119
+ "scalar_node",
120
+ "unwrap_node",
121
+ )
@@ -1,92 +1,168 @@
1
- import dataclasses
2
- import typing
3
-
4
- from fntypes.co import Option, Some
5
- from fntypes.option import Nothing
6
-
7
- import telegrinder.types
8
- from telegrinder.node.base import ComposeError, DataNode, ScalarNode
9
- from telegrinder.node.message import MessageNode
10
-
11
-
12
- @dataclasses.dataclass(slots=True)
13
- class Attachment(DataNode):
14
- attachment_type: typing.Literal["audio", "document", "photo", "poll", "video"]
15
- audio: Option[telegrinder.types.Audio] = dataclasses.field(
16
- default_factory=lambda: Nothing(),
17
- kw_only=True,
18
- )
19
- document: Option[telegrinder.types.Document] = dataclasses.field(
20
- default_factory=lambda: Nothing(),
21
- kw_only=True,
22
- )
23
- photo: Option[list[telegrinder.types.PhotoSize]] = dataclasses.field(
24
- default_factory=lambda: Nothing(),
25
- kw_only=True,
26
- )
27
- poll: Option[telegrinder.types.Poll] = dataclasses.field(default_factory=lambda: Nothing(), kw_only=True)
28
- video: Option[telegrinder.types.Video] = dataclasses.field(
29
- default_factory=lambda: Nothing(),
30
- kw_only=True,
31
- )
32
-
33
- @classmethod
34
- def compose(cls, message: MessageNode) -> "Attachment":
35
- for attachment_type in ("audio", "document", "photo", "poll", "video"):
36
- match getattr(message, attachment_type, Nothing()):
37
- case Some(attachment):
38
- return cls(attachment_type, **{attachment_type: Some(attachment)})
39
- return cls.compose_error("No attachment found in message.")
40
-
41
-
42
- @dataclasses.dataclass(slots=True)
43
- class Photo(DataNode):
44
- sizes: list[telegrinder.types.PhotoSize]
45
-
46
- @classmethod
47
- def compose(cls, attachment: Attachment) -> typing.Self:
48
- if not attachment.photo:
49
- raise ComposeError("Attachment is not a photo.")
50
- return cls(attachment.photo.unwrap())
51
-
52
-
53
- class Video(ScalarNode, telegrinder.types.Video):
54
- @classmethod
55
- def compose(cls, attachment: Attachment) -> telegrinder.types.Video:
56
- if not attachment.video:
57
- raise ComposeError("Attachment is not a video.")
58
- return attachment.video.unwrap()
59
-
60
-
61
- class Audio(ScalarNode, telegrinder.types.Audio):
62
- @classmethod
63
- def compose(cls, attachment: Attachment) -> telegrinder.types.Audio:
64
- if not attachment.audio:
65
- raise ComposeError("Attachment is not an audio.")
66
- return attachment.audio.unwrap()
67
-
68
-
69
- class Document(ScalarNode, telegrinder.types.Document):
70
- @classmethod
71
- def compose(cls, attachment: Attachment) -> telegrinder.types.Document:
72
- if not attachment.document:
73
- raise ComposeError("Attachment is not a document.")
74
- return attachment.document.unwrap()
75
-
76
-
77
- class Poll(ScalarNode, telegrinder.types.Poll):
78
- @classmethod
79
- def compose(cls, attachment: Attachment) -> telegrinder.types.Poll:
80
- if not attachment.poll:
81
- raise ComposeError("Attachment is not a poll.")
82
- return attachment.poll.unwrap()
83
-
84
-
85
- __all__ = (
1
+ import dataclasses
2
+ import typing
3
+
4
+ from fntypes.option import Nothing, Option, Some
5
+
6
+ import telegrinder.types
7
+ from telegrinder.bot.cute_types.message import MessageCute
8
+ from telegrinder.node.base import ComposeError, DataNode, scalar_node
9
+
10
+ type AttachmentType = typing.Literal[
11
+ "audio",
12
+ "animation",
13
+ "document",
14
+ "photo",
15
+ "poll",
16
+ "voice",
17
+ "video",
18
+ "video_note",
19
+ "successful_payment",
20
+ ]
21
+
22
+
23
+ @dataclasses.dataclass(slots=True)
24
+ class Attachment(DataNode):
25
+ attachment_type: AttachmentType
26
+
27
+ animation: Option[telegrinder.types.Animation] = dataclasses.field(
28
+ default_factory=Nothing,
29
+ kw_only=True,
30
+ )
31
+ audio: Option[telegrinder.types.Audio] = dataclasses.field(
32
+ default_factory=Nothing,
33
+ kw_only=True,
34
+ )
35
+ document: Option[telegrinder.types.Document] = dataclasses.field(
36
+ default_factory=Nothing,
37
+ kw_only=True,
38
+ )
39
+ photo: Option[list[telegrinder.types.PhotoSize]] = dataclasses.field(
40
+ default_factory=Nothing,
41
+ kw_only=True,
42
+ )
43
+ poll: Option[telegrinder.types.Poll] = dataclasses.field(default_factory=lambda: Nothing(), kw_only=True)
44
+ voice: Option[telegrinder.types.Voice] = dataclasses.field(
45
+ default_factory=Nothing,
46
+ kw_only=True,
47
+ )
48
+ video: Option[telegrinder.types.Video] = dataclasses.field(
49
+ default_factory=Nothing,
50
+ kw_only=True,
51
+ )
52
+ video_note: Option[telegrinder.types.VideoNote] = dataclasses.field(
53
+ default_factory=Nothing,
54
+ kw_only=True,
55
+ )
56
+ successful_payment: Option[telegrinder.types.SuccessfulPayment] = dataclasses.field(
57
+ default_factory=Nothing,
58
+ kw_only=True,
59
+ )
60
+
61
+ @classmethod
62
+ def get_attachment_types(cls) -> tuple[AttachmentType, ...]:
63
+ return typing.get_args(AttachmentType.__value__)
64
+
65
+ @classmethod
66
+ def compose(cls, message: MessageCute) -> typing.Self:
67
+ for attachment_type in cls.get_attachment_types():
68
+ match getattr(message, attachment_type, Nothing()):
69
+ case Some(attachment):
70
+ return cls(attachment_type, **{attachment_type: Some(attachment)})
71
+ raise ComposeError("No attachment found in message.")
72
+
73
+
74
+ @dataclasses.dataclass(slots=True)
75
+ class Photo(DataNode):
76
+ sizes: list[telegrinder.types.PhotoSize]
77
+
78
+ @classmethod
79
+ def compose(cls, attachment: Attachment) -> typing.Self:
80
+ if not attachment.photo:
81
+ raise ComposeError("Attachment is not a photo.")
82
+ return cls(attachment.photo.unwrap())
83
+
84
+
85
+ @scalar_node
86
+ class Video:
87
+ @classmethod
88
+ def compose(cls, attachment: Attachment) -> telegrinder.types.Video:
89
+ if not attachment.video:
90
+ raise ComposeError("Attachment is not a video.")
91
+ return attachment.video.unwrap()
92
+
93
+
94
+ @scalar_node
95
+ class VideoNote:
96
+ @classmethod
97
+ def compose(cls, attachment: Attachment) -> telegrinder.types.VideoNote:
98
+ if not attachment.video_note:
99
+ raise ComposeError("Attachment is not a video note.")
100
+ return attachment.video_note.unwrap()
101
+
102
+
103
+ @scalar_node
104
+ class Audio:
105
+ @classmethod
106
+ def compose(cls, attachment: Attachment) -> telegrinder.types.Audio:
107
+ if not attachment.audio:
108
+ raise ComposeError("Attachment is not an audio.")
109
+ return attachment.audio.unwrap()
110
+
111
+
112
+ @scalar_node
113
+ class Animation:
114
+ @classmethod
115
+ def compose(cls, attachment: Attachment) -> telegrinder.types.Animation:
116
+ if not attachment.animation:
117
+ raise ComposeError("Attachment is not an animation.")
118
+ return attachment.animation.unwrap()
119
+
120
+
121
+ @scalar_node
122
+ class Voice:
123
+ @classmethod
124
+ def compose(cls, attachment: Attachment) -> telegrinder.types.Voice:
125
+ if not attachment.voice:
126
+ raise ComposeError("Attachment is not a voice.")
127
+ return attachment.voice.unwrap()
128
+
129
+
130
+ @scalar_node
131
+ class Document:
132
+ @classmethod
133
+ def compose(cls, attachment: Attachment) -> telegrinder.types.Document:
134
+ if not attachment.document:
135
+ raise ComposeError("Attachment is not a document.")
136
+ return attachment.document.unwrap()
137
+
138
+
139
+ @scalar_node
140
+ class Poll:
141
+ @classmethod
142
+ def compose(cls, attachment: Attachment) -> telegrinder.types.Poll:
143
+ if not attachment.poll:
144
+ raise ComposeError("Attachment is not a poll.")
145
+ return attachment.poll.unwrap()
146
+
147
+
148
+ @scalar_node
149
+ class SuccessfulPayment:
150
+ @classmethod
151
+ def compose(cls, attachment: Attachment) -> telegrinder.types.SuccessfulPayment:
152
+ if not attachment.successful_payment:
153
+ raise ComposeError("Attachment is not a successful payment.")
154
+ return attachment.successful_payment.unwrap()
155
+
156
+
157
+ __all__ = (
158
+ "Animation",
86
159
  "Attachment",
87
160
  "Audio",
88
161
  "Document",
89
162
  "Photo",
90
163
  "Poll",
91
- "Video",
92
- )
164
+ "SuccessfulPayment",
165
+ "Video",
166
+ "VideoNote",
167
+ "Voice",
168
+ )