PySPlusthon 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. PySPlusthon/__init__.py +3 -0
  2. PySPlusthon/client/__init__.py +1 -0
  3. PySPlusthon/client/attachments/__init__.py +29 -0
  4. PySPlusthon/client/attachments/get_file.py +22 -0
  5. PySPlusthon/client/attachments/send_animation.py +71 -0
  6. PySPlusthon/client/attachments/send_audio.py +54 -0
  7. PySPlusthon/client/attachments/send_contact.py +47 -0
  8. PySPlusthon/client/attachments/send_document.py +63 -0
  9. PySPlusthon/client/attachments/send_location.py +45 -0
  10. PySPlusthon/client/attachments/send_media_group.py +88 -0
  11. PySPlusthon/client/attachments/send_photo.py +67 -0
  12. PySPlusthon/client/attachments/send_sticker.py +51 -0
  13. PySPlusthon/client/attachments/send_video.py +56 -0
  14. PySPlusthon/client/attachments/send_voice.py +52 -0
  15. PySPlusthon/client/attachments/upload_file.py +82 -0
  16. PySPlusthon/client/chats/__init__.py +43 -0
  17. PySPlusthon/client/chats/ban_chat_member.py +24 -0
  18. PySPlusthon/client/chats/delete_chat_photo.py +32 -0
  19. PySPlusthon/client/chats/get_chat.py +69 -0
  20. PySPlusthon/client/chats/get_chat_administrators.py +18 -0
  21. PySPlusthon/client/chats/get_chat_history.py +39 -0
  22. PySPlusthon/client/chats/get_chat_member.py +16 -0
  23. PySPlusthon/client/chats/get_chat_members.py +29 -0
  24. PySPlusthon/client/chats/get_chat_members_count.py +21 -0
  25. PySPlusthon/client/chats/join_chat.py +31 -0
  26. PySPlusthon/client/chats/leave_chat.py +22 -0
  27. PySPlusthon/client/chats/pin_chat_message.py +31 -0
  28. PySPlusthon/client/chats/promote_chat_member.py +64 -0
  29. PySPlusthon/client/chats/restrict_chat_member.py +25 -0
  30. PySPlusthon/client/chats/set_chat_description.py +23 -0
  31. PySPlusthon/client/chats/set_chat_photo.py +33 -0
  32. PySPlusthon/client/chats/set_chat_title.py +23 -0
  33. PySPlusthon/client/chats/unban_chat_member.py +24 -0
  34. PySPlusthon/client/chats/unpin_all_chat_messages.py +38 -0
  35. PySPlusthon/client/chats/unpin_chat_message.py +33 -0
  36. PySPlusthon/client/client.py +232 -0
  37. PySPlusthon/client/invite_links/__init__.py +7 -0
  38. PySPlusthon/client/invite_links/create_chat_invite_link.py +14 -0
  39. PySPlusthon/client/invite_links/export_chat_invite_link.py +21 -0
  40. PySPlusthon/client/invite_links/revoke_chat_invite_link.py +23 -0
  41. PySPlusthon/client/messages/__init__.py +21 -0
  42. PySPlusthon/client/messages/answer_callback_query.py +12 -0
  43. PySPlusthon/client/messages/copy_message.py +43 -0
  44. PySPlusthon/client/messages/delete_message.py +29 -0
  45. PySPlusthon/client/messages/edit_message_caption.py +40 -0
  46. PySPlusthon/client/messages/edit_message_reply_markup.py +17 -0
  47. PySPlusthon/client/messages/edit_message_text.py +40 -0
  48. PySPlusthon/client/messages/forward_message.py +35 -0
  49. PySPlusthon/client/messages/send_message.py +38 -0
  50. PySPlusthon/client/stickers/__init__.py +9 -0
  51. PySPlusthon/client/stickers/add_sticker_to_set.py +15 -0
  52. PySPlusthon/client/stickers/create_new_sticker_set.py +16 -0
  53. PySPlusthon/client/stickers/delete_sticker_from_set.py +10 -0
  54. PySPlusthon/client/stickers/get_sticker_set.py +11 -0
  55. PySPlusthon/client/stickers/upload_sticker_file.py +16 -0
  56. PySPlusthon/client/updates/__init__.py +8 -0
  57. PySPlusthon/client/updates/delete_webhook.py +9 -0
  58. PySPlusthon/client/updates/get_updates.py +14 -0
  59. PySPlusthon/client/updates/get_webhook_info.py +10 -0
  60. PySPlusthon/client/updates/set_webhook.py +10 -0
  61. PySPlusthon/client/users/__init__.py +6 -0
  62. PySPlusthon/client/users/ask_review.py +14 -0
  63. PySPlusthon/client/users/get_me.py +16 -0
  64. PySPlusthon/conditions/__init__.py +43 -0
  65. PySPlusthon/conditions/all.py +6 -0
  66. PySPlusthon/conditions/animation.py +7 -0
  67. PySPlusthon/conditions/at_state.py +18 -0
  68. PySPlusthon/conditions/audio.py +7 -0
  69. PySPlusthon/conditions/author.py +13 -0
  70. PySPlusthon/conditions/caption.py +7 -0
  71. PySPlusthon/conditions/channel.py +11 -0
  72. PySPlusthon/conditions/channel_chat_created.py +7 -0
  73. PySPlusthon/conditions/chat.py +14 -0
  74. PySPlusthon/conditions/click.py +24 -0
  75. PySPlusthon/conditions/command.py +23 -0
  76. PySPlusthon/conditions/condition.py +88 -0
  77. PySPlusthon/conditions/contact.py +7 -0
  78. PySPlusthon/conditions/content.py +7 -0
  79. PySPlusthon/conditions/delete_chat_photo.py +7 -0
  80. PySPlusthon/conditions/document.py +7 -0
  81. PySPlusthon/conditions/entities.py +7 -0
  82. PySPlusthon/conditions/equals.py +14 -0
  83. PySPlusthon/conditions/forward.py +7 -0
  84. PySPlusthon/conditions/group.py +11 -0
  85. PySPlusthon/conditions/group_chat_created.py +7 -0
  86. PySPlusthon/conditions/is_admin.py +17 -0
  87. PySPlusthon/conditions/is_instance.py +10 -0
  88. PySPlusthon/conditions/is_joined.py +61 -0
  89. PySPlusthon/conditions/left_chat_member.py +7 -0
  90. PySPlusthon/conditions/location.py +7 -0
  91. PySPlusthon/conditions/media.py +7 -0
  92. PySPlusthon/conditions/media_group.py +7 -0
  93. PySPlusthon/conditions/new_chat_members.py +7 -0
  94. PySPlusthon/conditions/new_chat_photo.py +7 -0
  95. PySPlusthon/conditions/new_chat_title.py +7 -0
  96. PySPlusthon/conditions/number.py +12 -0
  97. PySPlusthon/conditions/photo.py +7 -0
  98. PySPlusthon/conditions/pinned_message.py +7 -0
  99. PySPlusthon/conditions/poll.py +7 -0
  100. PySPlusthon/conditions/private.py +11 -0
  101. PySPlusthon/conditions/regex.py +17 -0
  102. PySPlusthon/conditions/reply.py +7 -0
  103. PySPlusthon/conditions/sticker.py +7 -0
  104. PySPlusthon/conditions/supergroup_chat_created.py +7 -0
  105. PySPlusthon/conditions/text.py +7 -0
  106. PySPlusthon/conditions/video.py +7 -0
  107. PySPlusthon/conditions/voice.py +7 -0
  108. PySPlusthon/dispatcher/__init__.py +5 -0
  109. PySPlusthon/dispatcher/chain.py +165 -0
  110. PySPlusthon/dispatcher/dispatcher.py +124 -0
  111. PySPlusthon/dispatcher/logging_chain.py +36 -0
  112. PySPlusthon/dispatcher/monitoring_chain.py +19 -0
  113. PySPlusthon/dispatcher/printing_chain.py +21 -0
  114. PySPlusthon/enums/__init__.py +7 -0
  115. PySPlusthon/enums/chat_member_status.py +9 -0
  116. PySPlusthon/enums/chat_type.py +9 -0
  117. PySPlusthon/enums/message_media_type.py +16 -0
  118. PySPlusthon/enums/name_enum.py +13 -0
  119. PySPlusthon/enums/peer_type.py +8 -0
  120. PySPlusthon/enums/poll_type.py +8 -0
  121. PySPlusthon/enums/transaction_status.py +10 -0
  122. PySPlusthon/errors/__init__.py +11 -0
  123. PySPlusthon/errors/dispatching_errors/__init__.py +2 -0
  124. PySPlusthon/errors/dispatching_errors/break_dispatching.py +2 -0
  125. PySPlusthon/errors/dispatching_errors/continue_dispatching.py +2 -0
  126. PySPlusthon/errors/rpc_errors/__init__.py +8 -0
  127. PySPlusthon/errors/rpc_errors/bad_request_error.py +6 -0
  128. PySPlusthon/errors/rpc_errors/flood_error.py +6 -0
  129. PySPlusthon/errors/rpc_errors/forbidden_error.py +6 -0
  130. PySPlusthon/errors/rpc_errors/internal_error.py +6 -0
  131. PySPlusthon/errors/rpc_errors/not_found_error.py +6 -0
  132. PySPlusthon/errors/rpc_errors/rpc_error.py +23 -0
  133. PySPlusthon/errors/rpc_errors/too_many_requests.py +10 -0
  134. PySPlusthon/errors/rpc_errors/unauthorized_error.py +6 -0
  135. PySPlusthon/event_handlers/__init__.py +12 -0
  136. PySPlusthon/event_handlers/callback_query_handler.py +16 -0
  137. PySPlusthon/event_handlers/command_handler.py +46 -0
  138. PySPlusthon/event_handlers/connect_handler.py +19 -0
  139. PySPlusthon/event_handlers/disconnect_handler.py +18 -0
  140. PySPlusthon/event_handlers/edited_message_handler.py +16 -0
  141. PySPlusthon/event_handlers/error_handler.py +15 -0
  142. PySPlusthon/event_handlers/event_handler.py +53 -0
  143. PySPlusthon/event_handlers/initialize_handler.py +18 -0
  144. PySPlusthon/event_handlers/message_handler.py +16 -0
  145. PySPlusthon/event_handlers/shipping_query_handler.py +16 -0
  146. PySPlusthon/event_handlers/shutdown_handler.py +18 -0
  147. PySPlusthon/event_handlers/update_handler.py +16 -0
  148. PySPlusthon/network/__init__.py +1 -0
  149. PySPlusthon/network/httpconnection.py +74 -0
  150. PySPlusthon/objects/__init__.py +44 -0
  151. PySPlusthon/objects/animation.py +44 -0
  152. PySPlusthon/objects/audio.py +36 -0
  153. PySPlusthon/objects/callback_query.py +37 -0
  154. PySPlusthon/objects/chat.py +118 -0
  155. PySPlusthon/objects/chat_member.py +53 -0
  156. PySPlusthon/objects/chat_permissions.py +26 -0
  157. PySPlusthon/objects/chat_photo.py +24 -0
  158. PySPlusthon/objects/contact.py +18 -0
  159. PySPlusthon/objects/copy_text_button.py +18 -0
  160. PySPlusthon/objects/date.py +35 -0
  161. PySPlusthon/objects/document.py +36 -0
  162. PySPlusthon/objects/edited_message.py +27 -0
  163. PySPlusthon/objects/entity.py +21 -0
  164. PySPlusthon/objects/file.py +21 -0
  165. PySPlusthon/objects/forward_origin.py +22 -0
  166. PySPlusthon/objects/inline_keyboard.py +65 -0
  167. PySPlusthon/objects/inline_keyboard_button.py +42 -0
  168. PySPlusthon/objects/input_media.py +44 -0
  169. PySPlusthon/objects/input_media_photo.py +14 -0
  170. PySPlusthon/objects/input_media_video.py +14 -0
  171. PySPlusthon/objects/invite_link.py +32 -0
  172. PySPlusthon/objects/list.py +24 -0
  173. PySPlusthon/objects/location.py +14 -0
  174. PySPlusthon/objects/message.py +478 -0
  175. PySPlusthon/objects/message_id.py +31 -0
  176. PySPlusthon/objects/object.py +154 -0
  177. PySPlusthon/objects/order_info.py +19 -0
  178. PySPlusthon/objects/photo.py +31 -0
  179. PySPlusthon/objects/poll.py +34 -0
  180. PySPlusthon/objects/poll_option.py +16 -0
  181. PySPlusthon/objects/reply_keyboard.py +79 -0
  182. PySPlusthon/objects/reply_keyboard_button.py +29 -0
  183. PySPlusthon/objects/reply_keyboard_remove.py +10 -0
  184. PySPlusthon/objects/reply_markup.py +12 -0
  185. PySPlusthon/objects/shipping_address.py +22 -0
  186. PySPlusthon/objects/shipping_query.py +20 -0
  187. PySPlusthon/objects/sticker.py +54 -0
  188. PySPlusthon/objects/sticker_set.py +29 -0
  189. PySPlusthon/objects/transaction.py +25 -0
  190. PySPlusthon/objects/update.py +33 -0
  191. PySPlusthon/objects/user.py +60 -0
  192. PySPlusthon/objects/video.py +45 -0
  193. PySPlusthon/objects/voice.py +31 -0
  194. PySPlusthon/objects/webhook_info.py +16 -0
  195. PySPlusthon/proto/__init__.py +2 -0
  196. PySPlusthon/proto/enums_pb2.py +46 -0
  197. PySPlusthon/proto/enums_pb2.pyi +99 -0
  198. PySPlusthon/proto/enums_pb2_grpc.py +24 -0
  199. PySPlusthon/proto/requests/__init__.py +209 -0
  200. PySPlusthon/proto/requests/abacus_pb2.py +40 -0
  201. PySPlusthon/proto/requests/abacus_pb2.pyi +31 -0
  202. PySPlusthon/proto/requests/abacus_pb2_grpc.py +24 -0
  203. PySPlusthon/proto/requests/auth_pb2.py +49 -0
  204. PySPlusthon/proto/requests/auth_pb2.pyi +67 -0
  205. PySPlusthon/proto/requests/auth_pb2_grpc.py +24 -0
  206. PySPlusthon/proto/requests/configs_pb2.py +37 -0
  207. PySPlusthon/proto/requests/configs_pb2.pyi +15 -0
  208. PySPlusthon/proto/requests/configs_pb2_grpc.py +24 -0
  209. PySPlusthon/proto/requests/files_pb2.py +40 -0
  210. PySPlusthon/proto/requests/files_pb2.pyi +34 -0
  211. PySPlusthon/proto/requests/files_pb2_grpc.py +24 -0
  212. PySPlusthon/proto/requests/groups_pb2.py +82 -0
  213. PySPlusthon/proto/requests/groups_pb2.pyi +213 -0
  214. PySPlusthon/proto/requests/groups_pb2_grpc.py +24 -0
  215. PySPlusthon/proto/requests/messaging_pb2.py +56 -0
  216. PySPlusthon/proto/requests/messaging_pb2.pyi +119 -0
  217. PySPlusthon/proto/requests/messaging_pb2_grpc.py +24 -0
  218. PySPlusthon/proto/requests/presence_pb2.py +40 -0
  219. PySPlusthon/proto/requests/presence_pb2.pyi +24 -0
  220. PySPlusthon/proto/requests/presence_pb2_grpc.py +24 -0
  221. PySPlusthon/proto/requests/request_pb2.py +42 -0
  222. PySPlusthon/proto/requests/request_pb2.pyi +35 -0
  223. PySPlusthon/proto/requests/request_pb2_grpc.py +24 -0
  224. PySPlusthon/proto/requests/users_pb2.py +43 -0
  225. PySPlusthon/proto/requests/users_pb2.pyi +34 -0
  226. PySPlusthon/proto/requests/users_pb2_grpc.py +24 -0
  227. PySPlusthon/proto/responses/__init__.py +6 -0
  228. PySPlusthon/proto/responses/abacus_pb2.py +37 -0
  229. PySPlusthon/proto/responses/abacus_pb2.pyi +14 -0
  230. PySPlusthon/proto/responses/abacus_pb2_grpc.py +24 -0
  231. PySPlusthon/proto/responses/auth_pb2.py +42 -0
  232. PySPlusthon/proto/responses/auth_pb2.pyi +40 -0
  233. PySPlusthon/proto/responses/auth_pb2_grpc.py +24 -0
  234. PySPlusthon/proto/responses/files_pb2.py +39 -0
  235. PySPlusthon/proto/responses/files_pb2.pyi +27 -0
  236. PySPlusthon/proto/responses/files_pb2_grpc.py +24 -0
  237. PySPlusthon/proto/responses/groups_pb2.py +59 -0
  238. PySPlusthon/proto/responses/groups_pb2.pyi +90 -0
  239. PySPlusthon/proto/responses/groups_pb2_grpc.py +24 -0
  240. PySPlusthon/proto/responses/messaging_pb2.py +44 -0
  241. PySPlusthon/proto/responses/messaging_pb2.pyi +37 -0
  242. PySPlusthon/proto/responses/messaging_pb2_grpc.py +24 -0
  243. PySPlusthon/proto/responses/users_pb2.py +41 -0
  244. PySPlusthon/proto/responses/users_pb2.pyi +28 -0
  245. PySPlusthon/proto/responses/users_pb2_grpc.py +24 -0
  246. PySPlusthon/proto/structs/__init__.py +7 -0
  247. PySPlusthon/proto/structs/collections_pb2.py +54 -0
  248. PySPlusthon/proto/structs/collections_pb2.pyi +79 -0
  249. PySPlusthon/proto/structs/collections_pb2_grpc.py +24 -0
  250. PySPlusthon/proto/structs/files_pb2.py +52 -0
  251. PySPlusthon/proto/structs/files_pb2.pyi +93 -0
  252. PySPlusthon/proto/structs/files_pb2_grpc.py +24 -0
  253. PySPlusthon/proto/structs/groups_pb2.py +49 -0
  254. PySPlusthon/proto/structs/groups_pb2.pyi +144 -0
  255. PySPlusthon/proto/structs/groups_pb2_grpc.py +24 -0
  256. PySPlusthon/proto/structs/messaging_pb2.py +81 -0
  257. PySPlusthon/proto/structs/messaging_pb2.pyi +296 -0
  258. PySPlusthon/proto/structs/messaging_pb2_grpc.py +24 -0
  259. PySPlusthon/proto/structs/peers_pb2.py +47 -0
  260. PySPlusthon/proto/structs/peers_pb2.pyi +56 -0
  261. PySPlusthon/proto/structs/peers_pb2_grpc.py +24 -0
  262. PySPlusthon/proto/structs/set_updates_pb2.py +37 -0
  263. PySPlusthon/proto/structs/set_updates_pb2.pyi +15 -0
  264. PySPlusthon/proto/structs/set_updates_pb2_grpc.py +24 -0
  265. PySPlusthon/proto/structs/users_pb2.py +54 -0
  266. PySPlusthon/proto/structs/users_pb2.pyi +122 -0
  267. PySPlusthon/proto/structs/users_pb2_grpc.py +24 -0
  268. PySPlusthon/proto/updates/__init__.py +1 -0
  269. PySPlusthon/proto/updates/messaging_pb2.py +38 -0
  270. PySPlusthon/proto/updates/messaging_pb2.pyi +26 -0
  271. PySPlusthon/proto/updates/messaging_pb2_grpc.py +24 -0
  272. PySPlusthon/proto/ws_pb2.py +52 -0
  273. PySPlusthon/proto/ws_pb2.pyi +76 -0
  274. PySPlusthon/proto/ws_pb2_grpc.py +24 -0
  275. PySPlusthon/smart_call.py +73 -0
  276. PySPlusthon/states/__init__.py +3 -0
  277. PySPlusthon/states/state.py +11 -0
  278. PySPlusthon/states/state_group.py +13 -0
  279. PySPlusthon/states/state_machine.py +83 -0
  280. PySPlusthon/sync_support.py +48 -0
  281. pysplusthon-0.5.0.dist-info/METADATA +65 -0
  282. pysplusthon-0.5.0.dist-info/RECORD +285 -0
  283. pysplusthon-0.5.0.dist-info/WHEEL +5 -0
  284. pysplusthon-0.5.0.dist-info/licenses/LICENSE +19 -0
  285. pysplusthon-0.5.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,38 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+
