pyrobale 0.2.9.4__py3-none-any.whl → 0.3.5__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.
Files changed (47) hide show
  1. pyrobale/__init__.py +3 -0
  2. pyrobale/client/__init__.py +574 -0
  3. pyrobale/exceptions/__init__.py +0 -0
  4. pyrobale/exceptions/common.py +10 -0
  5. pyrobale/objects/__init__.py +86 -0
  6. pyrobale/objects/animation.py +33 -0
  7. pyrobale/objects/audio.py +24 -0
  8. pyrobale/objects/callbackquery.py +42 -0
  9. pyrobale/objects/chat.py +463 -0
  10. pyrobale/objects/chatmember.py +162 -0
  11. pyrobale/objects/chatphoto.py +18 -0
  12. pyrobale/objects/contact.py +16 -0
  13. pyrobale/objects/copytextbutton.py +5 -0
  14. pyrobale/objects/document.py +26 -0
  15. pyrobale/objects/enums.py +28 -0
  16. pyrobale/objects/file.py +15 -0
  17. pyrobale/objects/inlinekeyboardbutton.py +24 -0
  18. pyrobale/objects/inlinekeyboardmarkup.py +84 -0
  19. pyrobale/objects/inputfile.py +17 -0
  20. pyrobale/objects/inputmedias.py +166 -0
  21. pyrobale/objects/invoice.py +14 -0
  22. pyrobale/objects/keyboardbutton.py +19 -0
  23. pyrobale/objects/labeledprice.py +8 -0
  24. pyrobale/objects/location.py +4 -0
  25. pyrobale/objects/message.py +368 -0
  26. pyrobale/objects/messageid.py +3 -0
  27. pyrobale/objects/photosize.py +9 -0
  28. pyrobale/objects/precheckoutquery.py +21 -0
  29. pyrobale/objects/replykeyboardmarkup.py +54 -0
  30. pyrobale/objects/sticker.py +16 -0
  31. pyrobale/objects/stickerset.py +12 -0
  32. pyrobale/objects/successfulpayment.py +15 -0
  33. pyrobale/objects/update.py +23 -0
  34. pyrobale/objects/user.py +20 -0
  35. pyrobale/objects/utils.py +28 -0
  36. pyrobale/objects/video.py +20 -0
  37. pyrobale/objects/voice.py +4 -0
  38. pyrobale/objects/webappdata.py +3 -0
  39. pyrobale/objects/webappinfo.py +3 -0
  40. pyrobale-0.3.5.dist-info/METADATA +176 -0
  41. pyrobale-0.3.5.dist-info/RECORD +43 -0
  42. pyrobale-0.3.5.dist-info/licenses/LICENSE +21 -0
  43. pyrobale-0.2.9.4.dist-info/METADATA +0 -833
  44. pyrobale-0.2.9.4.dist-info/RECORD +0 -5
  45. pyrobale-0.2.9.4.dist-info/licenses/LICENSE +0 -678
  46. pyrobale.py +0 -2545
  47. {pyrobale-0.2.9.4.dist-info → pyrobale-0.3.5.dist-info}/WHEEL +0 -0
