RubigramClient 1.7.17__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 (132) hide show
  1. rubigram/__init__.py +15 -0
  2. rubigram/client.py +294 -0
  3. rubigram/enums/__init__.py +52 -0
  4. rubigram/enums/buttons/__init__.py +13 -0
  5. rubigram/enums/buttons/button_calendar_type.py +20 -0
  6. rubigram/enums/buttons/button_location_type.py +20 -0
  7. rubigram/enums/buttons/button_selection_get_type.py +20 -0
  8. rubigram/enums/buttons/button_selection_search_type.py +20 -0
  9. rubigram/enums/buttons/button_selection_type.py +22 -0
  10. rubigram/enums/buttons/button_textbox_type_keypad.py +20 -0
  11. rubigram/enums/buttons/button_textbox_type_line.py +20 -0
  12. rubigram/enums/buttons/button_type.py +58 -0
  13. rubigram/enums/chat_action_type.py +22 -0
  14. rubigram/enums/chat_keypad_type.py +20 -0
  15. rubigram/enums/chat_type.py +24 -0
  16. rubigram/enums/enum.py +6 -0
  17. rubigram/enums/file_type.py +28 -0
  18. rubigram/enums/forwarded_from_type.py +22 -0
  19. rubigram/enums/live_location_status.py +20 -0
  20. rubigram/enums/message_sender_type.py +20 -0
  21. rubigram/enums/metadata_type.py +18 -0
  22. rubigram/enums/parse_mode.py +20 -0
  23. rubigram/enums/payment_status_type.py +20 -0
  24. rubigram/enums/poll_status_type.py +20 -0
  25. rubigram/enums/update_endpoint_type.py +26 -0
  26. rubigram/enums/update_type.py +28 -0
  27. rubigram/errors.py +16 -0
  28. rubigram/filters.py +865 -0
  29. rubigram/http_session.py +96 -0
  30. rubigram/methods/__init__.py +26 -0
  31. rubigram/methods/chats/__init__.py +10 -0
  32. rubigram/methods/chats/get_chat.py +53 -0
  33. rubigram/methods/decorators/__init__.py +25 -0
  34. rubigram/methods/decorators/on_inline_message.py +70 -0
  35. rubigram/methods/decorators/on_message.py +62 -0
  36. rubigram/methods/decorators/on_remove_message.py +65 -0
  37. rubigram/methods/decorators/on_start.py +65 -0
  38. rubigram/methods/decorators/on_started_bot.py +70 -0
  39. rubigram/methods/decorators/on_stop.py +65 -0
  40. rubigram/methods/decorators/on_stopped_bot.py +70 -0
  41. rubigram/methods/decorators/on_update_message.py +70 -0
  42. rubigram/methods/files/__init__.py +32 -0
  43. rubigram/methods/files/download_file.py +118 -0
  44. rubigram/methods/files/get_file.py +41 -0
  45. rubigram/methods/files/get_file_name.py +41 -0
  46. rubigram/methods/files/request_send_file.py +49 -0
  47. rubigram/methods/files/send_file.py +133 -0
  48. rubigram/methods/files/send_gif.py +51 -0
  49. rubigram/methods/files/send_music.py +97 -0
  50. rubigram/methods/files/send_photo.py +95 -0
  51. rubigram/methods/files/send_video.py +96 -0
  52. rubigram/methods/files/send_voice.py +96 -0
  53. rubigram/methods/files/upload_file.py +114 -0
  54. rubigram/methods/messages/__init__.py +34 -0
  55. rubigram/methods/messages/delete_messages.py +84 -0
  56. rubigram/methods/messages/edit_chat_keypad.py +68 -0
  57. rubigram/methods/messages/edit_message.py +82 -0
  58. rubigram/methods/messages/edit_message_keypad.py +72 -0
  59. rubigram/methods/messages/edit_message_text.py +68 -0
  60. rubigram/methods/messages/forward_message.py +78 -0
  61. rubigram/methods/messages/remove_chat_keypad.py +46 -0
  62. rubigram/methods/messages/send_contact.py +114 -0
  63. rubigram/methods/messages/send_location.py +108 -0
  64. rubigram/methods/messages/send_message.py +115 -0
  65. rubigram/methods/messages/send_poll.py +104 -0
  66. rubigram/methods/messages/send_sticker.py +98 -0
  67. rubigram/methods/network/__init__.py +12 -0
  68. rubigram/methods/network/request.py +129 -0
  69. rubigram/methods/settings/__init__.py +16 -0
  70. rubigram/methods/settings/set_command.py +50 -0
  71. rubigram/methods/settings/setup_endpoints.py +48 -0
  72. rubigram/methods/settings/update_bot_endpoint.py +62 -0
  73. rubigram/methods/updates/__init__.py +14 -0
  74. rubigram/methods/updates/get_me.py +35 -0
  75. rubigram/methods/updates/get_update.py +62 -0
  76. rubigram/methods/utilities/__init__.py +14 -0
  77. rubigram/methods/utilities/dispatcher.py +66 -0
  78. rubigram/methods/utilities/run.py +118 -0
  79. rubigram/rubino/__init__.py +6 -0
  80. rubigram/rubino/client.py +374 -0
  81. rubigram/rubino/network.py +129 -0
  82. rubigram/server/__init__.py +6 -0
  83. rubigram/server/server.py +245 -0
  84. rubigram/state/__init__.py +7 -0
  85. rubigram/state/state.py +121 -0
  86. rubigram/state/storage.py +131 -0
  87. rubigram/types/__init__.py +66 -0
  88. rubigram/types/aux_data.py +28 -0
  89. rubigram/types/bot.py +51 -0
  90. rubigram/types/bot_command.py +26 -0
  91. rubigram/types/buttons/__init__.py +13 -0
  92. rubigram/types/buttons/button.py +59 -0
  93. rubigram/types/buttons/button_calendar.py +40 -0
  94. rubigram/types/buttons/button_location.py +40 -0
  95. rubigram/types/buttons/button_number_picker.py +34 -0
  96. rubigram/types/buttons/button_selection.py +48 -0
  97. rubigram/types/buttons/button_selection_item.py +32 -0
  98. rubigram/types/buttons/button_string_picker.py +29 -0
  99. rubigram/types/buttons/button_text_box.py +40 -0
  100. rubigram/types/chat.py +86 -0
  101. rubigram/types/config/__init__.py +6 -0
  102. rubigram/types/config/object.py +442 -0
  103. rubigram/types/contact_message.py +29 -0
  104. rubigram/types/file.py +78 -0
  105. rubigram/types/forwarded_from.py +39 -0
  106. rubigram/types/keypads/__init__.py +7 -0
  107. rubigram/types/keypads/keypad.py +31 -0
  108. rubigram/types/keypads/keypad_row.py +23 -0
  109. rubigram/types/live_location.py +44 -0
  110. rubigram/types/location.py +24 -0
  111. rubigram/types/messages/__init__.py +8 -0
  112. rubigram/types/messages/inline_message.py +78 -0
  113. rubigram/types/messages/message.py +117 -0
  114. rubigram/types/messages/update_message.py +341 -0
  115. rubigram/types/metadata/__init__.py +7 -0
  116. rubigram/types/metadata/metadata.py +43 -0
  117. rubigram/types/metadata/metadata_parts.py +42 -0
  118. rubigram/types/payment_status.py +30 -0
  119. rubigram/types/poll.py +32 -0
  120. rubigram/types/poll_status.py +40 -0
  121. rubigram/types/sticker.py +33 -0
  122. rubigram/types/updates/__init__.py +7 -0
  123. rubigram/types/updates/update.py +917 -0
  124. rubigram/types/updates/updates.py +56 -0
  125. rubigram/utils/__init__.py +14 -0
  126. rubigram/utils/auto_delete.py +93 -0
  127. rubigram/utils/parser.py +99 -0
  128. rubigramclient-1.7.17.dist-info/METADATA +215 -0
  129. rubigramclient-1.7.17.dist-info/RECORD +132 -0
  130. rubigramclient-1.7.17.dist-info/WHEEL +5 -0
  131. rubigramclient-1.7.17.dist-info/licenses/LICENSE +21 -0
  132. rubigramclient-1.7.17.dist-info/top_level.txt +1 -0
