maxapi-python 2.3.1__tar.gz → 2.4.0__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 (260) hide show
  1. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/PKG-INFO +3 -1
  2. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/account.rst +10 -0
  3. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/files.rst +8 -0
  4. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/chats.rst +34 -0
  5. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/client.rst +24 -2
  6. maxapi_python-2.4.0/docs/files.rst +174 -0
  7. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/index.rst +1 -0
  8. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/messages.rst +54 -3
  9. maxapi_python-2.4.0/docs/release-2-4-0.rst +210 -0
  10. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/enums.rst +9 -0
  11. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/index.rst +3 -1
  12. maxapi_python-2.4.0/docs/types/poll.rst +22 -0
  13. maxapi_python-2.4.0/docs/types/poll_attachment.rst +6 -0
  14. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/pyproject.toml +6 -1
  15. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/__init__.py +7 -2
  16. maxapi_python-2.4.0/src/pymax/_data/apk_fingerprints.json +682 -0
  17. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/auth/enums.py +1 -0
  18. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/auth/payloads.py +28 -2
  19. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/auth/service.py +88 -3
  20. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/chats/__init__.py +1 -0
  21. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/chats/enums.py +15 -0
  22. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/chats/payloads.py +16 -1
  23. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/chats/service.py +36 -1
  24. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/messages/payloads.py +12 -4
  25. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/messages/service.py +57 -14
  26. maxapi_python-2.4.0/src/pymax/api/self/__init__.py +3 -0
  27. maxapi_python-2.4.0/src/pymax/api/self/enums.py +20 -0
  28. maxapi_python-2.4.0/src/pymax/api/self/payloads.py +80 -0
  29. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/self/service.py +37 -0
  30. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/session/service.py +21 -8
  31. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/uploads/payloads.py +6 -0
  32. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/uploads/service.py +198 -21
  33. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/app.py +69 -15
  34. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/base.py +8 -0
  35. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/client_web.py +2 -2
  36. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/config.py +44 -7
  37. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/connection.py +29 -18
  38. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/dispatch/enums.py +1 -0
  39. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/dispatch/mapping.py +3 -1
  40. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/dispatch/resolvers.py +7 -1
  41. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/files/__init__.py +4 -1
  42. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/files/video.py +58 -0
  43. maxapi_python-2.4.0/src/pymax/files/voice.py +39 -0
  44. maxapi_python-2.4.0/src/pymax/fingerprint/__init__.py +1 -0
  45. maxapi_python-2.4.0/src/pymax/fingerprint/fingerprint.py +47 -0
  46. maxapi_python-2.4.0/src/pymax/fingerprint/models.py +11 -0
  47. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/auth.py +4 -0
  48. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/bots.py +3 -3
  49. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/chat.py +38 -0
  50. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/message.py +40 -11
  51. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/self.py +25 -1
  52. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/enums.py +13 -0
  53. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/tcp/payload.py +21 -1
  54. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/transport/tcp.py +6 -1
  55. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/transport/websocket.py +6 -3
  56. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/__init__.py +2 -1
  57. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/__init__.py +2 -1
  58. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/enums.py +17 -1
  59. maxapi_python-2.4.0/src/pymax/types/domain/attachments/poll.py +111 -0
  60. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/sticker.py +1 -1
  61. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/video.py +29 -8
  62. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/chat.py +9 -9
  63. maxapi_python-2.4.0/src/pymax/types/domain/handshake.py +16 -0
  64. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/login.py +30 -1
  65. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/message.py +21 -20
  66. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/user.py +1 -3
  67. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/__init__.py +1 -0
  68. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/reaction.py +2 -2
  69. maxapi_python-2.4.0/src/pymax/types/events/voice.py +5 -0
  70. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/api/test_auth_service.py +175 -2
  71. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/api/test_chat_user_self_session_services.py +42 -4
  72. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/api/test_message_service.py +64 -6
  73. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/api/test_upload_service.py +67 -4
  74. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/app/test_app_runtime.py +207 -6
  75. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/conftest.py +13 -0
  76. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/connection/test_connection.py +43 -0
  77. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/connection/test_readers_and_transports.py +31 -0
  78. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/dispatch/test_dispatcher.py +8 -0
  79. maxapi_python-2.4.0/tests/domain/test_login_models.py +63 -0
  80. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/domain/test_message_models.py +36 -0
  81. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/files/test_files_and_formatting.py +5 -0
  82. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/protocol/test_protocols.py +26 -0
  83. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/uv.lock +17 -1
  84. maxapi_python-2.3.1/docs/files.rst +0 -117
  85. maxapi_python-2.3.1/src/pymax/api/self/__init__.py +0 -2
  86. maxapi_python-2.3.1/src/pymax/api/self/enums.py +0 -11
  87. maxapi_python-2.3.1/src/pymax/api/self/payloads.py +0 -41
  88. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  89. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  90. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
  91. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.github/pull_request_template.md +0 -0
  92. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.github/workflows/publish.yml +0 -0
  93. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.github/workflows/tests.yml +0 -0
  94. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.gitignore +0 -0
  95. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/.pre-commit-config.yaml +0 -0
  96. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/LICENSE +0 -0
  97. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/README.md +0 -0
  98. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/_static/.gitkeep +0 -0
  99. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/auth.rst +0 -0
  100. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/client-client.rst +0 -0
  101. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/client-config.rst +0 -0
  102. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/client-web.rst +0 -0
  103. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/client.rst +0 -0
  104. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/api/router.rst +0 -0
  105. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/auth.rst +0 -0
  106. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/conf.py +0 -0
  107. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/examples.rst +0 -0
  108. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/faq.rst +0 -0
  109. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/formatting.rst +0 -0
  110. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/getting-started.rst +0 -0
  111. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-1-0.rst +0 -0
  112. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-1-1.rst +0 -0
  113. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-1-2.rst +0 -0
  114. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-1-3.rst +0 -0
  115. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-2-0.rst +0 -0
  116. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-3-0.rst +0 -0
  117. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/release-2-3-1.rst +0 -0
  118. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/router.rst +0 -0
  119. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/troubleshooting.rst +0 -0
  120. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/audio_attachment.rst +0 -0
  121. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/call_attachment.rst +0 -0
  122. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/chat.rst +0 -0
  123. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/contact_attachment.rst +0 -0
  124. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/contact_info.rst +0 -0
  125. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/control_attachment.rst +0 -0
  126. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/element.rst +0 -0
  127. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/file_attachment.rst +0 -0
  128. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/folder.rst +0 -0
  129. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/folder_list.rst +0 -0
  130. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/folder_update.rst +0 -0
  131. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/inline_keyboard_attachment.rst +0 -0
  132. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/message.rst +0 -0
  133. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/message_delete_event.rst +0 -0
  134. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/message_read_event.rst +0 -0
  135. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/name.rst +0 -0
  136. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/photo_attachment.rst +0 -0
  137. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/presence_event.rst +0 -0
  138. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/profile.rst +0 -0
  139. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/reaction_counter.rst +0 -0
  140. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/reaction_info.rst +0 -0
  141. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/reaction_update_event.rst +0 -0
  142. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/read_state.rst +0 -0
  143. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/session.rst +0 -0
  144. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/share_attachment.rst +0 -0
  145. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/sticker_attachment.rst +0 -0
  146. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/sync_overrides.rst +0 -0
  147. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/sync_state.rst +0 -0
  148. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/typing_event.rst +0 -0
  149. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/user.rst +0 -0
  150. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/types/video_attachment.rst +0 -0
  151. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/docs/users.rst +0 -0
  152. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/__init__.py +0 -0
  153. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/auth/__init__.py +0 -0
  154. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/auth/types.py +0 -0
  155. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/binding.py +0 -0
  156. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/bots/__init__.py +0 -0
  157. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/bots/payloads.py +0 -0
  158. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/bots/service.py +0 -0
  159. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/facade.py +0 -0
  160. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/messages/__init__.py +0 -0
  161. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/messages/enums.py +0 -0
  162. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/models.py +0 -0
  163. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/response.py +0 -0
  164. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/session/__init__.py +0 -0
  165. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/session/enums.py +0 -0
  166. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/session/payloads.py +0 -0
  167. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/uploads/__init__.py +0 -0
  168. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/uploads/models.py +0 -0
  169. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/users/__init__.py +0 -0
  170. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/users/enums.py +0 -0
  171. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/users/payloads.py +0 -0
  172. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/api/users/service.py +0 -0
  173. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/__init__.py +0 -0
  174. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/base.py +0 -0
  175. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/email.py +0 -0
  176. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/models.py +0 -0
  177. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/providers.py +0 -0
  178. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/qr.py +0 -0
  179. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/service.py +0 -0
  180. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/auth/sms.py +0 -0
  181. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/client.py +0 -0
  182. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/__init__.py +0 -0
  183. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/pending.py +0 -0
  184. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/readers/__init__.py +0 -0
  185. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/readers/base.py +0 -0
  186. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/readers/tcp.py +0 -0
  187. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/connection/readers/ws.py +0 -0
  188. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/dispatch/__init__.py +0 -0
  189. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/dispatch/dispatcher.py +0 -0
  190. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/dispatch/router.py +0 -0
  191. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/exceptions.py +0 -0
  192. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/files/base.py +0 -0
  193. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/files/file.py +0 -0
  194. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/files/photo.py +0 -0
  195. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/files/static.py +0 -0
  196. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/formatting/__init__.py +0 -0
  197. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/formatting/markdown.py +0 -0
  198. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/__init__.py +0 -0
  199. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/base.py +0 -0
  200. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/protocol.py +0 -0
  201. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/infra/user.py +0 -0
  202. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/logging.py +0 -0
  203. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/__init__.py +0 -0
  204. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/base.py +0 -0
  205. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/models.py +0 -0
  206. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/tcp/__init__.py +0 -0
  207. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/tcp/compression.py +0 -0
  208. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/tcp/framing.py +0 -0
  209. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/tcp/protocol.py +0 -0
  210. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/ws/__init__.py +0 -0
  211. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/protocol/ws/protocol.py +0 -0
  212. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/py.typed +0 -0
  213. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/routers.py +0 -0
  214. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/session/__init__.py +0 -0
  215. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/session/models.py +0 -0
  216. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/session/protocol.py +0 -0
  217. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/session/store.py +0 -0
  218. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/telemetry/__init__.py +0 -0
  219. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/telemetry/navigation.py +0 -0
  220. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/telemetry/payloads.py +0 -0
  221. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/telemetry/service.py +0 -0
  222. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/transport/__init__.py +0 -0
  223. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/transport/base.py +0 -0
  224. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/__init__.py +0 -0
  225. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/audio.py +0 -0
  226. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/call.py +0 -0
  227. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/contact.py +0 -0
  228. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/control.py +0 -0
  229. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/file.py +0 -0
  230. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/keyboards/__init__.py +0 -0
  231. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/keyboards/inline.py +0 -0
  232. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/photo.py +0 -0
  233. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/share.py +0 -0
  234. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/attachments/unknown.py +0 -0
  235. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/auth.py +0 -0
  236. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/base.py +0 -0
  237. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/bots.py +0 -0
  238. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/element.py +0 -0
  239. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/enums.py +0 -0
  240. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/error.py +0 -0
  241. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/folder.py +0 -0
  242. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/member.py +0 -0
  243. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/name.py +0 -0
  244. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/presence.py +0 -0
  245. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/profile.py +0 -0
  246. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/session.py +0 -0
  247. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/domain/sync.py +0 -0
  248. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/file.py +0 -0
  249. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/mark.py +0 -0
  250. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/message.py +0 -0
  251. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/presence.py +0 -0
  252. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/typing.py +0 -0
  253. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/src/pymax/types/events/video.py +0 -0
  254. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/__init__.py +0 -0
  255. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/auth/test_auth_flows.py +0 -0
  256. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/domain/test_bound_models.py +0 -0
  257. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/domain/test_user_models.py +0 -0
  258. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/session/test_store.py +0 -0
  259. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/telemetry/test_telemetry.py +0 -0
  260. {maxapi_python-2.3.1 → maxapi_python-2.4.0}/tests/test_logging.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxapi-python
