spluspy 2.0.8__tar.gz → 2.0.9__tar.gz

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 (305) hide show
  1. {spluspy-2.0.8 → spluspy-2.0.9}/CHANGELOG.md +10 -0
  2. {spluspy-2.0.8 → spluspy-2.0.9}/PKG-INFO +1 -1
  3. {spluspy-2.0.8 → spluspy-2.0.9}/pyproject.toml +1 -1
  4. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/__version__.py +1 -1
  5. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/dialogs.py +97 -0
  6. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/client/client.py +312 -19
  7. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/version_check.py +2 -1
  8. {spluspy-2.0.8 → spluspy-2.0.9}/.gitignore +0 -0
  9. {spluspy-2.0.8 → spluspy-2.0.9}/CONTRIBUTING.md +0 -0
  10. {spluspy-2.0.8 → spluspy-2.0.9}/Dockerfile +0 -0
  11. {spluspy-2.0.8 → spluspy-2.0.9}/LICENSE +0 -0
  12. {spluspy-2.0.8 → spluspy-2.0.9}/MANIFEST.in +0 -0
  13. {spluspy-2.0.8 → spluspy-2.0.9}/README.md +0 -0
  14. {spluspy-2.0.8 → spluspy-2.0.9}/README.rst +0 -0
  15. {spluspy-2.0.8 → spluspy-2.0.9}/examples/01_hello_bot.py +0 -0
  16. {spluspy-2.0.8 → spluspy-2.0.9}/examples/02_echo_bot.py +0 -0
  17. {spluspy-2.0.8 → spluspy-2.0.9}/examples/03_command_bot.py +0 -0
  18. {spluspy-2.0.8 → spluspy-2.0.9}/examples/04_private_only.py +0 -0
  19. {spluspy-2.0.8 → spluspy-2.0.9}/examples/05_group_only.py +0 -0
  20. {spluspy-2.0.8 → spluspy-2.0.9}/examples/06_regex_bot.py +0 -0
  21. {spluspy-2.0.8 → spluspy-2.0.9}/examples/07_user_filter.py +0 -0
  22. {spluspy-2.0.8 → spluspy-2.0.9}/examples/08_combined_filters.py +0 -0
  23. {spluspy-2.0.8 → spluspy-2.0.9}/examples/09_inline_keyboard.py +0 -0
  24. {spluspy-2.0.8 → spluspy-2.0.9}/examples/10_reply_keyboard.py +0 -0
  25. {spluspy-2.0.8 → spluspy-2.0.9}/examples/11_message_actions.py +0 -0
  26. {spluspy-2.0.8 → spluspy-2.0.9}/examples/12_media_bot.py +0 -0
  27. {spluspy-2.0.8 → spluspy-2.0.9}/examples/13_fsm_bot.py +0 -0
  28. {spluspy-2.0.8 → spluspy-2.0.9}/examples/14_plugin_bot.py +0 -0
  29. {spluspy-2.0.8 → spluspy-2.0.9}/examples/15_middleware_bot.py +0 -0
  30. {spluspy-2.0.8 → spluspy-2.0.9}/examples/16_scheduler_bot.py +0 -0
  31. {spluspy-2.0.8 → spluspy-2.0.9}/examples/17_conversation.py +0 -0
  32. {spluspy-2.0.8 → spluspy-2.0.9}/examples/18_chat_management.py +0 -0
  33. {spluspy-2.0.8 → spluspy-2.0.9}/examples/19_event_types.py +0 -0
  34. {spluspy-2.0.8 → spluspy-2.0.9}/examples/20_sync_bot.py +0 -0
  35. {spluspy-2.0.8 → spluspy-2.0.9}/examples/21_album_handler.py +0 -0
  36. {spluspy-2.0.8 → spluspy-2.0.9}/examples/22_download_bot.py +0 -0
  37. {spluspy-2.0.8 → spluspy-2.0.9}/examples/23_url_button.py +0 -0
  38. {spluspy-2.0.8 → spluspy-2.0.9}/examples/24_string_session.py +0 -0
  39. {spluspy-2.0.8 → spluspy-2.0.9}/examples/25_error_handling.py +0 -0
  40. {spluspy-2.0.8 → spluspy-2.0.9}/examples/25_working_bot.py +0 -0
  41. {spluspy-2.0.8 → spluspy-2.0.9}/examples/26_message_entities.py +0 -0
  42. {spluspy-2.0.8 → spluspy-2.0.9}/examples/27_search_messages.py +0 -0
  43. {spluspy-2.0.8 → spluspy-2.0.9}/examples/28_poll_bot.py +0 -0
  44. {spluspy-2.0.8 → spluspy-2.0.9}/examples/29_dice_bot.py +0 -0
  45. {spluspy-2.0.8 → spluspy-2.0.9}/examples/30_cache_bot.py +0 -0
  46. {spluspy-2.0.8 → spluspy-2.0.9}/examples/31_reaction_bot.py +0 -0
  47. {spluspy-2.0.8 → spluspy-2.0.9}/examples/32_mark_read_bot.py +0 -0
  48. {spluspy-2.0.8 → spluspy-2.0.9}/examples/33_context_manager.py +0 -0
  49. {spluspy-2.0.8 → spluspy-2.0.9}/examples/34_user_info.py +0 -0
  50. {spluspy-2.0.8 → spluspy-2.0.9}/examples/35_chat_info.py +0 -0
  51. {spluspy-2.0.8 → spluspy-2.0.9}/examples/36_forward_copy.py +0 -0
  52. {spluspy-2.0.8 → spluspy-2.0.9}/examples/37_admin_bot.py +0 -0
  53. {spluspy-2.0.8 → spluspy-2.0.9}/examples/38_media_filters.py +0 -0
  54. {spluspy-2.0.8 → spluspy-2.0.9}/examples/39_status_bot.py +0 -0
  55. {spluspy-2.0.8 → spluspy-2.0.9}/examples/40_delete_detection.py +0 -0
  56. {spluspy-2.0.8 → spluspy-2.0.9}/examples/41_read_detection.py +0 -0
  57. {spluspy-2.0.8 → spluspy-2.0.9}/examples/42_raw_events.py +0 -0
  58. {spluspy-2.0.8 → spluspy-2.0.9}/examples/43_poll_handler.py +0 -0
  59. {spluspy-2.0.8 → spluspy-2.0.9}/examples/44_reaction_handler.py +0 -0
  60. {spluspy-2.0.8 → spluspy-2.0.9}/examples/45_typing_handler.py +0 -0
  61. {spluspy-2.0.8 → spluspy-2.0.9}/examples/46_get_messages.py +0 -0
  62. {spluspy-2.0.8 → spluspy-2.0.9}/examples/47_iter_messages.py +0 -0
  63. {spluspy-2.0.8 → spluspy-2.0.9}/examples/48_get_members.py +0 -0
  64. {spluspy-2.0.8 → spluspy-2.0.9}/examples/49_resolve_username.py +0 -0
  65. {spluspy-2.0.8 → spluspy-2.0.9}/examples/50_invoke.py +0 -0
  66. {spluspy-2.0.8 → spluspy-2.0.9}/setup.py +0 -0
  67. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/__init__.py +0 -0
  68. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/__init__.py +0 -0
  69. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/_updates/__init__.py +0 -0
  70. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/_updates/entitycache.py +0 -0
  71. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/_updates/messagebox.py +0 -0
  72. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/_updates/session.py +0 -0
  73. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/__init__.py +0 -0
  74. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/account.py +0 -0
  75. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/auth.py +0 -0
  76. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/bots.py +0 -0
  77. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/buttons.py +0 -0
  78. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/chats.py +0 -0
  79. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/downloads.py +0 -0
  80. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/messageparse.py +0 -0
  81. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/messages.py +0 -0
  82. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/soroushclient.py +0 -0
  83. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/telegrambaseclient.py +0 -0
  84. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/updates.py +0 -0
  85. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/uploads.py +0 -0
  86. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/client/users.py +0 -0
  87. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/__init__.py +0 -0
  88. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/aes.py +0 -0
  89. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/aesctr.py +0 -0
  90. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/authkey.py +0 -0
  91. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/cdndecrypter.py +0 -0
  92. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/factorization.py +0 -0
  93. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/fast_aes.pyx +0 -0
  94. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/fast_rsa.pyx +0 -0
  95. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/libssl.py +0 -0
  96. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/crypto/rsa.py +0 -0
  97. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/custom.py +0 -0
  98. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/errors/__init__.py +0 -0
  99. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/errors/common.py +0 -0
  100. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/errors/rpcbaseerrors.py +0 -0
  101. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/errors/rpcerrorlist.py +0 -0
  102. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/__init__.py +0 -0
  103. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/album.py +0 -0
  104. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/callbackquery.py +0 -0
  105. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/chataction.py +0 -0
  106. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/common.py +0 -0
  107. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/inlinequery.py +0 -0
  108. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/messagedeleted.py +0 -0
  109. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/messageedited.py +0 -0
  110. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/messageread.py +0 -0
  111. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/newmessage.py +0 -0
  112. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/raw.py +0 -0
  113. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/events/userupdate.py +0 -0
  114. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/extensions/__init__.py +0 -0
  115. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/extensions/binaryreader.py +0 -0
  116. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/extensions/html.py +0 -0
  117. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/extensions/markdown.py +0 -0
  118. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/extensions/messagepacker.py +0 -0
  119. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/functions.py +0 -0
  120. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/helpers.py +0 -0
  121. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/hints.py +0 -0
  122. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/__init__.py +0 -0
  123. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/authenticator.py +0 -0
  124. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/__init__.py +0 -0
  125. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/connection.py +0 -0
  126. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/http.py +0 -0
  127. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/tcpabridged.py +0 -0
  128. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/tcpfull.py +0 -0
  129. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/tcpintermediate.py +0 -0
  130. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/tcpmtproxy.py +0 -0
  131. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/tcpobfuscated.py +0 -0
  132. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/connection/websocket.py +0 -0
  133. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/mtprotoplainsender.py +0 -0
  134. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/mtprotosender.py +0 -0
  135. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/mtprotostate.py +0 -0
  136. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/network/requeststate.py +0 -0
  137. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/password.py +0 -0
  138. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/requestiter.py +0 -0
  139. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/sessions/__init__.py +0 -0
  140. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/sessions/abstract.py +0 -0
  141. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/sessions/memory.py +0 -0
  142. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/sessions/sqlite.py +0 -0
  143. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/sessions/string.py +0 -0
  144. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/sync.py +0 -0
  145. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/__init__.py +0 -0
  146. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/alltlobjects.py +0 -0
  147. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/core/__init__.py +0 -0
  148. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/core/gzippacked.py +0 -0
  149. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/core/messagecontainer.py +0 -0
  150. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/core/rpcresult.py +0 -0
  151. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/core/tlmessage.py +0 -0
  152. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/__init__.py +0 -0
  153. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/adminlogevent.py +0 -0
  154. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/button.py +0 -0
  155. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/chatgetter.py +0 -0
  156. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/conversation.py +0 -0
  157. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/dialog.py +0 -0
  158. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/draft.py +0 -0
  159. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/file.py +0 -0
  160. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/forward.py +0 -0
  161. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/inlinebuilder.py +0 -0
  162. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/inlineresult.py +0 -0
  163. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/inlineresults.py +0 -0
  164. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/inputsizedfile.py +0 -0
  165. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/message.py +0 -0
  166. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/messagebutton.py +0 -0
  167. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/participantpermissions.py +0 -0
  168. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/qrlogin.py +0 -0
  169. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/sendergetter.py +0 -0
  170. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/custom/types.py +0 -0
  171. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/__init__.py +0 -0
  172. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/account.py +0 -0
  173. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/auth.py +0 -0
  174. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/bots.py +0 -0
  175. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/channels.py +0 -0
  176. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/chatlists.py +0 -0
  177. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/conference.py +0 -0
  178. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/contacts.py +0 -0
  179. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/folders.py +0 -0
  180. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/help.py +0 -0
  181. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/langpack.py +0 -0
  182. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/messages.py +0 -0
  183. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/payments.py +0 -0
  184. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/phone.py +0 -0
  185. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/photos.py +0 -0
  186. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/premium.py +0 -0
  187. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/stats.py +0 -0
  188. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/stories.py +0 -0
  189. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/thirdParty.py +0 -0
  190. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/updates.py +0 -0
  191. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/upload.py +0 -0
  192. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/functions/users.py +0 -0
  193. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/patched/__init__.py +0 -0
  194. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/tlobject.py +0 -0
  195. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/__init__.py +0 -0
  196. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/account.py +0 -0
  197. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/auth.py +0 -0
  198. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/bots.py +0 -0
  199. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/channels.py +0 -0
  200. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/chatlists.py +0 -0
  201. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/conference.py +0 -0
  202. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/contacts.py +0 -0
  203. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/help.py +0 -0
  204. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/messages.py +0 -0
  205. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/payments.py +0 -0
  206. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/phone.py +0 -0
  207. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/photos.py +0 -0
  208. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/premium.py +0 -0
  209. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/stats.py +0 -0
  210. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/stickers.py +0 -0
  211. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/storage.py +0 -0
  212. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/stories.py +0 -0
  213. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/thirdParty.py +0 -0
  214. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/update.py +0 -0
  215. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/updates.py +0 -0
  216. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/upload.py +0 -0
  217. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/tl/types/users.py +0 -0
  218. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/types.py +0 -0
  219. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/utils.py +0 -0
  220. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/_engine/version.py +0 -0
  221. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/admin.py +0 -0
  222. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/afk.py +0 -0
  223. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/cli.py +0 -0
  224. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/client/__init__.py +0 -0
  225. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/client/conversation.py +0 -0
  226. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/compat.py +0 -0
  227. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/config.py +0 -0
  228. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/errors/__init__.py +0 -0
  229. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/errors/exceptions.py +0 -0
  230. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/__init__.py +0 -0
  231. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/album.py +0 -0
  232. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/base.py +0 -0
  233. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/callback.py +0 -0
  234. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/chat_action.py +0 -0
  235. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/edited.py +0 -0
  236. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/inline.py +0 -0
  237. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/message.py +0 -0
  238. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/message_deleted.py +0 -0
  239. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/message_read.py +0 -0
  240. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/events/user_update.py +0 -0
  241. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/filters/__init__.py +0 -0
  242. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/filters/filters.py +0 -0
  243. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/fsm/__init__.py +0 -0
  244. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/fsm/state.py +0 -0
  245. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/middleware/__init__.py +0 -0
  246. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/middleware/base.py +0 -0
  247. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/middleware/rate_limit.py +0 -0
  248. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/mirror.py +0 -0
  249. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/__init__.py +0 -0
  250. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/bot.py +0 -0
  251. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/chat.py +0 -0
  252. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/enums.py +0 -0
  253. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/media.py +0 -0
  254. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/message.py +0 -0
  255. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/objects.py +0 -0
  256. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/models/user.py +0 -0
  257. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/__init__.py +0 -0
  258. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/client.py +0 -0
  259. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/connection.py +0 -0
  260. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/http_client.py +0 -0
  261. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/mtproto.py +0 -0
  262. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/protocols.py +0 -0
  263. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/spluspy_adapter.py +0 -0
  264. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/network/transport.py +0 -0
  265. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/plugins/__init__.py +0 -0
  266. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/plugins/loader.py +0 -0
  267. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/py.typed +0 -0
  268. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/scheduler/__init__.py +0 -0
  269. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/scheduler/scheduler.py +0 -0
  270. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/session/__init__.py +0 -0
  271. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/session/base.py +0 -0
  272. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/session/memory.py +0 -0
  273. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/session/sqlite.py +0 -0
  274. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/session/string.py +0 -0
  275. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/__init__.py +0 -0
  276. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/base.py +0 -0
  277. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/entity_cache.py +0 -0
  278. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/memory.py +0 -0
  279. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/postgres.py +0 -0
  280. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/redis.py +0 -0
  281. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/storage/sqlite.py +0 -0
  282. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/sync/__init__.py +0 -0
  283. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/sync/client.py +0 -0
  284. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/__init__.py +0 -0
  285. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/batch.py +0 -0
  286. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/cache.py +0 -0
  287. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/chat_lock.py +0 -0
  288. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/file_transfer.py +0 -0
  289. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/helpers.py +0 -0
  290. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/logger.py +0 -0
  291. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/rate_limiter.py +0 -0
  292. {spluspy-2.0.8 → spluspy-2.0.9}/spluspy/utils/resolver.py +0 -0
  293. {spluspy-2.0.8 → spluspy-2.0.9}/tests/__init__.py +0 -0
  294. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_client.py +0 -0
  295. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_filters.py +0 -0
  296. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_fsm.py +0 -0
  297. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_fsm_enhanced.py +0 -0
  298. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_middleware.py +0 -0
  299. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_rate_limiter.py +0 -0
  300. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_resolver.py +0 -0
  301. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_scheduler.py +0 -0
  302. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_session.py +0 -0
  303. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_storage.py +0 -0
  304. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_types.py +0 -0
  305. {spluspy-2.0.8 → spluspy-2.0.9}/tests/test_utils.py +0 -0
