maxapi-python 2.4.0__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.4.0 → maxapi_python-2.4.1}/PKG-INFO +6 -4
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/README.md +4 -2
- maxapi_python-2.4.1/TODO.md +44 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/account.rst +2 -3
- {maxapi_python-2.4.0 → 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.4.0 → maxapi_python-2.4.1}/docs/api/client.rst +2 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/auth.rst +24 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/chats.rst +8 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/client.rst +109 -6
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/faq.rst +5 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/files.rst +18 -7
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/index.rst +1 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/messages.rst +69 -5
- maxapi_python-2.4.1/docs/release-2-4-1.rst +103 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/troubleshooting.rst +4 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/enums.rst +9 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/index.rst +4 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/pyproject.toml +2 -2
- maxapi_python-2.4.1/scripts/todo.py +48 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/__init__.py +4 -2
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/_data/apk_fingerprints.json +102 -17
- maxapi_python-2.4.1/src/pymax/_data/rootca_ssl_rsa2022.crt +33 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/auth/service.py +14 -2
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/chats/payloads.py +2 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/chats/service.py +7 -0
- maxapi_python-2.4.1/src/pymax/api/messages/__init__.py +1 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/messages/payloads.py +9 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/messages/service.py +106 -12
- maxapi_python-2.4.1/src/pymax/api/uploads/payloads.py +63 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/uploads/service.py +77 -62
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/app.py +23 -4
- {maxapi_python-2.4.0 → 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.4.0 → maxapi_python-2.4.1}/src/pymax/auth/providers.py +6 -2
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/auth/sms.py +11 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/base.py +83 -9
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/client.py +39 -10
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/client_web.py +15 -12
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/config.py +63 -21
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/base.py +58 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/video.py +32 -40
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/voice.py +18 -4
- maxapi_python-2.4.1/src/pymax/fingerprint/fingerprint.py +30 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/fingerprint/models.py +1 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/chat.py +9 -5
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/message.py +9 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/protocol.py +5 -1
- {maxapi_python-2.4.0 → 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.4.0 → maxapi_python-2.4.1}/src/pymax/session/store.py +73 -5
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/transport/tcp.py +11 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/call.py +7 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/contact.py +3 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/control.py +3 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/enums.py +16 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/video.py +3 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/enums.py +7 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/message.py +87 -7
- 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.4.0 → maxapi_python-2.4.1}/tests/api/test_auth_service.py +8 -19
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/api/test_chat_user_self_session_services.py +10 -2
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/api/test_message_service.py +6 -3
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/api/test_upload_service.py +6 -7
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/app/test_app_runtime.py +122 -1
- maxapi_python-2.4.1/tests/app/test_client_user_agent_config.py +37 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/auth/test_auth_flows.py +4 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/conftest.py +11 -2
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/connection/test_readers_and_transports.py +1 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/domain/test_bound_models.py +1 -1
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/session/test_store.py +65 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/uv.lock +5 -5
- maxapi_python-2.4.0/src/pymax/api/messages/__init__.py +0 -1
- maxapi_python-2.4.0/src/pymax/api/uploads/payloads.py +0 -31
- maxapi_python-2.4.0/src/pymax/fingerprint/fingerprint.py +0 -47
- maxapi_python-2.4.0/src/pymax/session/models.py +0 -11
- maxapi_python-2.4.0/src/pymax/session/protocol.py +0 -14
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.github/pull_request_template.md +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.github/workflows/publish.yml +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.github/workflows/tests.yml +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.gitignore +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/.pre-commit-config.yaml +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/LICENSE +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/_static/.gitkeep +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/api/client-client.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/api/client-config.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/api/client-web.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/api/files.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/api/router.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/conf.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/examples.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/formatting.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/getting-started.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-1-0.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-1-1.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-1-2.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-1-3.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-2-0.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-3-0.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-3-1.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/release-2-4-0.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/router.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/audio_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/call_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/chat.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/contact_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/contact_info.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/control_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/element.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/file_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/folder.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/folder_list.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/folder_update.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/inline_keyboard_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/message.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/message_delete_event.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/message_read_event.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/name.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/photo_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/poll.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/poll_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/presence_event.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/profile.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/reaction_counter.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/reaction_info.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/reaction_update_event.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/read_state.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/session.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/share_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/sticker_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/sync_overrides.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/sync_state.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/typing_event.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/user.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/types/video_attachment.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/docs/users.rst +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/auth/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/auth/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/auth/payloads.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/auth/types.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/binding.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/bots/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/bots/payloads.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/bots/service.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/chats/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/chats/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/facade.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/messages/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/response.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/self/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/self/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/self/payloads.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/self/service.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/session/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/session/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/session/payloads.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/session/service.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/uploads/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/uploads/models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/users/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/users/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/users/payloads.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/api/users/service.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/auth/base.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/auth/email.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/auth/models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/auth/qr.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/auth/service.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/connection.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/pending.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/readers/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/readers/base.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/readers/tcp.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/connection/readers/ws.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/dispatch/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/dispatch/dispatcher.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/dispatch/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/dispatch/mapping.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/dispatch/resolvers.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/dispatch/router.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/exceptions.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/file.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/photo.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/files/static.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/fingerprint/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/formatting/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/formatting/markdown.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/auth.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/base.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/bots.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/self.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/infra/user.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/logging.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/base.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/enums.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/compression.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/framing.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/payload.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/tcp/protocol.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/ws/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/protocol/ws/protocol.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/py.typed +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/routers.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/telemetry/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/telemetry/navigation.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/telemetry/payloads.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/telemetry/service.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/transport/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/transport/base.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/transport/websocket.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/audio.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/file.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/keyboards/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/keyboards/inline.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/photo.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/poll.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/share.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/sticker.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/attachments/unknown.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/auth.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/base.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/bots.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/chat.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/element.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/error.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/folder.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/handshake.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/login.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/member.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/name.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/presence.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/profile.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/session.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/sync.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/domain/user.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/file.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/mark.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/message.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/presence.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/reaction.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/typing.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/video.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/src/pymax/types/events/voice.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/__init__.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/connection/test_connection.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/dispatch/test_dispatcher.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/domain/test_login_models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/domain/test_message_models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/domain/test_user_models.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/files/test_files_and_formatting.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/protocol/test_protocols.py +0 -0
- {maxapi_python-2.4.0 → maxapi_python-2.4.1}/tests/telemetry/test_telemetry.py +0 -0
- {maxapi_python-2.4.0 → 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.4.
|
|
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
|
|
@@ -43,6 +43,7 @@ Python-библиотека для Max API.
|
|
|
43
43
|
[](https://www.python.org/)
|
|
44
44
|
[](LICENSE)
|
|
45
45
|
[](https://pypi.org/project/maxapi-python/)
|
|
46
|
+
[](https://pepy.tech/projects/maxapi-python)
|
|
46
47
|
|
|
47
48
|
> [!WARNING]
|
|
48
49
|
> PyMax использует неофициальный внутренний API Max. API может измениться без
|
|
@@ -62,10 +63,11 @@ WebSocket.
|
|
|
62
63
|
- Авторизация по телефону и SMS-коду через `Client`.
|
|
63
64
|
- QR-авторизация web-клиента через `WebClient`.
|
|
64
65
|
- Роутеры, фильтры, `on_start`, raw-события и typed events.
|
|
65
|
-
- Сообщения:
|
|
66
|
+
- Сообщения: отправка и планирование, ответы, реакции, pin, read, delete и история.
|
|
66
67
|
- Чаты, группы, участники, invite-ссылки и настройки групп.
|
|
67
68
|
- Пользователи, контакты, профиль, папки, активные сессии и 2FA.
|
|
68
|
-
- Вложения: `Photo`, `File`, `Video`.
|
|
69
|
+
- Вложения: `Photo`, `File`, `Video`, `Voice`, `VideoNote`.
|
|
70
|
+
- Выбор версии mobile-клиента с локальным или обновляемым каталогом fingerprints.
|
|
69
71
|
- SQLite-сессии, sync-state, reconnect и debug-логи.
|
|
70
72
|
- Pydantic-модели и удобные domain-объекты.
|
|
71
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
|
|
@@ -129,9 +129,8 @@ login или ping:
|
|
|
129
129
|
-------------
|
|
130
130
|
|
|
131
131
|
``client.me`` равен ``None``
|
|
132
|
-
Login еще не
|
|
133
|
-
|
|
134
|
-
lifecycle.
|
|
132
|
+
Login еще не завершился. Читайте профиль внутри ``on_start`` или после
|
|
133
|
+
успешного ``await client.connect()``.
|
|
135
134
|
|
|
136
135
|
Фото профиля не обновилось
|
|
137
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
|
|
|
@@ -129,10 +129,13 @@ login/sync, а также методы для загрузки, создания
|
|
|
129
129
|
|
|
130
130
|
.. code-block:: python
|
|
131
131
|
|
|
132
|
+
from pymax import Photo
|
|
133
|
+
|
|
132
134
|
await client.change_group_profile(
|
|
133
135
|
chat_id=123456,
|
|
134
136
|
name="Новый заголовок",
|
|
135
137
|
description="Описание группы",
|
|
138
|
+
photo=Photo(path="group.jpg"),
|
|
136
139
|
)
|
|
137
140
|
|
|
138
141
|
await client.change_group_settings(
|
|
@@ -141,6 +144,11 @@ login/sync, а также методы для загрузки, создания
|
|
|
141
144
|
only_admin_can_call=True,
|
|
142
145
|
)
|
|
143
146
|
|
|
147
|
+
``name``, ``description`` и ``photo`` независимы: передавайте только поля,
|
|
148
|
+
которые нужно изменить. Значение ``None`` исключает поле из запроса. Перед
|
|
149
|
+
обновлением профиля PyMax автоматически загружает ``Photo`` и отправляет Max
|
|
150
|
+
полученный photo token.
|
|
151
|
+
|
|
144
152
|
Через объект ``Chat`` можно менять настройки и перевыпускать invite-ссылку:
|
|
145
153
|
|
|
146
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,12 +27,31 @@ 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
|
+
|
|
36
55
|
Если ``start()`` запущен отдельной задачей, ``stop()`` штатно закрывает
|
|
37
56
|
соединение и завершает эту задачу без ``CancelledError``:
|
|
38
57
|
|
|
@@ -51,7 +70,7 @@ Client
|
|
|
51
70
|
После успешного login клиент хранит несколько кешей, которые пришли от Max:
|
|
52
71
|
|
|
53
72
|
``client.me``
|
|
54
|
-
Профиль текущего
|
|
73
|
+
Профиль текущего аккаунта.
|
|
55
74
|
|
|
56
75
|
``client.chats``
|
|
57
76
|
Чаты из login/sync. Это не гарантированно полный список всех чатов.
|
|
@@ -106,7 +125,46 @@ Client
|
|
|
106
125
|
Имя файла сессии внутри ``work_dir``.
|
|
107
126
|
|
|
108
127
|
``extra_config``
|
|
109
|
-
Настройки соединения, логов, 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
|
+
существовать.
|
|
110
168
|
|
|
111
169
|
Тип устройства
|
|
112
170
|
---------------
|
|
@@ -209,6 +267,8 @@ Client
|
|
|
209
267
|
qr_provider=ConfirmQrWithClient(mobile_client),
|
|
210
268
|
)
|
|
211
269
|
|
|
270
|
+
.. _client-session-guide:
|
|
271
|
+
|
|
212
272
|
Сессия и sync-state
|
|
213
273
|
-------------------
|
|
214
274
|
|
|
@@ -218,6 +278,7 @@ Client
|
|
|
218
278
|
* ``device_id``;
|
|
219
279
|
* телефон;
|
|
220
280
|
* ``mt_instance_id``;
|
|
281
|
+
* device/user-agent;
|
|
221
282
|
* sync-маркеры ``chats_sync``, ``contacts_sync``, ``drafts_sync``,
|
|
222
283
|
``presence_sync`` и ``config_hash``.
|
|
223
284
|
|
|
@@ -225,11 +286,49 @@ Client
|
|
|
225
286
|
``session_name="account.db"`` это будет ``cache/account.db``. Если файл удалить,
|
|
226
287
|
PyMax потеряет token и попросит авторизацию снова.
|
|
227
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
|
+
|
|
228
298
|
При login PyMax отправляет сохраненные маркеры серверу. Если маркер актуален,
|
|
229
299
|
сервер может вернуть только изменения. Поэтому повторный запуск отличается от
|
|
230
300
|
первого: первый запуск обычно использует ``-1`` и получает начальный sync,
|
|
231
301
|
а последующие запуски продолжают с сохраненного состояния.
|
|
232
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
|
+
|
|
233
332
|
Принудительный sync
|
|
234
333
|
-------------------
|
|
235
334
|
|
|
@@ -278,6 +377,10 @@ Reconnect
|
|
|
278
377
|
а новый ``App`` снова получает тот же root router. ``on_start`` вызывается
|
|
279
378
|
после каждого успешного reconnect.
|
|
280
379
|
|
|
380
|
+
Если сервер отозвал login token, ``ExtraConfig(relogin=True)`` по умолчанию
|
|
381
|
+
сбрасывает текущую сессию и запускает авторизацию заново. Значение ``False``
|
|
382
|
+
отключает этот автоматический сброс.
|
|
383
|
+
|
|
281
384
|
Перед повторным подключением можно зарегистрировать ``on_disconnect``:
|
|
282
385
|
|
|
283
386
|
.. code-block:: python
|
|
@@ -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.
|
|
@@ -17,7 +17,8 @@ Files
|
|
|
17
17
|
|
|
18
18
|
``Voice``
|
|
19
19
|
Голосовое сообщение. Поддерживается только формат OGG; PyMax не
|
|
20
|
-
конвертирует другие аудиоформаты.
|
|
20
|
+
конвертирует другие аудиоформаты. Длительность можно передать вручную или
|
|
21
|
+
определить автоматически через extra ``video``.
|
|
21
22
|
|
|
22
23
|
``VideoNote``
|
|
23
24
|
Круглое видеосообщение. Можно передать длительность вручную или установить
|
|
@@ -79,8 +80,9 @@ Files
|
|
|
79
80
|
``Voice`` и ``VideoNote`` имя берется из ``path`` или ``url``, если не
|
|
80
81
|
передано явно.
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
``duration`` для ``Voice`` и ``VideoNote`` задается в миллисекундах. Если
|
|
84
|
+
длительность не передана, установите дополнительную зависимость для её
|
|
85
|
+
автоматического определения:
|
|
84
86
|
|
|
85
87
|
.. code-block:: console
|
|
86
88
|
|
|
@@ -121,11 +123,20 @@ orientation hint. H.264 profile и level специально фиксирова
|
|
|
121
123
|
1. PyMax запрашивает у Max временный upload URL.
|
|
122
124
|
2. Читает файл из ``path``, ``url`` или ``raw``.
|
|
123
125
|
3. Загружает данные HTTP-запросом.
|
|
124
|
-
4. Для ``File
|
|
125
|
-
|
|
126
|
+
4. Для ``File`` и обычного ``Video`` ждет служебное событие готовности до
|
|
127
|
+
60 секунд.
|
|
126
128
|
5. Подставляет token/file_id/video_id в отправляемое сообщение.
|
|
127
129
|
|
|
128
130
|
Фото проходит проще: после HTTP-upload PyMax сразу достает token из ответа.
|
|
131
|
+
``Voice`` и ``VideoNote`` отправляются сразу после HTTP-upload. Если Max
|
|
132
|
+
ответил ``attachment.not.ready``, PyMax ждет событие готовности до 60 секунд и
|
|
133
|
+
повторяет отправку сообщения один раз.
|
|
134
|
+
|
|
135
|
+
Общий timeout HTTP-загрузки ``File``, ``Video``, ``Voice`` и ``VideoNote``
|
|
136
|
+
задается через ``ExtraConfig(upload_timeout=...)`` в секундах; значение по
|
|
137
|
+
умолчанию - ``900``. Он не применяется к ``Photo`` и не меняет отдельный
|
|
138
|
+
60-секундный лимит ожидания обработки. ``0`` и отрицательные значения
|
|
139
|
+
отключают общий timeout, но не отдельный 60-секундный socket/read timeout.
|
|
129
140
|
|
|
130
141
|
Скачать входящий файл
|
|
131
142
|
---------------------
|
|
@@ -170,5 +181,5 @@ orientation hint. H.264 profile и level специально фиксирова
|
|
|
170
181
|
что событие готовности файла не пришло за 60 секунд.
|
|
171
182
|
|
|
172
183
|
``Automatic video duration detection requires the 'video' extra``
|
|
173
|
-
|
|
174
|
-
``maxapi-python[video]``.
|
|
184
|
+
Для ``Voice`` или ``VideoNote`` передайте ``duration`` в миллисекундах либо
|
|
185
|
+
установите ``maxapi-python[video]``.
|
|
@@ -83,6 +83,57 @@ Messages
|
|
|
83
83
|
source_chat_id=123456,
|
|
84
84
|
)
|
|
85
85
|
|
|
86
|
+
Reply и forward во входящем сообщении
|
|
87
|
+
-------------------------------------
|
|
88
|
+
|
|
89
|
+
Если сообщение является reply или forward, поле ``message.link`` содержит
|
|
90
|
+
исходное ``message`` и его ``chat_id``. Для forward Max также может прислать
|
|
91
|
+
``chat_name``, ``chat_link``, ``chat_access_type`` и ``chat_icon_url``; для
|
|
92
|
+
скрытого источника эти поля равны ``None``. У обычного сообщения ``link`` равен
|
|
93
|
+
``None``.
|
|
94
|
+
|
|
95
|
+
.. code-block:: python
|
|
96
|
+
|
|
97
|
+
@client.on_message()
|
|
98
|
+
async def on_message(message: Message, client: Client) -> None:
|
|
99
|
+
if message.link is not None:
|
|
100
|
+
print("source:", message.link.chat_id, message.link.message.id)
|
|
101
|
+
|
|
102
|
+
Отложенная отправка
|
|
103
|
+
-------------------
|
|
104
|
+
|
|
105
|
+
``client.send_message()``, ``message.answer()`` и ``message.reply()`` принимают
|
|
106
|
+
``send_at`` трех видов:
|
|
107
|
+
|
|
108
|
+
* ``datetime`` - абсолютное время отправки;
|
|
109
|
+
* ``timedelta`` - задержка относительно текущего локального времени;
|
|
110
|
+
* ``int`` - Unix time в секундах.
|
|
111
|
+
|
|
112
|
+
.. code-block:: python
|
|
113
|
+
|
|
114
|
+
from datetime import datetime, timedelta, timezone
|
|
115
|
+
|
|
116
|
+
await client.send_message(
|
|
117
|
+
chat_id=123456,
|
|
118
|
+
text="Через пять минут",
|
|
119
|
+
send_at=timedelta(minutes=5),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
await client.send_message(
|
|
123
|
+
chat_id=123456,
|
|
124
|
+
text="В назначенное время",
|
|
125
|
+
send_at=datetime(2026, 9, 1, 12, 0, tzinfo=timezone.utc),
|
|
126
|
+
notify=False,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
``None`` и ``0`` означают немедленную отправку. Значение ``notify`` также
|
|
130
|
+
используется сервером при срабатывании отложенного сообщения.
|
|
131
|
+
|
|
132
|
+
У полученного отложенного сообщения поле ``delayed_attributes`` содержит
|
|
133
|
+
``time_to_fire`` в миллисекундах и флаги уведомлений. Для обычного сообщения
|
|
134
|
+
оно равно ``None``. Получить отложенные сообщения можно через
|
|
135
|
+
``fetch_history(item_type=ItemType.DELAYED)``.
|
|
136
|
+
|
|
86
137
|
Опросы
|
|
87
138
|
------
|
|
88
139
|
|
|
@@ -135,7 +186,7 @@ Messages
|
|
|
135
186
|
print(state.total)
|
|
136
187
|
|
|
137
188
|
Ответ, реакции, удаление и прочтение
|
|
138
|
-
|
|
189
|
+
------------------------------------
|
|
139
190
|
|
|
140
191
|
.. code-block:: python
|
|
141
192
|
|
|
@@ -160,6 +211,11 @@ Messages
|
|
|
160
211
|
WebSocket-клиент - как ``str``. Если вызываете метод напрямую, выбирайте
|
|
161
212
|
тип по клиенту.
|
|
162
213
|
|
|
214
|
+
Методы ``add_reaction()``, ``get_reactions()`` и ``remove_reaction()``
|
|
215
|
+
принимают ID сообщений только как ``int``. При этом ``get_reactions()``
|
|
216
|
+
возвращает словарь со строковыми ключами, потому что именно так ID приходят в
|
|
217
|
+
ответе Max.
|
|
218
|
+
|
|
163
219
|
Служебные события
|
|
164
220
|
-----------------
|
|
165
221
|
|
|
@@ -232,10 +288,15 @@ Max присылает разные формы событий. Некоторы
|
|
|
232
288
|
полю ``type``: фото, видео, файл, стикер, аудио, опрос, контакт, звонок, share
|
|
233
289
|
или inline-клавиатура.
|
|
234
290
|
|
|
291
|
+
Неизвестный ``_type`` не отклоняет все сообщение: PyMax возвращает
|
|
292
|
+
``UnknownAttachment``, сохраняет исходный тип в ``type``, а остальные поля - в
|
|
293
|
+
``model_extra``. Это позволяет принять payload нового типа до добавления его
|
|
294
|
+
отдельной модели в библиотеку.
|
|
295
|
+
|
|
235
296
|
.. code-block:: python
|
|
236
297
|
|
|
237
298
|
from pymax import Client, Message
|
|
238
|
-
from pymax.types.domain import FileAttachment, PhotoAttachment
|
|
299
|
+
from pymax.types.domain import FileAttachment, PhotoAttachment, UnknownAttachment
|
|
239
300
|
|
|
240
301
|
@client.on_message()
|
|
241
302
|
async def on_message(message: Message, client: Client) -> None:
|
|
@@ -252,6 +313,8 @@ Max присылает разные формы событий. Некоторы
|
|
|
252
313
|
file_id=attach.file_id,
|
|
253
314
|
)
|
|
254
315
|
print(file_info.url if file_info else "no url")
|
|
316
|
+
elif isinstance(attach, UnknownAttachment):
|
|
317
|
+
print("unknown:", attach.type, attach.model_extra)
|
|
255
318
|
|
|
256
319
|
Частые ошибки
|
|
257
320
|
-------------
|
|
@@ -266,6 +329,7 @@ Max присылает разные формы событий. Некоторы
|
|
|
266
329
|
знаете ``chat_id`` из другого источника.
|
|
267
330
|
|
|
268
331
|
Pydantic validation error на attachments
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
332
|
+
Неизвестный ``_type`` обрабатывается через ``UnknownAttachment``, но
|
|
333
|
+
поврежденный или неполный payload уже известного типа все еще может не пройти
|
|
334
|
+
валидацию. Включите debug-логи, посмотрите raw payload через ``on_raw`` и
|
|
335
|
+
обновите PyMax или добавьте обработку нового формата.
|