3
- Version: 2.3.1
3
+ Version: 2.4.0
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
@@ -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
 
@@ -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:
@@ -90,6 +90,40 @@ 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
 
@@ -33,6 +33,18 @@ Client
33
33
  6. Вызывается ``on_start``.
34
34
  7. Клиент слушает события до закрытия соединения или отмены задачи.
35
35
 
36
+ Если ``start()`` запущен отдельной задачей, ``stop()`` штатно закрывает
37
+ соединение и завершает эту задачу без ``CancelledError``:
38
+
39
+ .. code-block:: python
40
+
41
+ import asyncio
42
+
43
+ task = asyncio.create_task(client.start())
44
+ # ... работа приложения ...
45
+ await client.stop()
46
+ await task
47
+
36
48
  Данные после login
37
49
  ------------------
38
50
 
@@ -54,6 +66,15 @@ Client
54
66
  Для актуализации используйте явные методы: ``fetch_chats()``, ``get_chat()``,
55
67
  ``get_users()``, ``fetch_users()`` и ``fetch_history()``.
56
68
 
69
+ После handshake можно проверить, требует ли Max обновления версии приложения:
70
+
71
+ .. code-block:: python
72
+
73
+ @client.on_start()
74
+ async def on_start(client: Client) -> None:
75
+ if client.is_update_available():
76
+ print("Для выбранной версии приложения доступно обновление")
77
+
57
78
  Создание клиента
