rubigramclient 1.7.35__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 (328) hide show
  1. rubigram/__init__.py +19 -0
  2. rubigram/ask.py +145 -0
  3. rubigram/bot/__init__.py +2 -0
  4. rubigram/bot/bot.py +255 -0
  5. rubigram/bot/dispatcher.py +58 -0
  6. rubigram/bot/enums/__init__.py +51 -0
  7. rubigram/bot/enums/buttons/__init__.py +13 -0
  8. rubigram/bot/enums/buttons/button_calendar_type.py +11 -0
  9. rubigram/bot/enums/buttons/button_location_type.py +11 -0
  10. rubigram/bot/enums/buttons/button_selection_get_type.py +11 -0
  11. rubigram/bot/enums/buttons/button_selection_search_type.py +11 -0
  12. rubigram/bot/enums/buttons/button_selection_type.py +12 -0
  13. rubigram/bot/enums/buttons/button_textbox_type_keypad.py +11 -0
  14. rubigram/bot/enums/buttons/button_textbox_type_line.py +11 -0
  15. rubigram/bot/enums/buttons/button_type.py +30 -0
  16. rubigram/bot/enums/chat_keypad_type.py +12 -0
  17. rubigram/bot/enums/chat_type.py +13 -0
  18. rubigram/bot/enums/file_type.py +16 -0
  19. rubigram/bot/enums/forwarded_from_type.py +12 -0
  20. rubigram/bot/enums/live_location_status.py +11 -0
  21. rubigram/bot/enums/message_sender_type.py +11 -0
  22. rubigram/bot/enums/metadata_type.py +18 -0
  23. rubigram/bot/enums/parse_mode.py +11 -0
  24. rubigram/bot/enums/payment_status_type.py +11 -0
  25. rubigram/bot/enums/poll_status_type.py +11 -0
  26. rubigram/bot/enums/update_endpoint_type.py +14 -0
  27. rubigram/bot/enums/update_type.py +15 -0
  28. rubigram/bot/errors/__init__.py +2 -0
  29. rubigram/bot/errors/api_error.py +12 -0
  30. rubigram/bot/errors/errors.py +34 -0
  31. rubigram/bot/filters/__init__.py +1 -0
  32. rubigram/bot/filters/filters.py +458 -0
  33. rubigram/bot/handlers/__init__.py +14 -0
  34. rubigram/bot/handlers/delete_message_handler.py +14 -0
  35. rubigram/bot/handlers/edit_message_handler.py +14 -0
  36. rubigram/bot/handlers/handler.py +41 -0
  37. rubigram/bot/handlers/inline_query_handler.py +14 -0
  38. rubigram/bot/handlers/message_handler.py +14 -0
  39. rubigram/bot/handlers/start_bot_handler.py +14 -0
  40. rubigram/bot/handlers/start_handler.py +14 -0
  41. rubigram/bot/handlers/stop_bot_handler.py +14 -0
  42. rubigram/bot/handlers/stop_handler.py +14 -0
  43. rubigram/bot/methods/__init__.py +26 -0
  44. rubigram/bot/methods/advanced/__init__.py +7 -0
  45. rubigram/bot/methods/advanced/invoke.py +38 -0
  46. rubigram/bot/methods/chat/__init__.py +18 -0
  47. rubigram/bot/methods/chat/ban_chat_member.py +28 -0
  48. rubigram/bot/methods/chat/get_chat.py +28 -0
  49. rubigram/bot/methods/chat/get_chat_member.py +28 -0
  50. rubigram/bot/methods/chat/unban_chat_member.py +28 -0
  51. rubigram/bot/methods/decorators/__init__.py +17 -0
  52. rubigram/bot/methods/decorators/on_deleted_message.py +24 -0
  53. rubigram/bot/methods/decorators/on_edited_message.py +24 -0
  54. rubigram/bot/methods/decorators/on_inline_query.py +24 -0
  55. rubigram/bot/methods/decorators/on_message.py +34 -0
  56. rubigram/bot/methods/decorators/on_start.py +24 -0
  57. rubigram/bot/methods/decorators/on_started_bot.py +24 -0
  58. rubigram/bot/methods/decorators/on_stop.py +24 -0
  59. rubigram/bot/methods/decorators/on_stopped_bot.py +24 -0
  60. rubigram/bot/methods/messages/__init__.py +57 -0
  61. rubigram/bot/methods/messages/auto_delete_message.py +41 -0
  62. rubigram/bot/methods/messages/delete_messages.py +33 -0
  63. rubigram/bot/methods/messages/download_file.py +52 -0
  64. rubigram/bot/methods/messages/edit_chat_keypad.py +23 -0
  65. rubigram/bot/methods/messages/edit_message.py +32 -0
  66. rubigram/bot/methods/messages/edit_message_keypad.py +21 -0
  67. rubigram/bot/methods/messages/edit_message_text.py +32 -0
  68. rubigram/bot/methods/messages/forward_message.py +34 -0
  69. rubigram/bot/methods/messages/get_file.py +29 -0
  70. rubigram/bot/methods/messages/remove_chat_keypad.py +15 -0
  71. rubigram/bot/methods/messages/request_send_file.py +40 -0
  72. rubigram/bot/methods/messages/send_contact.py +47 -0
  73. rubigram/bot/methods/messages/send_file.py +67 -0
  74. rubigram/bot/methods/messages/send_gif.py +40 -0
  75. rubigram/bot/methods/messages/send_location.py +47 -0
  76. rubigram/bot/methods/messages/send_message.py +50 -0
  77. rubigram/bot/methods/messages/send_music.py +40 -0
  78. rubigram/bot/methods/messages/send_photo.py +40 -0
  79. rubigram/bot/methods/messages/send_poll.py +47 -0
  80. rubigram/bot/methods/messages/send_sticker.py +45 -0
  81. rubigram/bot/methods/messages/send_video.py +40 -0
  82. rubigram/bot/methods/messages/send_voice.py +40 -0
  83. rubigram/bot/methods/messages/upload.py +56 -0
  84. rubigram/bot/methods/settings/__init__.py +14 -0
  85. rubigram/bot/methods/settings/set_bot_command.py +20 -0
  86. rubigram/bot/methods/settings/update_bot_endpoint.py +16 -0
  87. rubigram/bot/methods/updates/__init__.py +12 -0
  88. rubigram/bot/methods/updates/get_update.py +22 -0
  89. rubigram/bot/methods/user/__init__.py +7 -0
  90. rubigram/bot/methods/user/get_me.py +26 -0
  91. rubigram/bot/methods/utilities/__init__.py +20 -0
  92. rubigram/bot/methods/utilities/add_handler.py +23 -0
  93. rubigram/bot/methods/utilities/remove_handler.py +16 -0
  94. rubigram/bot/methods/utilities/run.py +89 -0
  95. rubigram/bot/methods/utilities/start.py +26 -0
  96. rubigram/bot/methods/utilities/stop.py +24 -0
  97. rubigram/bot/types/__init__.py +67 -0
  98. rubigram/bot/types/aux_data.py +29 -0
  99. rubigram/bot/types/base/__init__.py +6 -0
  100. rubigram/bot/types/base/base.py +33 -0
  101. rubigram/bot/types/bot.py +46 -0
  102. rubigram/bot/types/bot_command.py +29 -0
  103. rubigram/bot/types/buttons/__init__.py +13 -0
  104. rubigram/bot/types/buttons/button.py +49 -0
  105. rubigram/bot/types/buttons/button_calendar.py +33 -0
  106. rubigram/bot/types/buttons/button_location.py +34 -0
  107. rubigram/bot/types/buttons/button_number_picker.py +30 -0
  108. rubigram/bot/types/buttons/button_selection.py +37 -0
  109. rubigram/bot/types/buttons/button_selection_item.py +29 -0
  110. rubigram/bot/types/buttons/button_string_picker.py +28 -0
  111. rubigram/bot/types/buttons/button_text_box.py +33 -0
  112. rubigram/bot/types/chat.py +50 -0
  113. rubigram/bot/types/contact_message.py +32 -0
  114. rubigram/bot/types/file.py +73 -0
  115. rubigram/bot/types/forwarded_from.py +37 -0
  116. rubigram/bot/types/keypads/__init__.py +7 -0
  117. rubigram/bot/types/keypads/keypad.py +33 -0
  118. rubigram/bot/types/keypads/keypad_row.py +27 -0
  119. rubigram/bot/types/live_location.py +47 -0
  120. rubigram/bot/types/location.py +29 -0
  121. rubigram/bot/types/messages/__init__.py +7 -0
  122. rubigram/bot/types/messages/inline_message.py +73 -0
  123. rubigram/bot/types/messages/message.py +184 -0
  124. rubigram/bot/types/metadata/__init__.py +7 -0
  125. rubigram/bot/types/metadata/metadata.py +29 -0
  126. rubigram/bot/types/metadata/metadata_parts.py +39 -0
  127. rubigram/bot/types/payment_status.py +32 -0
  128. rubigram/bot/types/poll.py +35 -0
  129. rubigram/bot/types/poll_status.py +40 -0
  130. rubigram/bot/types/propagation.py +9 -0
  131. rubigram/bot/types/sticker.py +35 -0
  132. rubigram/bot/types/updates/__init__.py +7 -0
  133. rubigram/bot/types/updates/update.py +119 -0
  134. rubigram/bot/types/updates/updates.py +31 -0
  135. rubigram/bot/web/__init__.py +2 -0
  136. rubigram/bot/web/webhook.py +89 -0
  137. rubigram/bot/web/websocket.py +5 -0
  138. rubigram/client.py +440 -0
  139. rubigram/connection/__init__.py +6 -0
  140. rubigram/connection/connection.py +77 -0
  141. rubigram/crypto/__init__.py +1 -0
  142. rubigram/crypto/crypto.py +144 -0
  143. rubigram/dispatcher.py +59 -0
  144. rubigram/enums/__init__.py +4 -0
  145. rubigram/enums/auth/__init__.py +3 -0
  146. rubigram/enums/auth/sent_code_status.py +7 -0
  147. rubigram/enums/auth/sent_code_type.py +7 -0
  148. rubigram/enums/auth/sign_in_status.py +8 -0
  149. rubigram/enums/chats/__init__.py +26 -0
  150. rubigram/enums/chats/chat_access.py +24 -0
  151. rubigram/enums/chats/chat_message.py +7 -0
  152. rubigram/enums/chats/chat_reaction.py +7 -0
  153. rubigram/enums/chats/chat_status.py +9 -0
  154. rubigram/enums/chats/chat_type.py +9 -0
  155. rubigram/enums/chats/chat_update.py +7 -0
  156. rubigram/enums/chats/folder_exclude.py +7 -0
  157. rubigram/enums/chats/folder_include.py +10 -0
  158. rubigram/enums/chats/folder_type.py +6 -0
  159. rubigram/enums/chats/voice_chat_action.py +7 -0
  160. rubigram/enums/chats/voice_chat_status.py +7 -0
  161. rubigram/enums/messages/__init__.py +5 -0
  162. rubigram/enums/messages/file_type.py +13 -0
  163. rubigram/enums/messages/live_status_type.py +5 -0
  164. rubigram/enums/messages/message_action.py +7 -0
  165. rubigram/enums/messages/message_type.py +17 -0
  166. rubigram/enums/messages/notification_type.py +5 -0
  167. rubigram/enums/setting/__init__.py +4 -0
  168. rubigram/enums/setting/online_time_type.py +6 -0
  169. rubigram/enums/setting/parse_mode.py +6 -0
  170. rubigram/enums/setting/platform.py +8 -0
  171. rubigram/enums/setting/run_type.py +6 -0
  172. rubigram/errors/__init__.py +2 -0
  173. rubigram/errors/errors.py +86 -0
  174. rubigram/errors/rpc_error.py +14 -0
  175. rubigram/filters/__init__.py +2 -0
  176. rubigram/filters/filter.py +109 -0
  177. rubigram/filters/filters.py +255 -0
  178. rubigram/handlers/__init__.py +11 -0
  179. rubigram/handlers/connect_handler.py +14 -0
  180. rubigram/handlers/disconnect_handler.py +14 -0
  181. rubigram/handlers/handler.py +89 -0
  182. rubigram/handlers/message_handler.py +14 -0
  183. rubigram/handlers/start_handler.py +14 -0
  184. rubigram/handlers/stop_handler.py +14 -0
  185. rubigram/listener.py +162 -0
  186. rubigram/methods/__init__.py +21 -0
  187. rubigram/methods/advanced/__init__.py +13 -0
  188. rubigram/methods/advanced/invoke.py +67 -0
  189. rubigram/methods/advanced/request_send_file.py +21 -0
  190. rubigram/methods/advanced/upload.py +157 -0
  191. rubigram/methods/advanced/websocket.py +235 -0
  192. rubigram/methods/auth/__init__.py +13 -0
  193. rubigram/methods/auth/logout.py +8 -0
  194. rubigram/methods/auth/register_device.py +24 -0
  195. rubigram/methods/auth/send_code.py +33 -0
  196. rubigram/methods/auth/sign_in.py +34 -0
  197. rubigram/methods/chats/__init__.py +45 -0
  198. rubigram/methods/chats/action_on_join_request.py +20 -0
  199. rubigram/methods/chats/add_channel.py +23 -0
  200. rubigram/methods/chats/add_group.py +21 -0
  201. rubigram/methods/chats/ban_group_member.py +23 -0
  202. rubigram/methods/chats/ban_member.py +13 -0
  203. rubigram/methods/chats/delete_chat_history.py +13 -0
  204. rubigram/methods/chats/edit_group_info.py +5 -0
  205. rubigram/methods/chats/get_banned_group_members.py +13 -0
  206. rubigram/methods/chats/get_chat_info.py +14 -0
  207. rubigram/methods/chats/get_chats.py +11 -0
  208. rubigram/methods/chats/get_chats_updates.py +13 -0
  209. rubigram/methods/chats/get_group_admin_members.py +14 -0
  210. rubigram/methods/chats/get_group_link.py +9 -0
  211. rubigram/methods/chats/get_join_requests.py +9 -0
  212. rubigram/methods/chats/join_channel.py +29 -0
  213. rubigram/methods/chats/join_group.py +12 -0
  214. rubigram/methods/chats/leave_group.py +14 -0
  215. rubigram/methods/chats/set_channel_admin.py +86 -0
  216. rubigram/methods/chats/set_group_admin.py +82 -0
  217. rubigram/methods/chats/update_channel_username.py +14 -0
  218. rubigram/methods/decorators/__init__.py +15 -0
  219. rubigram/methods/decorators/on_chat_update.py +0 -0
  220. rubigram/methods/decorators/on_connect.py +20 -0
  221. rubigram/methods/decorators/on_delete_message.py +0 -0
  222. rubigram/methods/decorators/on_disconnect.py +20 -0
  223. rubigram/methods/decorators/on_edit_message.py +0 -0
  224. rubigram/methods/decorators/on_message.py +34 -0
  225. rubigram/methods/decorators/on_message_update.py +0 -0
  226. rubigram/methods/decorators/on_sotp.py +13 -0
  227. rubigram/methods/decorators/on_start.py +13 -0
  228. rubigram/methods/decorators/on_update.py +0 -0
  229. rubigram/methods/messages/__init__.py +30 -0
  230. rubigram/methods/messages/auto_delete_message.py +41 -0
  231. rubigram/methods/messages/delete_messages.py +21 -0
  232. rubigram/methods/messages/edit_message.py +29 -0
  233. rubigram/methods/messages/forward_messages.py +27 -0
  234. rubigram/methods/messages/get_link_from_app_url.py +11 -0
  235. rubigram/methods/messages/get_message_share_url.py +13 -0
  236. rubigram/methods/messages/get_messages.py +49 -0
  237. rubigram/methods/messages/get_messages_by_id.py +18 -0
  238. rubigram/methods/messages/get_messages_interval.py +13 -0
  239. rubigram/methods/messages/get_messages_updates.py +15 -0
  240. rubigram/methods/messages/send_file.py +108 -0
  241. rubigram/methods/messages/send_live.py +46 -0
  242. rubigram/methods/messages/send_message.py +35 -0
  243. rubigram/methods/settings/__init__.py +7 -0
  244. rubigram/methods/settings/update_profile.py +31 -0
  245. rubigram/methods/updates/__init__.py +7 -0
  246. rubigram/methods/users/__init__.py +13 -0
  247. rubigram/methods/users/get_contacts.py +12 -0
  248. rubigram/methods/users/get_me.py +9 -0
  249. rubigram/methods/users/get_user_info.py +13 -0
  250. rubigram/methods/users/update_username.py +13 -0
  251. rubigram/methods/utilities/__init__.py +23 -0
  252. rubigram/methods/utilities/add_handler.py +33 -0
  253. rubigram/methods/utilities/connect.py +15 -0
  254. rubigram/methods/utilities/dsiconnect.py +15 -0
  255. rubigram/methods/utilities/get_updates.py +25 -0
  256. rubigram/methods/utilities/polling.py +38 -0
  257. rubigram/methods/utilities/remvoe_handler.py +33 -0
  258. rubigram/methods/utilities/run.py +38 -0
  259. rubigram/methods/utilities/start.py +29 -0
  260. rubigram/methods/utilities/stop.py +25 -0
  261. rubigram/parser/__init__.py +1 -0
  262. rubigram/parser/markdown.py +152 -0
  263. rubigram/parser/parser.py +21 -0
  264. rubigram/server/__init__.py +1 -0
  265. rubigram/server/server.py +93 -0
  266. rubigram/session/__init__.py +0 -0
  267. rubigram/session/json.py +4 -0
  268. rubigram/session/session.py +0 -0
  269. rubigram/storage/__init__.py +6 -0
  270. rubigram/storage/storage.py +50 -0
  271. rubigram/sync.py +94 -0
  272. rubigram/types/__init__.py +18 -0
  273. rubigram/types/auth/__init__.py +8 -0
  274. rubigram/types/auth/sent_code.py +73 -0
  275. rubigram/types/auth/sign_in.py +58 -0
  276. rubigram/types/avatar.py +27 -0
  277. rubigram/types/base/__init__.py +9 -0
  278. rubigram/types/base/base.py +26 -0
  279. rubigram/types/chats/__init__.py +16 -0
  280. rubigram/types/chats/chat.py +77 -0
  281. rubigram/types/chats/chat_message.py +55 -0
  282. rubigram/types/chats/chat_update.py +33 -0
  283. rubigram/types/chats/get_chats.py +27 -0
  284. rubigram/types/keypad.py +21 -0
  285. rubigram/types/keypad_row.py +9 -0
  286. rubigram/types/messages/__init__.py +36 -0
  287. rubigram/types/messages/badge.py +18 -0
  288. rubigram/types/messages/contact_message.py +25 -0
  289. rubigram/types/messages/file_inline.py +44 -0
  290. rubigram/types/messages/forwarded_from.py +22 -0
  291. rubigram/types/messages/last_message.py +28 -0
  292. rubigram/types/messages/live_data.py +24 -0
  293. rubigram/types/messages/live_status.py +24 -0
  294. rubigram/types/messages/location.py +22 -0
  295. rubigram/types/messages/map_view.py +23 -0
  296. rubigram/types/messages/message.py +75 -0
  297. rubigram/types/messages/message_data.py +20 -0
  298. rubigram/types/messages/message_info.py +33 -0
  299. rubigram/types/messages/message_update.py +40 -0
  300. rubigram/types/messages/rubino_post.py +21 -0
  301. rubigram/types/messages/sticker.py +26 -0
  302. rubigram/types/messages/sticker_file.py +27 -0
  303. rubigram/types/online_time.py +20 -0
  304. rubigram/types/server/__init__.py +8 -0
  305. rubigram/types/server/request_send_file.py +32 -0
  306. rubigram/types/server/upload_file.py +16 -0
  307. rubigram/types/settings/__init__.py +8 -0
  308. rubigram/types/settings/session.py +67 -0
  309. rubigram/types/settings/sessions_info.py +27 -0
  310. rubigram/types/stories/__init__.py +6 -0
  311. rubigram/types/stories/story.py +17 -0
  312. rubigram/types/updates/__init__.py +10 -0
  313. rubigram/types/updates/notification.py +27 -0
  314. rubigram/types/updates/update.py +71 -0
  315. rubigram/types/updates/update_parametrs.py +27 -0
  316. rubigram/types/users/__init__.py +11 -0
  317. rubigram/types/users/user.py +61 -0
  318. rubigram/types/users/user_info.py +107 -0
  319. rubigram/types/warnings/__init__.py +7 -0
  320. rubigram/types/warnings/color.py +21 -0
  321. rubigram/types/warnings/warning.py +25 -0
  322. rubigram/utils/__init__.py +1 -0
  323. rubigram/utils/utils.py +278 -0
  324. rubigramclient-1.7.35.dist-info/METADATA +222 -0
  325. rubigramclient-1.7.35.dist-info/RECORD +328 -0
  326. rubigramclient-1.7.35.dist-info/WHEEL +5 -0
  327. rubigramclient-1.7.35.dist-info/licenses/LICENSE +22 -0
  328. rubigramclient-1.7.35.dist-info/top_level.txt +1 -0
