spluspy 2.0.7__tar.gz → 2.0.8__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 (306) hide show
  1. {spluspy-2.0.7 → spluspy-2.0.8}/CHANGELOG.md +3 -2
  2. {spluspy-2.0.7 → spluspy-2.0.8}/PKG-INFO +1 -1
  3. {spluspy-2.0.7 → spluspy-2.0.8}/pyproject.toml +1 -1
  4. spluspy-2.0.8/setup.py +48 -0
  5. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/__version__.py +1 -1
  6. spluspy-2.0.8/spluspy/_engine/crypto/__init__.py +86 -0
  7. spluspy-2.0.8/spluspy/_engine/crypto/fast_aes.pyx +226 -0
  8. spluspy-2.0.8/spluspy/_engine/crypto/fast_rsa.pyx +312 -0
  9. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/binaryreader.py +29 -3
  10. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/mtprotosender.py +1 -1
  11. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/client/client.py +227 -18
  12. spluspy-2.0.7/spluspy/_engine/crypto/__init__.py +0 -10
  13. {spluspy-2.0.7 → spluspy-2.0.8}/.gitignore +0 -0
  14. {spluspy-2.0.7 → spluspy-2.0.8}/CONTRIBUTING.md +0 -0
  15. {spluspy-2.0.7 → spluspy-2.0.8}/Dockerfile +0 -0
  16. {spluspy-2.0.7 → spluspy-2.0.8}/LICENSE +0 -0
  17. {spluspy-2.0.7 → spluspy-2.0.8}/MANIFEST.in +0 -0
  18. {spluspy-2.0.7 → spluspy-2.0.8}/README.md +0 -0
  19. {spluspy-2.0.7 → spluspy-2.0.8}/README.rst +0 -0
  20. {spluspy-2.0.7 → spluspy-2.0.8}/examples/01_hello_bot.py +0 -0
  21. {spluspy-2.0.7 → spluspy-2.0.8}/examples/02_echo_bot.py +0 -0
  22. {spluspy-2.0.7 → spluspy-2.0.8}/examples/03_command_bot.py +0 -0
  23. {spluspy-2.0.7 → spluspy-2.0.8}/examples/04_private_only.py +0 -0
  24. {spluspy-2.0.7 → spluspy-2.0.8}/examples/05_group_only.py +0 -0
  25. {spluspy-2.0.7 → spluspy-2.0.8}/examples/06_regex_bot.py +0 -0
  26. {spluspy-2.0.7 → spluspy-2.0.8}/examples/07_user_filter.py +0 -0
  27. {spluspy-2.0.7 → spluspy-2.0.8}/examples/08_combined_filters.py +0 -0
  28. {spluspy-2.0.7 → spluspy-2.0.8}/examples/09_inline_keyboard.py +0 -0
  29. {spluspy-2.0.7 → spluspy-2.0.8}/examples/10_reply_keyboard.py +0 -0
  30. {spluspy-2.0.7 → spluspy-2.0.8}/examples/11_message_actions.py +0 -0
  31. {spluspy-2.0.7 → spluspy-2.0.8}/examples/12_media_bot.py +0 -0
  32. {spluspy-2.0.7 → spluspy-2.0.8}/examples/13_fsm_bot.py +0 -0
  33. {spluspy-2.0.7 → spluspy-2.0.8}/examples/14_plugin_bot.py +0 -0
  34. {spluspy-2.0.7 → spluspy-2.0.8}/examples/15_middleware_bot.py +0 -0
  35. {spluspy-2.0.7 → spluspy-2.0.8}/examples/16_scheduler_bot.py +0 -0
  36. {spluspy-2.0.7 → spluspy-2.0.8}/examples/17_conversation.py +0 -0
  37. {spluspy-2.0.7 → spluspy-2.0.8}/examples/18_chat_management.py +0 -0
  38. {spluspy-2.0.7 → spluspy-2.0.8}/examples/19_event_types.py +0 -0
  39. {spluspy-2.0.7 → spluspy-2.0.8}/examples/20_sync_bot.py +0 -0
  40. {spluspy-2.0.7 → spluspy-2.0.8}/examples/21_album_handler.py +0 -0
  41. {spluspy-2.0.7 → spluspy-2.0.8}/examples/22_download_bot.py +0 -0
  42. {spluspy-2.0.7 → spluspy-2.0.8}/examples/23_url_button.py +0 -0
  43. {spluspy-2.0.7 → spluspy-2.0.8}/examples/24_string_session.py +0 -0
  44. {spluspy-2.0.7 → spluspy-2.0.8}/examples/25_error_handling.py +0 -0
  45. {spluspy-2.0.7 → spluspy-2.0.8}/examples/25_working_bot.py +0 -0
  46. {spluspy-2.0.7 → spluspy-2.0.8}/examples/26_message_entities.py +0 -0
  47. {spluspy-2.0.7 → spluspy-2.0.8}/examples/27_search_messages.py +0 -0
  48. {spluspy-2.0.7 → spluspy-2.0.8}/examples/28_poll_bot.py +0 -0
  49. {spluspy-2.0.7 → spluspy-2.0.8}/examples/29_dice_bot.py +0 -0
  50. {spluspy-2.0.7 → spluspy-2.0.8}/examples/30_cache_bot.py +0 -0
  51. {spluspy-2.0.7 → spluspy-2.0.8}/examples/31_reaction_bot.py +0 -0
  52. {spluspy-2.0.7 → spluspy-2.0.8}/examples/32_mark_read_bot.py +0 -0
  53. {spluspy-2.0.7 → spluspy-2.0.8}/examples/33_context_manager.py +0 -0
  54. {spluspy-2.0.7 → spluspy-2.0.8}/examples/34_user_info.py +0 -0
  55. {spluspy-2.0.7 → spluspy-2.0.8}/examples/35_chat_info.py +0 -0
  56. {spluspy-2.0.7 → spluspy-2.0.8}/examples/36_forward_copy.py +0 -0
  57. {spluspy-2.0.7 → spluspy-2.0.8}/examples/37_admin_bot.py +0 -0
  58. {spluspy-2.0.7 → spluspy-2.0.8}/examples/38_media_filters.py +0 -0
  59. {spluspy-2.0.7 → spluspy-2.0.8}/examples/39_status_bot.py +0 -0
  60. {spluspy-2.0.7 → spluspy-2.0.8}/examples/40_delete_detection.py +0 -0
  61. {spluspy-2.0.7 → spluspy-2.0.8}/examples/41_read_detection.py +0 -0
  62. {spluspy-2.0.7 → spluspy-2.0.8}/examples/42_raw_events.py +0 -0
  63. {spluspy-2.0.7 → spluspy-2.0.8}/examples/43_poll_handler.py +0 -0
  64. {spluspy-2.0.7 → spluspy-2.0.8}/examples/44_reaction_handler.py +0 -0
  65. {spluspy-2.0.7 → spluspy-2.0.8}/examples/45_typing_handler.py +0 -0
  66. {spluspy-2.0.7 → spluspy-2.0.8}/examples/46_get_messages.py +0 -0
  67. {spluspy-2.0.7 → spluspy-2.0.8}/examples/47_iter_messages.py +0 -0
  68. {spluspy-2.0.7 → spluspy-2.0.8}/examples/48_get_members.py +0 -0
  69. {spluspy-2.0.7 → spluspy-2.0.8}/examples/49_resolve_username.py +0 -0
  70. {spluspy-2.0.7 → spluspy-2.0.8}/examples/50_invoke.py +0 -0
  71. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/__init__.py +0 -0
  72. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/__init__.py +0 -0
  73. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/__init__.py +0 -0
  74. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/entitycache.py +0 -0
  75. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/messagebox.py +0 -0
  76. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/session.py +0 -0
  77. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/__init__.py +0 -0
  78. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/account.py +0 -0
  79. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/auth.py +0 -0
  80. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/bots.py +0 -0
  81. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/buttons.py +0 -0
  82. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/chats.py +0 -0
  83. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/dialogs.py +0 -0
  84. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/downloads.py +0 -0
  85. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/messageparse.py +0 -0
  86. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/messages.py +0 -0
  87. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/soroushclient.py +0 -0
  88. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/telegrambaseclient.py +0 -0
  89. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/updates.py +0 -0
  90. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/uploads.py +0 -0
  91. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/users.py +0 -0
  92. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/aes.py +0 -0
  93. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/aesctr.py +0 -0
  94. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/authkey.py +0 -0
  95. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/cdndecrypter.py +0 -0
  96. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/factorization.py +0 -0
  97. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/libssl.py +0 -0
  98. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/rsa.py +0 -0
  99. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/custom.py +0 -0
  100. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/__init__.py +0 -0
  101. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/common.py +0 -0
  102. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/rpcbaseerrors.py +0 -0
  103. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/rpcerrorlist.py +0 -0
  104. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/__init__.py +0 -0
  105. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/album.py +0 -0
  106. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/callbackquery.py +0 -0
  107. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/chataction.py +0 -0
  108. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/common.py +0 -0
  109. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/inlinequery.py +0 -0
  110. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/messagedeleted.py +0 -0
  111. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/messageedited.py +0 -0
  112. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/messageread.py +0 -0
  113. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/newmessage.py +0 -0
  114. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/raw.py +0 -0
  115. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/userupdate.py +0 -0
  116. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/__init__.py +0 -0
  117. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/html.py +0 -0
  118. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/markdown.py +0 -0
  119. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/messagepacker.py +0 -0
  120. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/functions.py +0 -0
  121. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/helpers.py +0 -0
  122. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/hints.py +0 -0
  123. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/__init__.py +0 -0
  124. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/authenticator.py +0 -0
  125. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/__init__.py +0 -0
  126. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/connection.py +0 -0
  127. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/http.py +0 -0
  128. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpabridged.py +0 -0
  129. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpfull.py +0 -0
  130. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpintermediate.py +0 -0
  131. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpmtproxy.py +0 -0
  132. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpobfuscated.py +0 -0
  133. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/websocket.py +0 -0
  134. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/mtprotoplainsender.py +0 -0
  135. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/mtprotostate.py +0 -0
  136. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/requeststate.py +0 -0
  137. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/password.py +0 -0
  138. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/requestiter.py +0 -0
  139. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/__init__.py +0 -0
  140. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/abstract.py +0 -0
  141. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/memory.py +0 -0
  142. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/sqlite.py +0 -0
  143. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/string.py +0 -0
  144. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sync.py +0 -0
  145. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/__init__.py +0 -0
  146. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/alltlobjects.py +0 -0
  147. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/__init__.py +0 -0
  148. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/gzippacked.py +0 -0
  149. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/messagecontainer.py +0 -0
  150. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/rpcresult.py +0 -0
  151. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/tlmessage.py +0 -0
  152. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/__init__.py +0 -0
  153. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/adminlogevent.py +0 -0
  154. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/button.py +0 -0
  155. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/chatgetter.py +0 -0
  156. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/conversation.py +0 -0
  157. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/dialog.py +0 -0
  158. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/draft.py +0 -0
  159. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/file.py +0 -0
  160. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/forward.py +0 -0
  161. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inlinebuilder.py +0 -0
  162. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inlineresult.py +0 -0
  163. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inlineresults.py +0 -0
  164. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inputsizedfile.py +0 -0
  165. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/message.py +0 -0
  166. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/messagebutton.py +0 -0
  167. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/participantpermissions.py +0 -0
  168. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/qrlogin.py +0 -0
  169. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/sendergetter.py +0 -0
  170. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/types.py +0 -0
  171. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/__init__.py +0 -0
  172. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/account.py +0 -0
  173. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/auth.py +0 -0
  174. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/bots.py +0 -0
  175. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/channels.py +0 -0
  176. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/chatlists.py +0 -0
  177. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/conference.py +0 -0
  178. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/contacts.py +0 -0
  179. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/folders.py +0 -0
  180. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/help.py +0 -0
  181. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/langpack.py +0 -0
  182. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/messages.py +0 -0
  183. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/payments.py +0 -0
  184. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/phone.py +0 -0
  185. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/photos.py +0 -0
  186. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/premium.py +0 -0
  187. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/stats.py +0 -0
  188. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/stories.py +0 -0
  189. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/thirdParty.py +0 -0
  190. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/updates.py +0 -0
  191. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/upload.py +0 -0
  192. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/users.py +0 -0
  193. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/patched/__init__.py +0 -0
  194. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/tlobject.py +0 -0
  195. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/__init__.py +0 -0
  196. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/account.py +0 -0
  197. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/auth.py +0 -0
  198. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/bots.py +0 -0
  199. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/channels.py +0 -0
  200. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/chatlists.py +0 -0
  201. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/conference.py +0 -0
  202. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/contacts.py +0 -0
  203. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/help.py +0 -0
  204. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/messages.py +0 -0
  205. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/payments.py +0 -0
  206. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/phone.py +0 -0
  207. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/photos.py +0 -0
  208. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/premium.py +0 -0
  209. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/stats.py +0 -0
  210. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/stickers.py +0 -0
  211. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/storage.py +0 -0
  212. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/stories.py +0 -0
  213. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/thirdParty.py +0 -0
  214. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/update.py +0 -0
  215. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/updates.py +0 -0
  216. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/upload.py +0 -0
  217. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/users.py +0 -0
  218. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/types.py +0 -0
  219. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/utils.py +0 -0
  220. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/version.py +0 -0
  221. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/admin.py +0 -0
  222. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/afk.py +0 -0
  223. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/cli.py +0 -0
  224. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/client/__init__.py +0 -0
  225. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/client/conversation.py +0 -0
  226. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/compat.py +0 -0
  227. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/config.py +0 -0
  228. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/errors/__init__.py +0 -0
  229. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/errors/exceptions.py +0 -0
  230. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/__init__.py +0 -0
  231. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/album.py +0 -0
  232. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/base.py +0 -0
  233. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/callback.py +0 -0
  234. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/chat_action.py +0 -0
  235. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/edited.py +0 -0
  236. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/inline.py +0 -0
  237. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/message.py +0 -0
  238. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/message_deleted.py +0 -0
  239. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/message_read.py +0 -0
  240. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/user_update.py +0 -0
  241. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/filters/__init__.py +0 -0
  242. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/filters/filters.py +0 -0
  243. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/fsm/__init__.py +0 -0
  244. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/fsm/state.py +0 -0
  245. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/middleware/__init__.py +0 -0
  246. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/middleware/base.py +0 -0
  247. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/middleware/rate_limit.py +0 -0
  248. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/mirror.py +0 -0
  249. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/__init__.py +0 -0
  250. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/bot.py +0 -0
  251. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/chat.py +0 -0
  252. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/enums.py +0 -0
  253. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/media.py +0 -0
  254. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/message.py +0 -0
  255. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/objects.py +0 -0
  256. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/user.py +0 -0
  257. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/__init__.py +0 -0
  258. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/client.py +0 -0
  259. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/connection.py +0 -0
  260. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/http_client.py +0 -0
  261. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/mtproto.py +0 -0
  262. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/protocols.py +0 -0
  263. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/spluspy_adapter.py +0 -0
  264. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/transport.py +0 -0
  265. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/plugins/__init__.py +0 -0
  266. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/plugins/loader.py +0 -0
  267. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/py.typed +0 -0
  268. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/scheduler/__init__.py +0 -0
  269. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/scheduler/scheduler.py +0 -0
  270. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/__init__.py +0 -0
  271. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/base.py +0 -0
  272. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/memory.py +0 -0
  273. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/sqlite.py +0 -0
  274. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/string.py +0 -0
  275. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/__init__.py +0 -0
  276. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/base.py +0 -0
  277. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/entity_cache.py +0 -0
  278. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/memory.py +0 -0
  279. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/postgres.py +0 -0
  280. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/redis.py +0 -0
  281. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/sqlite.py +0 -0
  282. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/sync/__init__.py +0 -0
  283. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/sync/client.py +0 -0
  284. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/__init__.py +0 -0
  285. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/batch.py +0 -0
  286. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/cache.py +0 -0
  287. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/chat_lock.py +0 -0
  288. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/file_transfer.py +0 -0
  289. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/helpers.py +0 -0
  290. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/logger.py +0 -0
  291. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/rate_limiter.py +0 -0
  292. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/resolver.py +0 -0
  293. {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/version_check.py +0 -0
  294. {spluspy-2.0.7 → spluspy-2.0.8}/tests/__init__.py +0 -0
  295. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_client.py +0 -0
  296. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_filters.py +0 -0
  297. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_fsm.py +0 -0
  298. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_fsm_enhanced.py +0 -0
  299. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_middleware.py +0 -0
  300. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_rate_limiter.py +0 -0
  301. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_resolver.py +0 -0
  302. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_scheduler.py +0 -0
  303. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_session.py +0 -0
  304. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_storage.py +0 -0
  305. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_types.py +0 -0
  306. {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_utils.py +0 -0
@@ -5,10 +5,11 @@ 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.7] - 2026-07-11
8
+ ## [2.0.8] - 2026-07-12
9
9
 
10
10
  ### Changed
11
- - Version bump to 2.0.7
11
+ - Version bump to 2.0.8
12
+ - Downgraded verbose internal warnings (USER_ALREADY_JOINED, missing access_hash, TypeNotFoundError) from WARNING to DEBUG level to reduce log noise
12
13
 
13
14
  ## [2.0.6] - 2026-07-11
14
15
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spluspy
3
- Version: 2.0.7
3
+ Version: 2.0.8
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.7"
7
+ version = "2.0.8"
8
8
  description = "A modern async Python library for interacting with Soroush Plus"
9
9
  readme = "README.md"
10
10
  license = "MIT"
spluspy-2.0.8/setup.py ADDED
@@ -0,0 +1,48 @@
1
+ """
2
+ setup.py — Build script for spluspy Cython extensions.
3
+
4
+ Build locally with:
5
+
6
+ pip install cython cryptography
7
+ python setup.py build_ext --inplace
8
+
9
+ Or install in editable/development mode:
10
+
11
+ pip install -e ".[speed]"
12
+
13
+ The compiled ``.so`` / ``.pyd`` modules are placed alongside the source
14
+ ``.pyx`` files so the dispatcher in ``__init__.py`` can find them at
15
+ import time.
16
+ """
17
+ from setuptools import setup, Extension
18
+ from Cython.Build import cythonize
19
+
20
+ extensions = [
21
+ Extension(
22
+ "spluspy._engine.crypto.fast_aes",
23
+ sources=["spluspy/_engine/crypto/fast_aes.pyx"],
24
+ # No extra link flags needed — OpenSSL is loaded at runtime via
25
+ # the cryptography library's bundled libcrypto or via ctypes.
26
+ ),
27
+ Extension(
28
+ "spluspy._engine.crypto.fast_rsa",
29
+ sources=["spluspy/_engine/crypto/fast_rsa.pyx"],
30
+ # The cryptography package is a runtime dependency of this module.
31
+ # It is listed in pyproject.toml under [project.optional-dependencies]
32
+ # under the "crypto" extra.
33
+ ),
34
+ ]
35
+
36
+ setup(
37
+ ext_modules=cythonize(
38
+ extensions,
39
+ compiler_directives={
40
+ "language_level": "3", # Python 3 semantics
41
+ "boundscheck": False, # skip bounds checks for speed
42
+ "wraparound": False, # skip negative-index wrapping
43
+ "cdivision": True, # use C division (no ZeroDivisionError)
44
+ "initializedcheck": False, # skip memoryview init checks
45
+ "nonecheck": False, # skip None checks on typed vars
46
+ },
47
+ ),
48
+ )
@@ -1,6 +1,6 @@
1
1
  """SplusPy version information."""
2
2
 
3
- __version__ = "2.0.7"
3
+ __version__ = "2.0.8"
4
4
  __author__ = "Ali Mirshekari"
5
5
  __license__ = "MIT"
6
6
  __url__ = "https://github.com/Itskillmaster/spluspy"
@@ -0,0 +1,86 @@
1
+ """
2
+ This module contains several utilities regarding cryptographic purposes,
3
+ such as the AES IGE mode used by SoroushPlus, the authorization key bound with
4
+ their data centers, and so on.
5
+
6
+ Dispatching strategy
7
+ --------------------
8
+ The ``AES`` class and the ``rsa`` submodule are resolved at import time
9
+ using a two-tier fallback:
10
+
11
+ 1. **Fast path** – compiled Cython extensions (``fast_aes`` / ``fast_rsa``)
12
+ backed by OpenSSL via the ``cryptography`` library.
13
+ 2. **Pure-Python path** – ``aes`` (``pyaes`` / ``cryptg`` / ``libssl``) and
14
+ ``rsa`` (``rsa`` package).
15
+
16
+ If the compiled extensions are not available (the ``.so`` / ``.pyd`` files
17
+ have not been built, or a required dependency is missing), the dispatcher
18
+ silently falls back to the pure-Python implementations.
19
+ """
20
+ import sys as _sys
21
+ import logging as _logging
22
+
23
+ _log = _logging.getLogger(__name__)
24
+
25
+ # ---------------------------------------------------------------------------
26
+ # AES dispatcher — prefers Cython fast_aes, falls back to pure-Python aes
27
+ # ---------------------------------------------------------------------------
28
+ try:
29
+ from .fast_aes import encrypt_ige as _fast_encrypt_ige
30
+ from .fast_aes import decrypt_ige as _fast_decrypt_ige
31
+
32
+ class AES:
33
+ """
34
+ AES-IGE encryption / decryption interface.
35
+
36
+ When the Cython ``fast_aes`` extension is available the operations
37
+ are dispatched to OpenSSL (via the ``cryptography`` library) through
38
+ a Cython-typed wrapper. Otherwise the pure-Python ``aes.AES``
39
+ implementation is used.
40
+ """
41
+
42
+ __slots__ = () # no instance state — all methods are static
43
+
44
+ @staticmethod
45
+ def encrypt_ige(plain_text: bytes, key: bytes, iv: bytes) -> bytes:
46
+ """Encrypt *plain_text* using AES-IGE."""
47
+ return _fast_encrypt_ige(plain_text, key, iv)
48
+
49
+ @staticmethod
50
+ def decrypt_ige(cipher_text: bytes, key: bytes, iv: bytes) -> bytes:
51
+ """Decrypt *cipher_text* using AES-IGE."""
52
+ return _fast_decrypt_ige(cipher_text, key, iv)
53
+
54
+ _log.debug('fast_aes Cython extension loaded – using OpenSSL AES-IGE')
55
+
56
+ except ImportError:
57
+ from .aes import AES
58
+ _log.debug('fast_aes not available – using pure-Python AES fallback')
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # RSA dispatcher — prefers Cython fast_rsa, falls back to pure-Python rsa
62
+ #
63
+ # Consumers typically ``from ..crypto import rsa`` which resolves the
64
+ # submodule *rsa*. By injecting ``fast_rsa`` into ``sys.modules`` under
65
+ # the same dotted name *before* any other code imports ``.rsa``, we can
66
+ # transparently swap in the faster implementation.
67
+ # ---------------------------------------------------------------------------
68
+ _RSA_PKG = f'{__name__}.rsa' # e.g. "spluspy._engine.crypto.rsa"
69
+
70
+ try:
71
+ from . import fast_rsa as _fast_rsa # noqa: F401 — triggers import
72
+
73
+ # Only replace if the original rsa module hasn't been imported yet.
74
+ if _RSA_PKG not in _sys.modules:
75
+ _sys.modules[_RSA_PKG] = _fast_rsa
76
+ _log.debug('fast_rsa Cython extension loaded – using OpenSSL RSA')
77
+ except ImportError:
78
+ _log.debug('fast_rsa not available – using pure-Python RSA fallback')
79
+
80
+ # ---------------------------------------------------------------------------
81
+ # Other submodules — always imported directly (no fast variant yet)
82
+ # ---------------------------------------------------------------------------
83
+ from .aesctr import AESModeCTR
84
+ from .authkey import AuthKey
85
+ from .factorization import Factorization
86
+ from .cdndecrypter import CdnDecrypter
@@ -0,0 +1,226 @@
1
+ # cython: language_level=3, boundscheck=False, wraparound=False
2
+ """
3
+ High-performance AES-IGE encryption/decryption using OpenSSL via Cython.
4
+
5
+ This module provides AES-IGE encrypt/decrypt optimized with:
6
+ - Direct OpenSSL calls via the ``cryptography`` library's bundled bindings
7
+ (falls back to ``ctypes.util.find_library`` if unavailable).
8
+ - C-level ``malloc``/``memcpy``/``free`` for buffer management, avoiding
9
+ intermediate Python objects in the hot path.
10
+
11
+ Falls back gracefully: if neither the ``cryptography`` library nor a
12
+ system OpenSSL is reachable, an ``ImportError`` is raised at import time
13
+ so the dispatcher in ``__init__.py`` can select the pure-Python path.
14
+ """
15
+ import ctypes
16
+ import ctypes.util
17
+ import os
18
+ import sys
19
+ from libc.stdlib cimport malloc, free
20
+ from libc.string cimport memcpy
21
+
22
+ # ---------------------------------------------------------------------------
23
+ # OpenSSL loading
24
+ # ---------------------------------------------------------------------------
25
+ cdef bint _loaded = False
26
+ cdef object _lib = None # ctypes CDLL handle
27
+ cdef object _AES_set_encrypt_key = None
28
+ cdef object _AES_set_decrypt_key = None
29
+ cdef object _AES_ige_encrypt = None
30
+
31
+ # AES_KEY struct size (AES-256: 4*(14+1)*4 = 240 bytes rd_key + 4 bytes rounds)
32
+ cdef int _AES_KEY_SIZE = 260
33
+
34
+
35
+ cdef void _ensure_openssl():
36
+ """Lazily load OpenSSL and configure ctypes function signatures."""
37
+ global _loaded, _lib
38
+ global _AES_set_encrypt_key, _AES_set_decrypt_key, _AES_ige_encrypt
39
+ if _loaded:
40
+ return
41
+ _loaded = True
42
+
43
+ # --- Strategy 1: use the cryptography library's bundled OpenSSL ---
44
+ try:
45
+ from cryptography.hazmat.bindings.openssl import binding
46
+ _lib = binding.Binding.lib
47
+ except Exception:
48
+ _lib = None
49
+
50
+ # --- Strategy 2: fall back to system OpenSSL ---
51
+ if _lib is None:
52
+ try:
53
+ _lib = ctypes.cdll.LoadLibrary(
54
+ ctypes.util.find_library('ssl')
55
+ or ctypes.util.find_library('crypto')
56
+ )
57
+ except OSError:
58
+ _lib = None
59
+
60
+ if _lib is None:
61
+ return
62
+
63
+ # Configure AES_set_encrypt_key
64
+ _AES_set_encrypt_key = _lib.AES_set_encrypt_key
65
+ _AES_set_encrypt_key.restype = ctypes.c_int
66
+ _AES_set_encrypt_key.argtypes = [
67
+ ctypes.c_char_p, # const unsigned char *userKey
68
+ ctypes.c_int, # int bits
69
+ ctypes.c_void_p, # AES_KEY *aesKey
70
+ ]
71
+
72
+ # Configure AES_set_decrypt_key
73
+ _AES_set_decrypt_key = _lib.AES_set_decrypt_key
74
+ _AES_set_decrypt_key.restype = ctypes.c_int
75
+ _AES_set_decrypt_key.argtypes = [
76
+ ctypes.c_char_p, # const unsigned char *userKey
77
+ ctypes.c_int, # int bits
78
+ ctypes.c_void_p, # AES_KEY *aesKey
79
+ ]
80
+
81
+ # Configure AES_ige_encrypt — use c_void_p for all pointer args so we
82
+ # can pass integer addresses from Cython malloc'd buffers.
83
+ _AES_ige_encrypt = _lib.AES_ige_encrypt
84
+ _AES_ige_encrypt.restype = None
85
+ _AES_ige_encrypt.argtypes = [
86
+ ctypes.c_void_p, # const unsigned char *in
87
+ ctypes.c_void_p, # unsigned char *out
88
+ ctypes.c_size_t, # size_t length
89
+ ctypes.c_void_p, # AES_KEY *key
90
+ ctypes.c_void_p, # unsigned char *iv (32 bytes)
91
+ ctypes.c_int, # int enc (1=encrypt, 0=decrypt)
92
+ ]
93
+
94
+
95
+ # ---------------------------------------------------------------------------
96
+ # Public API
97
+ # ---------------------------------------------------------------------------
98
+
99
+ def encrypt_ige(bytes plain_text, bytes key, bytes iv) -> bytes:
100
+ """
101
+ AES-IGE *encrypt* using OpenSSL.
102
+
103
+ :param plain_text: plaintext (will be padded to a 16-byte boundary).
104
+ :param key: AES key (16, 24 or 32 bytes).
105
+ :param iv: 32-byte IGE initialization vector.
106
+ :returns: ciphertext bytes.
107
+ :raises RuntimeError: if OpenSSL is not available.
108
+ """
109
+ _ensure_openssl()
110
+ if _AES_ige_encrypt is None:
111
+ raise RuntimeError(
112
+ "OpenSSL AES_ige_encrypt is not available. "
113
+ "Install the ``cryptography`` package or ensure libssl/libcrypto "
114
+ "is reachable via ctypes."
115
+ )
116
+
117
+ # Pad plaintext to 16-byte boundary (matches existing aes.py behaviour)
118
+ cdef Py_ssize_t pt_len = len(plain_text)
119
+ cdef int remainder = pt_len % 16
120
+ if remainder:
121
+ plain_text = plain_text + os.urandom(16 - remainder)
122
+ pt_len = len(plain_text)
123
+
124
+ # Allocate C-level buffers via libc (no Python object overhead)
125
+ cdef unsigned char *in_buf = <unsigned char *>malloc(pt_len)
126
+ cdef unsigned char *out_buf = <unsigned char *>malloc(pt_len)
127
+ cdef unsigned char *aes_key = <unsigned char *>malloc(_AES_KEY_SIZE)
128
+
129
+ if in_buf == NULL or out_buf == NULL or aes_key == NULL:
130
+ free(in_buf)
131
+ free(out_buf)
132
+ free(aes_key)
133
+ raise MemoryError("Failed to allocate buffers for AES-IGE")
134
+
135
+ cdef int rc = 0
136
+ cdef const unsigned char[:] pt_view = plain_text
137
+ cdef const unsigned char[:] iv_view = iv
138
+
139
+ try:
140
+ # Copy plaintext into C buffer
141
+ memcpy(in_buf, &pt_view[0], <size_t>pt_len)
142
+
143
+ # Set up AES encrypt key schedule
144
+ # key is passed as bytes (ctypes c_char_p); aes_key as void* integer
145
+ rc = _AES_set_encrypt_key(key, <int>(len(key) * 8), <size_t>aes_key)
146
+ if rc != 0:
147
+ raise RuntimeError(f"AES_set_encrypt_key failed (rc={rc})")
148
+
149
+ # Perform IGE encryption — all pointer args as integer addresses
150
+ _AES_ige_encrypt(
151
+ <size_t>in_buf,
152
+ <size_t>out_buf,
153
+ <size_t>pt_len,
154
+ <size_t>aes_key,
155
+ <size_t>&iv_view[0],
156
+ <int>1, # AES_ENCRYPT
157
+ )
158
+
159
+ # Build Python bytes from C buffer
160
+ return bytes(out_buf[:pt_len])
161
+ finally:
162
+ free(in_buf)
163
+ free(out_buf)
164
+ free(aes_key)
165
+
166
+
167
+ def decrypt_ige(bytes cipher_text, bytes key, bytes iv) -> bytes:
168
+ """
169
+ AES-IGE *decrypt* using OpenSSL.
170
+
171
+ :param cipher_text: ciphertext (must be a multiple of 16 bytes).
172
+ :param key: AES key (16, 24 or 32 bytes).
173
+ :param iv: 32-byte IGE initialization vector.
174
+ :returns: plaintext bytes.
175
+ :raises RuntimeError: if OpenSSL is not available.
176
+ """
177
+ _ensure_openssl()
178
+ if _AES_ige_encrypt is None:
179
+ raise RuntimeError(
180
+ "OpenSSL AES_ige_encrypt is not available. "
181
+ "Install the ``cryptography`` package or ensure libssl/libcrypto "
182
+ "is reachable via ctypes."
183
+ )
184
+
185
+ cdef Py_ssize_t ct_len = len(cipher_text)
186
+
187
+ # Allocate C-level buffers
188
+ cdef unsigned char *in_buf = <unsigned char *>malloc(ct_len)
189
+ cdef unsigned char *out_buf = <unsigned char *>malloc(ct_len)
190
+ cdef unsigned char *aes_key = <unsigned char *>malloc(_AES_KEY_SIZE)
191
+
192
+ if in_buf == NULL or out_buf == NULL or aes_key == NULL:
193
+ free(in_buf)
194
+ free(out_buf)
195
+ free(aes_key)
196
+ raise MemoryError("Failed to allocate buffers for AES-IGE")
197
+
198
+ cdef int rc = 0
199
+ cdef const unsigned char[:] ct_view = cipher_text
200
+ cdef const unsigned char[:] iv_view = iv
201
+
202
+ try:
203
+ # Copy ciphertext into C buffer
204
+ memcpy(in_buf, &ct_view[0], <size_t>ct_len)
205
+
206
+ # Set up AES decrypt key schedule
207
+ rc = _AES_set_decrypt_key(key, <int>(len(key) * 8), <size_t>aes_key)
208
+ if rc != 0:
209
+ raise RuntimeError(f"AES_set_decrypt_key failed (rc={rc})")
210
+
211
+ # Perform IGE decryption
212
+ _AES_ige_encrypt(
213
+ <size_t>in_buf,
214
+ <size_t>out_buf,
215
+ <size_t>ct_len,
216
+ <size_t>aes_key,
217
+ <size_t>&iv_view[0],
218
+ <int>0, # AES_DECRYPT
219
+ )
220
+
221
+ # Build Python bytes from C buffer
222
+ return bytes(out_buf[:ct_len])
223
+ finally:
224
+ free(in_buf)
225
+ free(out_buf)
226
+ free(aes_key)