RubigramClient 1.4.0__py3-none-any.whl → 1.4.2__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 RubigramClient might be problematic. Click here for more details.

rubigram/types.py CHANGED
@@ -1,408 +1,242 @@
1
- from dataclasses import dataclass
2
- from typing import Any, Dict, List, Literal, Optional
1
+ from dataclasses import dataclass, fields, is_dataclass
2
+ from typing import Any, Type, Union, TypeVar, Literal, Optional, get_origin, get_args
3
3
  import rubigram
4
4
 
5
5
 
6
+ T = TypeVar("T", bound="Dict")
7
+
8
+
6
9
  @dataclass
7
- class Location:
10
+ class Dict:
11
+ def to_dict(self) -> dict[str, Any]:
12
+ data = {}
13
+ for field in fields(self):
14
+ value = getattr(self, field.name)
15
+ if is_dataclass(value):
16
+ data[field.name] = value.to_dict()
17
+ elif isinstance(value, list):
18
+ data[field.name] = [i.to_dict() if is_dataclass(i)
19
+ else i for i in value]
20
+ else:
21
+ data[field.name] = value
22
+ return data
23
+
24
+ @classmethod
25
+ def from_dict(cls: Type[T], data: dict[str, Any]) -> Optional[T]:
26
+ if data is None:
27
+ data = {}
28
+ init_data = {}
29
+ for field in fields(cls):
30
+ value = data.get(field.name)
31
+ field_type = field.type
32
+ origin = get_origin(field_type)
33
+ if isinstance(value, dict) and isinstance(field_type, type) and issubclass(field_type, Dict):
34
+ init_data[field.name] = field_type.from_dict(value)
35
+ elif origin == list:
36
+ inner_type = get_args(field_type)[0]
37
+ if isinstance(inner_type, type) and issubclass(inner_type, Dict):
38
+ init_data[field.name] = [inner_type.from_dict(
39
+ v) if isinstance(v, dict) else v for v in (value or [])]
40
+ else:
41
+ init_data[field.name] = value or []
42
+ elif get_origin(field_type) is Union:
43
+ args = get_args(field_type)
44
+ dict_type = next((a for a in args if isinstance(
45
+ a, type) and issubclass(a, Dict)), None)
46
+ if dict_type and isinstance(value, dict):
47
+ init_data[field.name] = dict_type.from_dict(value)
48
+ else:
49
+ init_data[field.name] = value
50
+ else:
51
+ init_data[field.name] = value
52
+ return cls(**init_data)
53
+
54
+
55
+ @dataclass
56
+ class Location(Dict):
8
57
  longitude: Optional[str] = None
9
58
  latitude: Optional[str] = None
10
-
11
- def _dict(self) -> Dict:
12
- return {
13
- "longitude": self.longitude,
14
- "latitude": self.latitude
15
- }
16
-
17
- @classmethod
18
- def read(cls, data: dict[str, Any]) -> "Location":
19
- return cls(
20
- longitude = data.get("longitude"),
21
- latitude = data.get("latitude"),
22
- )
59
+
23
60
 
24
61
  @dataclass
25
- class ButtonSelectionItem:
62
+ class OpenChatData(Dict):
63
+ object_guid: Optional[str] = None
64
+ object_type: Optional[Literal["User", "Bot", "Group", "Channel"]] = None
65
+
66
+
67
+ @dataclass
68
+ class JoinChannelData(Dict):
69
+ username: Optional[str] = None
70
+ ask_join: Optional[bool] = False
71
+
72
+
73
+ @dataclass
74
+ class ButtonLink(Dict):
75
+ type: Optional[Literal["joinchannel", "url"]] = None
76
+ link_url: Optional[str] = None
77
+ joinchannel_data: Optional[JoinChannelData] = None
78
+ open_chat_data: Optional[OpenChatData] = None
79
+
80
+
81
+ @dataclass
82
+ class ButtonSelectionItem(Dict):
26
83
  text: Optional[str] = None