58
79
  ----------------
59
80
 
@@ -300,13 +321,14 @@ Debug-логи показывают handshake, login, входящие собы
300
321
  Клиент собирает несколько API-направлений:
301
322
 
302
323
  Сообщения
303
- ``send_message()``, ``forward_message()``, ``fetch_history()``,
324
+ ``send_message()``, ``forward_message()``, ``fetch_history()``, ``vote_poll()``,
304
325
  ``delete_message()``, ``pin_message()``, ``read_message()``, реакции и
305
326
  получение URL для входящих файлов/видео.
306
327
 
307
328
  Чаты
308
329
  ``get_chat()``, ``fetch_chats()``, создание групп, invite-ссылки,
309
- участники, настройки групп, удаление чатов и выход из групп/каналов.
330
+ участники, назначение администраторов, настройки групп, удаление чатов и
331
+ выход из групп/каналов.
310
332
 
311
333
  Пользователи
312
334
  ``get_user()``, ``get_users()``, ``fetch_users()``, ``search_by_phone()``,
@@ -0,0 +1,174 @@
1
+ Files
2
+ =====
3
+
4
+ Что это
5
+ -------
6
+
7
+ Для отправки вложений PyMax использует пять основных классов:
8
+
9
+ ``Photo``
10
+ Фото. Проверяет расширение и MIME-тип.
11
+
12
+ ``Video``
13
+ Видео. Загружается чанками и ждет событие готовности от Max.
14
+
15
+ ``File``
16
+ Обычный файл. Тоже загружается чанками и ждет событие готовности.
17
+
18
+ ``Voice``
19
+ Голосовое сообщение. Поддерживается только формат OGG; PyMax не
20
+ конвертирует другие аудиоформаты.
21
+
22
+ ``VideoNote``
23
+ Круглое видеосообщение. Можно передать длительность вручную или установить
24
+ extra ``video`` для автоматического определения.
25
+
26
+ Как отправить файл
27
+ ------------------
28
+
29
+ .. code-block:: python
30
+
31
+ import asyncio
32
+
33
+ from pymax import Client, File, Photo, Video, VideoNote, Voice
34
+
35
+ client = Client(phone="+79990000000", work_dir="cache")
36
+
37
+
38
+ @client.on_start()
39
+ async def send_files(client: Client) -> None:
40
+ chat = await client.get_chat(123456)
41
+
42
+ await chat.answer(
43
+ text="Фото",
44
+ attachments=[Photo(path="image.jpg")],
45
+ )
46
+
47
+ await chat.answer(
48
+ text="Документ",
49
+ attachments=[File(path="report.pdf")],
50
+ )
51
+
52
+ await chat.answer(
53
+ text="Видео",
54
+ attachments=[Video(path="clip.mp4")],
55
+ )
56
+
57
+ await chat.answer(attachments=[Voice(path="voice.ogg")])
58
+ await chat.answer(
59
+ attachments=[VideoNote(path="circle.mp4", duration=4200)]
60
+ )
61
+
62
+
63
+ asyncio.run(client.start())
64
+
65
+ Источники данных
66
+ ----------------
67
+
68
+ Можно передать ровно один источник:
69
+
70
+ .. code-block:: python
71
+
72
+ Photo(path="image.jpg")
73
+ File(url="https://example.com/report.pdf")
74
+ Video(raw=b"...", name="clip.mp4")
75
+ Voice(path="voice.ogg")
76
+ VideoNote(path="circle.mp4", duration=4200)
77
+
78
+ Для ``raw`` обязательно указывайте ``name``. Для ``File``, ``Video``,
79
+ ``Voice`` и ``VideoNote`` имя берется из ``path`` или ``url``, если не
80
+ передано явно.
81
+
82
+ Если длительность ``VideoNote`` не передана, установите дополнительную
83
+ зависимость:
84
+
85
+ .. code-block:: console
86
+
87
+ uv add "maxapi-python[video]"
88
+
89
+ Формат Voice и VideoNote
90
+ ------------------------
91
+
92
+ Для ``Voice`` используйте готовый OGG-файл. Простого переименования MP3, WAV
93
+ или другого аудиофайла в ``.ogg`` недостаточно: PyMax загружает исходные байты
94
+ без перекодирования.
95
+
96
+ ``VideoNote`` также не перекодирует видео. Для совместимости с официальным
97
+ клиентом 26.21.1 рекомендуется следующий формат:
98
+
99
+ * контейнер MP4;
100
+ * видео H.264/AVC, 480x480, 30 FPS и bitrate около 1 024 000 bit/s;
101
+ * pixel format ``yuv420p`` при подготовке через FFmpeg;
102
+ * ключевой кадр примерно раз в секунду, то есть GOP около 30 кадров;
103
+ * аудио AAC в том же MP4-контейнере;
104
+ * длительность до 60 секунд.
105
+
106
+ Официальный клиент задает квадратное разрешение, фиксированные 30 FPS и
107
+ максимальную длительность через server config. Нижняя граница в одну секунду
108
+ не является подтвержденным ограничением upload API, поэтому PyMax ее не
109
+ проверяет.
110
+
111
+ Поворот лучше физически применить при перекодировании и убрать rotation
112
+ metadata: так файл меньше зависит от того, как конкретный клиент обработает
113
+ orientation hint. H.264 profile и level специально фиксировать не требуется.
114
+ ``faststart`` официальный recorder явно не включает; при самостоятельной
115
+ подготовке файла его можно использовать, но для PyMax это не обязательное
116
+ условие.
117
+
118
+ Как работает upload
119
+ -------------------
120
+
121
+ 1. PyMax запрашивает у Max временный upload URL.
122
+ 2. Читает файл из ``path``, ``url`` или ``raw``.
123
+ 3. Загружает данные HTTP-запросом.
124
+ 4. Для ``File``, ``Video``, ``Voice`` и ``VideoNote`` ждет служебное событие
125
+ готовности до 60 секунд.
126
+ 5. Подставляет token/file_id/video_id в отправляемое сообщение.
127
+
128
+ Фото проходит проще: после HTTP-upload PyMax сразу достает token из ответа.
129
+
130
+ Скачать входящий файл
131
+ ---------------------
132
+
133
+ ``FileAttachment`` содержит ID, но для скачивания нужен временный URL:
134
+
135
+ .. code-block:: python
136
+
137
+ from pymax import Client, Message
138
+ from pymax.types.domain import FileAttachment
139
+
140
+ @client.on_message()
141
+ async def on_message(message: Message, client: Client) -> None:
142
+ if message.chat_id is None:
143
+ return
144
+
145
+ for attach in message.attaches:
146
+ if isinstance(attach, FileAttachment):
147
+ info = await client.get_file_by_id(
148
+ chat_id=message.chat_id,
149
+ message_id=message.id,
150
+ file_id=attach.file_id,
151
+ )
152
+ print(info.url if info else "URL не получен")
153
+
154
+ Частые ошибки
155
+ -------------
156
+
157
+ ``ValueError: Only one of raw, url or path must be provided``
158
+ Передайте только один источник файла.
159
+
160
+ ``ValueError: Name must be provided for raw data``
161
+ Для bytes укажите имя: ``File(raw=data, name="file.bin")``.
162
+
163
+ ``Invalid photo extension``
164
+ ``Photo`` принимает ``.jpg``, ``.jpeg``, ``.png``, ``.gif``, ``.webp`` и
165
+ ``.bmp``.
166
+
167
+ ``UploadError``
168
+ Upload-сервис не получил нужный ответ от Max. Включите ``DEBUG``-логи:
169
+ часто причина в недоступном URL, неверном размере файла, timeout или в том,
170
+ что событие готовности файла не пришло за 60 секунд.
171
+
172
+ ``Automatic video duration detection requires the 'video' extra``
173
+ Передайте ``duration`` в миллисекундах или установите
174
+ ``maxapi-python[video]``.
@@ -22,6 +22,7 @@ PyMax - асинхронная Python-библиотека для Max API. Он
22
22
  :maxdepth: 1