@@ -0,0 +1,442 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from typing import (
7
+ Optional,
8
+ TypeVar,
9
+ Union,
10
+ Type,
11
+ Any,
12
+ get_type_hints,
13
+ get_origin,
14
+ get_args
15
+ )
16
+ from dataclasses import fields
17
+ from json import dumps
18
+ import sys
19
+ import rubigram
20
+
21
+
22
+ T = TypeVar("T", bound="Object")
23
+
24
+
25
+ FIELDS_CACHE: dict[type, tuple] = {}
26
+ TYPE_HINTS_CACHE: dict[type, dict] = {}
27
+
28
+
29
+ def get_fields(cls: type):
30
+ """
31
+ Get cached dataclass fields for a class.
32
+
33
+ This function caches the result of `dataclasses.fields()` to avoid
34
+ repeated computation for the same class.
35
+
36
+ Parameters:
37
+ cls (type):
38
+ The dataclass type to get fields for.
39
+
40
+ Returns:
41
+ tuple[Field]: A tuple of field objects for the dataclass.
42
+
43
+ Example:
44
+ .. code-block:: python
45
+ fields = get_fields(User)
46
+ for field in fields:
47
+ print(field.name, field.type)
48
+ """
49
+ cached = FIELDS_CACHE.get(cls)
50
+ if cached is None:
51
+ cached = fields(cls)
52
+ FIELDS_CACHE[cls] = cached
53
+ return cached
54
+
55
+
56
+ def get_cached_type_hints(cls: type) -> dict:
57
+ """
58
+ Get cached type hints for a class.
59
+
60
+ This function retrieves and caches type annotations for a class,
61
+ respecting the module's global namespace for forward references.
62
+
63
+ Parameters:
64
+ cls (type):
65
+ The class to get type hints for.
66
+
67
+ Returns:
68
+ dict[str, type]: A dictionary mapping field names to their types.
69
+
70
+ Note:
71
+ If type hints cannot be retrieved (e.g., due to forward references
72
+ in a different module), an empty dictionary is returned and cached.
73
+
74
+ Example:
75
+ .. code-block:: python
76
+ hints = get_cached_type_hints(User)
77
+ print(hints["user_id"]) # <class 'int'>
78
+ """
79
+ cached = TYPE_HINTS_CACHE.get(cls)
80
+ if cached is None:
81
+ try:
82
+ module = sys.modules[cls.__module__]
83
+ cached = get_type_hints(cls, globalns=module.__dict__)
84
+ except Exception:
85
+ cached = {}
86
+ TYPE_HINTS_CACHE[cls] = cached
87
+ return cached
88
+
89
+
90
+ def strip_optional(tp):
91
+ """
92
+ Extract the non-None type from an Optional annotation.
93
+
94
+ Given a Union type (typically from Optional[T]), returns T.
95
+ If no non-None type is found, returns the original type.
96
+
97
+ Parameters:
98
+ tp (type):
99
+ The type annotation, e.g., Optional[int] or Union[int, None].
100
+
101
+ Returns:
102
+ type: The non-None type from the union, or the original type.
103
+
104
+ Example:
105
+ .. code-block:: python
106
+ t = strip_optional(Optional[int]) # returns <class 'int'>
107
+ t = strip_optional(Union[int, str, None]) # returns <class 'int'>
108
+ """
109
+ for arg in get_args(tp):
110
+ if arg is not type(None):
111
+ return arg
112
+ return tp
113
+
114
+
115
+ def is_object_type(tp) -> bool:
116
+ """
117
+ Check if a type is a subclass of Object.
118
+
119
+ Parameters:
120
+ tp (type):
121
+ The type to check.
122
+
123
+ Returns:
124
+ bool: True if tp is a class and subclass of Object, False otherwise.
125
+
126
+ Example:
127
+ .. code-block:: python
128
+ is_object_type(User) # True if User extends Object
129
+ is_object_type(int) # False
130
+ """
131
+ return isinstance(tp, type) and issubclass(tp, Object)
132
+
133
+
134
+ def clear_none(data: Any):
135
+ """
136
+ Recursively remove None values from dictionaries and lists.
137
+
138
+ This function deeply traverses nested structures and removes:
139
+ - Keys with None values from dictionaries
140
+ - None items from lists
141
+
142
+ Parameters:
143
+ data (Any):
144
+ The data structure to clean. Can be dict, list, or any other type.
145
+
146
+ Returns:
147
+ Any: The cleaned data structure with None values removed.
148
+
149
+ Note:
150
+ Returns non-dict/list values unchanged.
151
+
152
+ Example:
153
+ .. code-block:: python
154
+ data = {"a": 1, "b": None, "c": [1, None, {"d": None}]}
155
+ cleaned = clear_none(data)
156
+ # Result: {"a": 1, "c": [1, {}]}
157
+ """
158
+ if isinstance(data, dict):
159
+ return {
160
+ key: clear_none(value)
161
+ for key, value in data.items()
162
+ if value is not None
163
+ }
164
+ if isinstance(data, list):
165
+ return [
166
+ clear_none(i)
167
+ for i in data
168
+ if i is not None
169
+ ]
170
+ return data
171
+
172
+
173
+ class Object:
174
+ """
175
+ Base class for all API data models in Rubigram.
176
+
177
+ This class provides serialization, deserialization, and client binding
178
+ functionality for dataclass-based models. It handles complex type
179
+ annotations including Optional, List, and nested Object types.
180
+
181
+ The class is designed to work with Rubika API responses, automatically
182
+ parsing JSON data into Python objects and vice versa.
183
+
184
+ Attributes:
185
+ client (Optional[rubigram.Client]):
186
+ The client instance bound to this object. Used for making
187
+ subsequent API calls from within the object context.
188
+
189
+ Slots:
190
+ __slots__ = ("client",): Optimizes memory usage by restricting
191
+ dynamic attribute creation.
192
+
193
+ Example:
194
+ .. code-block:: python
195
+ @dataclass
196
+ class User(Object):
197
+ user_id: int
198
+ name: str
199
+ profile: Optional[Profile] = None
200
+
201
+ # Parse from API response
202
+ user = User.parse({"user_id": 123, "name": "John"})
203
+
204
+ # Serialize to JSON
205
+ json_str = user.jsonify()
206
+
207
+ # Bind to client for API operations
208
+ user.bind(client)
209
+ """
210
+
211
+ __slots__ = ("client",)
212
+
213
+ def bind(self, client: "rubigram.Client") -> None:
214
+ """
215
+ Bind a client instance to this object and all nested Object instances.
216
+
217
+ This method recursively traverses the object's fields and binds the
218
+ client to any nested Object instances or lists containing Objects.
219
+
220
+ Parameters:
221
+ client (rubigram.Client):
222
+ The client instance to bind.
223
+
224
+ Returns:
225
+ None
226
+
227
+ Note:
228
+ The client is stored using `object.__setattr__` to bypass
229
+ the restrictions of `__slots__`.
230
+
231
+ Example:
232
+ .. code-block:: python
233
+ user.bind(client)
234
+ # Now user and all nested objects can use client for API calls
235
+ """
236
+ object.__setattr__(self, "client", client)
237
+
238
+ for field in get_fields(self.__class__):
239
+ value = getattr(self, field.name)
240
+
241
+ if isinstance(value, Object):
242
+ value.bind(client)
243
+
244
+ elif isinstance(value, list):
245
+ for item in value:
246
+ if isinstance(item, Object):
247
+ item.bind(client)
248
+
249
+ def as_dict(self) -> dict:
250
+ """
251
+ Convert the object to a dictionary representation suitable for JSON serialization.
252
+
253
+ Returns:
254
+ dict: A dictionary where:
255
+ - Object instances are converted to dict with "_" type marker
256
+ - Lists are recursively processed
257
+ - Simple values are included as-is
258
+
259
+ Note:
260
+ This method adds a "_" key with the class name for Object instances,
261
+ matching Rubika API's type indicator convention.
262
+
263
+ Example:
264
+ .. code-block:: python
265
+ user = User(user_id=123, name="John")
266
+ data = user.as_dict()
267
+ # Result: {"user_id": 123, "name": "John"}
268
+
269
+ profile = Profile(avatar="url")
270
+ user.profile = profile
271
+ data = user.as_dict()
272
+ # Result: {"user_id": 123, "name": "John",
273
+ # "profile": {"_": "Profile", "avatar": "url"}}
274
+ """
275
+ result = {}
276
+
277
+ for field in get_fields(self.__class__):
278
+ value = getattr(self, field.name)
279
+
280
+ if isinstance(value, Object):
281
+ result[field.name] = {
282
+ "_": value.__class__.__name__,
283
+ **value.as_dict()
284
+ }
285
+
286
+ elif isinstance(value, list):
287
+ result[field.name] = [
288
+ (
289
+ {"_": v.__class__.__name__, **v.as_dict()}
290
+ if isinstance(v, Object)
291
+ else v
292
+ )
293
+ for v in value
294
+ ]
295
+
296
+ else:
297
+ result[field.name] = value
298
+
299
+ return result
300
+
301
+ def jsonify(self, exclude_none: bool = True) -> str:
302
+ """
303
+ Serialize the object to a JSON string.
304
+
305
+ Parameters:
306
+ exclude_none (bool, optional):
307
+ If True (default), removes None values from the output.
308
+ If False, includes None values in the JSON.
309
+
310
+ Returns:
311
+ str: A formatted JSON string with:
312
+ - ASCII characters preserved
313
+ - 4-space indentation
314
+ - Type marker "_" included
315
+
316
+ Note:
317
+ Uses `default=str` to handle non-serializable types by
318
+ converting them to strings.
319
+
320
+ Example:
321
+ .. code-block:: python
322
+ user = User(user_id=123, name="John", profile=None)
323
+ json_str = user.jsonify()
324
+ # Result: '{"_": "User", "user_id": 123, "name": "John"}'
325
+
326
+ json_str = user.jsonify(exclude_none=False)
327
+ # Result: '{"_": "User", "user_id": 123, "name": "John", "profile": null}'
328
+ """
329
+ data = self.as_dict()
330
+
331
+ if exclude_none:
332
+ data = clear_none(data)
333
+
334
+ return dumps(
335
+ {"_": self.__class__.__name__, **data},
336
+ ensure_ascii=False,
337
+ indent=4,
338
+ default=str
339
+ )
340
+
341
+ @classmethod
342
+ def parse(cls: Type[T], data: dict, client: Optional["rubigram.Client"] = None) -> T:
343
+ """
344
+ Parse a dictionary (typically from JSON API response) into an Object instance.
345
+
346
+ This is the primary factory method for creating Object instances from
347
+ Rubika API responses. It handles:
348
+ - Type conversion based on field annotations
349
+ - Nested Object parsing
350
+ - Optional and List type handling
351
+ - Client binding
352
+
353
+ Parameters:
354
+ data (dict):
355
+ The dictionary data to parse, typically from `response.json()`.
356
+ client (Optional[rubigram.Client], optional):
357
+ Client instance to bind to the created object and its children.
358
+
359
+ Returns:
360
+ T: An instance of the calling class, populated with data.
361
+
362
+ Raises:
363
+ TypeError: If data cannot be parsed according to field types.
364
+ KeyError: If required fields are missing (depending on dataclass defaults).
365
+
366
+ Note:
367
+ - The "_" key (type marker) is automatically stripped from input data
368
+ - For lists of Objects, each item is parsed recursively
369
+ - Missing fields are set to None
370
+
371
+ Example:
372
+ .. code-block:: python
373
+ json_data = {
374
+ "_": "User",
375
+ "user_id": 123,
376
+ "name": "John",
377
+ "profile": {"_": "Profile", "avatar": "url"}
378
+ }
379
+ user = User.parse(json_data, client=my_client)
380
+ print(user.user_id) # 123
381
+ print(user.profile.avatar) # "url"
382
+ """
383
+ if not data:
384
+ obj = cls()
385
+ if client:
386
+ obj.bind(client)
387
+ return obj
388
+
389
+ data = {key: value for key, value in data.items() if key != "_"}
390
+ init_data = {}
391
+
392
+ fields_ = get_fields(cls)
393
+ type_hints = get_cached_type_hints(cls)
394
+
395
+ for field in fields_:
396
+ raw = data.get(field.name)
397
+
398
+ if raw is None:
399
+ init_data[field.name] = None
400
+ continue
401
+
402
+ field_type = type_hints.get(field.name, field.type)
403
+ origin = get_origin(field_type)
404
+
405
+ if isinstance(raw, dict) and "_" in raw:
406
+ raw = {k: v for k, v in raw.items() if k != "_"}
407
+
408
+ if origin is list and isinstance(raw, list):
409
+ inner = get_args(field_type)[0]
410
+ inner_origin = get_origin(inner)
411
+
412
+ if inner_origin is Union:
413
+ inner = strip_optional(inner)
414
+
415
+ if is_object_type(inner):
416
+ init_data[field.name] = [
417
+ inner.parse(v, client) if isinstance(v, dict) else v
418
+ for v in raw
419
+ ]
420
+ else:
421
+ init_data[field.name] = raw
422
+
423
+ elif origin is Union:
424
+ inner = strip_optional(field_type)
425
+
426
+ if is_object_type(inner) and isinstance(raw, dict):
427
+ init_data[field.name] = inner.parse(raw, client)
428
+ else:
429
+ init_data[field.name] = raw
430
+
431
+ else:
432
+ init_data[field.name] = raw
433
+
434
+ obj = cls(**init_data)
435
+
436
+ if client:
437
+ obj.bind(client)
438
+
439
+ return obj
440
+
441
+ def __str__(self) -> str:
442
+ return self.jsonify()
@@ -0,0 +1,29 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from typing import Optional
7
+ from dataclasses import dataclass
8
+ from .config import Object
9
+
10
+
11
+ @dataclass
12
+ class ContactMessage(Object):
13
+ """
14
+ **Represents a contact message containing user contact information.**
15
+ `from rubigram.types import ContactMessage`
16
+
17
+ Attributes:
18
+ phone_number (`str`):
19
+ The contact's phone number.
20
+
21
+ first_name (`Optional[str]`):
22
+ The contact's first name.
23
+
24
+ last_name (`Optional[str]`):
25
+ The contact's last name.
26
+ """
27
+ phone_number: str
28
+ first_name: Optional[str] = None
29
+ last_name: Optional[str] = None
rubigram/types/file.py ADDED
@@ -0,0 +1,78 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Optional
9
+ from dataclasses import dataclass
10
+ from .config import Object
11
+ import mimetypes
12
+ import rubigram
13
+
14
+
15
+
16
+ @dataclass
17
+ class File(Object):
18
+ """
19
+ **Represents a file object in Rubigram.**
20
+ `from rubigram.types import File`
21
+
22
+ Contains metadata about a file, such as its unique identifier,
23
+ name, size, and MIME type.
24
+
25
+ Attributes:
26
+ file_id (`str`):
27
+ Unique identifier for the file.
28
+
29
+ file_name (`Optional[str]`):
30
+ Name of the file (e.g., 'photo.png').
31
+
32
+ size (`Optional[int]`):
33
+ Size of the file in bytes.
34
+
35
+ file_type (`Optional[str]`):
36
+ MIME type of the file (e.g., 'image/png', 'video/mp4').
37
+ Automatically detected from the file name if not provided.
38
+ """
39
+
40
+ file_id: str
41
+ file_name: Optional[str] = None
42
+ size: Optional[int] = None
43
+ file_type: Optional[str] = None
44
+
45
+ def __post_init__(self):
46
+ if not self.file_name:
47
+ self.file_type = rubigram.enums.FileType.FILE
48
+ return
49
+
50
+ mime_type, _ = mimetypes.guess_type(self.file_name)
51
+ if not mime_type:
52
+ self.file_type = rubigram.enums.FileType.FILE
53
+ return
54
+
55
+ mime_main = mime_type.split("/")[0]
56
+ mime_sub = mime_type.split("/")[1]
57
+
58
+ if mime_main == "image":
59
+
60
+ if mime_sub == "gif":
61
+ self.file_type = rubigram.enums.FileType.GIF
62
+
63
+ else:
64
+ self.file_type = rubigram.enums.FileType.IMAGE
65
+
66
+ elif mime_main == "video":
67
+ self.file_type = rubigram.enums.FileType.VIDEO
68
+
69
+ elif mime_main == "audio":
70
+
71
+ if mime_sub in ["ogg", "amr", "m4a"]:
72
+ self.file_type = rubigram.enums.FileType.VOICE
73
+
74
+ else:
75
+ self.file_type = rubigram.enums.FileType.MUSIC
76
+
77
+ else:
78
+ self.file_type = rubigram.enums.FileType.FILE
@@ -0,0 +1,39 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Optional, Union
9
+ from dataclasses import dataclass
10
+ from .config import Object
11
+ import rubigram
12
+
13
+
14
+ @dataclass
15
+ class ForwardedFrom(Object):
16
+ """
17
+ **Represents information about the original sender of a forwarded message.**
18
+ `from rubigram.types import ForwardedFrom`
19
+
20
+ Includes the type of sender, the original message ID, and identifiers
21
+ for the chat or sender from which the message was forwarded.
22
+
23
+ Attributes:
24
+ type_from (`Optional[rubigram.enums.ForwardedFromType]`):
25
+ Type of the original sender (User, Bot, Channel).
26
+
27
+ message_id (`Optional[str]`):
28
+ ID of the original message.
29
+
30
+ from_chat_id (`Optional[str]`):
31
+ Chat ID where the original message was sent.
32
+
33
+ from_sender_id (`Optional[str]`):
34
+ Sender ID of the original message.
35
+ """
36
+ type_from: Optional[Union[str, rubigram.enums.ForwardedFromType]] = None
37
+ message_id: Optional[str] = None
38
+ from_chat_id: Optional[str] = None
39
+ from_sender_id: Optional[str] = None
@@ -0,0 +1,7 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from .keypad import Keypad
7
+ from .keypad_row import KeypadRow
@@ -0,0 +1,31 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import dataclass, field
9
+ from ..config import Object
10
+ import rubigram
11
+
12
+
13
+ @dataclass
14
+ class Keypad(Object):
15
+ """
16
+ **Represents a chat keypad, which may contain multiple rows of buttons.**
17
+ `from rubigram.types import Keypad`
18
+
19
+ Attributes:
20
+ rows (`list[rubigram.types.KeypadRow]`):
21
+ A list of KeypadRow objects representing the keypad layout.
22
+
23
+ resize_keyboard (`bool`):
24
+ Whether the keyboard should be resized to fit the screen. Defaults to True.
25
+
26
+ on_time_keyboard (`bool`):
27
+ Whether the keyboard should appear temporarily and disappear after use. Defaults to False.
28
+ """
29
+ rows: list[rubigram.types.KeypadRow] = field(default_factory=list)
30
+ resize_keyboard: bool = True
31
+ on_time_keyboard: bool = False
@@ -0,0 +1,23 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import dataclass, field
9
+ from ..config import Object
10
+ import rubigram
11
+
12
+
13
+ @dataclass
14
+ class KeypadRow(Object):
15
+ """
16
+ **Represents a single row of buttons in a chat keypad.**
17
+ `from rubigram.types import KeypadRow`
18
+
19
+ Attributes:
20
+ buttons (`list[rubigram.types.Button]`):
21
+ A list of Button objects in this row.
22
+ """
23
+ buttons: list[rubigram.types.Button] = field(default_factory=list)
@@ -0,0 +1,44 @@
1
+ # RubigramClient - Rubika API library for python
2
+ # Copyright (C) 2025-present Javad <https://github.com/DevJavad>
3
+ # Github - https://github.com/DevJavad/rubigram
4
+
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Optional, Union
9
+ from dataclasses import dataclass
10
+ from .config import Object
11
+ import rubigram
12
+
13
+
14
+ @dataclass
15
+ class LiveLocation(Object):
16
+ """
17
+ **Represents a live location shared by a user.**
18
+ `from rubigram.types import LiveLocation`
19
+
20
+ Attributes:
21
+ start_time (`Optional[str]`):
22
+ The start time of the live location sharing.
23
+
24
+ live_period (`Optional[int]`):
25
+ Duration of the live location in seconds.
26
+
27
+ current_location (`Optional[rubigram.types.Location]`):
28
+ Current coordinates of the live location.
29
+
30
+ user_id (`Optional[str]`):
31
+ User ID of the person sharing the location.
32
+
33
+ status (`Optional[Union[str, rubigram.enums.LiveLocationStatus]]`):
34
+ Status of the live location (Live or Stopped).
35
+
36
+ last_update_time (`Optional[str]`):
37
+ Timestamp of the last location update.
38
+ """
39
+ start_time: Optional[str] = None
40
+ live_period: Optional[int] = None
41
+ current_location: Optional[rubigram.types.Location] = None
42
+ user_id: Optional[str] = None
43
+ status: Optional[Union[str, rubigram.enums.LiveLocationStatus]] = None
44
+ last_update_time: Optional[str] = None