27
84
  image_url: Optional[str] = None
28
85
  type: Optional[Literal["TextOnly", "TextImgThu", "TextImgBig"]] = None
29
-
30
- def _dict(self) -> Dict:
31
- return {
32
- "text": self.text,
33
- "image_url": self.image_url,
34
- "type": self.type
35
- }
86
+
36
87
 
37
88
  @dataclass
38
- class ButtonTextbox:
89
+ class ButtonTextbox(Dict):
39
90
  type_line: Optional[Literal["SingleLine", "MultiLine"]] = None
40
91
  type_keypad: Optional[Literal["String", "Number"]] = None
41
92
  place_holder: Optional[str] = None
42
93
  title: Optional[str] = None
43
94
  default_value: Optional[str] = None
44
-
45
- def _dict(self) -> Dict:
46
- return {
47
- "type_line": self.type_line,
48
- "type_keypad": self.type_keypad,
49
- "place_holder": self.place_holder,
50
- "title": self.title,
51
- "default_value": self.default_value
52
- }
95
+
53
96
 
54
97
  @dataclass
55
- class ButtonLocation:
98
+ class ButtonLocation(Dict):
56
99
  default_pointer_location: Optional[Location] = None
57
100
  default_map_location: Optional[Location] = None
58
101
  type: Optional[Literal["Picker", "View"]] = None
59
102
  title: Optional[str] = None
60
103
  location_image_url: Optional[str] = None
61
-
62
- def _dict(self) -> Dict:
63
- return {
64
- "default_pointer_location": self.default_pointer_location._dict() if self.default_pointer_location else None,
65
- "default_map_location": self.default_map_location._dict() if self.default_map_location else None,
66
- "type": self.type,
67
- "title": self.title,
68
- "location_image_url": self.location_image_url
69
- }
70
-
104
+
105
+
71
106
  @dataclass
72
- class ButtonStringPicker:
73
- items: Optional[List[str]] = None
107
+ class ButtonStringPicker(Dict):
108
+ items: Optional[list[str]] = None
74
109
  default_value: Optional[str] = None
75
110
  title: Optional[str] = None
76
-
77
- def _dict(self) -> Dict:
78
- return {
79
- "items": self.items,
80
- "default_value": self.default_value,
81
- "title": self.title,
82
- }
111
+
83
112
 
84
113
  @dataclass
85
- class ButtonNumberPicker:
114
+ class ButtonNumberPicker(Dict):
86
115
  min_value: Optional[str] = None
87
116
  max_value: Optional[str] = None
88
117
  default_value: Optional[str] = None
89
118
  title: Optional[str] = None
90
-
91
- def _dict(self) -> Dict:
92
- return {
93
- "min_value": self.min_value,
94
- "max_value": self.max_value,
95
- "default_value": self.default_value,
96
- "title": self.title
97
- }
98
-
119
+
120
+
99
121
  @dataclass
100
- class ButtonCalendar:
122
+ class ButtonCalendar(Dict):
101
123
  default_value: Optional[str] = None
102
124
  type: Optional[Literal["DatePersian", "DateGregorian"]] = None
103
125
  min_year: Optional[str] = None
104
126
  max_year: Optional[str] = None
105
127
  title: Optional[str] = None
106
-
107
- def _dict(self) -> Dict:
108
- return {
109
- "default_value": self.default_value,
110
- "type": self.type,
111
- "min_year": self.min_year,
112
- "max_year": self.max_year,
113
- "title": self.title
114
- }
128
+
115
129
 
116
130
  @dataclass
117
- class ButtonSelection:
131
+ class ButtonSelection(Dict):
118
132
  selection_id: Optional[str] = None
119
133
  search_type: Optional[str] = None
120
134
  get_type: Optional[str] = None