23
23
  :caption: Новости
24
24
 
25
+ release-2-4-0
25
26
  release-2-3-1
26
27
  release-2-3-0
27
28
  release-2-2-0
@@ -83,6 +83,57 @@ Messages
83
83
  source_chat_id=123456,
84
84
  )
85
85
 
86
+ Опросы
87
+ ------
88
+
89
+ Опрос можно отправить без текста. Настройки объединяются оператором ``|``:
90
+
91
+ .. code-block:: python
92
+
93
+ from pymax.types import Poll, PollAnswer, PollFlags
94
+
95
+ await client.send_message(
96
+ chat_id=123456,
97
+ attachments=[
98
+ Poll(
99
+ title="Какой вариант выбрать?",
100
+ answers=[
101
+ PollAnswer(text="Первый"),
102
+ PollAnswer(text="Второй"),
103
+ ],
104
+ settings=(
105
+ PollFlags.FLAG_SETTINGS_ANONYMOUS
106
+ | PollFlags.FLAG_SETTINGS_REVOTE
107
+ ),
108
+ )
109
+ ],
110
+ )
111
+
112
+ Для голосования нужны ID сообщения, опроса и вариантов из входящего
113
+ ``PollAttachment``:
114
+
115
+ .. code-block:: python
116
+
117
+ from pymax import Message
118
+ from pymax.types import PollAttachment
119
+
120
+ @client.on_message()
121
+ async def vote(message: Message, client: Client) -> None:
122
+ if message.chat_id is None:
123
+ return
124
+
125
+ for attach in message.attaches:
126
+ if isinstance(attach, PollAttachment):
127
+ answer_id = attach.answers[0].answer_id
128
+ if answer_id is not None:
129
+ state = await client.vote_poll(
130
+ chat_id=message.chat_id,
131
+ message_id=message.id,
132
+ poll_id=attach.poll_id,
133
+ answer_ids=[answer_id],
134
+ )
135
+ print(state.total)
136
+
86
137
  Ответ, реакции, удаление и прочтение