5
+
6
+ class UnpinAllChatMessages:
7
+
8
+ async def unpin_all_chat_messages(
9
+ self: "PySPlusthon.Client",
10
+ chat_id: Union[int, str]
11
+ ) -> bool:
12
+ if self.is_userbot():
13
+ from PySPlusthon.proto import requests, structs
14
+ peer_id, peer_type = map(int, chat_id.split("|"))
15
+
16
+ if peer_type in (1, 4):
17
+ response = await self.execute(requests.LoadPinnedMessages(
18
+ peer=structs.ExPeer(type=peer_type, id=peer_id)
19
+ ))
20
+
21
+ message_ids = [
22
+ structs.MessageId(date=pinned_message.date, rid=pinned_message.rid)
23
+ for pinned_message in response.pinned_messages
24
+ ]
25
+
26
+ return await self.execute(requests.UnPinMessages(
27
+ peer=structs.ExPeer(type=peer_type, id=peer_id),
28
+ message_ids=message_ids,
29
+ all=True
30
+ ))
31
+
32
+ elif peer_type in (2, 3, 5):
33
+ return await self.execute(requests.RemovePin(
34
+ group_peer=structs.GroupOutPeer(group_id=peer_id)
35
+ ))
36
+
37
+ chat_id = await self.resolve_peer_id(chat_id)
38
+ return await self.auto_execute("unpinAllChatMessages", locals())
@@ -0,0 +1,33 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import resolve_message_id
5
+
6
+
7
+ class UnpinChatMessage:
8
+
9
+ async def unpin_chat_message(
10
+ self: "PySPlusthon.Client",
11
+ chat_id: Union[int, str],
12
+ message_id: Union[int, str]
13
+ ) -> bool:
14
+ if self.is_userbot():
15
+ from PySPlusthon.proto import requests, structs
16
+ peer_id, peer_type = map(int, chat_id.split("|"))
17
+ message_id = resolve_message_id(message_id)
18
+
19
+ if peer_type in (1, 4):
20
+ return await self.execute(requests.UnPinMessages(
21
+ peer=structs.ExPeer(type=peer_type, id=peer_id),
22
+ message_ids=[structs.MessageId(date=message_id.date, rid=message_id.rid)]
23
+ ))
24
+
25
+ elif peer_type in (2, 3, 5):
26
+ return await self.execute(requests.RemoveSinglePin(
27
+ group_peer=structs.GroupOutPeer(group_id=peer_id),
28
+ rid=message_id.rid,
29
+ date=message_id.date
30
+ ))
31
+
32
+ chat_id = await self.resolve_peer_id(chat_id)
33
+ return await self.auto_execute("unpinChatMessage", locals())
@@ -0,0 +1,232 @@
1
+ from json import dumps, loads
2
+ from asyncio import get_event_loop, sleep
3
+ from inspect import iscoroutine, iscoroutinefunction, stack
4
+ from io import BufferedReader, BytesIO
5
+ from typing import get_type_hints
6
+ import re
7
+ from pathlib import Path
8
+ import sys
9
+ from typing import Union
10
+ import base64
11
+
12
+ from httpx import ConnectError
13
+
14
+ from .messages import Messages
15
+ from .updates import Updates
16
+ from .users import Users
17
+ from .attachments import Attachments
18
+ from .chats import Chats
19
+ from .invite_links import InviteLinks
20
+ from .stickers import Stickers
21
+ from ..objects import Object, wrap, unwrap, Chat, User, Message
22
+ from ..errors import TooManyRequestsError, RPCError
23
+ from ..network import HTTPConnection
24
+ from ..dispatcher import Dispatcher, Chain, PrintingChain
25
+ from ..smart_call import remove_unwanted_keyword_parameters, run_asynchronously
26
+ from ..sync_support import add_sync_support_to_object
27
+ from ..event_handlers import ConnectHandler, DisconnectHandler, InitializeHandler, ShutdownHandler
28
+
29
+
30
+ @add_sync_support_to_object
31
+ class Client(Chain, Messages, Updates, Users, Attachments, Chats, InviteLinks, Stickers):
32
+ WORKDIR = Path(sys.argv[0]).parent
33
+
34
+ def __init__(
35
+ self,
36
+ token: str,
37
+ async_workers: int = None,
38
+ sync_workers: int = None,
39
+ use_concurrency: bool = True,
40
+ time_out: int = None,
41
+ workdir: Union[Path, str] = None,
42
+ sleep_threshold: int = 60,
43
+ proxy=None,
44
+ base_url: str = None,
45
+ short_url: str = None
46
+ ):
47
+ super().__init__("default", None, PrintingChain())
48
+ self.token = token
49
+ self.time_out = time_out
50
+ if workdir is None:
51
+ self.workdir = self.WORKDIR
52
+ else:
53
+ self.workdir = workdir if isinstance(workdir, Path) else Path(workdir)
54
+ self.dispatcher = Dispatcher(
55
+ self,
56
+ async_workers=async_workers,
57
+ sync_workers=sync_workers,
58
+ use_concurrency=use_concurrency
59
+ )
60
+ self.http_connection = HTTPConnection(token, time_out, proxy, base_url, short_url)
61
+ self.sleep_threshold = sleep_threshold
62
+ self.user = None
63
+ self.is_disconnected = False
64
+ self.last_update_id = None
65
+
66
+ def __repr__(self):
67
+ client_name = type(self).__name__
68
+ try:
69
+ name = self.user.full_name
70
+ except AttributeError:
71
+ name = "Not initialized yet"
72
+ return f"{client_name}({name})"
73
+
74
+ def is_userbot(self):
75
+ return False
76
+
77
+ async def initialize(self):
78
+ await self.dispatcher.start()
79
+ await self.dispatcher.dispatch_event(self, InitializeHandler)
80
+
81
+ async def shutdown(self):
82
+ await self.dispatcher.dispatch_event(self, ShutdownHandler)
83
+ await self.dispatcher.stop()
84
+
85
+ async def resolve_peer_id(self, chat_id):
86
+ if isinstance(chat_id, str) and not chat_id.isnumeric():
87
+ peer = await self.get_chat(chat_id)
88
+ return peer.id
89
+ if isinstance(chat_id, (Chat, User)):
90
+ return chat_id.id
91
+ return chat_id
92
+
93
+ async def connect(self):
94
+ if self.is_started:
95
+ raise ConnectionError("Connection is already started")
96
+ self.is_started = True
97
+ await self.http_connection.start()
98
+ if get_event_loop().is_running():
99
+ self.user = await self.get_me()
100
+
101
+ async def disconnect(self):
102
+ if not self.is_started:
103
+ raise ConnectionError("Connection is already stopped")
104
+ self.is_started = False
105
+ await self.http_connection.stop()
106
+
107
+ async def __aenter__(self):
108
+ await self.connect()
109
+ return self
110
+
111
+ async def __aexit__(self, *args):
112
+ try:
113
+ await self.disconnect()
114
+ except ConnectionError:
115
+ return
116
+
117
+ def __enter__(self):
118
+ self.connect()
119
+ return self
120
+
121
+ def __exit__(self, *args):
122
+ try:
123
+ self.disconnect()
124
+ except ConnectionError:
125
+ return
126
+
127
+ async def execute_http(self, service: str, json: bool = None, **data):
128
+ data = {k: v for k, v in data.items() if v is not None}
129
+ files = {}
130
+ if json is None:
131
+ for value in data.values():
132
+ if isinstance(value, (bytes, BufferedReader, BytesIO)):
133
+ json = False
134
+ break
135
+ else:
136
+ json = True
137
+ for key, value in data.items():
138
+ data[key] = unwrap(value)
139
+ if not json:
140
+ for key, value in data.copy().items():
141
+ if isinstance(value, (bytes, BufferedReader, BytesIO)):
142
+ files[key] = value
143
+ del data[key]
144
+ elif isinstance(value, dict):
145
+ data[key] = dumps(value)
146
+ while True:
147
+ try:
148
+ if json:
149
+ return await self.http_connection.request(service, json=data)
150
+ return await self.http_connection.request(service, data=data, files=files)
151
+ except RPCError as error:
152
+ if error.seconds <= self.sleep_threshold:
153
+ print(f"[Too many requests] retry after: {error.seconds} (caused by {service})")
154
+ await sleep(error.seconds)
155
+ else:
156
+ raise error
157
+
158
+ async def execute(self, service: str, json: bool = None, **data):
159
+ return await self.execute_http(service, json=json, **data)
160
+
161
+ async def auto_execute(self, service: str, data: dict, json: bool = None):
162
+ bound_method_name = stack()[1].function
163
+ bound_method = getattr(self, bound_method_name)
164
+ type_hints = get_type_hints(bound_method)
165
+ del data["self"]
166
+ del type_hints["self"]
167
+ return_type_hint = type_hints.pop("return")
168
+ result = await self.execute(service, json, **data)
169
+ result = wrap(return_type_hint, result)
170
+ if isinstance(result, Object):
171
+ result.bind(self)
172
+ return result
173
+
174
+ async def start_polling(self, clear_pending_updates: bool = True):
175
+ await self.delete_webhook()
176
+ await self.initialize()
177
+ while True:
178
+ try:
179
+ if self.last_update_id is None:
180
+ try:
181
+ if not clear_pending_updates:
182
+ raise Exception()
183
+ updates = await self.get_updates(offset=-1)
184
+ except Exception:
185
+ updates = await self.get_updates()
186
+ else:
187
+ updates = await self.get_updates(offset=self.last_update_id + 1)
188
+ except ConnectError:
189
+ if not self.is_disconnected:
190
+ self.is_disconnected = True
191
+ await self.dispatcher.dispatch_event(self, DisconnectHandler)
192
+ except Exception as error:
193
+ await self.dispatcher.dispatch_event(self, error)
194
+ else:
195
+ if self.is_disconnected:
196
+ self.is_disconnected = False
197
+ await self.dispatcher.dispatch_event(self, ConnectHandler)
198
+ for update in updates:
199
+ if self.last_update_id is not None and self.last_update_id >= update.id:
200
+ continue
201
+ self.last_update_id = update.id
202
+ await self.dispatcher.dispatch_event(self, update.get_effective_update())
203
+
204
+ def run(self, function=None, **kwargs):
205
+ try:
206
+ self.connect()
207
+ if function is None:
208
+ self.start_polling(**kwargs)
209
+ elif iscoroutine(function):
210
+ loop = get_event_loop()
211
+ loop.run_until_complete(function)
212
+ elif iscoroutinefunction(function):
213
+ kwargs = remove_unwanted_keyword_parameters(function, client=self, **kwargs)
214
+ loop = get_event_loop()
215
+ loop.run_until_complete(function(**kwargs))
216
+ else:
217
+ kwargs = remove_unwanted_keyword_parameters(function, client=self, **kwargs)
218
+ function(**kwargs)
219
+ except KeyboardInterrupt:
220
+ return
221
+ finally:
222
+ if self.dispatcher.is_started:
223
+ self.shutdown()
224
+ self.disconnect()
225
+
226
+ async def download(self, file_id: str):
227
+ return await self.http_connection.download_file(file_id)
228
+
229
+ def create_referral_link(self, name, value) -> str:
230
+ if self.user is None:
231
+ raise RuntimeError("Client not initialized. Connect first.")
232
+ return f"{self.http_connection.short_url}/{self.user.username}?{name}={value}"
@@ -0,0 +1,7 @@
1
+ from .create_chat_invite_link import CreateChatInviteLink
2
+ from .export_chat_invite_link import ExportChatInviteLink
3
+ from .revoke_chat_invite_link import RevokeChatInviteLink
4
+
5
+
6
+ class InviteLinks(CreateChatInviteLink, ExportChatInviteLink, RevokeChatInviteLink):
7
+ pass
@@ -0,0 +1,14 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import InviteLink
5
+
6
+
7
+ class CreateChatInviteLink:
8
+
9
+ async def create_chat_invite_link(
10
+ self: "PySPlusthon.Client",
11
+ chat_id: Union[int, str]
12
+ ) -> InviteLink:
13
+ chat_id = await self.resolve_peer_id(chat_id)
14
+ return await self.auto_execute("createChatInviteLink", locals())
@@ -0,0 +1,21 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+
5
+
6
+ class ExportChatInviteLink:
7
+
8
+ async def export_chat_invite_link(
9
+ self: "PySPlusthon.Client",
10
+ chat_id: Union[int, str]
11
+ ) -> str:
12
+ if self.is_userbot():
13
+ from PySPlusthon.proto import requests, structs
14
+ peer_id, peer_type = map(int, chat_id.split("|"))
15
+ response = await self.execute(requests.GetGroupInviteUrl(
16
+ group_peer=structs.GroupOutPeer(group_id=peer_id, access_hash=1)
17
+ ))
18
+ return response.url
19
+
20
+ chat_id = await self.resolve_peer_id(chat_id)
21
+ return await self.auto_execute("exportChatInviteLink", locals())
@@ -0,0 +1,23 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import InviteLink
5
+
6
+
7
+ class RevokeChatInviteLink:
8
+
9
+ async def revoke_chat_invite_link(
10
+ self: "PySPlusthon.Client",
11
+ chat_id: Union[int, str],
12
+ invite_link: str
13
+ ) -> InviteLink:
14
+ if self.is_userbot():
15
+ from PySPlusthon.proto import requests, structs
16
+ peer_id, peer_type = map(int, chat_id.split("|"))
17
+ response = await self.execute(requests.RevokeInviteUrl(
18
+ group_peer=structs.GroupOutPeer(group_id=peer_id, access_hash=1)
19
+ ))
20
+ return InviteLink(link=response.url)
21
+
22
+ chat_id = await self.resolve_peer_id(chat_id)
23
+ return await self.auto_execute("revokeChatInviteLink", locals())
@@ -0,0 +1,21 @@
1
+ from .answer_callback_query import AnswerCallbackQuery
2
+ from .send_message import SendMessage
3
+ from .edit_message_caption import EditMessageCaption
4
+ from .edit_message_reply_markup import EditMessageReplyMarkup
5
+ from .edit_message_text import EditMessageText
6
+ from .forward_message import ForwardMessage
7
+ from .delete_message import DeleteMessage
8
+ from .copy_message import CopyMessage
9
+
10
+
11
+ class Messages(
12
+ AnswerCallbackQuery,
13
+ SendMessage,
14
+ EditMessageCaption,
15
+ EditMessageReplyMarkup,
16
+ EditMessageText,
17
+ ForwardMessage,
18
+ DeleteMessage,
19
+ CopyMessage
20
+ ):
21
+ pass
@@ -0,0 +1,12 @@
1
+ import PySPlusthon
2
+
3
+
4
+ class AnswerCallbackQuery:
5
+
6
+ async def answer_callback_query(
7
+ self: "PySPlusthon.Client",
8
+ callback_query_id: str,
9
+ text: str,
10
+ show_alert: bool = False
11
+ ) -> bool:
12
+ return await self.auto_execute("answerCallbackQuery", locals())
@@ -0,0 +1,43 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import Message, resolve_message_id
5
+
6
+
7
+ class CopyMessage:
8
+
9
+ async def copy_message(
10
+ self: "PySPlusthon.Client",
11
+ chat_id: Union[int, str],
12
+ from_chat_id: Union[int, str],
13
+ message_id: Union[int, str]
14
+ ) -> Message:
15
+ if self.is_userbot():
16
+ from PySPlusthon.proto import requests, structs
17
+ peer_id, peer_type = map(int, chat_id.split("|"))
18
+ from_peer_id, from_peer_type = map(int, from_chat_id.split("|"))
19
+ message_id = resolve_message_id(message_id)
20
+ peer = structs.Peer(type=from_peer_type, id=from_peer_id)
21
+ response = await self.execute(requests.LoadHistory(
22
+ peer=peer,
23
+ date=message_id.date,
24
+ load_mode=2,
25
+ limit=1
26
+ ))
27
+ result = response.history[0]
28
+ return await self.execute(requests.SendMessage(
29
+ peer=structs.Peer(
30
+ type=peer_type,
31
+ id=peer_id
32
+ ),
33
+ rid=self.ws_connection.create_rid(),
34
+ message=result.message,
35
+ ex_peer=structs.Peer(
36
+ type=peer_type,
37
+ id=peer_id
38
+ )
39
+ ))
40
+
41
+ chat_id = await self.resolve_peer_id(chat_id)
42
+ from_chat_id = await self.resolve_peer_id(from_chat_id)
43
+ return await self.auto_execute("copyMessage", locals())
@@ -0,0 +1,29 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import resolve_message_id
5
+
6
+
7
+ class DeleteMessage:
8
+
9
+ async def delete_message(
10
+ self: "PySPlusthon.Client",
11
+ chat_id: Union[int, str],
12
+ message_id: Union[int, str]
13
+ ) -> bool:
14
+ if self.is_userbot():
15
+ from PySPlusthon.proto import requests, structs
16
+ peer_id, peer_type = map(int, chat_id.split("|"))
17
+ message_id = resolve_message_id(message_id)
18
+ return await self.execute(requests.DeleteMessage(
19
+ peer=structs.Peer(
20
+ type=peer_type,
21
+ id=peer_id
22
+ ),
23
+ rids=[message_id.rid],
24
+ dates=structs.DeleteDates(dates=[message_id.date]),
25
+ just_mine=False
26
+ ))
27
+
28
+ chat_id = await self.resolve_peer_id(chat_id)
29
+ return await self.auto_execute("deleteMessage", locals())
@@ -0,0 +1,40 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import Message
5
+ from PySPlusthon import objects
6
+ from ...objects import resolve_message_id
7
+
8
+
9
+ class EditMessageCaption:
10
+
11
+ async def edit_message_caption(
12
+ self: "PySPlusthon.Client",
13
+ chat_id: Union[int, str],
14
+ message_id: Union[int, str],
15
+ caption: str,
16
+ reply_markup: "objects.ReplyMarkup" = None
17
+ ) -> Message:
18
+ if self.is_userbot():
19
+ from PySPlusthon.proto import requests, structs
20
+ peer_id, peer_type = map(int, chat_id.split("|"))
21
+ message_id = resolve_message_id(message_id)
22
+ peer = structs.Peer(type=peer_type, id=peer_id)
23
+ response = await self.execute(requests.LoadHistory(
24
+ peer=peer,
25
+ date=message_id.date,
26
+ load_mode=2,
27
+ limit=1
28
+ ))
29
+ result = response.history[0].message
30
+ return await self.execute(requests.UpdateMessage(
31
+ peer=structs.Peer(
32
+ type=peer_type,
33
+ id=peer_id
34
+ ),
35
+ rid=message_id.rid,
36
+ updated_message=result
37
+ ))
38
+
39
+ chat_id = await self.resolve_peer_id(chat_id)
40
+ return await self.auto_execute("editMessageCaption", locals())
@@ -0,0 +1,17 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import Message
5
+ from PySPlusthon import objects
6
+
7
+
8
+ class EditMessageReplyMarkup:
9
+
10
+ async def edit_message_reply_markup(
11
+ self: "PySPlusthon.Client",
12
+ chat_id: Union[int, str],
13
+ message_id: int,
14
+ reply_markup: "objects.ReplyMarkup"
15
+ ) -> Message:
16
+ chat_id = await self.resolve_peer_id(chat_id)
17
+ return await self.auto_execute("editMessageReplyMarkup", locals())
@@ -0,0 +1,40 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import Message
5
+ from PySPlusthon import objects
6
+ from ...objects import resolve_message_id
7
+
8
+
9
+ class EditMessageText:
10
+
11
+ async def edit_message_text(
12
+ self: "PySPlusthon.Client",
13
+ chat_id: Union[int, str],
14
+ message_id: Union[int, str],
15
+ text: str,
16
+ reply_markup: "objects.ReplyMarkup" = None
17
+ ) -> Message:
18
+ if self.is_userbot():
19
+ from PySPlusthon.proto import requests, structs
20
+ peer_id, peer_type = map(int, chat_id.split("|"))
21
+ message_id = resolve_message_id(message_id)
22
+ peer = structs.Peer(type=peer_type, id=peer_id)
23
+ response = await self.execute(requests.LoadHistory(
24
+ peer=peer,
25
+ date=message_id.date,
26
+ load_mode=2,
27
+ limit=1
28
+ ))
29
+ result = response.history[0].message
30
+ return await self.execute(requests.UpdateMessage(
31
+ peer=structs.Peer(
32
+ type=peer_type,
33
+ id=peer_id
34
+ ),
35
+ rid=message_id.rid,
36
+ updated_message=result
37
+ ))
38
+
39
+ chat_id = await self.resolve_peer_id(chat_id)
40
+ return await self.auto_execute("editMessageText", locals())
@@ -0,0 +1,35 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import Message, resolve_message_id
5
+
6
+
7
+ class ForwardMessage:
8
+
9
+ async def forward_message(
10
+ self: "PySPlusthon.Client",
11
+ chat_id: Union[int, str],
12
+ from_chat_id: Union[int, str],
13
+ message_id: Union[int, str]
14
+ ) -> Message:
15
+ if self.is_userbot():
16
+ from PySPlusthon.proto import requests, structs
17
+ peer_id, peer_type = map(int, chat_id.split("|"))
18
+ message_peer_id, message_peer_type = map(int, from_chat_id.split("|"))
19
+ message_id = resolve_message_id(message_id)
20
+ return await self.execute(requests.ForwardMessages(
21
+ peer=structs.Peer(
22
+ type=peer_type,
23
+ id=peer_id
24
+ ),
25
+ rid=[self.ws_connection.create_rid()],
26
+ forwarded_messages=[structs.HistoryMessageIdentifier(
27
+ peer=structs.OutPeer(type=message_peer_type, id=message_peer_id),
28
+ random_id=message_id.rid,
29
+ date=message_id.date
30
+ )]
31
+ ))
32
+
33
+ chat_id = await self.resolve_peer_id(chat_id)
34
+ from_chat_id = await self.resolve_peer_id(from_chat_id)
35
+ return await self.auto_execute("forwardMessage", locals())
@@ -0,0 +1,38 @@
1
+ from typing import Union
2
+
3
+ import PySPlusthon
4
+ from ...objects import Message
5
+ from PySPlusthon import objects
6
+
7
+
8
+ class SendMessage:
9
+
10
+ async def send_message(
11
+ self: "PySPlusthon.Client",
12
+ chat_id: Union[int, str],
13
+ text: str,
14
+ reply_markup: "objects.ReplyMarkup" = None,
15
+ reply_to_message_id: int = None
16
+ ) -> Message:
17
+ if self.is_userbot():
18
+ from PySPlusthon.proto import requests, structs
19
+ peer_id, peer_type = map(int, chat_id.split("|"))
20
+ return await self.execute(requests.SendMessage(
21
+ peer=structs.Peer(
22
+ type=peer_type,
23
+ id=peer_id
24
+ ),
25
+ rid=self.ws_connection.create_rid(),
26
+ message=structs.Message(
27
+ text_message=structs.TextMessage(
28
+ text=text
29
+ )
30
+ ),
31
+ ex_peer=structs.Peer(
32
+ type=peer_type,
33
+ id=peer_id
34
+ )
35
+ ))
36
+
37
+ chat_id = await self.resolve_peer_id(chat_id)
38
+ return await self.auto_execute("sendMessage", locals())
@@ -0,0 +1,9 @@
1
+ from .delete_sticker_from_set import DeleteStickerFromSet
2
+ from .get_sticker_set import GetStickerSet
3
+ from .create_new_sticker_set import CreateNewStickerSet
4
+ from .upload_sticker_file import UploadStickerFile
5
+ from .add_sticker_to_set import AddStickerToSet
6
+
7
+
8
+ class Stickers(GetStickerSet, CreateNewStickerSet, DeleteStickerFromSet, UploadStickerFile, AddStickerToSet):
9
+ pass