rubigram/__init__.py ADDED
@@ -0,0 +1,19 @@
1
+ class StopPropagation(StopAsyncIteration):
2
+ pass
3
+
4
+
5
+ class ContinuePropagation(StopAsyncIteration):
6
+ pass
7
+
8
+
9
+ from .rubigram import handlers, sync, types
10
+
11
+ from .rubigram.storage import Storage
12
+ from .rubigram import enums
13
+ from .rubigram.client import Client
14
+ from .rubigram.bot import Bot
15
+
16
+
17
+ __version__ = "1.7.35"
18
+ __author__ = ["PyJavad", "DeveloperYasin"]
19
+ __github__ = "https://github.ocm/DevJavad/rubigram"
rubigram/ask.py ADDED
@@ -0,0 +1,145 @@
1
+ # rubigram/ask.py
2
+
3
+ import asyncio
4
+ import rubigram
5
+ from typing import Optional, Union
6
+
7
+ from rubigram.filters import Filter
8
+ from rubigram.types import Update
9
+
10
+
11
+ class AskManager:
12
+ """
13
+ Ask manager for handling interactive conversations with users
14
+ Compatible with Rubigram's existing Storage and State system
15
+ """
16
+
17
+ def __init__(self, client:"rubigram.Client"):
18
+ self.client = client
19
+ self._pending_asks: dict[str, asyncio.Future] = {}
20
+ self._pending_filters: dict[str, Optional[Filter]] = {}
21
+ self._default_timeout = 60
22
+
23
+ # Register internal handler
24
+ self._register_handler()
25
+
26
+ def _register_handler(self):
27
+ """Register internal handler to catch user responses"""
28
+
29
+ @self.client.on_message(group=-999) # Highest priority
30
+ async def _ask_response_handler(client, update: Update):
31
+ user_id = str(update.message.author_object_guid)
32
+
33
+ if user_id in self._pending_asks:
34
+ future = self._pending_asks[user_id]
35
+ answer_filter = self._pending_filters.get(user_id)
36
+
37
+ # Check if message passes the filter
38
+ if answer_filter is not None:
39
+ if not await self._check_filter(client,answer_filter, update):
40
+ return False # Don't consume, let other handlers process
41
+
42
+ if not future.done():
43
+ future.set_result(update)
44
+ del self._pending_asks[user_id]
45
+ del self._pending_filters[user_id]
46
+ return True # Consumed by ask handler
47
+
48
+ return False
49
+
50
+ async def _check_filter(self,client, filter_obj: Filter, update: Update) -> bool:
51
+ """Check if update passes the filter"""
52
+ if callable(filter_obj):
53
+ result = filter_obj(client, update)
54
+ if asyncio.iscoroutine(result):
55
+ return await result
56
+ return result
57
+ return True
58
+
59
+ async def ask(
60
+ self,
61
+ user_id: Union[str, int],
62
+ question: str,
63
+ timeout: Optional[int] = None,
64
+ filters: Optional[Filter] = None,
65
+ parse_mode: Optional[str] = None,
66
+ reply_to_message_id: Optional[str] = None,
67
+ **kwargs
68
+ ) -> Update:
69
+ """
70
+ Send a question to user and wait for response
71
+
72
+ Args:
73
+ user_id: User's GUID or ID
74
+ question: Question text to send
75
+ timeout: Timeout in seconds (None = infinite)
76
+ filters: Filter for response (e.g., filters.text, filters.photo)
77
+ parse_mode: Parse mode for question message
78
+ reply_to_message_id: Reply to specific message
79
+ **kwargs: Additional arguments for send_message
80
+
81
+ Returns:
82
+ Update object containing user's response
83
+
84
+ Raises:
85
+ TimeoutError: If user doesn't respond within timeout
86
+ """
87
+ user_id = str(user_id)
88
+
89
+ # Create future for waiting
90
+ future = asyncio.Future()
91
+
92
+ # Store pending ask
93
+ self._pending_asks[user_id] = future
94
+ self._pending_filters[user_id] = filters
95
+
96
+ # Send question
97
+ x = await self.client.send_message(
98
+ user_id,
99
+ question,
100
+ parse_mode=parse_mode,
101
+ reply_to_message_id=reply_to_message_id,
102
+ **kwargs
103
+ )
104
+
105
+ # Handle timeout
106
+ timeout_seconds = timeout if timeout is not None else self._default_timeout
107
+
108
+ try:
109
+ if timeout_seconds > 0:
110
+ response = await asyncio.wait_for(future, timeout=timeout_seconds)
111
+ else:
112
+ response = await future
113
+ return response
114
+ except asyncio.TimeoutError:
115
+ raise TimeoutError(f"No response received from user {user_id} within {timeout_seconds} seconds")
116
+ finally:
117
+ # Cleanup
118
+ self._pending_asks.pop(user_id, None)
119
+ self._pending_filters.pop(user_id, None)
120
+
121
+ def is_waiting(self, user_id: Union[str, int]) -> bool:
122
+ """Check if user has a pending ask"""
123
+ return str(user_id) in self._pending_asks
124
+
125
+ def cancel(self, user_id: Union[str, int]) -> bool:
126
+ """Cancel pending ask for a user"""
127
+ user_id = str(user_id)
128
+ if user_id in self._pending_asks:
129
+ self._pending_asks[user_id].cancel()
130
+ del self._pending_asks[user_id]
131
+ self._pending_filters.pop(user_id, None)
132
+ return True
133
+ return False
134
+
135
+
136
+ # Mixin to add to Client class
137
+ class AskMixin:
138
+ """Mixin to add ask functionality to Client"""
139
+
140
+ @property
141
+ def ask(self) -> AskManager:
142
+ """Get ask manager instance"""
143
+ if not hasattr(self, '_ask_manager'):
144
+ self._ask_manager = AskManager(self)
145
+ return self._ask_manager
@@ -0,0 +1,2 @@
1
+ from .bot import Bot
2
+ from ...bot import errors, enums, types, filters
rubigram/bot/bot.py ADDED
@@ -0,0 +1,255 @@
1
+ import os
2
+ import sys
3
+ import time
4
+ import logging
5
+
6
+ from pathlib import Path
7
+ from importlib import import_module
8
+ from typing import Optional, Callable
9
+ from asyncio import AbstractEventLoop, Semaphore
10
+ from concurrent.futures.thread import ThreadPoolExecutor as Executor
11
+
12
+ from rubigram.parser import Parser
13
+ from rubigram import utils, Storage
14
+ from rubigram.bot.methods import Methods
15
+ from rubigram.connection import Connection
16
+ from rubigram.bot.dispatcher import Dispatcher
17
+ from rubigram.server import Server
18
+ from rubigram.bot.enums import ParseMode
19
+ from rubigram.bot.handlers import Handler
20
+ from rubigram.bot.web import Webhook
21
+ from rubigram.bot.types import Bot as Me
22
+
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ class Bot(Methods):
28
+
29
+ WORKERS = min(32, (os.cpu_count() or 0) + 4)
30
+ PARENT_DIR = Path(sys.argv[0]).parent
31
+ WORKDIR = PARENT_DIR
32
+
33
+ def __init__(
34
+ self,
35
+ token: str,
36
+ offset_id: Optional[str] = None,
37
+ auto_delete: Optional[int] = None,
38
+ parse_mode: "ParseMode" = ParseMode.MARKDOWN,
39
+
40
+ use_webhook: bool = False,
41
+ webhook_url: Optional[str] = None,
42
+ host: str = "127.0.0.1",
43
+ port: int = 8080,
44
+ set_new_webhook: bool = True,
45
+
46
+ delay: int = 1,
47
+ retry: int = 3,
48
+ backoff: int = 1,
49
+ workers: int = WORKERS,
50
+ workdir: ... = WORKDIR,
51
+
52
+ plugins: Optional[dict] = None,
53
+ timeout: int = 15,
54
+ connect_timeout: int = 20,
55
+ max_connections: int = 100,
56
+ socket_read_timeout: int = 20,
57
+
58
+ proxy: Optional[str] = None,
59
+ semaphore: Optional[Semaphore] = None,
60
+ loop: Optional[AbstractEventLoop] = None
61
+ ):
62
+ self.token = token
63
+ self.offset_id = offset_id or f"{int(time.time()):08x}{'0'*16}"
64
+ self.parse_mode = parse_mode
65
+ self.auto_delete = auto_delete
66
+
67
+ self.use_webhook = use_webhook
68
+ self.webhook_url = webhook_url
69
+ self.host = host
70
+ self.port = port
71
+
72
+ self.delay = delay
73
+ self.retry = retry
74
+ self.backoff = backoff
75
+ self.workers = workers
76
+ self.plugins = plugins
77
+
78
+ self.timeout = timeout
79
+ self.connect_timeout = connect_timeout
80
+ self.max_connections = max_connections
81
+ self.socket_read_timeout = socket_read_timeout
82
+
83
+ self.proxy = proxy
84
+
85
+ self.semaphore = semaphore or Semaphore(workers)
86
+ self.executor = Executor(workers, thread_name_prefix="Handler")
87
+
88
+ if isinstance(loop, AbstractEventLoop):
89
+ self.loop = loop
90
+ else:
91
+ loop = utils.get_event_loop()
92
+
93
+ self.me: Optional["Me"] = None
94
+
95
+ self.stop_handler: Optional[Callable] = None
96
+ self.start_handler: Optional[Callable] = None
97
+
98
+ self.storage = Storage()
99
+ self.parser = Parser(parse_mode)
100
+
101
+ self.connection = Connection(
102
+ timeout,
103
+ connect_timeout,
104
+ max_connections,
105
+ socket_read_timeout
106
+ )
107
+
108
+ self.server = Server(self.connection, retry, delay, backoff, proxy)
109
+ self.set_new_webhook = set_new_webhook
110
+
111
+ self.dispatcher = Dispatcher(self)
112
+ if use_webhook:
113
+ self.webhook = Webhook(self)
114
+ else:
115
+ self.webhook = None
116
+
117
+ self.API_URL: str = "https://botapi.rubika.ir/v3/{}/".format(token)
118
+
119
+ def __enter__(self):
120
+ return self.start()
121
+
122
+ def __exit__(self, *args):
123
+ try:
124
+ return self.stop()
125
+ except ConnectionError:
126
+ pass
127
+
128
+ async def __aenter__(self):
129
+ await self.start()
130
+ return self
131
+
132
+ async def __aexit__(self, *args):
133
+ try:
134
+ await self.stop()
135
+ except ConnectionError:
136
+ pass
137
+
138
+ def load_plugins(self):
139
+ if self.plugins:
140
+ plugins = self.plugins.copy()
141
+
142
+ for option in ["include", "exclude"]:
143
+ if plugins.get(option, []):
144
+ plugins[option] = [
145
+ (i.split()[0], i.split()[1:] or None)
146
+ for i in self.plugins[option]
147
+ ]
148
+ else:
149
+ return
150
+
151
+ if plugins.get("enabled", True):
152
+ root = plugins["root"]
153
+ include = plugins.get("include", [])
154
+ exclude = plugins.get("exclude", [])
155
+
156
+ count = 0
157
+
158
+ if not include:
159
+ for path in sorted(Path(root.replace(".", "/")).rglob("*.py")):
160
+ module_path = '.'.join(path.parent.parts + (path.stem,))
161
+ module = import_module(module_path)
162
+
163
+ for name in vars(module).keys():
164
+ # noinspection PyBroadException
165
+ try:
166
+ for handler, group in getattr(module, name).handlers:
167
+ if isinstance(handler, Handler) and isinstance(group, int):
168
+ self.add_handler(handler, group)
169
+
170
+ logger.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
171
+ self.token, type(handler).__name__, name, group, module_path))
172
+
173
+ count += 1
174
+ except Exception:
175
+ pass
176
+ else:
177
+ for path, handlers in include:
178
+ module_path = root + "." + path
179
+ warn_non_existent_functions = True
180
+
181
+ try:
182
+ module = import_module(module_path)
183
+ except ImportError:
184
+ logger.warning(
185
+ '[%s] [LOAD] Ignoring non-existent module "%s"', self.token, module_path)
186
+ continue
187
+
188
+ if "__path__" in dir(module):
189
+ logger.warning(
190
+ '[%s] [LOAD] Ignoring namespace "%s"', self.token, module_path)
191
+ continue
192
+
193
+ if handlers is None:
194
+ handlers = vars(module).keys()
195
+ warn_non_existent_functions = False
196
+
197
+ for name in handlers:
198
+ # noinspection PyBroadException
199
+ try:
200
+ for handler, group in getattr(module, name).handlers:
201
+ if isinstance(handler, Handler) and isinstance(group, int):
202
+ self.add_handler(handler, group)
203
+
204
+ logger.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
205
+ self.token, type(handler).__name__, name, group, module_path))
206
+
207
+ count += 1
208
+ except Exception:
209
+ if warn_non_existent_functions:
210
+ logger.warning('[{}] [LOAD] Ignoring non-existent function "{}" from "{}"'.format(
211
+ self.token, name, module_path))
212
+
213
+ if exclude:
214
+ for path, handlers in exclude:
215
+ module_path = root + "." + path
216
+ warn_non_existent_functions = True
217
+
218
+ try:
219
+ module = import_module(module_path)
220
+ except ImportError:
221
+ logger.warning(
222
+ '[%s] [UNLOAD] Ignoring non-existent module "%s"', self.token, module_path)
223
+ continue
224
+
225
+ if "__path__" in dir(module):
226
+ logger.warning(
227
+ '[%s] [UNLOAD] Ignoring namespace "%s"', self.token, module_path)
228
+ continue
229
+
230
+ if handlers is None:
231
+ handlers = vars(module).keys()
232
+ warn_non_existent_functions = False
233
+
234
+ for name in handlers:
235
+ # noinspection PyBroadException
236
+ try:
237
+ for handler, group in getattr(module, name).handlers:
238
+ if isinstance(handler, Handler) and isinstance(group, int):
239
+ self.remove_handler(handler, group)
240
+
241
+ logger.info('[{}] [UNLOAD] {}("{}") from group {} in "{}"'.format(
242
+ self.token, type(handler).__name__, name, group, module_path))
243
+
244
+ count -= 1
245
+ except Exception:
246
+ if warn_non_existent_functions:
247
+ logger.warning('[{}] [UNLOAD] Ignoring non-existent function "{}" from "{}"'.format(
248
+ self.token, name, module_path))
249
+
250
+ if count > 0:
251
+ logger.info('[{}] Successfully loaded {} plugin{} from "{}"'.format(
252
+ self.token, count, "s" if count > 1 else "", root))
253
+ else:
254
+ logger.warning('[%s] No plugin loaded from "%s"',
255
+ self.token, root)
@@ -0,0 +1,58 @@
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
+ import logging
7
+ from typing import Union
8
+
9
+ import rubigram
10
+ from rubigram.bot.handlers import Handler
11
+ from rubigram.bot.types import Update, InlineMessage
12
+ from rubigram import StopPropagation, ContinuePropagation
13
+
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class Dispatcher:
19
+ def __init__(self, bot: "rubigram.Bot"):
20
+ self.bot = bot
21
+ self.handlers: dict[int, list["Handler"]] = {}
22
+
23
+ def start(self):
24
+ ...
25
+
26
+ def stop(self):
27
+ ...
28
+
29
+ def add_handler(
30
+ self,
31
+ handler: "Handler",
32
+ group: int = 0
33
+ ):
34
+ self.handlers.setdefault(group, [])
35
+ self.handlers[group].append(handler)
36
+
37
+ def remove_handler(
38
+ self,
39
+ handler: "Handler",
40
+ group: int = 0
41
+ ):
42
+ if group in self.handlers and handler in self.handlers[group]:
43
+ self.handlers[group].remove(handler)
44
+
45
+ async def dispatch(
46
+ self,
47
+ update: Union["Update", "InlineMessage"]
48
+ ):
49
+ for group in sorted(self.handlers):
50
+ for handler in self.handlers.get(group):
51
+ try:
52
+ status, call = await handler.execute(self.bot, update)
53
+ if status:
54
+ break
55
+ except ContinuePropagation:
56
+ continue
57
+ except StopPropagation:
58
+ raise
@@ -0,0 +1,51 @@
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 .buttons import (
7
+ ButtonCalendarType,
8
+ ButtonLocationType,
9
+ ButtonSelectionGetType,
10
+ ButtonSelectionSearchType,
11
+ ButtonSelectionType,
12
+ ButtonTextboxTypeLine,
13
+ ButtonTextboxTypeKeypad,
14
+ ButtonType
15
+ )
16
+ from .chat_keypad_type import ChatKeypadType
17
+ from .chat_type import ChatType
18
+ from .file_type import FileType
19
+ from .forwarded_from_type import ForwardedFromType
20
+ from .live_location_status import LiveLocationStatus
21
+ from .message_sender_type import MessageSenderType
22
+ from .parse_mode import ParseMode
23
+ from .payment_status_type import PaymentStatusType
24
+ from .poll_status_type import PollStatusType
25
+ from .update_endpoint_type import UpdateEndpointType
26
+ from .update_type import UpdateType
27
+ from .metadata_type import MetadataType
28
+
29
+ __all__ = [
30
+ "ButtonCalendarType",
31
+ "ButtonLocationType",
32
+ "ButtonSelectionGetType",
33
+ "ButtonSelectionSearchType",
34
+ "ButtonSelectionType",
35
+ "ButtonTextboxTypeLine",
36
+ "ButtonTextboxTypeKeypad",
37
+ "ButtonType",
38
+ "ChatActionType",
39
+ "ChatKeypadType",
40
+ "ChatType",
41
+ "FileType",
42
+ "ForwardedFromType",
43
+ "LiveLocationStatus",
44
+ "MessageSenderType",
45
+ "ParseMode",
46
+ "PaymentStatusType",
47
+ "PollStatusType",
48
+ "UpdateEndpointType",
49
+ "UpdateType",
50
+ "MetadataType"
51
+ ]
@@ -0,0 +1,13 @@
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 .button_calendar_type import ButtonCalendarType
7
+ from .button_location_type import ButtonLocationType
8
+ from .button_selection_get_type import ButtonSelectionGetType
9
+ from .button_selection_search_type import ButtonSelectionSearchType
10
+ from .button_selection_type import ButtonSelectionType
11
+ from .button_textbox_type_line import ButtonTextboxTypeLine
12
+ from .button_textbox_type_keypad import ButtonTextboxTypeKeypad
13
+ from .button_type import ButtonType
@@ -0,0 +1,11 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonCalendarType(Enum):
10
+ DATE_PERSIAN = "DatePersian"
11
+ DATE_GREGORIAN = "DateGregorian"
@@ -0,0 +1,11 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonLocationType(Enum):
10
+ PICKER = "Picker"
11
+ VIEW = "View"
@@ -0,0 +1,11 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonSelectionGetType(Enum):
10
+ LOCAL = "Local"
11
+ API = "Api"
@@ -0,0 +1,11 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonSelectionSearchType(Enum):
10
+ LOCAL = "Local"
11
+ API = "Api"
@@ -0,0 +1,12 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonSelectionType(Enum):
10
+ TEXT_ONLY = "TextOnly"
11
+ TEXT_IMG_THU = "TextImgThu"
12
+ TEXT_IMG_BIG = "TextImgBig"
@@ -0,0 +1,11 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonTextboxTypeKeypad(Enum):
10
+ STRING = "String"
11
+ NUMBER = "Number"
@@ -0,0 +1,11 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonTextboxTypeLine(Enum):
10
+ SINGLE_LINE = "SingleLine"
11
+ MULTI_LINE = "MultiLine"
@@ -0,0 +1,30 @@
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 enum import Enum
7
+
8
+
9
+ class ButtonType(Enum):
10
+ SIMPLE = "Simple"
11
+ SELECTION = "Selection"
12
+ CALENDAR = "Calendar"
13
+ NUMBER_PICKER = "NumberPicker"
14
+ STRING_PICKER = "StringPicker"
15
+ LOCATION = "Location"
16
+ PAYMENT = "Payment"
17
+ CAMERA_IMAGE = "CameraImage"
18
+ CAMERA_VIDEO = "CameraVideo"
19
+ GALLERY_IMAGE = "GalleryImage"
20
+ GALLERY_VIDEO = "GalleryVideo"
21
+ FILE = "File"
22
+ AUDIO = "Audio"
23
+ RECORD_AUDIO = "RecordAudio"
24
+ MY_PHONE_NUMBER = "MyPhoneNumber"
25
+ MY_LOCATION = "MyLocation"
26
+ TEXTBOX = "Textbox"
27
+ LINK = "Link"
28
+ ASK_MY_PHONE_NUMBER = "AskMyPhoneNumber"
29
+ ASK_LOCATION = "AskLocation"
30
+ BARCODE = "Barcode"
@@ -0,0 +1,12 @@
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 enum import Enum
7
+
8
+
9
+ class ChatKeypadType(Enum):
10
+ NEW = "New"
11
+ REMOVE = "Remove"
12
+ NONE = None