87
138
  ----------------------------------------
88
139
 
@@ -147,7 +198,7 @@ Messages
147
198
  .. code-block:: python
148
199
 
149
200
  history = await client.fetch_history(chat_id=123456, backward=50)
150
- for message in history or []:
201
+ for message in history:
151
202
  print(message.id, message.text)
152
203
 
153
204
  ``fetch_history()`` принимает ``item_type``. По умолчанию используются обычные
@@ -178,8 +229,8 @@ Max присылает разные формы событий. Некоторы
178
229
  --------
179
230
 
180
231
  Входящие вложения лежат в ``message.attaches``. Тип вложения определяется по
181
- полю ``type``: фото, видео, файл, стикер, аудио, контакт, звонок, share или
182
- inline-клавиатура.
232
+ полю ``type``: фото, видео, файл, стикер, аудио, опрос, контакт, звонок, share
233
+ или inline-клавиатура.
183
234
 
184
235
  .. code-block:: python
185
236
 
@@ -0,0 +1,210 @@
1
+ PyMax 2.4.0
2
+ ===========
3
+
4
+ Версия 2.4.0 добавляет опросы, голосовые сообщения, кружки, настройки
5
+ приватности и новые методы управления чатами. Одновременно уточнены контракты
6
+ существующих методов и исправлены проблемы с lifecycle клиента, повторной
7
+ авторизацией и WebSocket.
8
+
9
+ Ниже перечислены изменения относительно ``2.3.1``, которые важны при
10
+ использовании библиотеки и обновлении существующего кода.
11
+
12
+ Новый публичный API
13
+ -------------------
14
+
15
+ Опросы
16
+ ~~~~~~
17
+
18
+ Добавлены модели ``Poll``, ``PollAnswer`` и ``PollFlags`` для создания
19
+ опросов. Опрос отправляется обычным ``send_message()`` и может быть
20
+ единственным вложением без текста:
21
+
22
+ .. code-block:: python
23
+
24
+ from pymax.types import Poll, PollAnswer, PollFlags
25
+
26
+ message = await client.send_message(
27
+ chat_id=123456,
28
+ attachments=[
29
+ Poll(
30
+ title="Выберите вариант",
31
+ answers=[
32
+ PollAnswer(text="Первый"),
33
+ PollAnswer(text="Второй"),
34
+ ],
35
+ settings=PollFlags.FLAG_SETTINGS_REVOTE,
36
+ )
37
+ ],
38
+ )
39
+
40
+ Для голосования добавлен метод:
41
+
42
+ ``await client.vote_poll(chat_id, message_id, poll_id, answer_ids) -> PollState``
43
+
44
+ Входящий опрос представлен моделью ``PollAttachment``. Она содержит
45
+ ``poll_id``, варианты ответа и текущее состояние ``PollState`` с
46
+ типизированными результатами и голосами.
47
+
48
+ Голосовые сообщения и кружки
49
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50
+
51
+ Добавлены два типа отправляемых вложений:
52
+
53
+ ``Voice``
54
+ Голосовое сообщение. Принимает только готовый OGG-файл. PyMax не
55
+ перекодирует MP3, WAV и другие форматы.
56
+
57
+ ``VideoNote``
58
+ Круглое видеосообщение. Рекомендуемый формат — MP4 с H.264-видео 480x480,
59
+ 30 FPS и AAC-аудио. Длительность передается в миллисекундах через
60
+ ``duration``.
61
+
62
+ Оба класса экспортируются из ``pymax`` и передаются в ``attachments``:
63
+
64
+ .. code-block:: python
65
+
66
+ from pymax import VideoNote, Voice
67
+
68
+ await client.send_message(
69
+ chat_id=123456,
70
+ attachments=[Voice(path="voice.ogg")],
71
+ )
72
+ await client.send_message(
73
+ chat_id=123456,
74
+ attachments=[VideoNote(path="circle.mp4", duration=4200)],
75
+ )
76
+
77
+ Если ``duration`` для ``VideoNote`` не указан, PyMax может определить его
78
+ автоматически с необязательной зависимостью ``video``::
79
+
80
+ uv add "maxapi-python[video]"
81
+
82
+ Чаты и состояние аккаунта
83
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
84
+
85
+ .. list-table:: Новые методы
86
+ :header-rows: 1
87
+ :widths: 35 40 25
88
+
89
+ * - Метод
90
+ - Назначение
91
+ - Результат
92
+ * - ``get_chat_members(chat_id, marker=None, count=50)``
93
+ - Получить страницу участников чата. Ненулевой ``marker`` передается в
94
+ следующий вызов.
95
+ - ``tuple[list[Member], int]``
96
+ * - ``add_admin(chat_id, user_id, permissions)``
97
+ - Назначить администратора канала с явным списком
98
+ ``ChannelPermissions``.
99
+ - ``None``
100
+ * - ``set_presence(online=...)``
101
+ - Изменить статус, используемый при следующем login или ping.
102
+ - ``None``
103
+ * - ``is_update_available()``
104
+ - Проверить флаг обновления, полученный при handshake.
105
+ - ``bool``
106
+
107
+ Настройки приватности
108
+ ~~~~~~~~~~~~~~~~~~~~~
109
+
110
+ Добавлен метод
111
+ ``await client.change_profile_settings(settings) -> bool``. Он принимает
112
+ ``PrivacySettingsUpdate`` и изменяет только заполненные поля:
113
+
114
+ .. code-block:: python
115
+
116
+ from pymax import PrivacyAccess, PrivacySettingsUpdate
117
+
118
+ await client.change_profile_settings(
119
+ PrivacySettingsUpdate(
120
+ search_by_phone=PrivacyAccess.CONTACTS,
121
+ incoming_calls=PrivacyAccess.ALL,
122
+ chat_invites=PrivacyAccess.NOBODY,
123
+ phone_number_visibility=PrivacyAccess.CONTACTS,
124
+ hide_online_status=True,
125
+ safe_content_only=True,
126
+ )
127
+ )
128
+
129
+ Для настроек доступа используются ``PrivacyAccess.ALL``,
130
+ ``PrivacyAccess.CONTACTS`` и ``PrivacyAccess.NOBODY``. После успешного запроса
131
+ PyMax сохраняет новый ``config_hash`` в текущей сессии, поэтому следующая
132
+ авторизация продолжает синхронизацию с актуального состояния.
133
+
134
+ Изменения существующего API
135
+ ---------------------------
136
+
137
+ .. list-table:: Изменившиеся контракты
138
+ :header-rows: 1
139
+ :widths: 30 30 40
140
+
141
+ * - API
142
+ - Было в 2.3.1
143
+ - Стало в 2.4.0
144
+ * - ``send_message()`` и ``forward_message()``
145
+ - Возвращаемый тип допускал ``Message | None``.
146
+ - Возвращают ``Message``. Если сервер не прислал обязательный объект
147
+ сообщения, вызов завершается ошибкой.
148
+ * - ``Message.reply()``, ``Message.answer()``, ``Message.forward()`` и
149
+ ``Chat.answer()``
150
+ - Bound-методы также имели необязательный возвращаемый тип.
151
+ - Возвращают ``Message`` без лишней проверки на ``None``.
152
+ * - ``send_message()``, ``edit_message()``, ``Message.reply()``,
153
+ ``Message.answer()`` и ``Chat.answer()``
154
+ - Для type checker требовался текст.
155
+ - ``text`` может быть ``None``, если переданы вложения. Если нет ни
156
+ текста, ни вложений, выбрасывается ``ValueError``.
157
+ * - ``fetch_history()``
158
+ - При отсутствии сообщений мог вернуть ``None``.
159
+ - Всегда возвращает ``list[Message]``; пустая история — ``[]``.
160
+ * - ``get_bot_init_data()``
161
+ - ``chat_id`` был обязательным.
162
+ - ``chat_id`` необязателен, поэтому метод можно вызвать вне чата.
163
+ * - ``change_profile()``
164
+ - ``photo`` был типизирован как ``Any``.
165
+ - ``photo`` принимает ``Photo | None``.
166
+
167
+ Также исправлены типы частичных моделей протокола. В частности,
168
+ ``StickerAttachment.set_id`` теперь имеет тип ``int | None``, а поля неполных
169
+ событий реакций больше не считаются безусловно заполненными.
170
+
171
+ Breaking changes
172
+ ----------------
173
+
174
+ Методы и классы из 2.3.1 не удалялись и не переименовывались. Проверить перед
175
+ обновлением нужно два наблюдаемых изменения поведения:
176
+
177
+ * Код, который отличал ``None`` от пустого списка после ``fetch_history()``,
178
+ должен проверять пустоту списка: ``if not history``.
179
+ * Попытка отправить или отредактировать сообщение без текста и без вложений
180
+ теперь сразу завершается ``ValueError``. Сообщения только с вложением
181
+ поддерживаются штатно.
182
+
183
+ Изменения ``Message | None`` на ``Message`` у методов отправки и пересылки —
184
+ уточнение публичного контракта, а не новое успешное значение в runtime.
185
+ Пользователи mypy или Pyright могут удалить лишние проверки результата на
186
+ ``None``. При работе со ``StickerAttachment.set_id`` проверка на ``None``,
187
+ наоборот, теперь требуется.
188
+
189
+ Исправления стабильности и совместимости
190
+ ----------------------------------------
191
+
192
+ * Если текущую сессию отозвали с другого устройства, ответы
193
+ ``FAIL_LOGIN_TOKEN`` и ``FAIL_LOGOUT_ALL`` больше не оставляют клиент в
194
+ цикле переподключений. PyMax удаляет недействительный локальный token и
195
+ запускает авторизацию заново. Закрытие TLS-соединения ограничено timeout,
196
+ поэтому зависший shutdown не блокирует клиент бесконечно.
197
+ * ``stop()`` штатно завершает ожидающий ``start()``. Внешняя отмена задачи при
198
+ этом не поглощается и продолжает распространяться вызывающему коду.
199
+ * WebSocket-клиент использует актуальный endpoint и корректно обрабатывает
200
+ бинарные protocol frames.
201
+ * Mobile login поддерживает двухэтапный LOGIN/LOGIN2. Fingerprint устройства
202
+ выбирается автоматически из данных Android-версий от 26.9.1 до 26.25.0.
203
+ * Handshake без обязательного ``callsSeed`` завершается контролируемой ошибкой,
204
+ а не оставляет клиент в частично инициализированном состоянии.
205
+ * Исправлены очистка ожиданий при ошибках upload, выбор MP4 URL по качеству и
206
+ разбор частичных событий реакций и голосов в опросах.
207
+
208
+ Базовый набор зависимостей не изменился. Extra ``video`` нужен только для
209
+ автоматического определения длительности ``VideoNote``; при явном
210
+ ``duration`` он не требуется.
@@ -19,6 +19,15 @@ Domain enums
19
19
  .. autoclass:: pymax.types.domain.attachments.enums.TranscriptionStatus
