qqmusic-api-python 0.6.0__tar.gz → 0.6.2__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.
- qqmusic_api_python-0.6.2/CLAUDE.md +1 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/PKG-INFO +1 -1
- qqmusic_api_python-0.6.2/docs/reference/modules/private_message.md +3 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/release-notes.md +41 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/tutorial/client.md +12 -0
- qqmusic_api_python-0.6.2/examples/private_message.py +74 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/__init__.py +1 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/core/client.py +143 -64
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/core/request.py +1 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/core/versioning.py +4 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/comment.py +20 -0
- qqmusic_api_python-0.6.2/qqmusic_api/models/private_message.py +350 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/recommend.py +2 -10
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/request.py +3 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/__init__.py +2 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/comment.py +60 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/login.py +3 -1
- qqmusic_api_python-0.6.2/qqmusic_api/modules/private_message.py +518 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/recommend.py +8 -2
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/utils/device.py +4 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/utils/qimei.py +33 -36
- qqmusic_api_python-0.6.2/tests/test_private_message.py +38 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/uv.lock +256 -256
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/run.py +23 -10
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/app.py +19 -10
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/auth.py +30 -30
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/cache.py +14 -14
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/config.py +7 -4
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/credential_store.py +24 -21
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/security.py +2 -0
- qqmusic_api_python-0.6.2/web/src/modules/comment.py +24 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/modules/login.py +28 -5
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/modules/mv.py +1 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/modules/singer.py +1 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/modules/song.py +15 -4
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/modules/songlist.py +1 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/_helpers.py +9 -4
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/comment.py +33 -3
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/recommend.py +8 -2
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routing/params.py +27 -3
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routing/route_types.py +1 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routing/router_factory.py +2 -1
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/zensical.toml +1 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.agents/skills/pydantic/SKILL.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.agents/skills/python-standards/SKILL.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.agents/skills/tarsio/SKILL.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.agents/skills/tarsio/references/api-reference.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.agents/skills/uv-package-manager/SKILL.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.dockerignore +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/renovate.json +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/workflows/checking.yaml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/workflows/docs.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/workflows/release.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.github/workflows/testing.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.gitignore +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/.markdownlint-cli2.yaml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/AGENTS.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/LICENSE +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/README.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/assets/qq-music.svg +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/cliff.toml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/coding.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/contributing.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/index.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/core/client.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/core/exception.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/core/pagination.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/core/request.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/core/versioning.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/album.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/base.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/comment.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/login.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/lyric.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/mv.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/recommend.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/request.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/search.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/singer.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/song.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/songlist.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/top.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/model/user.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/album.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/comment.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/login.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/login_utils.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/lyric.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/mv.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/recommend.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/search.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/singer.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/song.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/songlist.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/top.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/reference/modules/user.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/tutorial/credential.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/tutorial/pagination.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/tutorial/start.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/docs/tutorial/web.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/examples/download_song.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/examples/phone_login.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/examples/qrcode_login.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/prek.toml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/pyproject.toml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/algorithms/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/algorithms/tripledes.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/core/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/core/exceptions.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/core/pagination.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/album.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/base.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/login.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/lyric.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/mv.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/search.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/singer.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/song.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/songlist.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/top.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/models/user.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/_base.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/album.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/login_utils.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/lyric.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/mv.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/search.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/singer.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/song.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/songlist.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/top.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/modules/user.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/utils/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/utils/common.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/qqmusic_api/utils/mqtt.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/scripts/ag-1.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/conftest.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_album.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_comment.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_login.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_login_utils.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_lyric.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_mv.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_recommend.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_search.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_singer.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_song.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_songlist.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_top.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/tests/test_user.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/.gitignore +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/Dockerfile +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/README.md +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/accounts.example.toml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/config.example.toml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/docker-compose.yml +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/deps.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/core/response.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/modules/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/album.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/login.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/lyric.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/mv.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/search.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/singer.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/song.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/songlist.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/top.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routes/user.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routing/__init__.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routing/docstrings.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/src/routing/executor.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/tests/test_web_docstrings.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/tests/test_web_enums.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/tests/test_web_route_validation.py +0 -0
- {qqmusic_api_python-0.6.0 → qqmusic_api_python-0.6.2}/web/tests/test_web_routes.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
|
|
2
|
+
## [[0.6.1](https://github.com/L-1124/QQMusicApi/compare/v0.6.0..v0.6.1)] - 2026-05-20
|
|
3
|
+
|
|
4
|
+
### Bug 修复
|
|
5
|
+
|
|
6
|
+
* 传入的platform不生效 ([b19bec5](https://github.com/L-1124/QQMusicApi/commit/b19bec52f044d6508d9506f7111fea6eee5b42de)) by [@L-1124](https://github.com/L-1124)
|
|
7
|
+
|
|
8
|
+
### 功能更新
|
|
9
|
+
|
|
10
|
+
* **(comment)** 支持添加评论和删除评论功能 ([dc5f568](https://github.com/L-1124/QQMusicApi/commit/dc5f5685d31f48b5dd8fc6bfcfdb6fb357884e7e)) by [@L-1124](https://github.com/L-1124)
|
|
11
|
+
* **(private-message)** 新增私信接口模块 ([0ce6c77](https://github.com/L-1124/QQMusicApi/commit/0ce6c77b423c01c684cf86ff7a7ee9ca9a70d9fa)) by [@L-1124](https://github.com/L-1124)
|
|
12
|
+
|
|
13
|
+
### 贡献者
|
|
14
|
+
|
|
15
|
+
* @L-1124
|
|
16
|
+
* @github-actions[bot]
|
|
17
|
+
|
|
18
|
+
## [[0.6.0](https://github.com/L-1124/QQMusicApi/compare/v0.5.3..v0.6.0)] - 2026-05-09
|
|
19
|
+
|
|
20
|
+
### Bug 修复
|
|
21
|
+
|
|
22
|
+
* **(login)** 修改手机验证码鉴权参数类型为字符串 ([5cfebc6](https://github.com/L-1124/QQMusicApi/commit/5cfebc67cc816e0ca1930f76386fc599215496af)) by [@L-1124](https://github.com/L-1124)
|
|
23
|
+
|
|
24
|
+
### 功能更新
|
|
25
|
+
|
|
26
|
+
* **(client)** 添加连接重试机制参数 ([38134a7](https://github.com/L-1124/QQMusicApi/commit/38134a74cfe9d3b623c46d74136687d9a2731848)) by [@L-1124](https://github.com/L-1124)
|
|
27
|
+
* **(core)** [**breaking**] 移除 `RequestGroup`,支持 `Client.gather` 批量并发请求,重构请求速率限制参数 ([632b6a8](https://github.com/L-1124/QQMusicApi/commit/632b6a85fe509bbbab7bbe6e7ae702e34ef49440)) by [@L-1124](https://github.com/L-1124)
|
|
28
|
+
* **(web)** 添加 Docker 支持 ([b6f4dfc](https://github.com/L-1124/QQMusicApi/commit/b6f4dfc824c45cdba784904fd937495ab15065cc)) by [@L-1124](https://github.com/L-1124)
|
|
29
|
+
* **(web)** 添加 Web 服务路由 ([154d714](https://github.com/L-1124/QQMusicApi/commit/154d714f4bd918ab6b23814f841b154e5b388c94)) by [@L-1124](https://github.com/L-1124) in [#247](https://github.com/L-1124/QQMusicApi/pull/247)
|
|
30
|
+
* [**breaking**] 不再支持配置 `Client` 部分参数并且修改并且初始化参数名 ([c4a7001](https://github.com/L-1124/QQMusicApi/commit/c4a7001a007128eba76b89004504b58be60c6f84)) by [@L-1124](https://github.com/L-1124)
|
|
31
|
+
|
|
32
|
+
### 功能重构
|
|
33
|
+
|
|
34
|
+
* **(algorithms)** [**breaking**] 移除 Web 端请求签名模块 ([21b3179](https://github.com/L-1124/QQMusicApi/commit/21b31794d89efebbf58505a4310dc95ecd9ba7f0)) by [@L-1124](https://github.com/L-1124)
|
|
35
|
+
* **(core)** 重构 API 客户端, 迁移 httpx → niquests ([fc4f1b7](https://github.com/L-1124/QQMusicApi/commit/fc4f1b77f2f001331f38a178a2a16e84279a4549)) by [@L-1124](https://github.com/L-1124)
|
|
36
|
+
* **(exception)** [**breaking**] 重构异常体系 ([3f7ef32](https://github.com/L-1124/QQMusicApi/commit/3f7ef3239f90cbcf3bf8ba64ab1561e89683df52)) by [@L-1124](https://github.com/L-1124)
|
|
37
|
+
|
|
38
|
+
### 贡献者
|
|
39
|
+
|
|
40
|
+
* @L-1124
|
|
41
|
+
* @github-actions[bot]
|
|
42
|
+
|
|
2
43
|
## [[0.5.3](https://github.com/L-1124/QQMusicApi/compare/v0.5.2..v0.5.3)] - 2026-05-01
|
|
3
44
|
|
|
4
45
|
### Bug 修复
|
|
@@ -94,3 +94,15 @@ async def main():
|
|
|
94
94
|
asyncio.run(_main())
|
|
95
95
|
|
|
96
96
|
```
|
|
97
|
+
|
|
98
|
+
## 设备信息
|
|
99
|
+
|
|
100
|
+
可通过 `device_path` 参数指定设备信息文件的路径进行持久化存储:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
client = Client(device_path="device.json")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
不传 `device_path` 则仅在内存维护设备状态,重启后丢失。
|
|
107
|
+
|
|
108
|
+
`Client.credential` 更改时设备信息保持不变。
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""私信只读接口示例."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
from qqmusic_api import Client, Credential
|
|
6
|
+
from qqmusic_api.models.private_message import PrivateMessageSession
|
|
7
|
+
|
|
8
|
+
MUSICID = 0
|
|
9
|
+
MUSICKEY = ""
|
|
10
|
+
|
|
11
|
+
credential = Credential(musicid=MUSICID, musickey=MUSICKEY)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def format_session_preview(index: int, session: PrivateMessageSession) -> str:
|
|
15
|
+
"""格式化私信会话预览."""
|
|
16
|
+
user = session.user
|
|
17
|
+
latest_message = session.new_msg
|
|
18
|
+
metadata = latest_message.meta_data if latest_message else None
|
|
19
|
+
latest_text = metadata.content if metadata and metadata.content else latest_message.tips if latest_message else ""
|
|
20
|
+
return (
|
|
21
|
+
f"{index}. session_id={session.session_id}, "
|
|
22
|
+
f"uin={user.uin if user else ''}, "
|
|
23
|
+
f"nick={user.nick if user else ''}, "
|
|
24
|
+
f"unread={session.new_msg_cnt}, "
|
|
25
|
+
f"last={latest_text or '<无文本预览>'}"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def main() -> None:
|
|
30
|
+
"""运行私信只读接口示例."""
|
|
31
|
+
async with Client(credential) as client:
|
|
32
|
+
session_result = await client.private_message.get_sessions(size=10)
|
|
33
|
+
print(f"会话列表: has_more={session_result.has_more}, count={len(session_result.sessions)}")
|
|
34
|
+
|
|
35
|
+
if not session_result.sessions:
|
|
36
|
+
print("当前账号没有可展示的私信会话。")
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
print("可用会话:")
|
|
40
|
+
for index, session in enumerate(session_result.sessions, start=1):
|
|
41
|
+
print(format_session_preview(index, session))
|
|
42
|
+
|
|
43
|
+
first_session = session_result.sessions[0]
|
|
44
|
+
target_user = first_session.user
|
|
45
|
+
message_result = await client.private_message.get_messages(
|
|
46
|
+
session_id=first_session.session_id,
|
|
47
|
+
user_id=target_user.uin if target_user else "",
|
|
48
|
+
size=20,
|
|
49
|
+
)
|
|
50
|
+
print(f"首个会话消息: has_more={message_result.has_more}, count={len(message_result.messages)}")
|
|
51
|
+
|
|
52
|
+
entries_result = await client.private_message.get_chat_entries(
|
|
53
|
+
[1, 2],
|
|
54
|
+
from_user_type=0,
|
|
55
|
+
user_id=target_user.uin if target_user else None,
|
|
56
|
+
)
|
|
57
|
+
entry_count = sum(len(entries) for entries in entries_result.entries.values())
|
|
58
|
+
print(f"聊天入口: ret_code={entries_result.ret_code}, entry_count={entry_count}")
|
|
59
|
+
|
|
60
|
+
media_msg_ids = [
|
|
61
|
+
message.id for message in message_result.messages if message.id and message.msg_type in {2, 3, 5, 6}
|
|
62
|
+
]
|
|
63
|
+
if not media_msg_ids:
|
|
64
|
+
print("当前会话没有可用于预览详情查询的图片或视频消息。")
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
detail_result = await client.private_message.get_media_message_details(
|
|
68
|
+
first_session.session_id,
|
|
69
|
+
media_msg_ids[:5],
|
|
70
|
+
)
|
|
71
|
+
print(f"媒体消息详情: count={len(detail_result.msg_ids)}")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
asyncio.run(main())
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"""API 客户端核心实现. 整合网络传输、鉴权与业务模块访问."""
|
|
2
2
|
|
|
3
|
-
import uuid
|
|
4
3
|
from collections import defaultdict
|
|
5
4
|
from functools import cached_property
|
|
6
5
|
from typing import TYPE_CHECKING, Any, Literal, cast, overload
|
|
7
6
|
|
|
7
|
+
import anyio
|
|
8
8
|
from niquests import AsyncSession, AsyncTokenBucketLimiter, PreparedRequest
|
|
9
|
+
from niquests.exceptions import RequestException
|
|
9
10
|
from niquests.models import Response
|
|
10
11
|
from niquests.typing import AsyncHookType, ProxyType, TLSClientCertType, TLSVerifyType
|
|
11
12
|
from tarsio import TarsDict
|
|
@@ -21,6 +22,7 @@ from .exceptions import (
|
|
|
21
22
|
CredentialExpiredError,
|
|
22
23
|
GlobalApiError,
|
|
23
24
|
HTTPError,
|
|
25
|
+
NetworkError,
|
|
24
26
|
RatelimitedError,
|
|
25
27
|
)
|
|
26
28
|
from .request import Request, RequestResultT, _build_result
|
|
@@ -32,6 +34,7 @@ if TYPE_CHECKING:
|
|
|
32
34
|
from ..modules.login import LoginApi
|
|
33
35
|
from ..modules.lyric import LyricApi
|
|
34
36
|
from ..modules.mv import MvApi
|
|
37
|
+
from ..modules.private_message import PrivateMessageApi
|
|
35
38
|
from ..modules.recommend import RecommendApi
|
|
36
39
|
from ..modules.search import SearchApi
|
|
37
40
|
from ..modules.singer import SingerApi
|
|
@@ -98,8 +101,9 @@ class Client:
|
|
|
98
101
|
|
|
99
102
|
self._device_store = DeviceManager(device_path)
|
|
100
103
|
|
|
101
|
-
self._guid = uuid.uuid4().hex
|
|
102
104
|
self._version_policy: VersionPolicy = DEFAULT_VERSION_POLICY
|
|
105
|
+
self._session_lock = anyio.Lock()
|
|
106
|
+
self._session_initialized = False
|
|
103
107
|
self._qimei_manager = QimeiManager(
|
|
104
108
|
device_store=self._device_store,
|
|
105
109
|
app_version=self._version_policy.get_qimei_app_version(),
|
|
@@ -107,6 +111,62 @@ class Client:
|
|
|
107
111
|
session=self._session,
|
|
108
112
|
)
|
|
109
113
|
|
|
114
|
+
async def _ensure_session(self) -> None:
|
|
115
|
+
async with self._session_lock:
|
|
116
|
+
if self._session_initialized:
|
|
117
|
+
return
|
|
118
|
+
device = await self._device_store.get_device()
|
|
119
|
+
if device.session_uid and device.session_sid:
|
|
120
|
+
self._session_initialized = True
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
finalcomm = self._version_policy.build_comm(
|
|
124
|
+
platform=Platform.ANDROID,
|
|
125
|
+
credential=self.credential,
|
|
126
|
+
device=device,
|
|
127
|
+
qimei=cast("dict[str, str]", await self._qimei_manager.get_cached()),
|
|
128
|
+
guid=device.open_udid,
|
|
129
|
+
)
|
|
130
|
+
payload: dict[str, Any] = {
|
|
131
|
+
"comm": finalcomm,
|
|
132
|
+
"req_0": {
|
|
133
|
+
"module": "music.getSession.session",
|
|
134
|
+
"method": "GetSession",
|
|
135
|
+
"param": {
|
|
136
|
+
"uid": device.session_uid or "",
|
|
137
|
+
"vkey": 0,
|
|
138
|
+
"caller": 0,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
user_agent = await self._get_user_agent(Platform.ANDROID)
|
|
143
|
+
try:
|
|
144
|
+
resp = await self._session.post(
|
|
145
|
+
"https://u.y.qq.com/cgi-bin/musicu.fcg",
|
|
146
|
+
json=payload,
|
|
147
|
+
headers={"User-Agent": user_agent},
|
|
148
|
+
proxies=self.proxies,
|
|
149
|
+
hooks=self.hooks,
|
|
150
|
+
cert=self.cert,
|
|
151
|
+
verify=self.verify,
|
|
152
|
+
)
|
|
153
|
+
await self._session.gather(resp)
|
|
154
|
+
except RequestException as exc:
|
|
155
|
+
raise NetworkError(str(exc)) from exc
|
|
156
|
+
if resp.status_code != 200:
|
|
157
|
+
raise HTTPError(
|
|
158
|
+
f"HTTP 请求状态码异常: {resp.status_code}",
|
|
159
|
+
status_code=cast("int", resp.status_code),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
resp_data = resp.json()
|
|
163
|
+
session_data = resp_data["req_0"]["data"]["session"]
|
|
164
|
+
device.session_uid = str(session_data["uid"])
|
|
165
|
+
device.session_sid = session_data["sid"]
|
|
166
|
+
device.session_vkey = session_data.get("vkey")
|
|
167
|
+
await self._device_store.save_device()
|
|
168
|
+
self._session_initialized = True
|
|
169
|
+
|
|
110
170
|
@cached_property
|
|
111
171
|
def comment(self) -> "CommentApi":
|
|
112
172
|
"""评论模块."""
|
|
@@ -114,6 +174,13 @@ class Client:
|
|
|
114
174
|
|
|
115
175
|
return CommentApi(self)
|
|
116
176
|
|
|
177
|
+
@cached_property
|
|
178
|
+
def private_message(self) -> "PrivateMessageApi":
|
|
179
|
+
"""私信模块."""
|
|
180
|
+
from ..modules.private_message import PrivateMessageApi
|
|
181
|
+
|
|
182
|
+
return PrivateMessageApi(self)
|
|
183
|
+
|
|
117
184
|
@cached_property
|
|
118
185
|
def recommend(self) -> "RecommendApi":
|
|
119
186
|
"""推荐模块."""
|
|
@@ -253,18 +320,21 @@ class Client:
|
|
|
253
320
|
headers["User-Agent"] = await self._get_user_agent(platform)
|
|
254
321
|
kwargs["headers"] = headers
|
|
255
322
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
323
|
+
try:
|
|
324
|
+
resp = await self._session.request(
|
|
325
|
+
method,
|
|
326
|
+
url,
|
|
327
|
+
**kwargs,
|
|
328
|
+
proxies=self.proxies,
|
|
329
|
+
hooks=self.hooks,
|
|
330
|
+
cert=self.cert,
|
|
331
|
+
verify=self.verify,
|
|
332
|
+
)
|
|
333
|
+
if not lazy:
|
|
334
|
+
await self._session.gather(resp)
|
|
335
|
+
return resp
|
|
336
|
+
except RequestException as exc:
|
|
337
|
+
raise NetworkError(str(exc)) from exc
|
|
268
338
|
|
|
269
339
|
async def request_api(
|
|
270
340
|
self,
|
|
@@ -277,39 +347,68 @@ class Client:
|
|
|
277
347
|
lazy: bool = False,
|
|
278
348
|
) -> Response:
|
|
279
349
|
"""发送 API 请求."""
|
|
280
|
-
|
|
350
|
+
target_platform = Platform.ANDROID if is_jce else platform or self.platform
|
|
351
|
+
if target_platform == Platform.ANDROID:
|
|
352
|
+
await self._ensure_session()
|
|
353
|
+
device = await self._device_store.get_device()
|
|
281
354
|
finalcomm = self._version_policy.build_comm(
|
|
282
|
-
platform=
|
|
355
|
+
platform=target_platform,
|
|
283
356
|
credential=credential or self.credential,
|
|
284
|
-
device=
|
|
357
|
+
device=device,
|
|
285
358
|
qimei=cast("dict[str, str]", await self._qimei_manager.get_cached())
|
|
286
|
-
if
|
|
359
|
+
if target_platform == Platform.ANDROID
|
|
287
360
|
else None,
|
|
288
|
-
guid=
|
|
361
|
+
guid=device.open_udid,
|
|
289
362
|
)
|
|
290
363
|
if comm:
|
|
291
364
|
finalcomm.update(comm)
|
|
292
365
|
|
|
293
|
-
user_agent = await self._get_user_agent(
|
|
366
|
+
user_agent = await self._get_user_agent(target_platform)
|
|
367
|
+
|
|
368
|
+
try:
|
|
369
|
+
if is_jce:
|
|
370
|
+
for k, v in finalcomm.items():
|
|
371
|
+
if not isinstance(v, str):
|
|
372
|
+
finalcomm[k] = str(v)
|
|
373
|
+
content = JceRequest(
|
|
374
|
+
finalcomm,
|
|
375
|
+
{
|
|
376
|
+
f"req_{idx}": JceRequestItem(
|
|
377
|
+
module=req["module"],
|
|
378
|
+
method=req["method"],
|
|
379
|
+
param=TarsDict(cast("dict[int, Any]", req["param"])),
|
|
380
|
+
)
|
|
381
|
+
for idx, req in enumerate(data)
|
|
382
|
+
},
|
|
383
|
+
).encode()
|
|
384
|
+
resp = await self._session.post(
|
|
385
|
+
"http://u.y.qq.com/cgi-bin/musicw.fcg",
|
|
386
|
+
data=content,
|
|
387
|
+
headers={"User-Agent": user_agent},
|
|
388
|
+
proxies=self.proxies,
|
|
389
|
+
hooks=self.hooks,
|
|
390
|
+
cert=self.cert,
|
|
391
|
+
verify=self.verify,
|
|
392
|
+
)
|
|
393
|
+
if not lazy:
|
|
394
|
+
await self._session.gather(resp)
|
|
395
|
+
return resp
|
|
396
|
+
|
|
397
|
+
payload: dict[str, Any] = {
|
|
398
|
+
"comm": finalcomm,
|
|
399
|
+
}
|
|
400
|
+
params = {}
|
|
401
|
+
for idx, req in enumerate(data):
|
|
402
|
+
payload[f"req_{idx}"] = {
|
|
403
|
+
"module": req["module"],
|
|
404
|
+
"method": req["method"],
|
|
405
|
+
"param": req["param"] if req["preserve_bool"] else bool_to_int(req["param"]),
|
|
406
|
+
}
|
|
294
407
|
|
|
295
|
-
if is_jce:
|
|
296
|
-
for k, v in finalcomm.items():
|
|
297
|
-
if not isinstance(v, str):
|
|
298
|
-
finalcomm[k] = str(v)
|
|
299
|
-
content = JceRequest(
|
|
300
|
-
finalcomm,
|
|
301
|
-
{
|
|
302
|
-
f"req_{idx}": JceRequestItem(
|
|
303
|
-
module=req["module"],
|
|
304
|
-
method=req["method"],
|
|
305
|
-
param=TarsDict(cast("dict[int, Any]", req["param"])),
|
|
306
|
-
)
|
|
307
|
-
for idx, req in enumerate(data)
|
|
308
|
-
},
|
|
309
|
-
).encode()
|
|
310
408
|
resp = await self._session.post(
|
|
311
|
-
"
|
|
312
|
-
|
|
409
|
+
"https://u.y.qq.com/cgi-bin/musicu.fcg",
|
|
410
|
+
json=payload,
|
|
411
|
+
params=params,
|
|
313
412
|
headers={"User-Agent": user_agent},
|
|
314
413
|
proxies=self.proxies,
|
|
315
414
|
hooks=self.hooks,
|
|
@@ -318,33 +417,10 @@ class Client:
|
|
|
318
417
|
)
|
|
319
418
|
if not lazy:
|
|
320
419
|
await self._session.gather(resp)
|
|
321
|
-
return resp
|
|
322
|
-
|
|
323
|
-
payload: dict[str, Any] = {
|
|
324
|
-
"comm": finalcomm,
|
|
325
|
-
}
|
|
326
|
-
params = {}
|
|
327
|
-
for idx, req in enumerate(data):
|
|
328
|
-
payload[f"req_{idx}"] = {
|
|
329
|
-
"module": req["module"],
|
|
330
|
-
"method": req["method"],
|
|
331
|
-
"param": req["param"] if req["preserve_bool"] else bool_to_int(req["param"]),
|
|
332
|
-
}
|
|
333
420
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
params=params,
|
|
338
|
-
headers={"User-Agent": user_agent},
|
|
339
|
-
proxies=self.proxies,
|
|
340
|
-
hooks=self.hooks,
|
|
341
|
-
cert=self.cert,
|
|
342
|
-
verify=self.verify,
|
|
343
|
-
)
|
|
344
|
-
if not lazy:
|
|
345
|
-
await self._session.gather(resp)
|
|
346
|
-
|
|
347
|
-
return resp
|
|
421
|
+
return resp
|
|
422
|
+
except RequestException as exc:
|
|
423
|
+
raise NetworkError(str(exc)) from exc
|
|
348
424
|
|
|
349
425
|
@overload
|
|
350
426
|
async def gather(
|
|
@@ -443,7 +519,10 @@ class Client:
|
|
|
443
519
|
)
|
|
444
520
|
batch_responses.append((batch_indices, response_task))
|
|
445
521
|
|
|
446
|
-
|
|
522
|
+
try:
|
|
523
|
+
await self._session.gather(*(resp for _, resp in batch_responses))
|
|
524
|
+
except RequestException as exc:
|
|
525
|
+
raise NetworkError(str(exc)) from exc
|
|
447
526
|
|
|
448
527
|
results: list[Any] = [_SENTINEL] * len(requests)
|
|
449
528
|
|
|
@@ -88,6 +88,8 @@ class VersionPolicy:
|
|
|
88
88
|
device.model,
|
|
89
89
|
device.version.sdk,
|
|
90
90
|
device.fingerprint,
|
|
91
|
+
device.session_uid,
|
|
92
|
+
device.session_sid,
|
|
91
93
|
)
|
|
92
94
|
if platform == Platform.ANDROID
|
|
93
95
|
else (),
|
|
@@ -113,7 +115,9 @@ class VersionPolicy:
|
|
|
113
115
|
QIMEI36=qimei["q36"] if qimei is not None else "",
|
|
114
116
|
OpenUDID=guid,
|
|
115
117
|
udid=guid,
|
|
118
|
+
uid=device.session_uid,
|
|
116
119
|
OpenUDID2=guid,
|
|
120
|
+
sid=device.session_sid,
|
|
117
121
|
aid=device.android_id,
|
|
118
122
|
os_ver=device.version.release,
|
|
119
123
|
phonetype=device.model,
|
|
@@ -203,3 +203,23 @@ class MomentCommentResponse(Response):
|
|
|
203
203
|
hint: str = Field(alias="Hint")
|
|
204
204
|
prev_list_loaded: int = Field(alias="PrevListLoaded")
|
|
205
205
|
map_cm_ext: dict[str, dict[str, Any]] = Field(default_factory=dict, alias="MapCmExt")
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class AddCommentResponse(Response):
|
|
209
|
+
"""添加评论接口的响应体.
|
|
210
|
+
|
|
211
|
+
Attributes:
|
|
212
|
+
subcode: 响应子代码.
|
|
213
|
+
msg: 响应消息.
|
|
214
|
+
id: 新增评论 ID.
|
|
215
|
+
parent: 父评论 ID.
|
|
216
|
+
floor: 楼层号.
|
|
217
|
+
verify_url: 验证码 URL (如果需要).
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
subcode: int = Field(alias="SubCode")
|
|
221
|
+
msg: str = Field(alias="Msg")
|
|
222
|
+
id: str = Field(alias="AddedCmId")
|
|
223
|
+
parent: str = Field(alias="ParentCmId")
|
|
224
|
+
floor: int = Field(json_schema_extra={"jsonpath": "$.Floor.Num"})
|
|
225
|
+
verify_url: str = Field(alias="VerifyUrl")
|