121
- items: Optional[ButtonSelectionItem] = None
135
+ items: Optional[list[ButtonSelectionItem]] = None
122
136
  is_multi_selection: Optional[bool] = None
123
137
  columns_count: Optional[str] = None
124
138
  title: Optional[str] = None
125
-
126
- def _dict(self) -> Dict:
127
- return {
128
- "selection_id": self.selection_id,
129
- "search_type": self.search_type,
130
- "get_type": self.get_type,
131
- "items": self.items._dict() if self.items else None,
132
- "is_multi_selection": self.is_multi_selection,
133
- "columns_count": self.columns_count,
134
- "title": self.title
135
- }
136
-
137
-
138
-
139
+
140
+
139
141
  @dataclass
140
- class Button:
142
+ class Button(Dict):
141
143
  id: Optional[str] = None
144
+ button_text: Optional[str] = None
142
145
  type: Literal[
143
146
  "Simple", "Selection", "Calendar", "NumberPicker", "StringPicker", "Location", "Payment",
144
147
  "CameraImage", "CameraVideo", "GalleryImage", "GalleryVideo", "File", "Audio", "RecordAudio",
145
148
  "MyPhoneNumber", "MyLocation", "Textbox", "Link", "AskMyPhoneNumber", "AskLocation", "Barcode"
146
149
  ] = "Simple"
147
- button_text: Optional[str] = None
148
150
  button_selection: Optional[ButtonSelection] = None
149
151
  button_calendar: Optional[ButtonCalendar] = None
150
152
  button_number_picker: Optional[ButtonNumberPicker] = None
151
153
  button_string_picker: Optional[ButtonStringPicker] = None
152
154
  button_location: Optional[ButtonLocation] = None
153
155
  button_textbox: Optional[ButtonTextbox] = None
154
-
155
- def _dict(self) -> Dict:
156
- return {
157
- "id": self.id,
158
- "type": self.type,
159
- "button_text": self.button_text,
160
- "button_selection": self.button_selection._dict() if self.button_selection else None,
161
- "button_calendar": self.button_calendar._dict() if self.button_calendar else None,
162
- "button_number_picker": self.button_number_picker._dict() if self.button_number_picker else None,
163
- "button_string_picker": self.button_string_picker._dict() if self.button_string_picker else None,
164
- "button_location": self.button_location._dict() if self.button_location else None,
165
- "button_textbox": self.button_textbox._dict() if self.button_textbox else None
166
- }
156
+ button_link: Optional[ButtonLink] = None
157
+
167
158
 
168
159
  @dataclass
169
- class KeypadRow:
170
- buttons: List[Button]
171
-
172
- def _dict(self) -> Dict:
173
- return {
174
- "buttons": [button._dict() for button in self.buttons]
175
- }
160
+ class KeypadRow(Dict):
161
+ buttons: list[Button]
162
+
176
163
 
177
164
  @dataclass
178
- class Keypad:
179
- rows: List[KeypadRow]
165
+ class Keypad(Dict):
166
+ rows: list[KeypadRow]
180
167
  resize_keyboard: bool = True
181
168
  on_time_keyboard: bool = False
182
-
183
- def _dict(self) -> Dict:
184
- return {
185
- "rows": [row._dict() for row in self.rows],
186
- "resize_keyboard": self.resize_keyboard,
187
- "one_time_keyboard": self.on_time_keyboard
188
- }
189
169
 
190
- @dataclass
191
- class MessageId:
192
- client: Optional["rubigram.Client"] = None
193
- message_id: Optional[str] = None
194
- file_id: Optional[str] = None
195
-
196
- @classmethod
197
- def read(cls, data: Dict[str, Any]) -> "MessageId":
198
- return cls(
199
- message_id = data.get("message_id"),
200
- file_id = data.get("file_id")
201
- )
202
-
203
170
 
204
171
  @dataclass
205
- class PollStatus:
172
+ class PollStatus(Dict):
206
173
  state: Optional[Literal["Open", "Closed"]] = None
207
174
  selection_index: Optional[int] = None
208
- percent_vote_options: Optional[List[int]] = None
175
+ percent_vote_options: Optional[list[int]] = None
209
176
  total_vote: Optional[int] = None
210
177
  show_total_votes: Optional[bool] = None
211
-
212
- @classmethod
213
- def read(cls, data: Dict[str, Any]) -> "PollStatus":
214
- return cls(
215
- state = data.get("state"),
216
- selection_index = data.get("selection_index"),
217
- percent_vote_options = data.get("percent_vote_options"),
218
- total_vote = data.get("total_vote"),
219
- show_total_votes = data.get("show_total_votes"),
220
- )
178
+
221
179
 
222
180
  @dataclass
223
- class File:
181
+ class File(Dict):
224
182
  file_id: Optional[str] = None
225
183
  file_name: Optional[str] = None
226
184
  size: Optional[str] = None
227
-
228
- @classmethod
229
- def read(cls, data: dict[str, Any]) -> "File":
230
- return cls(
231
- file_id = data.get("file_id"),
232
- file_name = data.get("file_name"),
233
- size = data.get("size"),
234
- )
235
-
185
+
186
+
236
187
  @dataclass
237
- class LiveLocation:
188
+ class LiveLocation(Dict):
238
189
  start_time: Optional[str] = None
239
190
  live_period: Optional[int] = None
240
191
  current_location: Optional[Location] = None
241
192
  user_id: Optional[str] = None
242
193
  status: Optional[Literal["Stopped", "Live"]] = None
243
194
  last_update_time: Optional[str] = None
244
-
245
- @classmethod
246
- def read(cls, data: dict[str, Any]) -> "LiveLocation":
247
- return cls(
248
- start_time = data.get("start_time"),
249
- live_period = data.get("live_period"),
250
- current_location = Location.read(data.get("current_location")) if "current_location" in data else None,
251
- user_id = data.get("user_id"),
252
- status = data.get("status"),
253
- last_update_time = data.get("last_update_time")
254
- )
255
-
195
+
196
+
256
197
  @dataclass
257
- class Poll:
198
+ class Poll(Dict):
258
199
  question: Optional[str] = None
259
- options: Optional[List[str]] = None
200
+ options: Optional[list[str]] = None
260
201
  poll_status: Optional[PollStatus] = None
261
-
262
- @classmethod
263
- def read(cls, data: dict[str, Any]) -> "Poll":
264
- return cls(
265
- question = data.get("question"),
266
- options = data.get("options"),
267
- poll_status = PollStatus.read(data.get("poll_status")) if "poll_status" in data else None
268
- )
269
-
202
+
203
+
270
204
  @dataclass
271
- class ContactMessage:
205
+ class ContactMessage(Dict):
272
206
  phone_number: Optional[str] = None
273
207
  first_name: Optional[str] = None
274
208
  last_name: Optional[str] = None
275
-
276
- @classmethod
277
- def read(cls, data: dict[str, Any]) -> "ContactMessage":
278
- return cls(
279
- phone_number = data.get("phone_number"),
280
- first_name = data.get("first_name"),
281
- last_name = data.get("last_name")
282
- )
283
-
209
+
210
+
284
211
  @dataclass
285
- class Sticker:
212
+ class Sticker(Dict):
286
213
  sticker_id: Optional[str] = None
287
214
  file: Optional[File] = None
288
215
  emoji_character: Optional[str] = None
289
-
290
- @classmethod
291
- def read(cls, data: dict[str, Any]) -> "Sticker":
292
- return cls(
293
- sticker_id = data.get("sticker_id"),
294
- file = File.read(data.get("file")) if "file" in data else None,
295
- emoji_character = data.get("emoji_character")
296
- )
216
+
297
217
 
298
218
  @dataclass
299
- class ForwardedFrom:
219
+ class ForwardedFrom(Dict):
300
220
  type_from: Optional[Literal["User", "Channel", "Bot"]] = None
301
221
  message_id: Optional[str] = None
302
222
  from_chat_id: Optional[str] = None
303
223
  from_sender_id: Optional[str] = None
304
-
305
- @classmethod
306
- def read(cls, data: dict[str, Any]) -> "ForwardedFrom":
307
- return cls(
308
- type_from = data.get("type_from"),
309
- message_id = data.get("message_id"),
310
- from_chat_id = data.get("from_chat_id"),
311
- from_sender_id = data.get("from_sender_id")
312
- )
224
+
313
225
 
314
226
  @dataclass
315
- class AuxData:
227
+ class AuxData(Dict):
316
228
  start_id: Optional[str] = None
317
229
  button_id: Optional[str] = None
318
-
319
- @classmethod
320
- def read(cls, data: Dict[str, Any]) -> "AuxData":
321
- return cls(
322
- start_id = data.get("start_id"),
323
- button_id = data.get("button_id")
324
- )
325
-
326
- @dataclass
327
- class PaymentStatus:
328
- payment_id: Optional[str] = None
329
- status: Optional[Literal["Paid", "NotPaid"]] = None
330
-
331
- @classmethod
332
- def read(cls, data: Dict[str, Any]) -> "PaymentStatus":
333
- return cls(
334
- payment_id = data.get("payment_id"),
335
- status = data.get("status")
336
- )
337
230
 
338
- @dataclass
339
- class Chat:
340
- chat_id: Optional[str] = None
341
- chat_type: Optional[Literal["User", "Bot", "Group", "Channel"]] = None
342
- user_id: Optional[str] = None
343
- first_name: Optional[str] = None
344
- last_name: Optional[str] = None
345
- title: Optional[str] = None
346
- username: Optional[str] = None
347
-
348
- @classmethod
349
- def read(cls, data: Dict[str, Any]) -> "Chat":
350
- return cls(
351
- chat_id = data.get("chat_id"),
352
- chat_type = data.get("chat_type"),
353
- user_id = data.get("user_id"),
354
- first_name = data.get("first_name"),
355
- last_name = data.get("last_name"),
356
- title = data.get("title"),
357
- username = data.get("username")
358
- )
359
231
 
360
232
  @dataclass
361
- class Bot:
362
- bot_id: Optional[str] = None
363
- bot_title: Optional[str] = None
364
- avatar: Optional[File] = None
365
- description: Optional[str] = None
366
- username: Optional[str] = None
367
- start_message: Optional[str] = None
368
- share_url: Optional[str] = None
369
-
370
- @classmethod
371
- def read(cls, data: Dict[str, Any]) -> "Bot":
372
- return cls(
373
- bot_id = data.get("bot_id"),
374
- bot_title = data.get("bot_title"),
375
- avatar = File.read(data.get("avatar")) if data.get("avatar") else None,
376
- description = data.get("description"),
377
- username = data.get("username"),
378
- start_message = data.get("start_message"),
379
- share_url = data.get("share_url")
380
- )
233
+ class PaymentStatus(Dict):
234
+ payment_id: Optional[str] = None
235
+ status: Optional[Literal["Paid", "NotPaid"]] = None
381
236
 
382
- @dataclass
383
- class InlineMessage:
384
- sender_id: Optional[str] = None
385
- text: Optional[str] = None
386
- message_id: Optional[str] = None
387
- chat_id: Optional[str] = None
388
- file: Optional[File] = None
389
- location: Optional[Location] = None
390
- aux_data: Optional[AuxData] = None
391
-
392
- @classmethod
393
- def read(cls, data: Dict[str, Any]) -> "InlineMessage":
394
- return cls(
395
- sender_id = data.get("sender_id"),
396
- text = data.get("text"),
397
- message_id = data.get("message_id"),
398
- chat_id = data.get("chat_id"),
399
- file = File.read(data.get("file")) if data.get("file") else None,
400
- location = Location.read(data.get("location")) if data.get("location") else None,
401
- aux_data = AuxData.read(data.get("aux_data")) if data.get("aux_data") else None
402
- )
403
237
 
404
238
  @dataclass
405
- class Message:
239
+ class Message(Dict):
406
240
  message_id: Optional[str] = None
407
241
  text: Optional[str] = None
408
242
  time: Optional[str] = None
@@ -419,55 +253,107 @@ class Message:
419
253
  contact_message: Optional[ContactMessage] = None
420
254
  poll: Optional[Poll] = None
421
255
  live_location: Optional[LiveLocation] = None
422
-
423
- @classmethod
424
- def read(cls, data: Dict[str, Any]) -> "Message":
425
- return cls(
426
- message_id = data["message_id"],
427
- text = data.get("text"),
428
- time = data["time"],
429
- is_edited = data["is_edited"],
430
- sender_type = data["sender_type"],
431
- sender_id = data["sender_id"],
432
- aux_data = AuxData.read(data["aux_data"]) if "aux_data" in data else None,
433
- file = File.read(data["file"]) if "file" in data else None,
434
- reply_to_message_id = data.get("reply_to_message_id"),
435
- forwarded_from = ForwardedFrom.read(data["forwarded_from"]) if "forwarded_from" in data else None,
436
- forwarded_no_link = data.get("forwarded_no_link"),
437
- location = Location.read(data["location"]) if "location" in data else None,
438
- sticker = Sticker.read(data["sticker"]) if "sticker" in data else None,
439
- contact_message = ContactMessage.read(data["contact_message"]) if "contact_message" in data else None,
440
- poll = Poll.read(data["poll"]) if "poll" in data else None,
441
- live_location = LiveLocation.read(data["live_location"]) if "live_location" in data else None
442
- )
256
+
257
+
258
+ @dataclass
259
+ class InlineMessage(Dict):
260
+ sender_id: Optional[str] = None
261
+ text: Optional[str] = None
262
+ message_id: Optional[str] = None
263
+ chat_id: Optional[str] = None
264
+ file: Optional[File] = None
265
+ location: Optional[Location] = None
266
+ aux_data: Optional[AuxData] = None
267
+
268
+
269
+ @dataclass
270
+ class Bot(Dict):
271
+ bot_id: Optional[str] = None
272
+ bot_title: Optional[str] = None
273
+ avatar: Optional[File] = None
274
+ description: Optional[str] = None
275
+ username: Optional[str] = None
276
+ start_message: Optional[str] = None
277
+ share_url: Optional[str] = None
278
+
279
+
280
+ @dataclass
281
+ class Chat(Dict):
282
+ chat_id: Optional[str] = None
283
+ chat_type: Optional[Literal["User", "Bot", "Group", "Channel"]] = None
284
+ user_id: Optional[str] = None
285
+ first_name: Optional[str] = None
286
+ last_name: Optional[str] = None
287
+ title: Optional[str] = None
288
+ username: Optional[str] = None
289
+
443
290
 
444
291
  @dataclass
445
- class Update:
292
+ class MessageId(Dict):
293
+ message_id: Optional[str] = None
294
+ file_id: Optional[str] = None
295
+
296
+
297
+ @dataclass
298
+ class Update(Dict):
446
299
  client: Optional["rubigram.Client"] = None
447
- type: Optional[Literal["NewMessage", "UpdatedMessage", "RemovedMessage", "StartedBot", "StoppedBot", "UpdatedPayment"]] = None
300
+ type: Optional[Literal["NewMessage", "UpdatedMessage", "RemovedMessage",
301
+ "StartedBot", "StoppedBot", "UpdatedPayment"]] = None
448
302
  chat_id: Optional[str] = None
449
- removed_message_id: Optional[str] = None
303
+ removed_message_id: Optional[str] = None
450
304
  new_message: Optional[Message] = None