20
20
  :members:
21
21
 
22
+ .. autoclass:: pymax.types.domain.attachments.enums.PollFlags
23
+ :members:
24
+
25
+ Chat API enums
26
+ --------------
27
+
28
+ .. autoclass:: pymax.api.chats.ChannelPermissions
29
+ :members:
30
+
22
31
  Client config enums
23
32
  -------------------
24
33
 
@@ -40,7 +40,7 @@ Types
40
40
  ``ContactInfo``
41
41
  Контакт телефонной книги для ``import_contacts()``.
42
42
 
43
- ``PhotoAttachment``, ``VideoAttachment``, ``FileAttachment`` и другие
43
+ ``PhotoAttachment``, ``VideoAttachment``, ``FileAttachment``, ``PollAttachment`` и другие
44
44
  Входящие вложения в ``message.attaches``.
45
45
 
46
46
  ``SyncState`` и ``SyncOverrides``
@@ -112,6 +112,8 @@ API reference
112
112
  control_attachment
113
113
  file_attachment
114
114
  photo_attachment
115
+ poll
116
+ poll_attachment
115
117
  share_attachment
116
118
  sticker_attachment
117
119
  video_attachment
@@ -0,0 +1,22 @@
1
+ Poll
2
+ ====
3
+
4
+ .. autoclass:: pymax.types.domain.attachments.poll.Poll
5
+ :members:
6
+ :show-inheritance:
7
+
8
+ .. autoclass:: pymax.types.domain.attachments.poll.PollAnswer
9
+ :members:
10
+ :show-inheritance:
11
+
12
+ .. autoclass:: pymax.types.domain.attachments.poll.PollState
13
+ :members:
14
+ :show-inheritance:
15
+
16
+ .. autoclass:: pymax.types.domain.attachments.poll.PollResult
17
+ :members:
18
+ :show-inheritance:
19
+
20
+ .. autoclass:: pymax.types.domain.attachments.poll.PollVote
21
+ :members:
22
+ :show-inheritance:
@@ -0,0 +1,6 @@
1
+ PollAttachment
2
+ ==============
3
+
4
+ .. autoclass:: pymax.types.domain.attachments.poll.PollAttachment
5
+ :members:
6
+ :show-inheritance: