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.
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/PKG-INFO +8 -4
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/README.md +4 -2
- maxapi_python-2.4.1/TODO.md +44 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/account.rst +12 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/auth.rst +2 -0
- maxapi_python-2.4.1/docs/api/client-session.rst +20 -0
- maxapi_python-2.4.1/docs/api/client-versions.rst +12 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client.rst +2 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/files.rst +8 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/auth.rst +24 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/chats.rst +42 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/client.rst +133 -8
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/faq.rst +5 -3
- maxapi_python-2.4.1/docs/files.rst +185 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/index.rst +2 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/messages.rst +123 -8
- maxapi_python-2.4.1/docs/release-2-4-0.rst +210 -0
- maxapi_python-2.4.1/docs/release-2-4-1.rst +103 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/troubleshooting.rst +4 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/enums.rst +18 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/index.rst +7 -4
- maxapi_python-2.4.1/docs/types/poll.rst +22 -0
- maxapi_python-2.4.1/docs/types/poll_attachment.rst +6 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/pyproject.toml +7 -2
- maxapi_python-2.4.1/scripts/todo.py +48 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/__init__.py +9 -2
- maxapi_python-2.4.1/src/pymax/_data/apk_fingerprints.json +767 -0
- maxapi_python-2.4.1/src/pymax/_data/rootca_ssl_rsa2022.crt +33 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/enums.py +1 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/payloads.py +28 -2
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/service.py +100 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/__init__.py +1 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/enums.py +15 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/payloads.py +18 -2
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/chats/service.py +43 -1
- maxapi_python-2.4.1/src/pymax/api/messages/__init__.py +1 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/messages/payloads.py +21 -7
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/messages/service.py +161 -24
- maxapi_python-2.4.1/src/pymax/api/self/__init__.py +3 -0
- maxapi_python-2.4.1/src/pymax/api/self/enums.py +20 -0
- maxapi_python-2.4.1/src/pymax/api/self/payloads.py +80 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/self/service.py +37 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/service.py +21 -8
- maxapi_python-2.4.1/src/pymax/api/uploads/payloads.py +63 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/uploads/service.py +247 -55
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/app.py +91 -18
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/__init__.py +2 -0
- maxapi_python-2.4.1/src/pymax/auth/exceptions.py +9 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/providers.py +6 -2
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/sms.py +11 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/base.py +90 -8
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/client.py +39 -10
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/client_web.py +17 -14
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/config.py +98 -19
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/connection.py +29 -18
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/enums.py +1 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/mapping.py +3 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/resolvers.py +7 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/__init__.py +4 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/base.py +58 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/video.py +51 -1
- maxapi_python-2.4.1/src/pymax/files/voice.py +53 -0
- maxapi_python-2.4.1/src/pymax/fingerprint/__init__.py +1 -0
- maxapi_python-2.4.1/src/pymax/fingerprint/fingerprint.py +30 -0
- maxapi_python-2.4.1/src/pymax/fingerprint/models.py +12 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/auth.py +4 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/bots.py +3 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/chat.py +47 -5
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/message.py +49 -14
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/protocol.py +5 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/self.py +25 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/enums.py +13 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/payload.py +21 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/session/__init__.py +1 -1
- maxapi_python-2.4.1/src/pymax/session/models.py +41 -0
- maxapi_python-2.4.1/src/pymax/session/protocol.py +40 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/session/store.py +73 -5
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/tcp.py +17 -4
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/websocket.py +6 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/__init__.py +2 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/__init__.py +2 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/call.py +7 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/contact.py +3 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/control.py +3 -0
- maxapi_python-2.4.1/src/pymax/types/domain/attachments/enums.py +60 -0
- maxapi_python-2.4.1/src/pymax/types/domain/attachments/poll.py +111 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/sticker.py +1 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/video.py +32 -11
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/chat.py +9 -9
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/enums.py +7 -0
- maxapi_python-2.4.1/src/pymax/types/domain/handshake.py +16 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/login.py +30 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/message.py +108 -27
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/user.py +1 -3
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/__init__.py +1 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/reaction.py +2 -2
- maxapi_python-2.4.1/src/pymax/types/events/voice.py +5 -0
- maxapi_python-2.4.1/src/pymax/versions/__init__.py +2 -0
- maxapi_python-2.4.1/src/pymax/versions/catalog.py +104 -0
- maxapi_python-2.4.1/src/pymax/versions/exceptions.py +10 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_auth_service.py +164 -2
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_chat_user_self_session_services.py +52 -6
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_message_service.py +70 -9
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/api/test_upload_service.py +66 -4
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/app/test_app_runtime.py +328 -6
- maxapi_python-2.4.1/tests/app/test_client_user_agent_config.py +37 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/auth/test_auth_flows.py +4 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/conftest.py +23 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/connection/test_connection.py +43 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/connection/test_readers_and_transports.py +32 -1
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/dispatch/test_dispatcher.py +8 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/domain/test_bound_models.py +1 -1
- maxapi_python-2.4.1/tests/domain/test_login_models.py +63 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/domain/test_message_models.py +36 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/files/test_files_and_formatting.py +5 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/protocol/test_protocols.py +26 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/session/test_store.py +65 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/uv.lock +21 -5
- maxapi_python-2.3.1/docs/files.rst +0 -117
- maxapi_python-2.3.1/src/pymax/api/messages/__init__.py +0 -1
- maxapi_python-2.3.1/src/pymax/api/self/__init__.py +0 -2
- maxapi_python-2.3.1/src/pymax/api/self/enums.py +0 -11
- maxapi_python-2.3.1/src/pymax/api/self/payloads.py +0 -41
- maxapi_python-2.3.1/src/pymax/api/uploads/payloads.py +0 -25
- maxapi_python-2.3.1/src/pymax/session/models.py +0 -11
- maxapi_python-2.3.1/src/pymax/session/protocol.py +0 -14
- maxapi_python-2.3.1/src/pymax/types/domain/attachments/enums.py +0 -28
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/pull_request_template.md +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/workflows/publish.yml +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.github/workflows/tests.yml +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.gitignore +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/.pre-commit-config.yaml +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/LICENSE +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/_static/.gitkeep +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client-client.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client-config.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/client-web.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/api/router.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/conf.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/examples.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/formatting.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/getting-started.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-0.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-1.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-2.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-1-3.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-2-0.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-3-0.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/release-2-3-1.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/router.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/audio_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/call_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/chat.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/contact_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/contact_info.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/control_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/element.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/file_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/folder.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/folder_list.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/folder_update.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/inline_keyboard_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/message.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/message_delete_event.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/message_read_event.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/name.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/photo_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/presence_event.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/profile.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/reaction_counter.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/reaction_info.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/reaction_update_event.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/read_state.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/session.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/share_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/sticker_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/sync_overrides.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/sync_state.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/typing_event.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/user.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/types/video_attachment.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/docs/users.rst +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/auth/types.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/binding.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/bots/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/bots/payloads.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/bots/service.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/facade.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/messages/enums.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/models.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/response.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/enums.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/session/payloads.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/uploads/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/uploads/models.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/enums.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/payloads.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/api/users/service.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/base.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/email.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/models.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/qr.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/auth/service.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/pending.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/base.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/tcp.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/connection/readers/ws.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/dispatcher.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/dispatch/router.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/exceptions.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/file.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/photo.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/files/static.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/formatting/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/formatting/markdown.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/base.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/infra/user.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/logging.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/base.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/models.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/compression.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/framing.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/protocol.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/ws/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/protocol/ws/protocol.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/py.typed +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/routers.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/navigation.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/payloads.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/telemetry/service.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/transport/base.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/audio.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/file.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/keyboards/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/keyboards/inline.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/photo.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/share.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/unknown.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/auth.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/base.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/bots.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/element.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/error.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/folder.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/member.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/name.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/presence.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/profile.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/session.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/domain/sync.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/file.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/mark.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/message.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/presence.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/typing.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/src/pymax/types/events/video.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/__init__.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/domain/test_user_models.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/telemetry/test_telemetry.py +0 -0
- {maxapi_python-2.3.1 → maxapi_python-2.4.1}/tests/test_logging.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: maxapi-python
|
|
3
|
-
Version: 2.
|
|
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
|
[](https://www.python.org/)
|
|
42
44
|
[](LICENSE)
|
|
43
45
|
[](https://pypi.org/project/maxapi-python/)
|
|
46
|
+
[](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
|
-
- Сообщения:
|
|
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
|
[](https://www.python.org/)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://pypi.org/project/maxapi-python/)
|
|
8
|
+
[](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
|
-
- Сообщения:
|
|
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
|
-
|
|
124
|
-
lifecycle.
|
|
132
|
+
Login еще не завершился. Читайте профиль внутри ``on_start`` или после
|
|
133
|
+
успешного ``await client.connect()``.
|
|
125
134
|
|
|
126
135
|
Фото профиля не обновилось
|
|
127
136
|
Если переданы и ``photo``, и ``photo_token``, PyMax загрузит ``photo`` и
|
|
@@ -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
|
|
@@ -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
|
-
|
|
12
|
-
|
|
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
|
-
Профиль текущего
|
|
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,
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
Неизвестный тип вложения сохраняется как ``UnknownAttachment`` и сам по себе не
|
|
97
|
+
должен ломать сообщение. Validation error обычно означает неполный или
|
|
98
|
+
измененный payload уже известной модели. Включите ``DEBUG``, снимите raw payload
|
|
99
|
+
через ``on_raw`` и обновите PyMax. Если ошибка повторяется, заведите issue с
|
|
100
|
+
очищенным payload без token, телефонов и приватных URL.
|