@@ -5,6 +5,16 @@ All notable changes to SplusPy will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [2.0.9] - 2026-07-12
9
+
10
+ ### Added
11
+ - `leave_all()` method to leave all groups and channels at once
12
+ - `delete_all_private()` method to delete all private chat dialogs
13
+ - `/delete_all_private` bot command with confirmation flow
14
+
15
+ ### Changed
16
+ - `/leave_all_groups` bot command now uses `leave_all()` to include channels
17
+
8
18
  ## [2.0.8] - 2026-07-12
9
19
 
10
20
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spluspy
3
- Version: 2.0.8
3
+ Version: 2.0.9
4
4
  Summary: A modern async Python library for interacting with Soroush Plus
5
5
  Project-URL: Homepage, https://github.com/Itskillmaster/spluspy
6
6
  Project-URL: Documentation, https://github.com/Itskillmaster/spluspy#readme
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "spluspy"
7
- version = "2.0.8"
7
+ version = "2.0.9"
8
8
  description = "A modern async Python library for interacting with Soroush Plus"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  """SplusPy version information."""
2
2
 
3
- __version__ = "2.0.8"
3
+ __version__ = "2.0.9"
4
4
  __author__ = "Ali Mirshekari"
5
5
  __license__ = "MIT"
6
6
  __url__ = "https://github.com/Itskillmaster/spluspy"
@@ -477,6 +477,103 @@ class DialogMethods:
477
477
 
478
478
  return result
479
479
 
480
+ async def delete_all_private(
481
+ self: 'SoroushClient',
482
+ *,
483
+ revoke: bool = False,
484
+ exclude_ids: typing.Optional[typing.List[int]] = None,
485
+ delay: float = 1.0,
486
+ on_progress: typing.Optional[typing.Callable] = None
487
+ ) -> dict:
488
+ """
489
+ Delete all private chat dialogs (user conversations).
490
+
491
+ Iterates through all dialogs, identifies private chats (users),
492
+ and deletes them. Useful for cleaning up bot spam or old conversations.
493
+
494
+ Arguments
495
+ revoke (`bool`, optional):
496
+ If ``True``, revoke (delete) messages for the other peer too.
497
+ Default is ``False``.
498
+
499
+ exclude_ids (list of `int`, optional):
500
+ List of user IDs to skip (e.g. your own account, important contacts).
501
+
502
+ delay (`float`, optional):
503
+ Delay in seconds between each delete to avoid flood waits.
504
+ Default is ``1.0``.
505
+
506
+ on_progress (callable, optional):
507
+ Callback called with ``(current, total, title)`` for progress updates.
508
+
509
+ Returns
510
+ Dict with 'success', 'failed', 'skipped' counts and details.
511
+
512
+ Example
513
+ .. code-block:: python
514
+
515
+ # Delete all private chats
516
+ result = await client.delete_all_private()
517
+ print(f"Deleted {result['success']} chats")
518
+
519
+ # Delete but keep certain users
520
+ result = await client.delete_all_private(exclude_ids=[12345, 67890])
521
+ """
522
+ exclude_ids = set(exclude_ids or [])
523
+ result = {"success": 0, "failed": 0, "skipped": 0, "details": []}
524
+
525
+ try:
526
+ dialogs = await self.get_dialogs(limit=None)
527
+ except Exception as exc:
528
+ _log.error("delete_all_private: failed to get dialogs: %s", exc)
529
+ return result
530
+
531
+ private_dialogs = []
532
+ for dialog in dialogs:
533
+ entity = dialog.entity
534
+ if entity is None:
535
+ continue
536
+ # Only user dialogs (private chats)
537
+ if not isinstance(entity, types.User):
538
+ continue
539
+ # Skip self
540
+ if entity.self:
541
+ continue
542
+ user_id = entity.id
543
+ if user_id in exclude_ids:
544
+ result["skipped"] += 1
545
+ result["details"].append({
546
+ "id": user_id,
547
+ "title": getattr(entity, 'first_name', None) or getattr(entity, 'username', str(user_id)),
548
+ "status": "skipped"
549
+ })
550
+ continue
551
+ private_dialogs.append((user_id, entity))
552
+
553
+ total = len(private_dialogs)
554
+ _log.info("delete_all_private: found %d private chats to delete", total)
555
+
556
+ for idx, (user_id, entity) in enumerate(private_dialogs):
557
+ title = getattr(entity, 'first_name', None) or getattr(entity, 'username', str(user_id))
558
+ if on_progress:
559
+ try:
560
+ on_progress(idx + 1, total, title)
561
+ except Exception:
562
+ pass
563
+ try:
564
+ await self.delete_dialog(entity, revoke=revoke)
565
+ result["success"] += 1
566
+ result["details"].append({"id": user_id, "title": title, "status": "deleted"})
567
+ _log.debug("delete_all_private: deleted %s (%d)", title, user_id)
568
+ except Exception as exc:
569
+ result["failed"] += 1
570
+ result["details"].append({"id": user_id, "title": title, "status": "failed"})
571
+ _log.warning("delete_all_private: failed to delete %s (%d): %s", title, user_id, exc)
572
+ if delay > 0 and idx < total - 1:
573
+ await asyncio.sleep(delay)
574
+
575
+ return result
576
+
480
577
  def conversation(
481
578
  self: 'SoroushClient',
482
579
  entity: 'hints.EntityLike',
@@ -1786,6 +1786,9 @@ class Client:
1786
1786
  async def leave_chat(self, chat_id: Union[int, str]) -> bool:
1787
1787
  """Leave a chat by ID, username, or invite link.
1788
1788
 
1789
+ Auto-detects whether the target is a channel/supergroup or a basic
1790
+ group and uses the correct TL method.
1791
+
1789
1792
  Args:
1790
1793
  chat_id: Chat integer ID, username (str), or t.me link.
1791
1794
 
@@ -1794,22 +1797,9 @@ class Client:
1794
1797
  """
1795
1798
  client = self._get_client()
1796
1799
  if not client:
1797
- logger.warning("leave_chat skipped: client not connected")
1798
1800
  return False
1799
1801
  resolved = self._resolve_chat_id(chat_id)
1800
- try:
1801
- if hasattr(client, "leave_chat"):
1802
- await client.leave_chat(resolved)
1803
- else:
1804
- await self._leave_chat_via_invoke(client, resolved)
1805
- logger.debug("leave_chat(%s) succeeded", chat_id)
1806
- return True
1807
- except Exception as exc:
1808
- logger.error("leave_chat(%s) failed: %s", chat_id, exc)
1809
- return False
1810
1802
 
1811
- async def _leave_chat_via_invoke(self, client: Any, resolved: Any) -> None:
1812
- """Leave a chat using raw TL invoke as a fallback."""
1813
1803
  try:
1814
1804
  from spluspy._engine import functions, types # type: ignore[import-untyped]
1815
1805
  except ImportError:
@@ -1818,14 +1808,317 @@ class Client:
1818
1808
  except ImportError:
1819
1809
  raise ImportError("No compatible MTProto library available for leave_chat")
1820
1810
 
1821
- entity = await client.get_entity(resolved)
1811
+ # 1. Try get_entity to detect type
1812
+ try:
1813
+ entity = await client.get_entity(resolved)
1814
+ if isinstance(entity, types.Channel):
1815
+ return await self.leave_channel(chat_id)
1816
+ elif isinstance(entity, types.Chat):
1817
+ return await self.leave_group(chat_id)
1818
+ else:
1819
+ return await self.leave_channel(chat_id)
1820
+ except Exception:
1821
+ pass
1822
1822
 
1823
- if isinstance(entity, types.Channel):
1824
- await client(functions.channels.LeaveChannelRequest(channel=entity))
1825
- elif isinstance(entity, types.Chat):
1826
- await client(functions.messages.DeleteChatUserRequest(chat_id=entity.id, user_id="me"))
1827
- else:
1823
+ # 2. Fallback: try get_input_entity
1824
+ try:
1825
+ input_peer = await client.get_input_entity(resolved)
1826
+ if isinstance(input_peer, types.InputPeerChannel):
1827
+ return await self.leave_channel(chat_id)
1828
+ elif isinstance(input_peer, types.InputPeerChat):
1829
+ return await self.leave_group(chat_id)
1830
+ else:
1831
+ return await self.leave_channel(chat_id)
1832
+ except Exception:
1833
+ pass
1834
+
1835
+ # 3. Fallback: try client.leave_chat
1836
+ if hasattr(client, "leave_chat"):
1837
+ try:
1838
+ await client.leave_chat(resolved)
1839
+ return True
1840
+ except Exception:
1841
+ pass
1842
+
1843
+ return False
1844
+
1845
+ async def leave_group(self, chat_id: Union[int, str]) -> bool:
1846
+ """Leave a basic group (supergroup or regular group).
1847
+
1848
+ Uses DeleteChatUserRequest — the correct method for groups.
1849
+
1850
+ Args:
1851
+ chat_id: Group integer ID.
1852
+
1853
+ Returns:
1854
+ True on success, False on failure.
1855
+ """
1856
+ client = self._get_client()
1857
+ if not client:
1858
+ return False
1859
+ resolved = self._resolve_chat_id(chat_id)
1860
+
1861
+ try:
1862
+ from spluspy._engine import functions # type: ignore[import-untyped]
1863
+ except ImportError:
1864
+ try:
1865
+ from telethon import functions # type: ignore[import-untyped]
1866
+ except ImportError:
1867
+ raise ImportError("No compatible MTProto library available")
1868
+
1869
+ # Strategy 1: kick_participant('me')
1870
+ if hasattr(client, 'kick_participant'):
1871
+ try:
1872
+ await client.kick_participant(resolved, 'me')
1873
+ return True
1874
+ except Exception:
1875
+ pass
1876
+
1877
+ # Strategy 2: get_entity → DeleteChatUserRequest
1878
+ try:
1879
+ entity = await client.get_entity(resolved)
1880
+ chat_id_raw = getattr(entity, 'chat_id', None) or getattr(entity, 'id', None)
1881
+ await client(functions.messages.DeleteChatUserRequest(
1882
+ chat_id=chat_id_raw, user_id="me"
1883
+ ))
1884
+ return True
1885
+ except Exception:
1886
+ pass
1887
+
1888
+ # Strategy 3: get_input_entity → DeleteChatUserRequest
1889
+ try:
1890
+ input_peer = await client.get_input_entity(resolved)
1891
+ chat_id_raw = getattr(input_peer, 'chat_id', None)
1892
+ if chat_id_raw is not None:
1893
+ await client(functions.messages.DeleteChatUserRequest(
1894
+ chat_id=chat_id_raw, user_id="me"
1895
+ ))
1896
+ return True
1897
+ except Exception:
1898
+ pass
1899
+
1900
+ return False
1901
+
1902
+ async def leave_channel(self, chat_id: Union[int, str]) -> bool:
1903
+ """Leave a channel or supergroup.
1904
+
1905
+ Uses LeaveChannelRequest — the correct method for channels.
1906
+
1907
+ Args:
1908
+ chat_id: Channel integer ID or username.
1909
+
1910
+ Returns:
1911
+ True on success, False on failure.
1912
+ """
1913
+ client = self._get_client()
1914
+ if not client:
1915
+ return False
1916
+ resolved = self._resolve_chat_id(chat_id)
1917
+
1918
+ try:
1919
+ from spluspy._engine import functions # type: ignore[import-untyped]
1920
+ except ImportError:
1921
+ try:
1922
+ from telethon import functions # type: ignore[import-untyped]
1923
+ except ImportError:
1924
+ raise ImportError("No compatible MTProto library available")
1925
+
1926
+ # Strategy 1: get_entity → LeaveChannelRequest
1927
+ try:
1928
+ entity = await client.get_entity(resolved)
1828
1929
  await client(functions.channels.LeaveChannelRequest(channel=entity))
1930
+ return True
1931
+ except Exception:
1932
+ pass
1933
+
1934
+ # Strategy 2: get_input_entity → LeaveChannelRequest
1935
+ try:
1936
+ input_peer = await client.get_input_entity(resolved)
1937
+ await client(functions.channels.LeaveChannelRequest(channel=input_peer))
1938
+ return True
1939
+ except Exception:
1940
+ pass
1941
+
1942
+ # Strategy 3: client.leave_chat fallback
1943
+ if hasattr(client, "leave_chat"):
1944
+ try:
1945
+ await client.leave_chat(resolved)
1946
+ return True
1947
+ except Exception:
1948
+ pass
1949
+
1950
+ return False
1951
+
1952
+ async def get_all_groups(self) -> list[dict]:
1953
+ """Get all groups and channels the bot is a member of.
1954
+
1955
+ Returns:
1956
+ List of dicts with keys: id, title, type ('channel' or 'chat')
1957
+ """
1958
+ client = self._get_client()
1959
+ if not client:
1960
+ logger.warning("get_all_groups skipped: client not connected")
1961
+ return []
1962
+
1963
+ try:
1964
+ dialogs = await client.get_dialogs(limit=None)
1965
+ except Exception as exc:
1966
+ logger.error("get_all_groups: failed to get dialogs: %s", exc)
1967
+ return []
1968
+
1969
+ groups = []
1970
+ for dialog in dialogs:
1971
+ entity = dialog.entity
1972
+ if entity is None:
1973
+ continue
1974
+ entity_type = type(entity).__name__
1975
+ # Skip users (not groups/channels)
1976
+ if "User" in entity_type:
1977
+ continue
1978
+ # Skip self
1979
+ if getattr(entity, 'id', None) == self._user_id:
1980
+ continue
1981
+ groups.append({
1982
+ "id": getattr(entity, 'id', 0),
1983
+ "title": getattr(entity, 'title', 'Unknown'),
1984
+ "type": "channel" if "Channel" in entity_type else "chat",
1985
+ "entity": entity,
1986
+ })
1987
+
1988
+ logger.debug("get_all_groups: found %d groups/channels", len(groups))
1989
+ return groups
1990
+
1991
+ async def leave_all_groups(self, exclude_ids: list[int] = None) -> dict:
1992
+ """Leave all basic groups and supergroups (not channels).
1993
+
1994
+ Args:
1995
+ exclude_ids: List of chat IDs to skip.
1996
+
1997
+ Returns:
1998
+ Dict with 'success', 'failed', 'skipped' counts and details.
1999
+ """
2000
+ exclude_ids = set(exclude_ids or [])
2001
+ all_groups = await self.get_all_groups()
2002
+ result = {"success": 0, "failed": 0, "skipped": 0, "details": []}
2003
+
2004
+ for g in all_groups:
2005
+ if g["type"] == "channel":
2006
+ continue # only groups
2007
+ chat_id = g["id"]
2008
+ if chat_id in exclude_ids:
2009
+ result["skipped"] += 1
2010
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "skipped"})
2011
+ continue
2012
+
2013
+ ok = await self.leave_group(chat_id)
2014
+ if ok:
2015
+ result["success"] += 1
2016
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "left"})
2017
+ else:
2018
+ result["failed"] += 1
2019
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "failed"})
2020
+ await asyncio.sleep(1)
2021
+
2022
+ return result
2023
+
2024
+ async def leave_all_channels(self, exclude_ids: list[int] = None) -> dict:
2025
+ """Leave all channels (not groups).
2026
+
2027
+ Args:
2028
+ exclude_ids: List of chat IDs to skip.
2029
+
2030
+ Returns:
2031
+ Dict with 'success', 'failed', 'skipped' counts and details.
2032
+ """
2033
+ exclude_ids = set(exclude_ids or [])
2034
+ all_groups = await self.get_all_groups()
2035
+ result = {"success": 0, "failed": 0, "skipped": 0, "details": []}
2036
+
2037
+ for g in all_groups:
2038
+ if g["type"] == "chat":
2039
+ continue # only channels
2040
+ chat_id = g["id"]
2041
+ if chat_id in exclude_ids:
2042
+ result["skipped"] += 1
2043
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "skipped"})
2044
+ continue
2045
+
2046
+ ok = await self.leave_channel(chat_id)
2047
+ if ok:
2048
+ result["success"] += 1
2049
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "left"})
2050
+ else:
2051
+ result["failed"] += 1
2052
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "failed"})
2053
+ await asyncio.sleep(1)
2054
+
2055
+ return result
2056
+
2057
+ async def leave_all(self, exclude_ids: list[int] = None) -> dict:
2058
+ """Leave all groups and channels.
2059
+
2060
+ Args:
2061
+ exclude_ids: List of chat IDs to skip.
2062
+
2063
+ Returns:
2064
+ Dict with 'success', 'failed', 'skipped' counts and details.
2065
+ """
2066
+ exclude_ids = set(exclude_ids or [])
2067
+ all_groups = await self.get_all_groups()
2068
+ result = {"success": 0, "failed": 0, "skipped": 0, "details": []}
2069
+
2070
+ for g in all_groups:
2071
+ chat_id = g["id"]
2072
+ if chat_id in exclude_ids:
2073
+ result["skipped"] += 1
2074
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "skipped"})
2075
+ continue
2076
+
2077
+ if g["type"] == "channel":
2078
+ ok = await self.leave_channel(chat_id)
2079
+ else:
2080
+ ok = await self.leave_group(chat_id)
2081
+
2082
+ if ok:
2083
+ result["success"] += 1
2084
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "left"})
2085
+ else:
2086
+ result["failed"] += 1
2087
+ result["details"].append({"id": chat_id, "title": g["title"], "status": "failed"})
2088
+ await asyncio.sleep(1)
2089
+
2090
+ return result
2091
+
2092
+ async def delete_all_private(
2093
+ self,
2094
+ *,
2095
+ revoke: bool = False,
2096
+ exclude_ids: list[int] = None,
2097
+ delay: float = 1.0,
2098
+ on_progress=None,
2099
+ ) -> dict:
2100
+ """Delete all private chat dialogs (user conversations).
2101
+
2102
+ Args:
2103
+ revoke: If True, revoke messages for the other peer too.
2104
+ exclude_ids: List of user IDs to skip.
2105
+ delay: Delay in seconds between each delete.
2106
+ on_progress: Callback ``(current, total, title)`` for progress.
2107
+
2108
+ Returns:
2109
+ Dict with 'success', 'failed', 'skipped' counts and details.
2110
+ """
2111
+ client = self._get_client()
2112
+ if not client:
2113
+ logger.warning("delete_all_private skipped: client not connected")
2114
+ return {"success": 0, "failed": 0, "skipped": 0, "details": []}
2115
+
2116
+ return await client.delete_all_private(
2117
+ revoke=revoke,
2118
+ exclude_ids=exclude_ids,
2119
+ delay=delay,
2120
+ on_progress=on_progress,
2121
+ )
1829
2122
 
1830
2123
  async def pin_message(self, chat_id: int, message: Union[Message, int], *, notify: bool = False) -> bool:
1831
2124
  """Pin a message in a chat.
@@ -70,7 +70,8 @@ def print_update_notice(new_version: str) -> None:
70
70
  print(
71
71
  f"\n\033[33m⚠ SplusPy {new_version} is available "
72
72
  f"(installed: {__version__}).\033[0m\n"
73
- f"\033[33m Run: pip install --upgrade spluspy\033[0m\n",
73
+ f"\033[33m Run: pip install --upgrade spluspy\033[0m\n"
74
+ f"\033[33m Channel » @SplusPy\033[0m\n",
74
75
  file=sys.stderr,
75
76
  )
76
77
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes