maxapi-python 2.3.1__tar.gz → 2.4.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 (276) hide show
  1. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/PKG-INFO +8 -4
  2. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/README.md +4 -2
  3. maxapi_python-2.4.1/TODO.md +44 -0
  4. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/account.rst +12 -3
  5. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/auth.rst +2 -0
  6. maxapi_python-2.4.1/docs/api/client-session.rst +20 -0
  7. maxapi_python-2.4.1/docs/api/client-versions.rst +12 -0
  8. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client.rst +2 -0
  9. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/files.rst +8 -0
  10. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/auth.rst +24 -0
  11. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/chats.rst +42 -0
  12. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/client.rst +133 -8
  13. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/faq.rst +5 -3
  14. maxapi_python-2.4.1/docs/files.rst +185 -0
  15. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/index.rst +2 -0
  16. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/messages.rst +123 -8
  17. maxapi_python-2.4.1/docs/release-2-4-0.rst +210 -0
  18. maxapi_python-2.4.1/docs/release-2-4-1.rst +103 -0
  19. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/troubleshooting.rst +4 -3
  20. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/enums.rst +18 -0
  21. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/index.rst +7 -4
  22. maxapi_python-2.4.1/docs/types/poll.rst +22 -0
  23. maxapi_python-2.4.1/docs/types/poll_attachment.rst +6 -0
  24. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/pyproject.toml +7 -2
  25. maxapi_python-2.4.1/scripts/todo.py +48 -0
  26. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/__init__.py +9 -2
  27. maxapi_python-2.4.1/src/pymax/_data/apk_fingerprints.json +767 -0
  28. maxapi_python-2.4.1/src/pymax/_data/rootca_ssl_rsa2022.crt +33 -0
  29. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/enums.py +1 -0
  30. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/payloads.py +28 -2
  31. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/service.py +100 -3
  32. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/__init__.py +1 -0
  33. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/enums.py +15 -0
  34. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/payloads.py +18 -2
  35. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/service.py +43 -1
  36. maxapi_python-2.4.1/src/pymax/api/messages/__init__.py +1 -0
  37. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/messages/payloads.py +21 -7
  38. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/messages/service.py +161 -24
  39. maxapi_python-2.4.1/src/pymax/api/self/__init__.py +3 -0
  40. maxapi_python-2.4.1/src/pymax/api/self/enums.py +20 -0
  41. maxapi_python-2.4.1/src/pymax/api/self/payloads.py +80 -0
  42. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/self/service.py +37 -0
  43. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/service.py +21 -8
  44. maxapi_python-2.4.1/src/pymax/api/uploads/payloads.py +63 -0
  45. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/uploads/service.py +247 -55
  46. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/app.py +91 -18
  47. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/__init__.py +2 -0
  48. maxapi_python-2.4.1/src/pymax/auth/exceptions.py +9 -0
  49. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/providers.py +6 -2
  50. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/sms.py +11 -1
  51. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/base.py +90 -8
  52. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/client.py +39 -10
  53. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/client_web.py +17 -14
  54. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/config.py +98 -19
  55. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/connection.py +29 -18
  56. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/enums.py +1 -0
  57. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/mapping.py +3 -1
  58. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/resolvers.py +7 -1
  59. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/__init__.py +4 -1
  60. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/base.py +58 -1
  61. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/video.py +51 -1
  62. maxapi_python-2.4.1/src/pymax/files/voice.py +53 -0
  63. maxapi_python-2.4.1/src/pymax/fingerprint/__init__.py +1 -0
  64. maxapi_python-2.4.1/src/pymax/fingerprint/fingerprint.py +30 -0
  65. maxapi_python-2.4.1/src/pymax/fingerprint/models.py +12 -0
  66. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/auth.py +4 -0
  67. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/bots.py +3 -3
  68. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/chat.py +47 -5
  69. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/message.py +49 -14
  70. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/protocol.py +5 -1
  71. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/self.py +25 -1
  72. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/enums.py +13 -0
  73. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/payload.py +21 -1
  74. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/session/__init__.py +1 -1
  75. maxapi_python-2.4.1/src/pymax/session/models.py +41 -0
  76. maxapi_python-2.4.1/src/pymax/session/protocol.py +40 -0
  77. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/session/store.py +73 -5
  78. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/tcp.py +17 -4
  79. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/websocket.py +6 -3
  80. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/__init__.py +2 -1
  81. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/__init__.py +2 -1
  82. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/call.py +7 -1
  83. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/contact.py +3 -3
  84. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/control.py +3 -0
  85. maxapi_python-2.4.1/src/pymax/types/domain/attachments/enums.py +60 -0
  86. maxapi_python-2.4.1/src/pymax/types/domain/attachments/poll.py +111 -0
  87. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/sticker.py +1 -1
  88. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/video.py +32 -11
  89. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/chat.py +9 -9
  90. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/enums.py +7 -0
  91. maxapi_python-2.4.1/src/pymax/types/domain/handshake.py +16 -0
  92. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/login.py +30 -1
  93. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/message.py +108 -27
  94. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/user.py +1 -3
  95. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/__init__.py +1 -0
  96. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/reaction.py +2 -2
  97. maxapi_python-2.4.1/src/pymax/types/events/voice.py +5 -0
  98. maxapi_python-2.4.1/src/pymax/versions/__init__.py +2 -0
  99. maxapi_python-2.4.1/src/pymax/versions/catalog.py +104 -0
  100. maxapi_python-2.4.1/src/pymax/versions/exceptions.py +10 -0
  101. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_auth_service.py +164 -2
  102. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_chat_user_self_session_services.py +52 -6
  103. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_message_service.py +70 -9
  104. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_upload_service.py +66 -4
  105. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/app/test_app_runtime.py +328 -6
  106. maxapi_python-2.4.1/tests/app/test_client_user_agent_config.py +37 -0
  107. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/auth/test_auth_flows.py +4 -1
  108. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/conftest.py +23 -1
  109. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/connection/test_connection.py +43 -0
  110. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/connection/test_readers_and_transports.py +32 -1
  111. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/dispatch/test_dispatcher.py +8 -0
  112. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/domain/test_bound_models.py +1 -1
  113. maxapi_python-2.4.1/tests/domain/test_login_models.py +63 -0
  114. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/domain/test_message_models.py +36 -0
  115. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/files/test_files_and_formatting.py +5 -0
  116. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/protocol/test_protocols.py +26 -0
  117. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/session/test_store.py +65 -0
  118. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/uv.lock +21 -5
  119. maxapi_python-2.3.1/docs/files.rst +0 -117
  120. maxapi_python-2.3.1/src/pymax/api/messages/__init__.py +0 -1
  121. maxapi_python-2.3.1/src/pymax/api/self/__init__.py +0 -2
  122. maxapi_python-2.3.1/src/pymax/api/self/enums.py +0 -11
  123. maxapi_python-2.3.1/src/pymax/api/self/payloads.py +0 -41
  124. maxapi_python-2.3.1/src/pymax/api/uploads/payloads.py +0 -25
  125. maxapi_python-2.3.1/src/pymax/session/models.py +0 -11
  126. maxapi_python-2.3.1/src/pymax/session/protocol.py +0 -14
  127. maxapi_python-2.3.1/src/pymax/types/domain/attachments/enums.py +0 -28
  128. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  129. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  130. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
  131. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/pull_request_template.md +0 -0
  132. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/workflows/publish.yml +0 -0
  133. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/workflows/tests.yml +0 -0
  134. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.gitignore +0 -0
  135. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.pre-commit-config.yaml +0 -0
  136. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/LICENSE +0 -0
  137. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/_static/.gitkeep +0 -0
  138. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client-client.rst +0 -0
  139. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client-config.rst +0 -0
  140. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client-web.rst +0 -0
  141. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/router.rst +0 -0
  142. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/conf.py +0 -0
  143. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/examples.rst +0 -0
  144. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/formatting.rst +0 -0
  145. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/getting-started.rst +0 -0
  146. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-0.rst +0 -0
  147. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-1.rst +0 -0
  148. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-2.rst +0 -0
  149. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-3.rst +0 -0
  150. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-2-0.rst +0 -0
  151. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-3-0.rst +0 -0
  152. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-3-1.rst +0 -0
  153. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/router.rst +0 -0
  154. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/audio_attachment.rst +0 -0
  155. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/call_attachment.rst +0 -0
  156. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/chat.rst +0 -0
  157. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/contact_attachment.rst +0 -0
  158. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/contact_info.rst +0 -0
  159. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/control_attachment.rst +0 -0
  160. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/element.rst +0 -0
  161. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/file_attachment.rst +0 -0
  162. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/folder.rst +0 -0
  163. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/folder_list.rst +0 -0
  164. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/folder_update.rst +0 -0
  165. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/inline_keyboard_attachment.rst +0 -0
  166. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/message.rst +0 -0
  167. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/message_delete_event.rst +0 -0
  168. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/message_read_event.rst +0 -0
  169. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/name.rst +0 -0
  170. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/photo_attachment.rst +0 -0
  171. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/presence_event.rst +0 -0
  172. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/profile.rst +0 -0
  173. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/reaction_counter.rst +0 -0
  174. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/reaction_info.rst +0 -0
  175. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/reaction_update_event.rst +0 -0
  176. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/read_state.rst +0 -0
  177. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/session.rst +0 -0
  178. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/share_attachment.rst +0 -0
  179. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/sticker_attachment.rst +0 -0
  180. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/sync_overrides.rst +0 -0
  181. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/sync_state.rst +0 -0
  182. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/typing_event.rst +0 -0
  183. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/user.rst +0 -0
  184. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/video_attachment.rst +0 -0
  185. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/users.rst +0 -0
  186. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/__init__.py +0 -0
  187. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/__init__.py +0 -0
  188. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/types.py +0 -0
  189. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/binding.py +0 -0
  190. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/bots/__init__.py +0 -0
  191. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/bots/payloads.py +0 -0
  192. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/bots/service.py +0 -0
  193. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/facade.py +0 -0
  194. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/messages/enums.py +0 -0
  195. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/models.py +0 -0
  196. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/response.py +0 -0
  197. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/__init__.py +0 -0
  198. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/enums.py +0 -0
  199. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/payloads.py +0 -0
  200. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/uploads/__init__.py +0 -0
  201. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/uploads/models.py +0 -0
  202. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/__init__.py +0 -0
  203. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/enums.py +0 -0
  204. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/payloads.py +0 -0
  205. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/service.py +0 -0
  206. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/base.py +0 -0
  207. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/email.py +0 -0
  208. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/models.py +0 -0
  209. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/qr.py +0 -0
  210. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/service.py +0 -0
  211. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/__init__.py +0 -0
  212. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/pending.py +0 -0
  213. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/__init__.py +0 -0
  214. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/base.py +0 -0
  215. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/tcp.py +0 -0
  216. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/ws.py +0 -0
  217. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/__init__.py +0 -0
  218. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/dispatcher.py +0 -0
  219. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/router.py +0 -0
  220. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/exceptions.py +0 -0
  221. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/file.py +0 -0
  222. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/photo.py +0 -0
  223. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/static.py +0 -0
  224. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/formatting/__init__.py +0 -0
  225. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/formatting/markdown.py +0 -0
  226. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/__init__.py +0 -0
  227. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/base.py +0 -0
  228. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/user.py +0 -0
  229. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/logging.py +0 -0
  230. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/__init__.py +0 -0
  231. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/base.py +0 -0
  232. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/models.py +0 -0
  233. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/__init__.py +0 -0
  234. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/compression.py +0 -0
  235. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/framing.py +0 -0
  236. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/protocol.py +0 -0
  237. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/ws/__init__.py +0 -0
  238. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/ws/protocol.py +0 -0
  239. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/py.typed +0 -0
  240. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/routers.py +0 -0
  241. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/__init__.py +0 -0
  242. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/navigation.py +0 -0
  243. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/payloads.py +0 -0
  244. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/service.py +0 -0
  245. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/__init__.py +0 -0
  246. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/base.py +0 -0
  247. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/__init__.py +0 -0
  248. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/audio.py +0 -0
  249. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/file.py +0 -0
  250. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/keyboards/__init__.py +0 -0
  251. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/keyboards/inline.py +0 -0
  252. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/photo.py +0 -0
  253. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/share.py +0 -0
  254. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/unknown.py +0 -0
  255. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/auth.py +0 -0
  256. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/base.py +0 -0
  257. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/bots.py +0 -0
  258. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/element.py +0 -0
  259. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/error.py +0 -0
  260. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/folder.py +0 -0
  261. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/member.py +0 -0
  262. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/name.py +0 -0
  263. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/presence.py +0 -0
  264. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/profile.py +0 -0
  265. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/session.py +0 -0
  266. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/sync.py +0 -0
  267. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/file.py +0 -0
  268. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/mark.py +0 -0
  269. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/message.py +0 -0
  270. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/presence.py +0 -0
  271. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/typing.py +0 -0
  272. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/video.py +0 -0
  273. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/__init__.py +0 -0
  274. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/domain/test_user_models.py +0 -0
  275. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/telemetry/test_telemetry.py +0 -0
  276. {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/test_logging.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: maxapi-python
3
- Version: 2.3.1
3
+ Version: 2.4.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
@@ -32,6 +32,8 @@ Requires-Dist: python-socks[asyncio]>=2.8.1
32
32
  Requires-Dist: qrcode>=8.2
33
33
  Requires-Dist: websockets>=16.0
34
34
  Requires-Dist: zstandard>=0.25.0
35
+ Provides-Extra: video
36
+ Requires-Dist: tinytag>=2.2.1; extra == 'video'
35
37
  Description-Content-Type: text/markdown
36
38
 
37
39
  # PyMax
@@ -41,6 +43,7 @@ Python-библиотека для Max API.
41
43
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
42
44
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
43
45
  [![Package](https://img.shields.io/badge/package-maxapi--python-orange.svg)](https://pypi.org/project/maxapi-python/)
46
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/maxapi-python?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/maxapi-python)
44
47
 
45
48
  > [!WARNING]
46
49
  > PyMax использует неофициальный внутренний API Max. API может измениться без
@@ -60,10 +63,11 @@ WebSocket.
60
63
  - Авторизация по телефону и SMS-коду через `Client`.
61
64
  - QR-авторизация web-клиента через `WebClient`.
62
65
  - Роутеры, фильтры, `on_start`, raw-события и typed events.
63
- - Сообщения: отправка, ответы, reply, реакции, pin, read, delete и история.
66
+ - Сообщения: отправка и планирование, ответы, реакции, pin, read, delete и история.
64
67
  - Чаты, группы, участники, invite-ссылки и настройки групп.
65
68
  - Пользователи, контакты, профиль, папки, активные сессии и 2FA.
66
- - Вложения: `Photo`, `File`, `Video`.
69
+ - Вложения: `Photo`, `File`, `Video`, `Voice`, `VideoNote`.
70
+ - Выбор версии mobile-клиента с локальным или обновляемым каталогом fingerprints.
67
71
  - SQLite-сессии, sync-state, reconnect и debug-логи.
68
72
  - Pydantic-модели и удобные domain-объекты.
69
73
 
@@ -5,6 +5,7 @@ Python-библиотека для Max API.
5
5
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
7
  [![Package](https://img.shields.io/badge/package-maxapi--python-orange.svg)](https://pypi.org/project/maxapi-python/)
8
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/maxapi-python?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/maxapi-python)
8
9
 
9
10
  > [!WARNING]
10
11
  > PyMax использует неофициальный внутренний API Max. API может измениться без
@@ -24,10 +25,11 @@ WebSocket.
24
25
  - Авторизация по телефону и SMS-коду через `Client`.
25
26
  - QR-авторизация web-клиента через `WebClient`.
26
27
  - Роутеры, фильтры, `on_start`, raw-события и typed events.
27
- - Сообщения: отправка, ответы, reply, реакции, pin, read, delete и история.
28
+ - Сообщения: отправка и планирование, ответы, реакции, pin, read, delete и история.
28
29
  - Чаты, группы, участники, invite-ссылки и настройки групп.
29
30
  - Пользователи, контакты, профиль, папки, активные сессии и 2FA.
30
- - Вложения: `Photo`, `File`, `Video`.
31
+ - Вложения: `Photo`, `File`, `Video`, `Voice`, `VideoNote`.
32
+ - Выбор версии mobile-клиента с локальным или обновляемым каталогом fingerprints.
31
33
  - SQLite-сессии, sync-state, reconnect и debug-логи.
32
34
  - Pydantic-модели и удобные domain-объекты.
33
35
 
@@ -0,0 +1,44 @@
1
+ # PyMax TODO :3
2
+
3
+ > [!NOTE]
4
+ > This file is maintained by the project owner. Please do not edit it in pull requests.
5
+
6
+ Format:
7
+ - Refactoring / Bugs: `TEXT. PATH. PRIORITY`
8
+ - Features: `TEXT. TARGET. PRIORITY`
9
+
10
+ ## Refactoring
11
+
12
+ - [ ] Перевести все аргументы, связанные со временем, на `DateTimeUnion`. `api/messages/service.py:65`. P: 50
13
+ - [ ] Перенести часть общих типов в `common`, например `SendAttachments`. -. P: 40
14
+ - [ ] Пересмотреть систему типов, возможно разбить её на более мелкие части. -. P: 70
15
+
16
+ ## Bugs
17
+
18
+ - [X] Исправить голосовые/кружки. `api/upload/service.py`. P: 100
19
+ - [X] Исправить генерацию device_id. `src/pymax/base.py:111`. P: 80
20
+
21
+ ## Features
22
+
23
+ - [ ] FSM. Почти готово. `2.5.0`. P: 80
24
+ - [ ] DI. `2.5.0`. P: 75
25
+ - [ ] Улучшенная система фильтров. Почти готово. `2.5.0`. P: 90
26
+
27
+
28
+ # Autogenerated TODO. Please, dont touch it
29
+ - [ ] src/pymax/api/chats/payloads.py:100: ENUMM!!!
30
+ - [ ] src/pymax/api/chats/payloads.py:123: ENUMM!!!
31
+ - [ ] src/pymax/api/messages/payloads.py:32: enum?
32
+ - [ ] src/pymax/api/messages/service.py:94: TypeAlias
33
+ - [ ] src/pymax/api/uploads/service.py:68: ENUM!!!!
34
+ - [ ] src/pymax/api/uploads/service.py:286: Error handing (yes, with 200 status 💔)
35
+ - [ ] src/pymax/api/users/service.py:133: maybe also return phone mapping?
36
+ - [ ] src/pymax/base.py:226: maybe impl it better way
37
+ - [ ] src/pymax/config.py:52: delete maybe
38
+ - [ ] src/pymax/dispatch/dispatcher.py:190: create iter_on_start_handlers
39
+ - [ ] src/pymax/protocol/tcp/payload.py:34: deprecate? idk
40
+ - [ ] src/pymax/transport/websocket.py:28: origin should be configurable
41
+ - [ ] src/pymax/types/domain/attachments/video.py:70: idk maybe | None = None better
42
+ - [ ] src/pymax/types/domain/user.py:14: move to another file
43
+ - [ ] src/pymax/types/events/message.py:49: impl it in the better way maybe
44
+ - [ ] src/pymax/versions/catalog.py:56: msg
@@ -53,6 +53,16 @@ Account
53
53
  photo_token="PHOTO_TOKEN",
54
54
  )
55
55
 
56
+ Статус присутствия
57
+ ------------------
58
+
59
+ ``set_presence()`` меняет статус, который будет использован при следующем
60
+ login или ping:
61
+
62
+ .. code-block:: python
63
+
64
+ client.set_presence(online=True)
65
+
56
66
  Папки чатов
57
67
  -----------
58
68
 
@@ -119,9 +129,8 @@ Account
119
129
  -------------
120
130
 
121
131
  ``client.me`` равен ``None``
122
- Login еще не завершился или клиент не запущен. Читайте профиль внутри
123
- ``on_start`` или после успешного ``await client.start()`` в собственном
124
- lifecycle.
132
+ Login еще не завершился. Читайте профиль внутри ``on_start`` или после
133
+ успешного ``await client.connect()``.
125
134
 
126
135
  Фото профиля не обновилось
127
136
  Если переданы и ``photo``, и ``photo_token``, PyMax загрузит ``photo`` и
@@ -33,3 +33,5 @@ Auth API
33
33
 
34
34
  .. autoclass:: pymax.ConsoleQrHandler
35
35
  :members:
36
+
37
+ .. autoclass:: pymax.PasswordAttemptsExceededError
@@ -0,0 +1,20 @@
1
+ Session storage
2
+ ===============
3
+
4
+ .. currentmodule:: pymax.session
5
+
6
+ ``Client`` и ``WebClient`` используют этот контракт для token,
7
+ device/user-agent и sync-state. Выбор и lifecycle хранилища описаны в разделе
8
+ :ref:`client-session-guide`.
9
+
10
+ .. autoclass:: SessionInfo
11
+ :members:
12
+
13
+ .. autoclass:: StoreProtocol
14
+ :members:
15
+
16
+ .. autoclass:: SessionStore
17
+ :members:
18
+
19
+ .. autoclass:: InMemoryStore
20
+ :members:
@@ -0,0 +1,12 @@
1
+ Version Catalog
2
+ ===============
3
+
4
+ .. currentmodule:: pymax.versions
5
+
6
+ ``VersionCatalog`` связывает версию Android-клиента с build number и
7
+ fingerprint, которые использует ``Client``.
8
+
9
+ .. autoclass:: VersionCatalog
10
+ :members:
11
+
12
+ .. autoclass:: VersionNotFoundError
@@ -23,3 +23,5 @@ Clients API
23
23
  client-client
24
24
  client-web
25
25
  client-config
26
+ client-session
27
+ client-versions
@@ -12,3 +12,11 @@ Files API
12
12
  .. autoclass:: pymax.Video
13
13
  :members:
14
14
  :show-inheritance:
15
+
16
+ .. autoclass:: pymax.VideoNote
17
+ :members:
18
+ :show-inheritance:
19
+
20
+ .. autoclass:: pymax.Voice
21
+ :members:
22
+ :show-inheritance:
@@ -88,6 +88,30 @@ Provider нужен, когда код приходит не из консоли
88
88
  Если provider вернет пустую строку или Max отклонит пароль, ``SmsAuthFlow``
89
89
  попросит пароль снова.
90
90
 
91
+ Количество попыток можно ограничить через ``ExtraConfig``:
92
+
93
+ .. code-block:: python
94
+
95
+ from pymax import Client, ExtraConfig, PasswordAttemptsExceededError
96
+
97
+ client = Client(
98
+ phone="+79990000000",
99
+ password_provider=EnvPasswordProvider(),
100
+ extra_config=ExtraConfig(password_max_attempts=3),
101
+ )
102
+
103
+ try:
104
+ await client.connect()
105
+ except PasswordAttemptsExceededError:
106
+ print("Пароль 2FA не принят")
107
+
108
+ ``password_max_attempts=None`` означает неограниченное число попыток и
109
+ сохраняет прежнее поведение. Пустой пароль, ``ApiError``, ошибка в ответе Max
110
+ и ответ без login token расходуют одну попытку. При ``0`` или отрицательном
111
+ значении provider не вызывается, а ``PasswordAttemptsExceededError``
112
+ возникает сразу. Исключение наследуется напрямую от ``Exception``, поэтому
113
+ его нужно перехватывать отдельно от ``PyMaxError``.
114
+
91
115
  Кастомный QR handler
92
116
  --------------------
93
117
 
@@ -90,15 +90,52 @@ login/sync, а также методы для загрузки, создания
90
90
  ``invite()`` работает только для групп и каналов. Для личного диалога тип чата
91
91
  не подходит, и метод завершится ошибкой.
92
92
 
93
+ Участники и администраторы канала
94
+ ---------------------------------
95
+
96
+ ``get_chat_members()`` возвращает одну страницу участников и маркер следующей:
97
+
98
+ .. code-block:: python
99
+
100
+ members, marker = await client.get_chat_members(chat_id=123456, count=50)
101
+ for member in members:
102
+ print(member.contact.id)
103
+
104
+ if marker:
105
+ next_members, marker = await client.get_chat_members(
106
+ chat_id=123456,
107
+ marker=marker,
108
+ count=50,
109
+ )
110
+
111
+ Назначить администратора канала можно с явным набором прав:
112
+
113
+ .. code-block:: python
114
+
115
+ from pymax.api.chats import ChannelPermissions
116
+
117
+ await client.add_admin(
118
+ chat_id=123456,
119
+ user_id=111,
120
+ permissions=[
121
+ ChannelPermissions.POST_MESSAGE,
122
+ ChannelPermissions.EDIT_MESSAGE,
123
+ ChannelPermissions.DELETE_MESSAGE,
124
+ ],
125
+ )
126
+
93
127
  Настройки и профиль группы
94
128
  --------------------------
95
129
 
96
130
  .. code-block:: python
97
131
 
132
+ from pymax import Photo
133
+
98
134
  await client.change_group_profile(
99
135
  chat_id=123456,
100
136
  name="Новый заголовок",
101
137
  description="Описание группы",
138
+ photo=Photo(path="group.jpg"),
102
139
  )
103
140
 
104
141
  await client.change_group_settings(
@@ -107,6 +144,11 @@ login/sync, а также методы для загрузки, создания
107
144
  only_admin_can_call=True,
108
145
  )
109
146
 
147
+ ``name``, ``description`` и ``photo`` независимы: передавайте только поля,
148
+ которые нужно изменить. Значение ``None`` исключает поле из запроса. Перед
149
+ обновлением профиля PyMax автоматически загружает ``Photo`` и отправляет Max
150
+ полученный photo token.
151
+
110
152
  Через объект ``Chat`` можно менять настройки и перевыпускать invite-ссылку:
111
153
 
112
154
  .. code-block:: python
@@ -7,9 +7,9 @@ Client
7
7
  ``Client`` и ``WebClient`` - главные объекты библиотеки. Они держат соединение,
8
8
  авторизацию, локальную сессию, кеш профиля/чатов и методы для API Max.
9
9
 
10
- ``Client`` не является обычным HTTP-wrapper-ом на один запрос. После
11
- ``await client.start()`` он остается подключенным, слушает события Max,
12
- отвечает на ping и вызывает ваши handler-ы.
10
+ ``Client`` не является обычным HTTP-wrapper-ом на один запрос. После запуска
11
+ он остается подключенным, слушает события Max, отвечает на ping и вызывает
12
+ ваши handler-ы.
13
13
 
14
14
  Как выбрать клиента
15
15
  -------------------
@@ -27,19 +27,50 @@ Client
27
27
 
28
28
  1. Вы создаете ``Client`` или ``WebClient``.
29
29
  2. Регистрируете handler-ы и подключаете роутеры.
30
- 3. Вызываете ``await client.start()``.
30
+ 3. Вызываете ``await client.start()`` или ``await client.connect()``.
31
31
  4. PyMax открывает соединение, делает handshake и login.
32
32
  5. После login доступны ``client.me`` и ``client.chats``.
33
33
  6. Вызывается ``on_start``.
34
34
  7. Клиент слушает события до закрытия соединения или отмены задачи.
35
35
 
36
+ ``start()`` - long-running режим с автоматическим reconnect. Метод не
37
+ возвращается, пока соединение не закрыто штатно или задача не отменена.
38
+
39
+ ``connect()`` выполняет один цикл подключения, login и ``on_start``, после
40
+ чего возвращается, оставляя соединение открытым. Он не запускает reconnect
41
+ loop: приложение само выполняет работу и затем вызывает ``stop()`` или
42
+ ``close()``.
43
+
44
+ .. code-block:: python
45
+
46
+ await client.connect()
47
+ try:
48
+ await client.send_message(chat_id=123456, text="Готово")
49
+ finally:
50
+ await client.close()
51
+
52
+ После успешного запуска состояние соединения доступно через
53
+ ``client.is_connected``.
54
+
55
+ Если ``start()`` запущен отдельной задачей, ``stop()`` штатно закрывает
56
+ соединение и завершает эту задачу без ``CancelledError``:
57
+
58
+ .. code-block:: python
59
+
60
+ import asyncio
61
+
62
+ task = asyncio.create_task(client.start())
63
+ # ... работа приложения ...
64
+ await client.stop()
65
+ await task
66
+
36
67
  Данные после login
37
68
  ------------------
38
69
 
39
70
  После успешного login клиент хранит несколько кешей, которые пришли от Max:
40
71
 
41
72
  ``client.me``
42
- Профиль текущего аккаунта или ``None``, если login еще не завершился.
73
+ Профиль текущего аккаунта.
43
74
 
44
75
  ``client.chats``
45
76
  Чаты из login/sync. Это не гарантированно полный список всех чатов.
@@ -54,6 +85,15 @@ Client
54
85
  Для актуализации используйте явные методы: ``fetch_chats()``, ``get_chat()``,
55
86
  ``get_users()``, ``fetch_users()`` и ``fetch_history()``.
56
87
 
88
+ После handshake можно проверить, требует ли Max обновления версии приложения:
89
+
90
+ .. code-block:: python
91
+
92
+ @client.on_start()
93
+ async def on_start(client: Client) -> None:
94
+ if client.is_update_available():
95
+ print("Для выбранной версии приложения доступно обновление")
96
+
57
97
  Создание клиента
58
98
  ----------------
59
99
 
@@ -85,7 +125,46 @@ Client
85
125
  Имя файла сессии внутри ``work_dir``.
86
126
 
87
127
  ``extra_config``
88
- Настройки соединения, логов, reconnect, token, device/user-agent и sync.
128
+ Настройки соединения, логов, reconnect, token, хранения сессии,
129
+ device/user-agent и sync.
130
+
131
+ ``app_version``
132
+ Версия Android-клиента, которую ``Client`` использует для user-agent и
133
+ fingerprint. По умолчанию - версия, возвращаемая
134
+ ``VersionCatalog.recommended()``.
135
+
136
+ ``catalog``
137
+ Каталог fingerprints для ``app_version``. По умолчанию используется
138
+ встроенный каталог.
139
+
140
+ Версия mobile-клиента
141
+ ---------------------
142
+
143
+ ``Client`` связывает выбранную ``app_version`` с соответствующими build number
144
+ и fingerprint. Разрешение версии происходит при ``connect()`` или ``start()``,
145
+ а не при создании объекта клиента.
146
+
147
+ .. code-block:: python
148
+
149
+ from pymax import Client
150
+ from pymax.versions import VersionCatalog
151
+
152
+ client = Client(
153
+ phone="+79990000000",
154
+ app_version="26.28.0",
155
+ catalog=VersionCatalog(remote=True),
156
+ )
157
+
158
+ Обычный ``VersionCatalog()`` использует только данные, поставляемые вместе с
159
+ PyMax. При ``remote=True`` метод ``load()`` загружает свежий каталог с
160
+ ``hashes.pymax.org`` и добавляет его записи поверх встроенных. Сетевые,
161
+ HTTP- и validation-ошибки удаленного каталога не скрываются и возникают во
162
+ время ``connect()``/``start()``.
163
+
164
+ Если выбранной версии нет в итоговом каталоге, PyMax выбрасывает
165
+ ``VersionNotFoundError``. Пользовательский ``ExtraConfig.user_agent`` не
166
+ отменяет проверку ``app_version``: fingerprint для версии всё равно должен
167
+ существовать.
89
168
 
90
169
  Тип устройства
91
170
  ---------------
@@ -188,6 +267,8 @@ Client
188
267
  qr_provider=ConfirmQrWithClient(mobile_client),
189
268
  )
190
269
 
270
+ .. _client-session-guide:
271
+
191
272
  Сессия и sync-state
192
273
  -------------------
193
274
 
@@ -197,6 +278,7 @@ Client
197
278
  * ``device_id``;
198
279
  * телефон;
199
280
  * ``mt_instance_id``;
281
+ * device/user-agent;
200
282
  * sync-маркеры ``chats_sync``, ``contacts_sync``, ``drafts_sync``,
201
283
  ``presence_sync`` и ``config_hash``.
202
284
 
@@ -204,11 +286,49 @@ Client
204
286
  ``session_name="account.db"`` это будет ``cache/account.db``. Если файл удалить,
205
287
  PyMax потеряет token и попросит авторизацию снова.
206
288
 
289
+ Для автоматически создаваемого user-agent PyMax восстанавливает из сессии
290
+ модель устройства, версию ОС, экран, locale и timezone. ``app_version`` и build
291
+ number всегда берутся из конфигурации текущего запуска, поэтому смена версии
292
+ клиента не сбрасывает сохраненный профиль устройства. Явный
293
+ ``ExtraConfig.user_agent`` имеет приоритет и заменяет значение из сессии.
294
+
295
+ Старый SQLite-файл обновляется автоматически: PyMax добавляет nullable-колонку
296
+ ``user_agent`` и при первом успешном login сохраняет в нее текущий payload.
297
+
207
298
  При login PyMax отправляет сохраненные маркеры серверу. Если маркер актуален,
208
299
  сервер может вернуть только изменения. Поэтому повторный запуск отличается от
209
300
  первого: первый запуск обычно использует ``-1`` и получает начальный sync,
210
301
  а последующие запуски продолжают с сохраненного состояния.
211
302
 
303
+ Пользовательский ``StoreProtocol`` может возвращать
304
+ ``SessionInfo.user_agent=None`` для совместимости, но тогда профиль устройства
305
+ не сохраняется между запусками. Чтобы получить стандартное поведение, храните и
306
+ возвращайте это необязательное поле вместе с остальными данными сессии.
307
+
308
+ Сессия только в памяти
309
+ ----------------------
310
+
311
+ Чтобы не создавать и не обновлять SQLite-файл, передайте
312
+ ``persist_session=False``:
313
+
314
+ .. code-block:: python
315
+
316
+ from pymax import Client, ExtraConfig
317
+
318
+ client = Client(
319
+ phone="+79990000000",
320
+ extra_config=ExtraConfig(
321
+ persist_session=False,
322
+ reconnect=False,
323
+ ),
324
+ )
325
+
326
+ В этом режиме PyMax использует отдельный ``InMemoryStore``. Переданный
327
+ ``ExtraConfig.store`` игнорируется. Сессия доступна только текущему runtime и
328
+ теряется при его пересоздании; reconnect без ``ExtraConfig.token`` поэтому снова
329
+ запускает SMS- или QR-авторизацию. Если автоматический reconnect в таком режиме
330
+ не нужен, отключите его как в примере.
331
+
212
332
  Принудительный sync
213
333
  -------------------
214
334
 
@@ -257,6 +377,10 @@ Reconnect
257
377
  а новый ``App`` снова получает тот же root router. ``on_start`` вызывается
258
378
  после каждого успешного reconnect.
259
379
 
380
+ Если сервер отозвал login token, ``ExtraConfig(relogin=True)`` по умолчанию
381
+ сбрасывает текущую сессию и запускает авторизацию заново. Значение ``False``
382
+ отключает этот автоматический сброс.
383
+
260
384
  Перед повторным подключением можно зарегистрировать ``on_disconnect``:
261
385
 
262
386
  .. code-block:: python
@@ -300,13 +424,14 @@ Debug-логи показывают handshake, login, входящие собы
300
424
  Клиент собирает несколько API-направлений:
301
425
 
302
426
  Сообщения
303
- ``send_message()``, ``forward_message()``, ``fetch_history()``,
427
+ ``send_message()``, ``forward_message()``, ``fetch_history()``, ``vote_poll()``,
304
428
  ``delete_message()``, ``pin_message()``, ``read_message()``, реакции и
305
429
  получение URL для входящих файлов/видео.
306
430
 
307
431
  Чаты
308
432
  ``get_chat()``, ``fetch_chats()``, создание групп, invite-ссылки,
309
- участники, настройки групп, удаление чатов и выход из групп/каналов.
433
+ участники, назначение администраторов, настройки групп, удаление чатов и
434
+ выход из групп/каналов.
310
435
 
311
436
  Пользователи
312
437
  ``get_user()``, ``get_users()``, ``fetch_users()``, ``search_by_phone()``,
@@ -93,6 +93,8 @@ Max не всегда присылает полный объект сообще
93
93
  Что делать при Pydantic validation error?
94
94
  -----------------------------------------
95
95
 
96
- Max мог прислать новый или неполный формат payload. Включите ``DEBUG``, снимите
97
- raw payload через ``on_raw`` и обновите PyMax. Если ошибка повторяется, заведите
98
- issue с очищенным payload без token, телефонов и приватных URL.
96
+ Неизвестный тип вложения сохраняется как ``UnknownAttachment`` и сам по себе не
97
+ должен ломать сообщение. Validation error обычно означает неполный или
98
+ измененный payload уже известной модели. Включите ``DEBUG``, снимите raw payload
99
+ через ``on_raw`` и обновите PyMax. Если ошибка повторяется, заведите issue с
100
+ очищенным payload без token, телефонов и приватных URL.