@@ -0,0 +1,368 @@
1
+ from typing import TYPE_CHECKING
2
+ from typing import Optional, Union
3
+
4
+ if TYPE_CHECKING:
5
+ from .utils import build_api_url
6
+ from ..objects.user import User
7
+ from ..objects.chat import Chat
8
+ from ..objects.chatphoto import ChatPhoto
9
+ from ..objects.animation import Animation
10
+ from ..objects.audio import Audio
11
+ from ..objects.document import Document
12
+ from ..objects.photosize import PhotoSize
13
+ from ..objects.sticker import Sticker
14
+ from ..objects.video import Video
15
+ from ..objects.voice import Voice
16
+ from ..objects.contact import Contact
17
+ from ..objects.location import Location
18
+ from ..objects.invoice import Invoice
19
+ from ..objects.successfulpayment import SuccessfulPayment
20
+ from ..objects.webappdata import WebAppData
21
+ from ..objects.webappinfo import WebAppInfo
22
+ from ..objects.inlinekeyboardmarkup import InlineKeyboardMarkup
23
+ from ..objects.replykeyboardmarkup import ReplyKeyboardMarkup
24
+ from ..client import Client
25
+ from ..objects.chat import Chat
26
+ from ..objects.user import User
27
+ import asyncio
28
+ import aiohttp
29
+
30
+
31
+ class Message:
32
+ """This class represents a Message object in Telegram.
33
+
34
+ A message can contain various types of content like text, media, location, etc.
35
+ It also provides methods to reply, edit, delete, and forward messages.
36
+
37
+ Attributes:
38
+ id (int): Unique message identifier
39
+ user (User): Sender of the message
40
+ date (int): Date the message was sent in Unix time
41
+ chat (Chat): Conversation the message belongs to
42
+ text (str): Text content of the message
43
+ forward_from (User): Original sender of a forwarded message
44
+ forward_from_chat (Chat): Original chat of a forwarded message
45
+ forward_from_message_id (int): Message ID in the original chat
46
+ forward_date (int): Date when message was forwarded
47
+ edite_date (int): Date when message was last edited
48
+ animation (Animation): Message is an animation
49
+ audio (Audio): Message is an audio file
50
+ document (Document): Message is a general file
51
+ photo (list[PhotoSize]): Message is a photo
52
+ sticker (Sticker): Message is a sticker
53
+ video (Video): Message is a video
54
+ voice (Voice): Message is a voice message
55
+ caption (str): Caption for media messages
56
+ contact (Contact): Message is a shared contact
57
+ location (Location): Message is a shared location
58
+ new_chat_members (list[User]): New members added to the chat
59
+ left_chat_member (User): Member removed from the chat
60
+ invoice (Invoice): Message is an invoice for payment
61
+ successful_payment (SuccessfulPayment): Message is a service message about successful payment
62
+ web_app_data (WebAppData): Data from a Web App
63
+ reply_markup (InlineKeyboardMarkup): Inline keyboard attached to the message
64
+ client (Client): Client instance associated with this message
65
+ """
66
+
67
+ def __init__(
68
+ self,
69
+ message_id: Optional[int] = None,
70
+ from_user: Optional["User"] = None,
71
+ date: Optional[int] = None,
72
+ chat: Optional["Chat"] = None,
73
+ text: Optional[str] = None,
74
+ forward_from: Optional["User"] = None,
75
+ forward_from_chat: Optional["Chat"] = None,
76
+ forward_from_message_id: Optional[int] = None,
77
+ forward_date: Optional[int] = None,
78
+ edite_date: Optional[int] = None,
79
+ animation: Optional["Animation"] = None,
80
+ audio: Optional["Audio"] = None,
81
+ document: Optional["Document"] = None,
82
+ photo: Optional[list["PhotoSize"]] = None,
83
+ sticker: Optional["Sticker"] = None,
84
+ video: Optional["Video"] = None,
85
+ voice: Optional["Voice"] = None,
86
+ caption: Optional[str] = None,
87
+ contact: Optional["Contact"] = None,
88
+ location: Optional["Location"] = None,
89
+ new_chat_members: Optional[list["User"]] = None,
90
+ left_chat_member: Optional["User"] = None,
91
+ invoice: Optional["Invoice"] = None,
92
+ successful_payment: Optional["SuccessfulPayment"] = None,
93
+ web_app_data: Optional["WebAppData"] = None,
94
+ reply_markup: Optional["InlineKeyboardMarkup"] = None,
95
+ **kwargs
96
+ ):
97
+ """Initialize a Message object with the provided attributes.
98
+
99
+ Args:
100
+ message_id: Unique message identifier
101
+ from_user: Sender of the message
102
+ date: Date the message was sent
103
+ chat: Conversation the message belongs to
104
+ text: Text content of the message
105
+ forward_from: Original sender of a forwarded message
106
+ forward_from_chat: Original chat of a forwarded message
107
+ forward_from_message_id: Message ID in the original chat
108
+ forward_date: Date when message was forwarded
109
+ edite_date: Date when message was last edited
110
+ animation: Animation content
111
+ audio: Audio content
112
+ document: Document content
113
+ photo: Photo content
114
+ sticker: Sticker content
115
+ video: Video content
116
+ voice: Voice message content
117
+ caption: Caption for media messages
118
+ contact: Contact content
119
+ location: Location content
120
+ new_chat_members: New members added to the chat
121
+ left_chat_member: Member removed from the chat
122
+ invoice: Invoice content
123
+ successful_payment: Successful payment information
124
+ web_app_data: Web App data
125
+ reply_markup: Inline keyboard markup
126
+ **kwargs: Additional keyword arguments
127
+ """
128
+ self.id: int = message_id
129
+ self.user: "User" = User(**from_user) if from_user else None
130
+ self.date: int = date
131
+ self.chat: Optional["Chat"] = (
132
+ chat if isinstance(chat, Chat) else Chat(**chat) if chat else None
133
+ )
134
+ self.forward_from: Optional["User"] = forward_from
135
+ self.forward_from_chat: Optional["Chat"] = forward_from_chat
136
+ self.forward_from_message_id: Optional[int] = forward_from_message_id
137
+ self.forward_date: Optional[int] = forward_date
138
+ self.edite_date: Optional[int] = edite_date
139
+ self.text: Optional[str] = text
140
+ self.animation: Optional["Animation"] = animation
141
+ self.audio: Optional["Audio"] = audio
142
+ self.document: Optional["Document"] = document
143
+ self.photo: Optional[list["PhotoSize"]] = photo
144
+ self.sticker: Optional["Sticker"] = sticker
145
+ self.video: Optional["Video"] = video
146
+ self.voice: Optional["Voice"] = voice
147
+ self.caption: Optional[str] = caption
148
+ self.contact: Optional["Contact"] = contact
149
+ self.location: Optional["Location"] = location
150
+ self.new_chat_members: Optional[list["User"]] = new_chat_members
151
+ self.left_chat_member: Optional["User"] = left_chat_member
152
+ self.invoice: Optional["Invoice"] = invoice
153
+ self.successful_payment: Optional["SuccessfulPayment"] = successful_payment
154
+ self.web_app_data: Optional["WebAppData"] = web_app_data
155
+ self.reply_markup: Optional["InlineKeyboardMarkup"] = reply_markup
156
+ self.client: Client = kwargs.get("kwargs", {}).get("client")
157
+
158
+ async def reply(
159
+ self,
160
+ text: str,
161
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
162
+ ):
163
+ """Reply to the current message with text.
164
+
165
+ Args:
166
+ text: The text to send
167
+ reply_markup: Optional keyboard markup for the message
168
+ """
169
+ if self.chat and self.chat.id:
170
+ await self.client.send_message(
171
+ self.chat.id, text, reply_markup=reply_markup
172
+ )
173
+
174
+ async def edit(
175
+ self,
176
+ text: str,
177
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
178
+ ):
179
+ """Edit the current message text.
180
+
181
+ Args:
182
+ text: The new text
183
+ reply_markup: Optional new keyboard markup
184
+ """
185
+ if self.chat and self.chat.id and self.id:
186
+ await self.client.edit_message(
187
+ self.chat.id, self.id, text, reply_markup=reply_markup
188
+ )
189
+
190
+ async def delete(self):
191
+ """Delete the current message."""
192
+ if self.chat and self.chat.id and self.id:
193
+ await self.client.delete(self.chat.id, self.id)
194
+
195
+ async def forward(self, chat_id: int):
196
+ """Forward the current message to another chat.
197
+
198
+ Args:
199
+ chat_id: Destination chat ID
200
+ """
201
+ if self.chat and self.chat.id and self.id:
202
+ await self.client.forward(self.chat.id, chat_id, self.id)
203
+
204
+ async def reply_photo(
205
+ self,
206
+ photo: str,
207
+ caption: Optional[str] = None,
208
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
209
+ ):
210
+ """Reply with a photo to the current message.
211
+
212
+ Args:
213
+ photo: Photo to send (file_id or URL)
214
+ caption: Optional caption for the photo
215
+ reply_markup: Optional keyboard markup
216
+ """
217
+ if self.chat and self.chat.id:
218
+ await self.client.send_photo(
219
+ self.chat.id, photo=photo, caption=caption, reply_markup=reply_markup
220
+ )
221
+
222
+ async def reply_video(
223
+ self,
224
+ video: str,
225
+ caption: Optional[str] = None,
226
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
227
+ ):
228
+ """Reply with a video to the current message.
229
+
230
+ Args:
231
+ video: Video to send (file_id or URL)
232
+ caption: Optional caption for the video
233
+ reply_markup: Optional keyboard markup
234
+ """
235
+ if self.chat and self.chat.id:
236
+ await self.client.send_video(
237
+ self.chat.id, video=video, caption=caption, reply_markup=reply_markup
238
+ )
239
+
240
+ async def reply_audio(
241
+ self,
242
+ audio: str,
243
+ caption: Optional[str] = None,
244
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
245
+ ):
246
+ """Reply with an audio file to the current message.
247
+
248
+ Args:
249
+ audio: Audio to send (file_id or URL)
250
+ caption: Optional caption for the audio
251
+ reply_markup: Optional keyboard markup
252
+ """
253
+ if self.chat and self.chat.id:
254
+ await self.client.send_audio(
255
+ self.chat.id, audio=audio, caption=caption, reply_markup=reply_markup
256
+ )
257
+
258
+ async def reply_document(
259
+ self,
260
+ document: str,
261
+ caption: Optional[str] = None,
262
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
263
+ ):
264
+ """Reply with a document to the current message.
265
+
266
+ Args:
267
+ document: Document to send (file_id or URL)
268
+ caption: Optional caption for the document
269
+ reply_markup: Optional keyboard markup
270
+ """
271
+ if self.chat and self.chat.id:
272
+ await self.client.send_document(
273
+ self.chat.id,
274
+ document=document,
275
+ caption=caption,
276
+ reply_markup=reply_markup,
277
+ )
278
+
279
+ async def reply_sticker(
280
+ self,
281
+ sticker: str,
282
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
283
+ ):
284
+ """Reply with a sticker to the current message.
285
+
286
+ Args:
287
+ sticker: Sticker to send (file_id or URL)
288
+ reply_markup: Optional keyboard markup
289
+ """
290
+ if self.chat and self.chat.id:
291
+ await self.client.send_sticker(
292
+ self.chat.id, sticker=sticker, reply_markup=reply_markup
293
+ )
294
+
295
+ async def reply_location(
296
+ self,
297
+ latitude: float,
298
+ longitude: float,
299
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
300
+ ):
301
+ """Reply with a location to the current message.
302
+
303
+ Args:
304
+ latitude: Latitude of the location
305
+ longitude: Longitude of the location
306
+ reply_markup: Optional keyboard markup
307
+ """
308
+ if self.chat and self.chat.id:
309
+ await self.client.send_location(
310
+ self.chat.id,
311
+ latitude=latitude,
312
+ longitude=longitude,
313
+ reply_markup=reply_markup,
314
+ )
315
+
316
+ async def reply_contact(
317
+ self,
318
+ phone_number: str,
319
+ first_name: str,
320
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
321
+ ):
322
+ """Reply with a contact to the current message.
323
+
324
+ Args:
325
+ phone_number: Contact's phone number
326
+ first_name: Contact's first name
327
+ reply_markup: Optional keyboard markup
328
+ """
329
+ if self.chat and self.chat.id:
330
+ await self.client.send_contact(
331
+ self.chat.id,
332
+ phone_number=phone_number,
333
+ first_name=first_name,
334
+ reply_markup=reply_markup,
335
+ )
336
+
337
+ async def reply_invoice(
338
+ self,
339
+ title: str,
340
+ description: str,
341
+ payload: str,
342
+ provider_token: str,
343
+ currency: str,
344
+ prices: list,
345
+ reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
346
+ ):
347
+ """Reply with an invoice to the current message.
348
+
349
+ Args:
350
+ title: Product name
351
+ description: Product description
352
+ payload: Bot-defined invoice payload
353
+ provider_token: Payment provider token
354
+ currency: Three-letter ISO 4217 currency code
355
+ prices: Price breakdown (amount in smallest units)
356
+ reply_markup: Optional keyboard markup
357
+ """
358
+ if self.chat and self.chat.id:
359
+ await self.client.send_invoice(
360
+ self.chat.id,
361
+ title=title,
362
+ description=description,
363
+ payload=payload,
364
+ provider_token=provider_token,
365
+ currency=currency,
366
+ prices=prices,
367
+ reply_markup=reply_markup,
368
+ )
@@ -0,0 +1,3 @@
1
+ class MessageId:
2
+ def __init__(self, message_id: int):
3
+ self.message_id = message_id
@@ -0,0 +1,9 @@
1
+ class PhotoSize:
2
+ def __init__(
3
+ self, file_id: str, file_unique_id: str, width: int, height: int, file_size: int
4
+ ):
5
+ self.file_id = file_id
6
+ self.file_unique_id = file_unique_id
7
+ self.width = width
8
+ self.height = height
9
+ self.file_size = file_size
@@ -0,0 +1,21 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from .user import User
5
+
6
+
7
+ class PreCheckoutQuery:
8
+ def __init__(
9
+ self,
10
+ id: str,
11
+ from_user: "User",
12
+ currency: str,
13
+ total_amount: int,
14
+ invoice_payload: str,
15
+ **kwargs
16
+ ) -> None:
17
+ self.id = id
18
+ self.from_user = from_user
19
+ self.currency = currency
20
+ self.total_amount = total_amount
21
+ self.invoice_payload = invoice_payload
@@ -0,0 +1,54 @@
1
+ from typing import TYPE_CHECKING, Union
2
+
3
+ if TYPE_CHECKING:
4
+ from .webappinfo import WebAppInfo
5
+ from .copytextbutton import CopyTextButton
6
+
7
+
8
+ class ReplyKeyboardMarkup:
9
+ """
10
+ Represents a reply keyboard.
11
+ Attributes:
12
+ Each dictionary contains the following keys:
13
+ - keyboard (list): A list of lists of dictionaries representing the buttons in the keyboard.
14
+ - text (str): The text of the button.
15
+ - request_contact (bool, optional): If True, the user's phone number will be sent.
16
+ - request_location (bool, optional): If True, the user's location will be sent.
17
+ - web_app (WebApp, optional): The web app associated with the button.
18
+ """
19
+
20
+ def __init__(self):
21
+ self.keyboard = []
22
+
23
+ def add_button(
24
+ self,
25
+ text: str,
26
+ request_contact: bool = None,
27
+ request_location: bool = None,
28
+ web_app: Union["WebAppInfo", str] = None,
29
+ ):
30
+ """Add a button to the current row."""
31
+ button = {"text": text}
32
+ if request_contact:
33
+ button["request_contact"] = request_contact
34
+ if request_location:
35
+ button["request_location"] = request_location
36
+ if web_app:
37
+ button["web_app"] = web_app
38
+
39
+ if not self.keyboard:
40
+ self.keyboard.append([])
41
+ self.keyboard[-1].append(button)
42
+ return self
43
+
44
+ def add_row(self):
45
+ """Add a new row for buttons."""
46
+ self.keyboard.append([])
47
+ return self
48
+
49
+ @property
50
+ def json(self):
51
+ return {"keyboard": self.keyboard}
52
+
53
+ def __str__(self):
54
+ return str(self.json)
@@ -0,0 +1,16 @@
1
+ class Sticker:
2
+ def __init__(
3
+ self,
4
+ file_id: str,
5
+ file_unique_id: str,
6
+ type: str,
7
+ width: int,
8
+ height: int,
9
+ file_size: int,
10
+ ):
11
+ self.file_id = file_id
12
+ self.file_unique_id = file_unique_id
13
+ self.type = type
14
+ self.width = width
15
+ self.height = height
16
+ self.file_size = file_size
@@ -0,0 +1,12 @@
1
+ from typing import List, TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from .sticker import Sticker
5
+ from .photosize import PhotoSize
6
+
7
+
8
+ class StickerSet:
9
+ def __init__(
10
+ self, name: str, title: str, stickers: List["Sticker"], thumb: "PhotoSize"
11
+ ):
12
+ pass
@@ -0,0 +1,15 @@
1
+ class SuccessfulPayment:
2
+ def __init__(
3
+ self,
4
+ currency: str,
5
+ total_amount: int,
6
+ invoice_payload: str,
7
+ telegram_payment_charge_id: str,
8
+ provider_payment_charge_id: str,
9
+ **kwargs
10
+ ):
11
+ self.currency = currency
12
+ self.total_amount = total_amount
13
+ self.invoice_payload = invoice_payload
14
+ self.telegram_payment_charge_id = telegram_payment_charge_id
15
+ self.provider_payment_charge_id = provider_payment_charge_id
@@ -0,0 +1,23 @@
1
+ from typing import TYPE_CHECKING, Optional
2
+
3
+ if TYPE_CHECKING:
4
+ from .message import Message
5
+ from .callbackquery import CallbackQuery
6
+ from .precheckoutquery import PreCheckoutQuery
7
+
8
+
9
+ class Update:
10
+ def __init__(
11
+ self,
12
+ update_id: int,
13
+ message: Optional["Message"] = None,
14
+ edited_message: Optional["Message"] = None,
15
+ callback_query: Optional["CallbackQuery"] = None,
16
+ pre_checkout_query: Optional["PreCheckoutQuery"] = None,
17
+ **kwargs
18
+ ):
19
+ self.update_id = update_id
20
+ self.message = message
21
+ self.edited_message = edited_message
22
+ self.callback_query = callback_query
23
+ self.pre_checkout_query = pre_checkout_query
@@ -0,0 +1,20 @@
1
+ from typing import Optional, Union
2
+ from .utils import build_api_url
3
+ import asyncio
4
+ import aiohttp
5
+
6
+
7
+ class User:
8
+ def __init__(
9
+ self,
10
+ id: int,
11
+ is_bot: bool,
12
+ first_name: str,
13
+ last_name: Optional[str],
14
+ username: Optional[str],
15
+ ):
16
+ self.id = id
17
+ self.is_bot = is_bot
18
+ self.first_name = first_name
19
+ self.last_name = last_name
20
+ self.username = username
@@ -0,0 +1,28 @@
1
+ import asyncio
2
+ import aiohttp
3
+
4
+
5
+ def build_api_url(base: str, endpoint: str) -> str:
6
+ return f"{base}/{endpoint}"
7
+
8
+
9
+ async def make_post(url: str, data: dict = None, headers: dict = None) -> dict:
10
+ async with aiohttp.ClientSession() as session:
11
+ async with session.post(url, json=data, headers=headers) as response:
12
+ return await response.json()
13
+
14
+
15
+ async def make_get(url: str, headers: dict = None) -> dict:
16
+ async with aiohttp.ClientSession() as session:
17
+ async with session.get(url, headers=headers) as response:
18
+ return await response.json()
19
+
20
+
21
+ def pythonize(dictionary: dict) -> dict:
22
+ """Converts a dictionary with keys in snake_case to camelCase."""
23
+ result = {}
24
+ for key, value in dictionary.items():
25
+ if key == "from":
26
+ key = "from_user"
27
+ result[key] = value
28
+ return result
@@ -0,0 +1,20 @@
1
+ class Video:
2
+ def __init__(
3
+ self,
4
+ file_id: str,
5
+ file_unique_id: str,
6
+ width: int,
7
+ height: int,
8
+ duration: int,
9
+ file_name: str,
10
+ mime_type: str,
11
+ file_size: int,
12
+ ):
13
+ self.file_id = file_id
14
+ self.file_unique_id = file_unique_id
15
+ self.width = width
16
+ self.height = height
17
+ self.duration = duration
18
+ self.file_name = file_name
19
+ self.mime_type = mime_type
20
+ self.file_size = file_size
@@ -0,0 +1,4 @@
1
+ class Voice:
2
+ def __init__(self, file_id: str, file_unique_id: str):
3
+ self.file_id = file_id
4
+ self.file_unique_id = file_unique_id
@@ -0,0 +1,3 @@
1
+ class WebAppData:
2
+ def __init__(self, data: str):
3
+ self.data = data
@@ -0,0 +1,3 @@
1
+ class WebAppInfo:
2
+ def __init__(self, url: str):
3
+ self.url = url