451
305
  updated_message: Optional[Message] = None
452
306
  updated_payment: Optional[PaymentStatus] = None
307
+
308
+ async def send_text(self, text: str,) -> "MessageId":
309
+ return await self.client.send_message(self.chat_id, text)
453
310
 
454
- @classmethod
455
- def read(cls, data: Dict[str, Any], client: Optional["rubigram.Client"] = None) -> "Update":
456
- return cls(
457
- client = client,
458
- type = data["type"],
459
- chat_id = data["chat_id"],
460
- removed_message_id = data.get("removed_message_id"),
461
- new_message = Message.read(data["new_message"]) if "new_message" in data else None,
462
- updated_message = Message.read(data["updated_message"]) if "updated_message" in data else None,
463
- updated_payment = PaymentStatus.read(data["updated_payment"]) if "updated_payment" in data else None
464
- )
465
-
466
- async def reply_text(self, text: str) -> "MessageId":
467
- return await self.client.send_message(self.chat_id, text, reply_to_message_id=self.new_message.message_id)
468
-
469
- async def reply_file(self, path: str, file_name: str, type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"] = "File") -> "MessageId":
470
- return await self.client.send_file(self.chat_id, path, file_name, type, reply_to_message_id=self.new_message.message_id)
471
-
472
- async def download(self, file_name: str):
473
- return await self.client.download_file(self.new_message.file.file_id, file_name)
311
+ async def download(self, name: str):
312
+ return await self.client.download_file(self.new_message.file.file_id, name)
313
+
314
+ async def reply(
315
+ self,
316
+ text: str,
317
+ chat_keypad: Keypad = None,
318
+ inline_keypad: Keypad = None,
319
+ chat_keypad_type: Literal["New", "Remove"] = None,
320
+ disable_notification: bool = None,
321
+ ) -> "MessageId":
322
+ return await self.client.send_message(self.chat_id, text, chat_keypad, inline_keypad, chat_keypad_type, disable_notification, self.new_message.message_id)
323
+
324
+ async def reply_file(
325
+ self,
326
+ file: str,
327
+ file_name: str,
328
+ type: Literal["File", "Image", "Voice",
329
+ "Music", "Gif", "Video"] = "File",
330
+ chat_keypad: Keypad = None,
331
+ inline_keypad: Keypad = None,
332
+ chat_keypad_type: Literal["New", "Remove"] = None,
333
+ disable_notification: bool = False,
334
+ ) -> "MessageId":
335
+ return await self.client.send_file(self.chat_id, file, file_name, type, chat_keypad, inline_keypad, chat_keypad_type, disable_notification, self.new_message.message_id)
336
+
337
+ async def reply_document(self, document: str, name: str, **kwargs) -> "MessageId":
338
+ return await self.reply_file(document, name, "File", **kwargs)
339
+
340
+ async def reply_photo(self, photo: str, name: str, **kwargs) -> "MessageId":
341
+ return await self.reply_file(photo, name, "Image", **kwargs)
342
+
343
+ async def reply_video(self, video: str, name: str, **kwargs) -> "MessageId":
344
+ return await self.reply_file(video, name, "Video", **kwargs)
345
+
346
+ async def reply_gif(self, gif: str, name: str, **kwargs) -> "MessageId":
347
+ return await self.reply_file(gif, name, "Gif", **kwargs)
348
+
349
+ async def reply_music(self, music: str, name: str, **kwargs) -> "MessageId":
350
+ return await self.reply_file(music, name, "Music", **kwargs)
351
+
352
+ async def reply_voice(self, voice: str, name: str, **kwargs) -> "MessageId":
353
+ return await self.reply_file(voice, name, "Voice", **kwargs)
354
+
355
+
356
+ @dataclass
357
+ class Updates(Dict):
358
+ updates: list[Update] = None
359
+ next_offset_id: Optional[str] = None