maxapi-python 2.1.3__tar.gz → 2.2.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.
- maxapi_python-2.2.0/.github/workflows/tests.yml +66 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/PKG-INFO +3 -11
- maxapi_python-2.2.0/docs/api/client-client.rst +18 -0
- maxapi_python-2.2.0/docs/api/client-config.rst +14 -0
- maxapi_python-2.2.0/docs/api/client-web.rst +17 -0
- maxapi_python-2.2.0/docs/api/client.rst +25 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/auth.rst +53 -1
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/client.rst +71 -2
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/index.rst +1 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/messages.rst +60 -1
- maxapi_python-2.2.0/docs/release-2-2-0.rst +57 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/router.rst +12 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/index.rst +4 -0
- maxapi_python-2.2.0/docs/types/message_read_event.rst +6 -0
- maxapi_python-2.2.0/docs/types/presence_event.rst +6 -0
- maxapi_python-2.2.0/docs/types/reaction_update_event.rst +6 -0
- maxapi_python-2.2.0/docs/types/typing_event.rst +6 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/pyproject.toml +10 -19
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/__init__.py +18 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/auth/payloads.py +7 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/auth/service.py +33 -30
- maxapi_python-2.2.0/src/pymax/api/binding.py +57 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/chats/service.py +34 -47
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/messages/enums.py +1 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/messages/payloads.py +16 -1
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/messages/service.py +85 -33
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/models.py +4 -6
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/response.py +2 -2
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/self/service.py +17 -26
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/session/payloads.py +2 -9
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/session/service.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/uploads/payloads.py +3 -9
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/uploads/service.py +33 -99
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/users/service.py +8 -16
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/app.py +2 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/qr.py +3 -9
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/sms.py +23 -11
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/base.py +38 -1
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/client.py +2 -1
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/client_web.py +1 -2
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/config.py +42 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/connection.py +2 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/readers/tcp.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/dispatch/dispatcher.py +36 -18
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/dispatch/enums.py +4 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/dispatch/mapping.py +34 -11
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/dispatch/resolvers.py +18 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/dispatch/router.py +34 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/formatting/markdown.py +22 -13
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/chat.py +12 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/message.py +74 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/logging.py +2 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/tcp/compression.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/tcp/framing.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/ws/protocol.py +3 -9
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/session/protocol.py +2 -6
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/session/store.py +8 -24
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/telemetry/navigation.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/telemetry/service.py +5 -17
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/transport/tcp.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/unknown.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/auth.py +24 -2
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/chat.py +38 -1
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/message.py +31 -1
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/presence.py +3 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/sync.py +5 -21
- maxapi_python-2.2.0/src/pymax/types/events/__init__.py +7 -0
- maxapi_python-2.2.0/src/pymax/types/events/mark.py +23 -0
- maxapi_python-2.2.0/src/pymax/types/events/message.py +89 -0
- maxapi_python-2.2.0/src/pymax/types/events/presence.py +15 -0
- maxapi_python-2.2.0/src/pymax/types/events/reaction.py +21 -0
- maxapi_python-2.2.0/src/pymax/types/events/typing.py +14 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/api/test_auth_service.py +60 -13
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/api/test_chat_user_self_session_services.py +46 -59
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/api/test_message_service.py +171 -9
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/api/test_upload_service.py +10 -31
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/app/test_app_runtime.py +5 -15
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/auth/test_auth_flows.py +73 -6
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/conftest.py +7 -21
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/connection/test_connection.py +9 -27
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/connection/test_readers_and_transports.py +3 -9
- maxapi_python-2.2.0/tests/dispatch/test_dispatcher.py +328 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/domain/test_bound_models.py +49 -19
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/files/test_files_and_formatting.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/protocol/test_protocols.py +1 -3
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/uv.lock +1 -51
- maxapi_python-2.1.3/docs/api/client.rst +0 -17
- maxapi_python-2.1.3/src/pymax/types/events/__init__.py +0 -3
- maxapi_python-2.1.3/src/pymax/types/events/message.py +0 -37
- maxapi_python-2.1.3/tests/dispatch/test_dispatcher.py +0 -102
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.github/pull_request_template.md +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.github/workflows/publish.yml +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.gitignore +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/.pre-commit-config.yaml +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/LICENSE +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/README.md +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/_static/.gitkeep +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/account.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/api/auth.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/api/files.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/api/router.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/chats.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/conf.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/examples.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/faq.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/files.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/formatting.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/getting-started.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/release-2-1-0.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/release-2-1-1.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/release-2-1-2.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/release-2-1-3.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/troubleshooting.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/audio_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/call_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/chat.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/contact_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/control_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/element.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/enums.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/file_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/folder.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/folder_list.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/folder_update.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/inline_keyboard_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/message.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/message_delete_event.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/name.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/photo_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/profile.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/reaction_counter.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/reaction_info.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/read_state.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/session.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/share_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/sticker_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/sync_overrides.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/sync_state.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/user.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/types/video_attachment.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/docs/users.rst +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/auth/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/auth/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/auth/types.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/bots/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/bots/payloads.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/bots/service.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/chats/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/chats/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/chats/payloads.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/facade.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/messages/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/self/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/self/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/self/payloads.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/session/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/session/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/uploads/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/uploads/models.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/users/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/users/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/api/users/payloads.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/email.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/models.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/providers.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/auth/service.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/pending.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/readers/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/readers/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/connection/readers/ws.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/dispatch/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/exceptions.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/files/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/files/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/files/file.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/files/photo.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/files/static.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/files/video.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/formatting/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/auth.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/bots.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/protocol.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/self.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/infra/user.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/models.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/tcp/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/tcp/payload.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/tcp/protocol.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/protocol/ws/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/py.typed +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/routers.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/session/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/session/models.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/telemetry/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/telemetry/payloads.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/transport/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/transport/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/transport/websocket.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/audio.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/call.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/contact.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/control.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/file.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/keyboards/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/keyboards/inline.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/photo.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/share.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/sticker.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/attachments/video.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/base.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/bots.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/element.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/enums.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/error.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/folder.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/login.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/member.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/name.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/profile.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/session.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/domain/user.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/events/file.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/src/pymax/types/events/video.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/__init__.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/domain/test_message_models.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/session/test_store.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/telemetry/test_telemetry.py +0 -0
- {maxapi_python-2.1.3 → maxapi_python-2.2.0}/tests/test_logging.py +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main, "dev/**"]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: checks-${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
lint:
|
|
18
|
+
name: Lint
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout repository
|
|
23
|
+
uses: actions/checkout@v6
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v8.1.0
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
|
|
30
|
+
- name: Install development dependencies
|
|
31
|
+
run: uv sync --group dev
|
|
32
|
+
|
|
33
|
+
- name: Check code formatting
|
|
34
|
+
run: uv run ruff format --check .
|
|
35
|
+
|
|
36
|
+
- name: Run Ruff linting
|
|
37
|
+
run: uv run ruff check .
|
|
38
|
+
|
|
39
|
+
tests:
|
|
40
|
+
name: Tests / Python ${{ matrix.python-version }}
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
|
|
43
|
+
strategy:
|
|
44
|
+
fail-fast: false
|
|
45
|
+
matrix:
|
|
46
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- name: Checkout repository
|
|
50
|
+
uses: actions/checkout@v6
|
|
51
|
+
|
|
52
|
+
- name: Install uv
|
|
53
|
+
uses: astral-sh/setup-uv@v8.1.0
|
|
54
|
+
with:
|
|
55
|
+
python-version: ${{ matrix.python-version }}
|
|
56
|
+
enable-cache: true
|
|
57
|
+
|
|
58
|
+
- name: Install development dependencies
|
|
59
|
+
run: uv sync --group dev
|
|
60
|
+
|
|
61
|
+
- name: Run tests with coverage
|
|
62
|
+
run: |
|
|
63
|
+
uv run pytest \
|
|
64
|
+
--cov=src/pymax \
|
|
65
|
+
--cov-report=term-missing:skip-covered \
|
|
66
|
+
--cov-report=markdown-append:$GITHUB_STEP_SUMMARY
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maxapi-python
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.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
|
|
7
7
|
Project-URL: Issues, https://github.com/MaxApiTeam/PyMax/issues
|
|
8
|
-
Project-URL: Documentation, https://
|
|
8
|
+
Project-URL: Documentation, https://docs.pymax.org
|
|
9
9
|
Author-email: ink <inkdev@proton.me>
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
License-File: LICENSE
|
|
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
24
|
Classifier: Typing :: Typed
|
|
24
25
|
Requires-Python: >=3.10
|
|
25
26
|
Requires-Dist: aiofiles>=25.1.0
|
|
@@ -30,15 +31,6 @@ Requires-Dist: pydantic>=2.10.0
|
|
|
30
31
|
Requires-Dist: python-socks[asyncio]>=2.8.1
|
|
31
32
|
Requires-Dist: qrcode>=8.2
|
|
32
33
|
Requires-Dist: websockets>=16.0
|
|
33
|
-
Provides-Extra: docs
|
|
34
|
-
Requires-Dist: furo>=2025.12.19; extra == 'docs'
|
|
35
|
-
Requires-Dist: sphinx-copybutton>=0.5.2; extra == 'docs'
|
|
36
|
-
Requires-Dist: sphinx>=8.1.3; extra == 'docs'
|
|
37
|
-
Provides-Extra: test
|
|
38
|
-
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'test'
|
|
39
|
-
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
|
|
40
|
-
Requires-Dist: pytest-timeout>=2.1.0; extra == 'test'
|
|
41
|
-
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
42
34
|
Description-Content-Type: text/markdown
|
|
43
35
|
|
|
44
36
|
# PyMax
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Client
|
|
2
|
+
======
|
|
3
|
+
|
|
4
|
+
.. currentmodule:: pymax
|
|
5
|
+
|
|
6
|
+
TCP-клиент с SMS-авторизацией. Это основной клиент для long-running
|
|
7
|
+
подключения, обработчиков событий и mobile API Max.
|
|
8
|
+
|
|
9
|
+
.. note::
|
|
10
|
+
|
|
11
|
+
``Client`` поддерживает ``ExtraConfig.device_type`` со значениями
|
|
12
|
+
``ANDROID``, ``IOS`` и ``DESKTOP``. Для :meth:`Client.authorize_qr_login`
|
|
13
|
+
используйте ``ANDROID`` или ``IOS``: с ``DESKTOP`` подтверждение QR-входа
|
|
14
|
+
не работает.
|
|
15
|
+
|
|
16
|
+
.. autoclass:: Client
|
|
17
|
+
:members:
|
|
18
|
+
:inherited-members:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Client Config
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
.. currentmodule:: pymax
|
|
5
|
+
|
|
6
|
+
Настройки, которые используются ``Client`` и ``WebClient``.
|
|
7
|
+
|
|
8
|
+
.. autoclass:: ExtraConfig
|
|
9
|
+
:members:
|
|
10
|
+
|
|
11
|
+
.. autoclass:: RegistrationConfig
|
|
12
|
+
:members:
|
|
13
|
+
|
|
14
|
+
.. autofunction:: configure_logging
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
WebClient
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
.. currentmodule:: pymax
|
|
5
|
+
|
|
6
|
+
WebSocket-клиент с QR-авторизацией. Он подходит, когда нужно подключаться как
|
|
7
|
+
web-клиент Max.
|
|
8
|
+
|
|
9
|
+
.. note::
|
|
10
|
+
|
|
11
|
+
В штатной конфигурации ``WebClient`` использует только ``DeviceType.WEB``.
|
|
12
|
+
Параметр ``ExtraConfig.device_type`` предназначен для ``Client`` и не
|
|
13
|
+
меняет тип устройства ``WebClient``.
|
|
14
|
+
|
|
15
|
+
.. autoclass:: WebClient
|
|
16
|
+
:members:
|
|
17
|
+
:inherited-members:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Clients API
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
.. currentmodule:: pymax
|
|
5
|
+
|
|
6
|
+
``Client`` и ``WebClient`` используют общий набор высокоуровневых методов,
|
|
7
|
+
но отличаются транспортом и способом авторизации:
|
|
8
|
+
|
|
9
|
+
``Client``
|
|
10
|
+
TCP-клиент с SMS-авторизацией. Поддерживает mobile ``device_type``:
|
|
11
|
+
``ANDROID``, ``IOS`` и ``DESKTOP``. Для подтверждения QR-входа через
|
|
12
|
+
:meth:`Client.authorize_qr_login` используйте ``ANDROID`` или ``IOS``:
|
|
13
|
+
с ``DESKTOP`` этот метод не работает.
|
|
14
|
+
|
|
15
|
+
``WebClient``
|
|
16
|
+
WebSocket-клиент с QR-авторизацией. В штатной конфигурации всегда
|
|
17
|
+
использует ``DeviceType.WEB``; ``ExtraConfig.device_type`` на него не
|
|
18
|
+
влияет.
|
|
19
|
+
|
|
20
|
+
.. toctree::
|
|
21
|
+
:maxdepth: 1
|
|
22
|
+
|
|
23
|
+
client-client
|
|
24
|
+
client-web
|
|
25
|
+
client-config
|
|
@@ -91,7 +91,7 @@ Provider нужен, когда код приходит не из консоли
|
|
|
91
91
|
Кастомный QR handler
|
|
92
92
|
--------------------
|
|
93
93
|
|
|
94
|
-
``QrHandler`` не
|
|
94
|
+
Обычно ``QrHandler`` не подтверждает QR сам. Его задача - показать ссылку
|
|
95
95
|
пользователю: вывести в терминал, отправить в web UI или положить в лог.
|
|
96
96
|
|
|
97
97
|
.. code-block:: python
|
|
@@ -110,6 +110,33 @@ Provider нужен, когда код приходит не из консоли
|
|
|
110
110
|
qr_provider=PrintQrUrl(),
|
|
111
111
|
)
|
|
112
112
|
|
|
113
|
+
Если у вас уже есть запущенный и авторизованный ``Client``, QR-ссылку можно
|
|
114
|
+
подтвердить программно через ``authorize_qr_login()``. Это удобно, когда
|
|
115
|
+
``WebClient`` получает QR, а основной mobile-клиент должен разрешить вход:
|
|
116
|
+
|
|
117
|
+
.. code-block:: python
|
|
118
|
+
|
|
119
|
+
from pymax import Client, WebClient
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class ConfirmQrWithClient:
|
|
123
|
+
def __init__(self, client: Client) -> None:
|
|
124
|
+
self.client = client
|
|
125
|
+
|
|
126
|
+
async def show_qr(self, qr_url: str) -> None:
|
|
127
|
+
await self.client.authorize_qr_login(qr_url)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
mobile_client = Client(phone="+79990000000", work_dir="cache")
|
|
131
|
+
# mobile_client должен уже пройти start/login в вашей программе.
|
|
132
|
+
web_client = WebClient(qr_provider=ConfirmQrWithClient(mobile_client))
|
|
133
|
+
|
|
134
|
+
``mobile_client`` должен быть уже авторизован к моменту вызова
|
|
135
|
+
``show_qr()``. Для такого подтверждения используйте ``Client`` с
|
|
136
|
+
``device_type`` ``ANDROID`` или ``IOS``; при ``DESKTOP`` метод
|
|
137
|
+
``authorize_qr_login()`` не работает. ``WebClient`` в штатной конфигурации
|
|
138
|
+
всегда использует ``WEB``.
|
|
139
|
+
|
|
113
140
|
Полный кастомный AuthFlow
|
|
114
141
|
-------------------------
|
|
115
142
|
|
|
@@ -146,6 +173,31 @@ Flow должен иметь async-метод ``authenticate(app)`` и верн
|
|
|
146
173
|
Если вам нужно только передать готовый token, проще использовать
|
|
147
174
|
``ExtraConfig(token="TOKEN")``. Тогда custom flow не нужен.
|
|
148
175
|
|
|
176
|
+
Регистрация нового аккаунта
|
|
177
|
+
---------------------------
|
|
178
|
+
|
|
179
|
+
Если номер ещё не зарегистрирован в Max, после SMS-кода сервер возвращает
|
|
180
|
+
токен регистрации. Чтобы стандартный ``SmsAuthFlow`` завершил создание
|
|
181
|
+
аккаунта, передайте имя через ``RegistrationConfig``:
|
|
182
|
+
|
|
183
|
+
.. code-block:: python
|
|
184
|
+
|
|
185
|
+
from pymax import Client, ExtraConfig, RegistrationConfig
|
|
186
|
+
|
|
187
|
+
client = Client(
|
|
188
|
+
phone="+79990000000",
|
|
189
|
+
extra_config=ExtraConfig(
|
|
190
|
+
registration_config=RegistrationConfig(
|
|
191
|
+
first_name="Max",
|
|
192
|
+
last_name="User",
|
|
193
|
+
)
|
|
194
|
+
),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
Для уже существующего аккаунта эта настройка не используется. Если Max
|
|
198
|
+
вернул токен регистрации, а ``registration_config`` не задан, авторизация
|
|
199
|
+
завершится с ``RuntimeError``.
|
|
200
|
+
|
|
149
201
|
Управление 2FA
|
|
150
202
|
--------------
|
|
151
203
|
|
|
@@ -16,9 +16,11 @@ Client
|
|
|
16
16
|
|
|
17
17
|
``Client``
|
|
18
18
|
TCP-клиент с авторизацией по телефону и SMS-коду. Это основной вариант.
|
|
19
|
+
Поддерживает ``device_type`` ``ANDROID``, ``IOS`` и ``DESKTOP``.
|
|
19
20
|
|
|
20
21
|
``WebClient``
|
|
21
|
-
WebSocket-клиент с QR-авторизацией.
|
|
22
|
+
WebSocket-клиент с QR-авторизацией. В штатной конфигурации работает как
|
|
23
|
+
``WEB``-устройство.
|
|
22
24
|
|
|
23
25
|
Жизненный цикл
|
|
24
26
|
--------------
|
|
@@ -85,6 +87,32 @@ Client
|
|
|
85
87
|
``extra_config``
|
|
86
88
|
Настройки соединения, логов, reconnect, token, device/user-agent и sync.
|
|
87
89
|
|
|
90
|
+
Тип устройства
|
|
91
|
+
---------------
|
|
92
|
+
|
|
93
|
+
``Client`` по умолчанию использует ``DeviceType.ANDROID``. Если нужно
|
|
94
|
+
поменять тип устройства, передайте ``device_type`` через ``ExtraConfig``:
|
|
95
|
+
|
|
96
|
+
.. code-block:: python
|
|
97
|
+
|
|
98
|
+
from pymax import Client, ExtraConfig
|
|
99
|
+
from pymax.api.session.enums import DeviceType
|
|
100
|
+
|
|
101
|
+
client = Client(
|
|
102
|
+
phone="+79990000000",
|
|
103
|
+
work_dir="cache",
|
|
104
|
+
extra_config=ExtraConfig(device_type=DeviceType.IOS),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
Для ``Client`` доступны ``ANDROID``, ``IOS`` и ``DESKTOP``. Практический
|
|
108
|
+
нюанс: ``authorize_qr_login()`` подтверждает QR-вход только из mobile-режима,
|
|
109
|
+
поэтому для него используйте ``ANDROID`` или ``IOS``. С ``DESKTOP`` этот метод
|
|
110
|
+
не работает.
|
|
111
|
+
|
|
112
|
+
``WebClient`` сам использует ``DeviceType.WEB``. Параметр
|
|
113
|
+
``ExtraConfig.device_type`` относится к ``Client`` и не меняет тип устройства
|
|
114
|
+
``WebClient``.
|
|
115
|
+
|
|
88
116
|
Авторизация
|
|
89
117
|
-----------
|
|
90
118
|
|
|
@@ -119,6 +147,47 @@ Client
|
|
|
119
147
|
extra_config=ExtraConfig(token="TOKEN"),
|
|
120
148
|
)
|
|
121
149
|
|
|
150
|
+
Подтверждение QR-входа
|
|
151
|
+
----------------------
|
|
152
|
+
|
|
153
|
+
``Client`` может подтверждать QR-вход по ссылке через
|
|
154
|
+
``authorize_qr_login()``. Это полезно, когда QR-ссылку показал другой клиент
|
|
155
|
+
или ваш UI получил ее от ``WebClient``:
|
|
156
|
+
|
|
157
|
+
.. code-block:: python
|
|
158
|
+
|
|
159
|
+
async def confirm_qr(client: Client, qr_link: str) -> None:
|
|
160
|
+
ok = await client.authorize_qr_login(qr_link)
|
|
161
|
+
print("QR подтвержден:", ok)
|
|
162
|
+
|
|
163
|
+
``Client`` для такого подтверждения должен быть уже авторизован. Также
|
|
164
|
+
проверьте ``device_type``: используйте ``ANDROID`` или ``IOS``, не
|
|
165
|
+
``DESKTOP``.
|
|
166
|
+
|
|
167
|
+
Если QR создает ``WebClient``, ссылку можно перехватить в своем
|
|
168
|
+
``QrHandler`` и подтвердить ее уже запущенным ``Client``:
|
|
169
|
+
|
|
170
|
+
.. code-block:: python
|
|
171
|
+
|
|
172
|
+
from pymax import Client, WebClient
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class ConfirmQrWithClient:
|
|
176
|
+
def __init__(self, client: Client) -> None:
|
|
177
|
+
self.client = client
|
|
178
|
+
|
|
179
|
+
async def show_qr(self, qr_url: str) -> None:
|
|
180
|
+
await self.client.authorize_qr_login(qr_url)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
mobile_client = Client(phone="+79990000000", work_dir="cache")
|
|
184
|
+
# mobile_client должен уже пройти start/login в вашей программе.
|
|
185
|
+
web_client = WebClient(
|
|
186
|
+
work_dir="cache",
|
|
187
|
+
session_name="web.db",
|
|
188
|
+
qr_provider=ConfirmQrWithClient(mobile_client),
|
|
189
|
+
)
|
|
190
|
+
|
|
122
191
|
Сессия и sync-state
|
|
123
192
|
-------------------
|
|
124
193
|
|
|
@@ -226,7 +295,7 @@ Debug-логи показывают handshake, login, входящие собы
|
|
|
226
295
|
``close_all_sessions()``. Подробнее: :doc:`account`.
|
|
227
296
|
|
|
228
297
|
Auth
|
|
229
|
-
``set_2fa()
|
|
298
|
+
``set_2fa()``, ``remove_2fa()`` и ``authorize_qr_login()``. Подробнее:
|
|
230
299
|
:doc:`auth`.
|
|
231
300
|
|
|
232
301
|
Частые ошибки
|
|
@@ -30,7 +30,27 @@ Messages
|
|
|
30
30
|
|
|
31
31
|
@client.on_message_delete()
|
|
32
32
|
async def on_delete(event: MessageDeleteEvent, client: Client) -> None:
|
|
33
|
-
print("deleted in chat:", event.
|
|
33
|
+
print("deleted in chat:", event.chat_id)
|
|
34
|
+
|
|
35
|
+
Получать и редактировать сообщения
|
|
36
|
+
----------------------------------
|
|
37
|
+
|
|
38
|
+
.. code-block:: python
|
|
39
|
+
|
|
40
|
+
message = await client.get_message(
|
|
41
|
+
chat_id=123456,
|
|
42
|
+
message_id=987654,
|
|
43
|
+
)
|
|
44
|
+
messages = await client.get_messages(
|
|
45
|
+
chat_id=123456,
|
|
46
|
+
message_ids=[987654, 987655],
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if message is not None:
|
|
50
|
+
await message.edit("Обновленный текст")
|
|
51
|
+
|
|
52
|
+
Через клиент то же редактирование доступно как
|
|
53
|
+
``client.edit_message(chat_id, message_id, text, ...)``.
|
|
34
54
|
|
|
35
55
|
Отправлять сообщения
|
|
36
56
|
--------------------
|
|
@@ -69,6 +89,45 @@ Messages
|
|
|
69
89
|
elif message.text == "/delete":
|
|
70
90
|
await message.delete(for_me=False)
|
|
71
91
|
|
|
92
|
+
.. note::
|
|
93
|
+
|
|
94
|
+
У низкоуровневого ``client.read_message(...)`` есть особенность Max:
|
|
95
|
+
для отметки прочтения TCP-клиент ожидает ``message_id`` как ``int``, а
|
|
96
|
+
WebSocket-клиент - как ``str``. Если вызываете метод напрямую, выбирайте
|
|
97
|
+
тип по клиенту.
|
|
98
|
+
|
|
99
|
+
Служебные события
|
|
100
|
+
-----------------
|
|
101
|
+
|
|
102
|
+
В ``2.2.0`` доступны отдельные обработчики набора текста, присутствия,
|
|
103
|
+
прочтения и реакций:
|
|
104
|
+
|
|
105
|
+
.. code-block:: python
|
|
106
|
+
|
|
107
|
+
from pymax import (
|
|
108
|
+
Client,
|
|
109
|
+
MessageReadEvent,
|
|
110
|
+
PresenceEvent,
|
|
111
|
+
ReactionUpdateEvent,
|
|
112
|
+
TypingEvent,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
@client.on_typing()
|
|
116
|
+
async def typing(event: TypingEvent, client: Client) -> None:
|
|
117
|
+
print(event.chat_id, event.user_id)
|
|
118
|
+
|
|
119
|
+
@client.on_presence()
|
|
120
|
+
async def presence(event: PresenceEvent, client: Client) -> None:
|
|
121
|
+
print(event.user_id, event.presence.status)
|
|
122
|
+
|
|
123
|
+
@client.on_message_read()
|
|
124
|
+
async def read(event: MessageReadEvent, client: Client) -> None:
|
|
125
|
+
print(event.chat_id, event.mark)
|
|
126
|
+
|
|
127
|
+
@client.on_reaction_update()
|
|
128
|
+
async def reactions(event: ReactionUpdateEvent, client: Client) -> None:
|
|
129
|
+
print(event.message_id, event.total_count)
|
|
130
|
+
|
|
72
131
|
История сообщений
|
|
73
132
|
-----------------
|
|
74
133
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
PyMax 2.2.0
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
Изменения относительно ``2.1.3``.
|
|
5
|
+
|
|
6
|
+
Добавлено
|
|
7
|
+
---------
|
|
8
|
+
|
|
9
|
+
* Получение сообщений по ID через ``get_message()`` и ``get_messages()``.
|
|
10
|
+
Те же операции доступны на bound-объекте ``Chat``.
|
|
11
|
+
* Редактирование сообщений через ``edit_message()`` и ``Message.edit()`` с
|
|
12
|
+
поддержкой markdown, фото, видео и файлов.
|
|
13
|
+
* События ``TypingEvent``, ``PresenceEvent``, ``MessageReadEvent`` и
|
|
14
|
+
``ReactionUpdateEvent`` с обработчиками ``on_typing()``, ``on_presence()``,
|
|
15
|
+
``on_message_read()`` и ``on_reaction_update()``.
|
|
16
|
+
* ``join_channel()`` для вступления в канал по полной ссылке или join-токену.
|
|
17
|
+
* Автоматическое завершение SMS-регистрации нового аккаунта через
|
|
18
|
+
``RegistrationConfig`` в ``ExtraConfig.registration_config``.
|
|
19
|
+
* Поддержка Python 3.14 в метаданных пакета и CI-матрице.
|
|
20
|
+
|
|
21
|
+
Исправлено
|
|
22
|
+
----------
|
|
23
|
+
|
|
24
|
+
* Позиции markdown-элементов теперь корректно считаются в UTF-16 для emoji и
|
|
25
|
+
других символов вне BMP.
|
|
26
|
+
* Удаление сообщения в ``WebClient`` распознается из события
|
|
27
|
+
``NOTIF_MESSAGE`` со статусом ``REMOVED``.
|
|
28
|
+
* ``MessageDeleteEvent`` принимает обе формы payload-а Max и не требует поле
|
|
29
|
+
``ttl``.
|
|
30
|
+
* ``PresenceEvent`` принимает частичные обновления, в которых Max присылает
|
|
31
|
+
``seen`` без ``status``.
|
|
32
|
+
* ``read_message()`` сохраняет тип ``message_id``: ``int`` для ``Client`` и
|
|
33
|
+
``str`` для ``WebClient``.
|
|
34
|
+
* Вложенные ``Message``, ``Chat`` и ``User`` из API-ответов и событий
|
|
35
|
+
привязываются к сервисам клиента, поэтому их bound-методы работают
|
|
36
|
+
последовательно.
|
|
37
|
+
|
|
38
|
+
Изменилось
|
|
39
|
+
----------
|
|
40
|
+
|
|
41
|
+
* ``MessageDeleteEvent`` всегда содержит ``chat_id``. Поля ``chat`` и
|
|
42
|
+
``message`` зависят от формы события и могут быть ``None``.
|
|
43
|
+
* Проверка типов ``pyright`` ограничена релизным пакетом ``src`` и снова
|
|
44
|
+
проходит без ошибок.
|
|
45
|
+
* Документация клиента разделена на отдельные API-страницы для ``Client``,
|
|
46
|
+
``WebClient`` и конфигурации.
|
|
47
|
+
|
|
48
|
+
Миграция
|
|
49
|
+
--------
|
|
50
|
+
|
|
51
|
+
* В обработчике удаления используйте ``event.chat_id`` вместо
|
|
52
|
+
``event.chat.id``: ``event.chat`` может отсутствовать в ``WebClient``.
|
|
53
|
+
* При прямом вызове ``read_message()`` передавайте ``int`` в ``Client`` и
|
|
54
|
+
``str`` в ``WebClient``.
|
|
55
|
+
* Для регистрации нового номера задайте
|
|
56
|
+
``ExtraConfig(registration_config=RegistrationConfig(...))``. Для уже
|
|
57
|
+
существующих аккаунтов настройка не нужна.
|
|
@@ -175,6 +175,18 @@ Raw events
|
|
|
175
175
|
async def raw(frame: InboundFrame, client: Client) -> None:
|
|
176
176
|
print(frame.opcode, frame.payload)
|
|
177
177
|
|
|
178
|
+
Другие события
|
|
179
|
+
--------------
|
|
180
|
+
|
|
181
|
+
Кроме новых и измененных сообщений, доступны специализированные декораторы:
|
|
182
|
+
|
|
183
|
+
* ``on_message_delete()`` и ``on_message_read()``;
|
|
184
|
+
* ``on_typing()`` и ``on_presence()``;
|
|
185
|
+
* ``on_reaction_update()`` и ``on_chat_update()``.
|
|
186
|
+
|
|
187
|
+
Все они поддерживают те же sync/async-фильтры и сигнатуру
|
|
188
|
+
``handler(event, client)``.
|
|
189
|
+
|
|
178
190
|
Частые ошибки
|
|
179
191
|
-------------
|
|
180
192
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "maxapi-python"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.2.0"
|
|
4
4
|
description = "Python wrapper для API мессенджера Max"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -20,6 +20,7 @@ classifiers = [
|
|
|
20
20
|
"Programming Language :: Python :: 3.11",
|
|
21
21
|
"Programming Language :: Python :: 3.12",
|
|
22
22
|
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
23
24
|
]
|
|
24
25
|
dependencies = [
|
|
25
26
|
"aiofiles>=25.1.0",
|
|
@@ -36,20 +37,8 @@ dependencies = [
|
|
|
36
37
|
Homepage = "https://github.com/MaxApiTeam/PyMax"
|
|
37
38
|
Repository = "https://github.com/MaxApiTeam/PyMax"
|
|
38
39
|
Issues = "https://github.com/MaxApiTeam/PyMax/issues"
|
|
39
|
-
Documentation = "https://
|
|
40
|
+
Documentation = "https://docs.pymax.org"
|
|
40
41
|
|
|
41
|
-
[project.optional-dependencies]
|
|
42
|
-
docs = [
|
|
43
|
-
"furo>=2025.12.19",
|
|
44
|
-
"sphinx>=8.1.3",
|
|
45
|
-
"sphinx-copybutton>=0.5.2",
|
|
46
|
-
]
|
|
47
|
-
test = [
|
|
48
|
-
"pytest>=8.0.0",
|
|
49
|
-
"pytest-asyncio>=0.24.0",
|
|
50
|
-
"pytest-cov>=5.0.0",
|
|
51
|
-
"pytest-timeout>=2.1.0",
|
|
52
|
-
]
|
|
53
42
|
|
|
54
43
|
[build-system]
|
|
55
44
|
requires = ["hatchling"]
|
|
@@ -88,28 +77,30 @@ test = [
|
|
|
88
77
|
dev = [
|
|
89
78
|
{include-group = "docs"},
|
|
90
79
|
{include-group = "test"},
|
|
91
|
-
"build>=1.2.0",
|
|
92
80
|
"pre-commit>=4.0.0",
|
|
93
81
|
"twine>=5.0.0",
|
|
94
82
|
"pyright>=1.1.390",
|
|
95
83
|
"ruff>=0.8.0",
|
|
96
84
|
]
|
|
97
85
|
|
|
86
|
+
[tool.uv]
|
|
87
|
+
package = true
|
|
88
|
+
|
|
98
89
|
[tool.pyright]
|
|
90
|
+
include = ["src"]
|
|
99
91
|
venv = ".venv"
|
|
100
92
|
venvPath = "."
|
|
101
93
|
|
|
102
94
|
[tool.ruff]
|
|
103
|
-
line-length =
|
|
104
|
-
target-version = "py310"
|
|
95
|
+
line-length = 99
|
|
105
96
|
|
|
106
97
|
[tool.ruff.lint]
|
|
107
98
|
select = ["E", "F", "I"]
|
|
108
|
-
ignore = [
|
|
99
|
+
ignore = []
|
|
109
100
|
|
|
110
101
|
[tool.ruff.lint.per-file-ignores]
|
|
111
|
-
"src/pymax/**/__init__.py" = ["F401", "F403"]
|
|
112
102
|
"tests/**" = ["F401"]
|
|
103
|
+
"**/__init__.py" = ["F401", "F403"]
|
|
113
104
|
|
|
114
105
|
[tool.ruff.format]
|
|
115
106
|
quote-style = "double"
|