maxapi-python 2.0.1__tar.gz → 2.1.1__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 (222) hide show
  1. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/.github/workflows/publish.yml +31 -1
  2. maxapi_python-2.1.1/.pre-commit-config.yaml +14 -0
  3. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/PKG-INFO +4 -1
  4. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/README.md +3 -0
  5. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/account.rst +15 -10
  6. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/index.rst +7 -0
  7. maxapi_python-2.1.1/docs/release-2-1-0.rst +43 -0
  8. maxapi_python-2.1.1/docs/release-2-1-1.rst +16 -0
  9. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/pyproject.toml +17 -15
  10. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/__init__.py +1 -1
  11. maxapi_python-2.1.1/src/pymax/api/auth/enums.py +28 -0
  12. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/auth/payloads.py +10 -6
  13. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/auth/service.py +75 -12
  14. maxapi_python-2.1.1/src/pymax/api/bots/__init__.py +1 -0
  15. maxapi_python-2.1.1/src/pymax/api/bots/payloads.py +7 -0
  16. maxapi_python-2.1.1/src/pymax/api/bots/service.py +35 -0
  17. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/chats/enums.py +1 -0
  18. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/chats/payloads.py +14 -0
  19. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/chats/service.py +112 -12
  20. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/facade.py +2 -0
  21. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/messages/payloads.py +5 -1
  22. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/messages/service.py +36 -11
  23. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/self/service.py +29 -10
  24. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/session/payloads.py +9 -2
  25. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/uploads/models.py +1 -4
  26. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/uploads/payloads.py +9 -3
  27. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/uploads/service.py +107 -37
  28. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/users/service.py +15 -5
  29. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/app.py +19 -5
  30. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/qr.py +11 -6
  31. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/sms.py +13 -4
  32. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/base.py +1 -0
  33. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/client.py +4 -1
  34. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/client_web.py +4 -2
  35. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/config.py +11 -3
  36. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/connection.py +15 -5
  37. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/readers/tcp.py +4 -2
  38. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/dispatch/dispatcher.py +28 -10
  39. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/dispatch/mapping.py +9 -2
  40. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/dispatch/router.py +2 -0
  41. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/files/base.py +6 -1
  42. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/formatting/markdown.py +4 -1
  43. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/auth.py +42 -0
  44. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/base.py +2 -0
  45. maxapi_python-2.1.1/src/pymax/infra/bots.py +33 -0
  46. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/chat.py +102 -1
  47. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/self.py +2 -6
  48. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/tcp/compression.py +3 -1
  49. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/tcp/framing.py +6 -11
  50. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/tcp/payload.py +3 -2
  51. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/tcp/protocol.py +13 -3
  52. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/ws/protocol.py +9 -3
  53. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/session/protocol.py +6 -2
  54. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/session/store.py +24 -8
  55. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/telemetry/navigation.py +3 -1
  56. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/telemetry/service.py +9 -3
  57. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/transport/tcp.py +14 -6
  58. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/transport/websocket.py +0 -2
  59. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/__init__.py +3 -0
  60. maxapi_python-2.1.1/src/pymax/types/domain/bots.py +14 -0
  61. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/error.py +3 -3
  62. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/folder.py +1 -1
  63. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/login.py +18 -6
  64. maxapi_python-2.1.1/src/pymax/types/domain/member.py +16 -0
  65. maxapi_python-2.1.1/src/pymax/types/domain/presence.py +15 -0
  66. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/sync.py +21 -5
  67. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/user.py +12 -0
  68. maxapi_python-2.1.1/tests/__init__.py +1 -0
  69. maxapi_python-2.1.1/tests/api/test_auth_service.py +246 -0
  70. maxapi_python-2.1.1/tests/api/test_chat_user_self_session_services.py +397 -0
  71. maxapi_python-2.1.1/tests/api/test_message_service.py +209 -0
  72. maxapi_python-2.1.1/tests/api/test_upload_service.py +188 -0
  73. maxapi_python-2.1.1/tests/app/test_app_runtime.py +152 -0
  74. maxapi_python-2.1.1/tests/auth/test_auth_flows.py +161 -0
  75. maxapi_python-2.1.1/tests/conftest.py +255 -0
  76. maxapi_python-2.1.1/tests/connection/test_connection.py +165 -0
  77. maxapi_python-2.1.1/tests/connection/test_readers_and_transports.py +193 -0
  78. maxapi_python-2.1.1/tests/dispatch/test_dispatcher.py +102 -0
  79. maxapi_python-2.1.1/tests/domain/test_bound_models.py +173 -0
  80. maxapi_python-2.1.1/tests/files/test_files_and_formatting.py +63 -0
  81. maxapi_python-2.1.1/tests/protocol/test_protocols.py +139 -0
  82. maxapi_python-2.1.1/tests/session/test_store.py +48 -0
  83. maxapi_python-2.1.1/tests/telemetry/test_telemetry.py +146 -0
  84. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/uv.lock +170 -165
  85. maxapi_python-2.0.1/src/pymax/api/auth/enums.py +0 -17
  86. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  87. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  88. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
  89. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/.github/pull_request_template.md +0 -0
  90. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/.gitignore +0 -0
  91. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/LICENSE +0 -0
  92. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/_static/.gitkeep +0 -0
  93. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/api/auth.rst +0 -0
  94. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/api/client.rst +0 -0
  95. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/api/files.rst +0 -0
  96. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/api/router.rst +0 -0
  97. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/auth.rst +0 -0
  98. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/chats.rst +0 -0
  99. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/client.rst +0 -0
  100. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/conf.py +0 -0
  101. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/examples.rst +0 -0
  102. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/faq.rst +0 -0
  103. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/files.rst +0 -0
  104. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/formatting.rst +0 -0
  105. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/getting-started.rst +0 -0
  106. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/messages.rst +0 -0
  107. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/router.rst +0 -0
  108. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/troubleshooting.rst +0 -0
  109. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/audio_attachment.rst +0 -0
  110. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/call_attachment.rst +0 -0
  111. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/chat.rst +0 -0
  112. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/contact_attachment.rst +0 -0
  113. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/control_attachment.rst +0 -0
  114. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/element.rst +0 -0
  115. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/enums.rst +0 -0
  116. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/file_attachment.rst +0 -0
  117. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/folder.rst +0 -0
  118. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/folder_list.rst +0 -0
  119. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/folder_update.rst +0 -0
  120. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/index.rst +0 -0
  121. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/inline_keyboard_attachment.rst +0 -0
  122. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/message.rst +0 -0
  123. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/message_delete_event.rst +0 -0
  124. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/name.rst +0 -0
  125. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/photo_attachment.rst +0 -0
  126. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/profile.rst +0 -0
  127. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/reaction_counter.rst +0 -0
  128. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/reaction_info.rst +0 -0
  129. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/read_state.rst +0 -0
  130. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/session.rst +0 -0
  131. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/share_attachment.rst +0 -0
  132. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/sticker_attachment.rst +0 -0
  133. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/sync_overrides.rst +0 -0
  134. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/sync_state.rst +0 -0
  135. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/user.rst +0 -0
  136. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/types/video_attachment.rst +0 -0
  137. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/docs/users.rst +0 -0
  138. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/__init__.py +0 -0
  139. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/auth/__init__.py +0 -0
  140. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/auth/types.py +0 -0
  141. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/chats/__init__.py +0 -0
  142. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/messages/__init__.py +0 -0
  143. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/messages/enums.py +0 -0
  144. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/models.py +0 -0
  145. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/response.py +0 -0
  146. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/self/__init__.py +0 -0
  147. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/self/enums.py +0 -0
  148. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/self/payloads.py +0 -0
  149. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/session/__init__.py +0 -0
  150. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/session/enums.py +0 -0
  151. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/session/service.py +0 -0
  152. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/uploads/__init__.py +0 -0
  153. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/users/__init__.py +0 -0
  154. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/users/enums.py +0 -0
  155. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/api/users/payloads.py +0 -0
  156. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/__init__.py +0 -0
  157. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/base.py +0 -0
  158. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/email.py +0 -0
  159. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/models.py +0 -0
  160. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/providers.py +0 -0
  161. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/auth/service.py +0 -0
  162. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/__init__.py +0 -0
  163. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/pending.py +0 -0
  164. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/readers/__init__.py +0 -0
  165. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/readers/base.py +0 -0
  166. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/connection/readers/ws.py +0 -0
  167. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/dispatch/__init__.py +0 -0
  168. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/dispatch/enums.py +0 -0
  169. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/dispatch/resolvers.py +0 -0
  170. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/exceptions.py +0 -0
  171. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/files/__init__.py +0 -0
  172. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/files/file.py +0 -0
  173. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/files/photo.py +0 -0
  174. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/files/static.py +0 -0
  175. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/files/video.py +0 -0
  176. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/formatting/__init__.py +0 -0
  177. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/__init__.py +0 -0
  178. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/message.py +0 -0
  179. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/protocol.py +0 -0
  180. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/infra/user.py +0 -0
  181. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/logging.py +0 -0
  182. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/__init__.py +0 -0
  183. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/base.py +0 -0
  184. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/enums.py +0 -0
  185. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/models.py +0 -0
  186. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/tcp/__init__.py +0 -0
  187. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/protocol/ws/__init__.py +0 -0
  188. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/py.typed +0 -0
  189. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/routers.py +0 -0
  190. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/session/__init__.py +0 -0
  191. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/session/models.py +0 -0
  192. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/telemetry/__init__.py +0 -0
  193. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/telemetry/payloads.py +0 -0
  194. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/transport/__init__.py +0 -0
  195. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/transport/base.py +0 -0
  196. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/__init__.py +0 -0
  197. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/__init__.py +0 -0
  198. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/audio.py +0 -0
  199. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/call.py +0 -0
  200. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/contact.py +0 -0
  201. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/control.py +0 -0
  202. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/enums.py +0 -0
  203. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/file.py +0 -0
  204. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/keyboards/__init__.py +0 -0
  205. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/keyboards/inline.py +0 -0
  206. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/photo.py +0 -0
  207. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/share.py +0 -0
  208. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/sticker.py +0 -0
  209. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/attachments/video.py +0 -0
  210. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/auth.py +0 -0
  211. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/base.py +0 -0
  212. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/chat.py +0 -0
  213. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/element.py +0 -0
  214. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/enums.py +0 -0
  215. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/message.py +0 -0
  216. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/name.py +0 -0
  217. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/profile.py +0 -0
  218. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/domain/session.py +0 -0
  219. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/events/__init__.py +0 -0
  220. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/events/file.py +0 -0
  221. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/events/message.py +0 -0
  222. {maxapi_python-2.0.1 → maxapi_python-2.1.1}/src/pymax/types/events/video.py +0 -0
@@ -9,22 +9,52 @@ permissions:
9
9
  contents: read
10
10
 
11
11
  jobs:
12
+ release-checks:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ with:
18
+ persist-credentials: false
19
+
20
+ - name: Set up uv
21
+ uses: astral-sh/setup-uv@v4
22
+ with:
23
+ python-version: "3.10"
24
+ enable-cache: true
25
+
26
+ - name: Check lint
27
+ run: uv run ruff check src tests
28
+
29
+ - name: Check formatting
30
+ run: uv run ruff format --check src tests
31
+
32
+ - name: Run tests
33
+ run: uv run pytest
34
+
35
+ - name: Build docs
36
+ run: uv run sphinx-build -b html docs /tmp/pymax-docs
37
+
12
38
  release-build:
13
39
  runs-on: ubuntu-latest
40
+ needs: release-checks
14
41
 
15
42
  steps:
16
43
  - uses: actions/checkout@v4
44
+ with:
45
+ persist-credentials: false
17
46
 
18
47
  - name: Set up uv
19
48
  uses: astral-sh/setup-uv@v4
20
49
  with:
21
50
  python-version: "3.10"
51
+ enable-cache: true
22
52
 
23
53
  - name: Build release distributions
24
54
  run: uv build
25
55
 
26
56
  - name: Check distributions
27
- run: uvx twine check dist/*
57
+ run: uv run twine check dist/*
28
58
 
29
59
  - name: Upload distributions
30
60
  uses: actions/upload-artifact@v4
@@ -0,0 +1,14 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: ruff-check
5
+ name: ruff check
6
+ entry: uv run ruff check --fix
7
+ language: system
8
+ types_or: [python, pyi]
9
+
10
+ - id: ruff-format
11
+ name: ruff format
12
+ entry: uv run ruff format
13
+ language: system
14
+ types_or: [python, pyi]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxapi-python
3
- Version: 2.0.1
3
+ Version: 2.1.1
4
4
  Summary: Python wrapper для API мессенджера Max
5
5
  Project-URL: Homepage, https://github.com/MaxApiTeam/PyMax
6
6
  Project-URL: Repository, https://github.com/MaxApiTeam/PyMax
@@ -196,6 +196,9 @@ client.include_router(router)
196
196
 
197
197
  ```bash
198
198
  uv sync --all-groups
199
+ uv run pre-commit install
200
+ uv run pre-commit run --all-files
201
+ uv run pytest
199
202
  uv run python -c "import pymax; print(pymax.__all__)"
200
203
  uv run sphinx-build -b html docs docs/_build/html
201
204
  ```
@@ -153,6 +153,9 @@ client.include_router(router)
153
153
 
154
154
  ```bash
155
155
  uv sync --all-groups
156
+ uv run pre-commit install
157
+ uv run pre-commit run --all-files
158
+ uv run pytest
156
159
  uv run python -c "import pymax; print(pymax.__all__)"
157
160
  uv run sphinx-build -b html docs docs/_build/html
158
161
  ```
@@ -32,21 +32,26 @@ Account
32
32
  Фотография профиля
33
33
  ------------------
34
34
 
35
- Сейчас ``change_profile(photo=...)`` не загружает файл напрямую. Для фото
36
- нужен ``photo_token`` от API Max:
35
+ Передайте ``Photo`` в ``change_profile(photo=...)``, чтобы PyMax сам загрузил
36
+ файл и применил новый токен фотографии:
37
37
 
38
38
  .. code-block:: python
39
39
 
40
- upload_url = await client.request_profile_photo_upload_url()
41
- print(upload_url)
40
+ from pymax import Photo
42
41
 
43
42
  await client.change_profile(
44
43
  first_name="Alex",
45
- photo_token="PHOTO_TOKEN",
44
+ photo=Photo(path="avatar.jpg"),
46
45
  )
47
46
 
48
- Если передать ``photo`` вместо ``photo_token``, PyMax выбросит
49
- ``NotImplementedError``.
47
+ Если у вас уже есть токен фотографии от API Max, его можно передать напрямую:
48
+
49
+ .. code-block:: python
50
+
51
+ await client.change_profile(
52
+ first_name="Alex",
53
+ photo_token="PHOTO_TOKEN",
54
+ )
50
55
 
51
56
  Папки чатов
52
57
  -----------
@@ -118,9 +123,9 @@ Account
118
123
  ``on_start`` или после успешного ``await client.start()`` в собственном
119
124
  lifecycle.
120
125
 
121
- ``NotImplementedError`` при ``change_profile(photo=...)``
122
- Прямая загрузка фото через параметр ``photo`` пока не реализована.
123
- Используйте ``photo_token``.
126
+ Фото профиля не обновилось
127
+ Если переданы и ``photo``, и ``photo_token``, PyMax загрузит ``photo`` и
128
+ использует новый токен загруженной фотографии.
124
129
 
125
130
  Папка создалась, но список старый
126
131
  Используйте ``get_folders()`` после изменения и сохраняйте новый
@@ -18,6 +18,13 @@ PyMax - асинхронная Python-библиотека для Max API. Он
18
18
  минимальный рабочий пример с авторизацией, обработчиком сообщений и запуском
19
19
  клиента.
20
20
 
21
+ .. toctree::
22
+ :maxdepth: 1
23
+ :caption: Новости
24
+
25
+ release-2-1-1
26
+ release-2-1-0
27
+
21
28
  .. toctree::
22
29
  :maxdepth: 2
23
30
  :caption: Руководство
@@ -0,0 +1,43 @@
1
+ PyMax 2.1.0
2
+ ===========
3
+
4
+ Изменения относительно ``2.0.1``.
5
+
6
+ Добавлено
7
+ ---------
8
+
9
+ * Заявки на вступление в группы и каналы: ``get_join_requests()``,
10
+ ``confirm_join_request()`` /
11
+ ``confirm_join_requests()`` и отклонить их через ``decline_join_request()`` /
12
+ ``decline_join_requests()``.
13
+ * Доменные типы ``Member`` и ``Presence`` для заявок.
14
+ * 2FA: ``check_2fa()`` и ``change_password()``.
15
+ * QR-вход: ``authorize_qr_login(qr_link)``.
16
+ * Web app-боты: ``get_bot_init_data(bot_id, chat_id, start_param=None)``.
17
+
18
+ Исправлено
19
+ ----------
20
+
21
+ * TCP-заголовок приведен к схеме Max: ``ver:1``, ``cmd:1``, ``seq:2``,
22
+ ``opcode:2``, ``len/cof:4``. ``seq`` больше не падает после ``255``.
23
+ * Upload фото, видео и файлов использует ``ExtraConfig.proxy`` для HTTP-отправки
24
+ на upload URL.
25
+ * ``MaxApiError.title`` и ``MaxApiError.localized_message`` могут быть ``None``.
26
+
27
+ Изменилось
28
+ ----------
29
+
30
+ * ``check_2fa()`` возвращает ``False``, если профиль еще не загружен или сервер
31
+ не прислал ``profile_options``.
32
+ * При заданном ``ExtraConfig.proxy`` upload-запросы тоже идут через proxy.
33
+ Proxy должен выдерживать большие HTTP POST-запросы.
34
+ * ``Capability`` разделен на ``ProfileOptions`` и ``TwoFactorAction``.
35
+ * ``ApiFacade`` получил ``bots``-сервис.
36
+
37
+ Миграция
38
+ --------
39
+
40
+ * Код на ``Client`` и ``WebClient`` обычно менять не нужно.
41
+ * Импорт ``pymax.api.auth.enums.Capability`` замените на ``TwoFactorAction`` или
42
+ ``ProfileOptions``.
43
+ * Если код ждал строку в ``MaxApiError.title``, теперь нужно учитывать ``None``.
@@ -0,0 +1,16 @@
1
+ PyMax 2.1.1
2
+ ===========
3
+
4
+ Изменения относительно ``2.1.0``.
5
+
6
+ Добавлено
7
+ ---------
8
+
9
+ * ``change_profile(photo=...)`` теперь загружает фотографию профиля напрямую.
10
+
11
+ Исправлено
12
+ ----------
13
+
14
+ * TLS-handshake при TCP-подключении через proxy передает ``server_hostname``.
15
+ * Локальный токен обновляется после ``close_all_sessions()`` и при получении
16
+ нового токена во время handshake.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "maxapi-python"
3
- version = "2.0.1"
3
+ version = "2.1.1"
4
4
  description = "Python wrapper для API мессенджера Max"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -89,24 +89,32 @@ dev = [
89
89
  {include-group = "docs"},
90
90
  {include-group = "test"},
91
91
  "build>=1.2.0",
92
+ "pre-commit>=4.0.0",
92
93
  "twine>=5.0.0",
93
94
  "pyright>=1.1.390",
94
- "black>=24.0.0",
95
- "isort>=5.13.0",
96
- "flake8>=7.0.0",
95
+ "ruff>=0.8.0",
97
96
  ]
98
97
 
99
98
  [tool.pyright]
100
99
  venv = ".venv"
101
100
  venvPath = "."
102
101
 
103
- [tool.black]
102
+ [tool.ruff]
104
103
  line-length = 79
105
- target-version = ["py310"]
104
+ target-version = "py310"
106
105
 
107
- [tool.flake8]
108
- max-line-length = 79
109
- max-complexity = 10
106
+ [tool.ruff.lint]
107
+ select = ["E", "F", "I"]
108
+ ignore = ["E501"]
109
+
110
+ [tool.ruff.lint.per-file-ignores]
111
+ "src/pymax/**/__init__.py" = ["F401", "F403"]
112
+ "tests/**" = ["F401"]
113
+
114
+ [tool.ruff.format]
115
+ quote-style = "double"
116
+ indent-style = "space"
117
+ line-ending = "auto"
110
118
 
111
119
  [tool.mypy]
112
120
  python_version = "3.10"
@@ -114,12 +122,6 @@ warn_return_any = true
114
122
  warn_unused_configs = true
115
123
  plugins = ["pydantic.mypy"]
116
124
 
117
- [tool.isort]
118
- profile = "black"
119
- line_length = 79
120
- multi_line_output = 3
121
- include_trailing_comma = true
122
-
123
125
  [tool.pytest.ini_options]
124
126
  asyncio_mode = "auto"
125
127
  testpaths = ["tests"]
@@ -1,4 +1,4 @@
1
- __version__ = "2.0.1"
1
+ __version__ = "2.1.1"
2
2
 
3
3
 
4
4
  from .auth import (
@@ -0,0 +1,28 @@
1
+ from enum import Enum
2
+
3
+
4
+ class AuthType(str, Enum):
5
+ START_AUTH = "START_AUTH"
6
+ CHECK_CODE = "CHECK_CODE"
7
+ REGISTER = "REGISTER"
8
+ RESEND = "RESEND"
9
+
10
+
11
+ class ProfileOptions(int, Enum):
12
+ """Битовые/числовые признаки профиля, связанные с 2FA."""
13
+
14
+ ESIA_VERIFIED_FLAG = 1
15
+ SECOND_FACTOR_PASSWORD_ENABLED = 2
16
+ SECOND_FACTOR_HAS_EMAIL = 3
17
+ SECOND_FACTOR_HAS_HINT = 4
18
+
19
+
20
+ class TwoFactorAction(int, Enum):
21
+ """Действия 2FA, передаваемые в expectedCapabilities."""
22
+
23
+ SET_PASSWORD = 0
24
+ UPDATE_PASSWORD = 1
25
+ RESTORE_PASSWORD = 2
26
+ HINT = 3
27
+ EMAIL = 4
28
+ REMOVE_2FA = 5
@@ -1,10 +1,10 @@
1
- from pydantic import Field, field_serializer
1
+ from pydantic import Field
2
2
 
3
3
  from pymax.api.models import CamelModel
4
4
  from pymax.api.session.payloads import MobileUserAgentPayload
5
5
  from pymax.types.domain.sync import DEFAULT_CONFIG_HASH, ConfigHash, SyncState
6
6
 
7
- from .enums import AuthType, Capability
7
+ from .enums import AuthType, TwoFactorAction
8
8
 
9
9
 
10
10
  class RequestCodePayload(CamelModel):
@@ -115,7 +115,7 @@ class SetHintPayload(CamelModel):
115
115
 
116
116
 
117
117
  class SetTwoFactorPayload(CamelModel):
118
- expected_capabilities: list[Capability]
118
+ expected_capabilities: list[TwoFactorAction]
119
119
  track_id: str
120
120
  password: str
121
121
  hint: str | None = None
@@ -123,7 +123,11 @@ class SetTwoFactorPayload(CamelModel):
123
123
 
124
124
  class RemoveTwoFactorPayload(CamelModel):
125
125
  track_id: str
126
- remove2fa: bool = True
127
- expected_capabilities: list[Capability] = Field(
128
- default_factory=lambda: [Capability.REMOVE_2FA]
126
+ remove2fa: bool = Field(default=True, alias="remove2fa")
127
+ expected_capabilities: list[TwoFactorAction] = Field(
128
+ default_factory=lambda: [TwoFactorAction.REMOVE_2FA]
129
129
  )
130
+
131
+
132
+ class ApproveQrLoginPayload(CamelModel):
133
+ qr_link: str
@@ -2,7 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
- from pymax.api.response import payload_item, payload_keys, require_payload_model
5
+ from pymax.api.response import (
6
+ payload_item,
7
+ payload_keys,
8
+ require_payload_model,
9
+ )
6
10
  from pymax.api.session.enums import DeviceType
7
11
  from pymax.auth import EmailCodeProvider
8
12
  from pymax.auth.providers import ConsoleEmailCodeProvider
@@ -17,8 +21,9 @@ from pymax.types.domain.auth import (
17
21
  )
18
22
  from pymax.types.domain.login import LoginResponse
19
23
 
20
- from .enums import Capability
24
+ from .enums import ProfileOptions, TwoFactorAction
21
25
  from .payloads import (
26
+ ApproveQrLoginPayload,
22
27
  CheckPasswordChallengePayload,
23
28
  CheckQrPayload,
24
29
  ConfirmQrPayload,
@@ -51,14 +56,18 @@ class AuthService:
51
56
  async def request_code(self, phone: str) -> StartAuthResponse:
52
57
  logger.info("requesting sms code phone_set=%s", bool(phone))
53
58
  frame = RequestCodePayload(phone=phone)
54
- response = await self.app.invoke(Opcode.AUTH_REQUEST, frame.to_payload())
59
+ response = await self.app.invoke(
60
+ Opcode.AUTH_REQUEST, frame.to_payload()
61
+ )
55
62
  logger.debug(
56
63
  "sms code request accepted payload_keys=%s",
57
64
  payload_keys(response),
58
65
  )
59
66
  return require_payload_model(response, StartAuthResponse)
60
67
 
61
- async def send_code(self, token: str, verify_code: str) -> CheckCodeResponse:
68
+ async def send_code(
69
+ self, token: str, verify_code: str
70
+ ) -> CheckCodeResponse:
62
71
  logger.info(
63
72
  "sending sms code token_set=%s code_set=%s",
64
73
  bool(token),
@@ -152,14 +161,18 @@ class AuthService:
152
161
  async def check_qr(self, track_id: str) -> CheckQrResponse:
153
162
  frame = CheckQrPayload(track_id=track_id)
154
163
 
155
- response = await self.app.invoke(Opcode.GET_QR_STATUS, frame.to_payload())
164
+ response = await self.app.invoke(
165
+ Opcode.GET_QR_STATUS, frame.to_payload()
166
+ )
156
167
 
157
168
  return require_payload_model(response, CheckQrResponse)
158
169
 
159
170
  async def confirm_qr(self, track_id: str) -> CheckCodeResponse:
160
171
  frame = ConfirmQrPayload(track_id=track_id)
161
172
 
162
- response = await self.app.invoke(Opcode.LOGIN_BY_QR, frame.to_payload())
173
+ response = await self.app.invoke(
174
+ Opcode.LOGIN_BY_QR, frame.to_payload()
175
+ )
163
176
 
164
177
  return require_payload_model(response, CheckCodeResponse)
165
178
 
@@ -182,11 +195,15 @@ class AuthService:
182
195
  logger.debug("creating auth track")
183
196
  frame = CreateAuthTrackPayload()
184
197
 
185
- response = await self.app.invoke(Opcode.AUTH_CREATE_TRACK, frame.to_payload())
198
+ response = await self.app.invoke(
199
+ Opcode.AUTH_CREATE_TRACK, frame.to_payload()
200
+ )
186
201
 
187
202
  return payload_item(response, "trackId", str)
188
203
 
189
- async def _set_email(self, track_id: str, email: str, provider: EmailCodeProvider) -> bool:
204
+ async def _set_email(
205
+ self, track_id: str, email: str, provider: EmailCodeProvider
206
+ ) -> bool:
190
207
  logger.info("setting 2fa email email_set=%s", bool(email))
191
208
 
192
209
  frame = RequestEmailCodePayload(
@@ -225,7 +242,9 @@ class AuthService:
225
242
  track_id=track_id,
226
243
  password=password,
227
244
  )
228
- await self.app.invoke(Opcode.AUTH_VALIDATE_PASSWORD, frame.to_payload())
245
+ await self.app.invoke(
246
+ Opcode.AUTH_VALIDATE_PASSWORD, frame.to_payload()
247
+ )
229
248
 
230
249
  return True
231
250
 
@@ -263,13 +282,13 @@ class AuthService:
263
282
  await self._set_hint(track_id, str(hint))
264
283
  has_hint = True
265
284
 
266
- expected_capabilities = [Capability.DEFAULT]
285
+ expected_capabilities = [TwoFactorAction.SET_PASSWORD]
267
286
 
268
287
  if has_hint:
269
- expected_capabilities.append(Capability.SECOND_FACTOR_HAS_HINT)
288
+ expected_capabilities.append(TwoFactorAction.HINT)
270
289
 
271
290
  if has_email:
272
- expected_capabilities.append(Capability.SECOND_FACTOR_HAS_EMAIL)
291
+ expected_capabilities.append(TwoFactorAction.EMAIL)
273
292
 
274
293
  frame = SetTwoFactorPayload(
275
294
  track_id=track_id,
@@ -311,3 +330,47 @@ class AuthService:
311
330
  await self.app.invoke(Opcode.AUTH_SET_2FA, frame.to_payload())
312
331
 
313
332
  return True
333
+
334
+ async def authorize_qr_login(self, qr_link: str) -> bool:
335
+ logger.info("approving qr login qr_link_set=%s", bool(qr_link))
336
+
337
+ frame = ApproveQrLoginPayload(qr_link=qr_link)
338
+
339
+ await self.app.invoke(Opcode.AUTH_QR_APPROVE, frame.to_payload())
340
+
341
+ return True
342
+
343
+ async def check_2fa(self) -> bool:
344
+ if not self.app.me or not self.app.me.profile_options:
345
+ return False
346
+
347
+ return (
348
+ ProfileOptions.SECOND_FACTOR_PASSWORD_ENABLED
349
+ in self.app.me.profile_options
350
+ )
351
+
352
+ async def change_password(
353
+ self, password_old: str, password_new: str
354
+ ) -> bool:
355
+ track_id = await self._get_track_id()
356
+
357
+ if not track_id:
358
+ logger.error("missing track_id in auth create track response")
359
+ raise RuntimeError("Failed to create auth track")
360
+
361
+ await self._check_2fa_password(track_id, password_old)
362
+
363
+ await self._set_password(track_id, password_new)
364
+
365
+ expected_capabilities = [TwoFactorAction.UPDATE_PASSWORD]
366
+
367
+ frame = SetTwoFactorPayload(
368
+ track_id=track_id,
369
+ password=password_new,
370
+ hint=None,
371
+ expected_capabilities=expected_capabilities,
372
+ )
373
+
374
+ await self.app.invoke(Opcode.AUTH_SET_2FA, frame.to_payload())
375
+ logger.info("2fa password set successfully")
376
+ return True
@@ -0,0 +1 @@
1
+ from .service import BotsService
@@ -0,0 +1,7 @@
1
+ from pymax.api.models import CamelModel
2
+
3
+
4
+ class RequestInitDataPayload(CamelModel):
5
+ bot_id: int
6
+ chat_id: int
7
+ start_param: str | None = None
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from pymax.api.response import require_payload_model
6
+ from pymax.logging import get_logger
7
+ from pymax.protocol import Opcode
8
+ from pymax.types.domain import InitData
9
+
10
+ from .payloads import RequestInitDataPayload
11
+
12
+ if TYPE_CHECKING:
13
+ from pymax.app import App
14
+
15
+
16
+ logger = get_logger(__name__)
17
+
18
+
19
+ class BotsService:
20
+ def __init__(self, app: App) -> None:
21
+ self.app = app
22
+
23
+ async def get_init_data(
24
+ self,
25
+ bot_id: int,
26
+ chat_id: int,
27
+ start_param: str | None = None,
28
+ ) -> InitData:
29
+ frame = RequestInitDataPayload(
30
+ bot_id=bot_id, chat_id=chat_id, start_param=start_param
31
+ )
32
+ response = await self.app.invoke(
33
+ Opcode.WEB_APP_INIT_DATA, frame.to_payload()
34
+ )
35
+ return require_payload_model(response, InitData)
@@ -21,6 +21,7 @@ class ChatOption(str, Enum):
21
21
  class ChatPayloadKey(str, Enum):
22
22
  CHAT = "chat"
23
23
  CHATS = "chats"
24
+ MEMBERS = "members"
24
25
 
25
26
 
26
27
  class ChatLinkPrefix(str, Enum):
@@ -101,3 +101,17 @@ class LeaveChatPayload(CamelModel):
101
101
 
102
102
  class FetchChatsPayload(CamelModel):
103
103
  marker: int
104
+
105
+
106
+ class FetchJoinRequests(CamelModel):
107
+ chat_id: int
108
+ type: str = "JOIN_REQUEST" # ENUM!!!!!
109
+ count: int = 100
110
+
111
+
112
+ class JoinRequestActionPayload(CamelModel):
113
+ chat_id: int
114
+ user_ids: list[int]
115
+ type: str = "JOIN_REQUEST" # TODO: ENUMM!!!
116
+ show_history: bool | None = True
117
+ operation: ChatMemberOperation