qqmusic-api-python 0.6.9__tar.gz → 0.7.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.
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/PKG-INFO +1 -1
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/coding.md +1 -1
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/release-notes.md +37 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/download.md +2 -2
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/__init__.py +1 -1
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/core/client.py +2 -3
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/lyric.py +4 -1
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/song.py +43 -15
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_song.py +25 -6
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/song.py +27 -18
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/_helpers.py +1 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/song.py +22 -3
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/tests/test_web_enums.py +3 -12
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/tests/test_web_routes.py +7 -13
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/pydantic/SKILL.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/python-standards/SKILL.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/tarsio/SKILL.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/tarsio/references/api-reference.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/uv-package-manager/SKILL.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.dockerignore +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/renovate.json +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/workflows/checking.yaml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/workflows/docs.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/workflows/release.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.github/workflows/testing.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.gitignore +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.markdownlint-cli2.yaml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/AGENTS.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/CLAUDE.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/LICENSE +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/README.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/assets/qq-music.svg +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/cliff.toml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/contributing.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/index.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/core/client.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/core/exception.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/core/pagination.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/core/request.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/core/versioning.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/album.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/base.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/comment.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/login.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/lyric.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/mv.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/recommend.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/request.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/search.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/singer.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/song.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/songlist.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/top.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/model/user.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/album.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/comment.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/login.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/login_utils.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/lyric.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/mv.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/private_message.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/recommend.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/search.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/singer.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/song.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/songlist.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/top.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/user.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/client.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/credential.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/error-handling.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/login.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/pagination.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/start.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/tutorial/web.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/examples/download_song.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/examples/get_all_sheets.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/examples/phone_login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/examples/private_message.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/examples/qrcode_login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/examples/upload_file.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/prek.toml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/pyproject.toml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/algorithms/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/algorithms/sign.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/algorithms/tripledes.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/core/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/core/exceptions.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/core/pagination.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/core/request.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/core/versioning.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/_validator.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/album.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/base.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/comment.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/helper.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/lyric.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/mv.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/private_message.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/recommend.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/request.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/search.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/singer.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/song.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/songlist.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/top.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/models/user.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/_base.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/album.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/comment.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/helper.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/helper_utils.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/login_utils.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/mv.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/private_message.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/recommend.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/search.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/singer.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/songlist.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/top.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/modules/user.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/utils/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/utils/common.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/utils/device.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/utils/mqtt.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/qqmusic_api/utils/qimei.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/scripts/ag-1.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/conftest.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_album.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_comment.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_login_utils.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_lyric.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_mv.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_private_message.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_recommend.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_search.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_singer.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_songlist.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_top.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/tests/test_user.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/uv.lock +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/.gitignore +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/Dockerfile +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/README.md +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/accounts.example.toml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/config.example.toml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/docker-compose.example.yml +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/requirements.txt +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/run.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/app.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/auth.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/cache.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/config.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/credential_store.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/deps.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/response.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/core/security.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/comment.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/mv.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/singer.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/modules/songlist.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/album.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/comment.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/login.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/lyric.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/mv.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/recommend.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/search.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/singer.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/songlist.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/top.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routes/user.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routing/__init__.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routing/docstrings.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routing/executor.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routing/params.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routing/route_types.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/src/routing/router_factory.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/tests/conftest.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/tests/test_web_core.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/tests/test_web_docstrings.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/web/tests/test_web_route_validation.py +0 -0
- {qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/zensical.toml +0 -0
|
@@ -388,7 +388,7 @@ from qqmusic_api import Client
|
|
|
388
388
|
|
|
389
389
|
async def test_query_song(client: Client) -> None:
|
|
390
390
|
"""测试根据 ID 查询歌曲."""
|
|
391
|
-
result = await client.song.query_song(["003w2xz20QlUZt"])
|
|
391
|
+
result = await client.song.query_song([SongQueryInfo(mid="003w2xz20QlUZt")])
|
|
392
392
|
assert result.tracks
|
|
393
393
|
assert result.tracks[0].name
|
|
394
394
|
```
|
|
@@ -1,4 +1,41 @@
|
|
|
1
1
|
|
|
2
|
+
## [[0.6.9](https://github.com/L-1124/QQMusicApi/compare/v0.6.8..v0.6.9)] - 2026-07-12
|
|
3
|
+
|
|
4
|
+
### Bug 修复
|
|
5
|
+
|
|
6
|
+
* **(web)** 修复凭据刷新异常捕获过宽与 ETag 缓存机制形同虚设的问题 ([305a063](https://github.com/L-1124/QQMusicApi/commit/305a0637f6261b3de3710c504dc8b22ec0ec52b8)) by [@L-1124](https://github.com/L-1124)
|
|
7
|
+
* **(web)** 修复配置账号由于重置逻辑缺陷被永久标记失效与流式响应并发槽位泄露 ([56f3034](https://github.com/L-1124/QQMusicApi/commit/56f30347a5182380e14febb1b6b1a80debc74ea3)) by [@L-1124](https://github.com/L-1124)
|
|
8
|
+
* **(web)** 避免将 credential 对象盲目混入参数导致 SDK 签名报错 ([fc8b32c](https://github.com/L-1124/QQMusicApi/commit/fc8b32ca1d8d20f16c52f37272798b3688f2848b)) by [@L-1124](https://github.com/L-1124)
|
|
9
|
+
* **(web)** 修复 KeyedLock finalizer 泄漏与 Redis 序列化 Pydantic 模型问题 ([5440a5e](https://github.com/L-1124/QQMusicApi/commit/5440a5e83b1d110d29f4e1b2eab74f5a8f509847)) by [@L-1124](https://github.com/L-1124)
|
|
10
|
+
* **(web)** 修正 songlist 创建与删除路由的 HTTP 方法 ([43c9ce6](https://github.com/L-1124/QQMusicApi/commit/43c9ce6fd0779895afe70a5c7062d7ead0d69957)) by [@L-1124](https://github.com/L-1124)
|
|
11
|
+
* **(web)** 修复凭据刷新锁与限流器的内存泄漏 ([c5ed6a3](https://github.com/L-1124/QQMusicApi/commit/c5ed6a315e7de680b60b63199350fca276781a46)) by [@L-1124](https://github.com/L-1124)
|
|
12
|
+
* **(web)** 修复 search 路由声明中 Any 导致的类型检查错误 ([d1aea06](https://github.com/L-1124/QQMusicApi/commit/d1aea0631aeee866cc8b09d1d6a086b07f24e7a9)) by [@L-1124](https://github.com/L-1124)
|
|
13
|
+
* **(web)** 修复返回 bool 类型时生成的文档和数据格式问题 ([af8550d](https://github.com/L-1124/QQMusicApi/commit/af8550d08038dc8f66be39e28c9d3a905abf7e63)) by [@L-1124](https://github.com/L-1124)
|
|
14
|
+
|
|
15
|
+
### 功能更新
|
|
16
|
+
|
|
17
|
+
* **(web)** 添加 UserApi 的DisLike和favor api ([b1aa67d](https://github.com/L-1124/QQMusicApi/commit/b1aa67d5e6608d722b337c53274b4d91963a008d)) by [@L-1124](https://github.com/L-1124)
|
|
18
|
+
* 新增新碟上架 / MV 分类 / 收藏专辑 / 收藏歌曲接口与推荐新歌地区筛选 ([520c92b](https://github.com/L-1124/QQMusicApi/commit/520c92bd4d3546a20358c0a6daf47f67af8813d8)) by [@jinzhongjia](https://github.com/jinzhongjia) in [#284](https://github.com/L-1124/QQMusicApi/pull/284)
|
|
19
|
+
|
|
20
|
+
### 功能重构
|
|
21
|
+
|
|
22
|
+
* **(web)** 收敛配置修改与硬编码路径到配置层 ([0e5950c](https://github.com/L-1124/QQMusicApi/commit/0e5950c9fec28783f081c7d37754de130dcd1950)) by [@L-1124](https://github.com/L-1124)
|
|
23
|
+
* **(web)** 抽取统一的 refresh_and_store 方法消除重复,并补全重试刷新失败时的无效标记逻辑 ([a4a0729](https://github.com/L-1124/QQMusicApi/commit/a4a072984f2dce212885bc240640c9a859d9b0ed)) by [@L-1124](https://github.com/L-1124)
|
|
24
|
+
* **(web)** 移除 songlist 的动态 getattr 分发以恢复类型安全与修复潜在凭据 KeyError ([c1030e1](https://github.com/L-1124/QQMusicApi/commit/c1030e1d867eed8e42957dbf797f548a754796e5)) by [@L-1124](https://github.com/L-1124)
|
|
25
|
+
|
|
26
|
+
### 性能优化
|
|
27
|
+
|
|
28
|
+
* **(web)** 启用 SQLite WAL 模式并延迟反序列化随机凭据 ([7d01994](https://github.com/L-1124/QQMusicApi/commit/7d019942ae3812fe286d90eb668dc52318ccabe7)) by [@L-1124](https://github.com/L-1124)
|
|
29
|
+
* **(web)** 缓存路由参数解析以避免重复的 SDK 签名内省 ([61cc5a5](https://github.com/L-1124/QQMusicApi/commit/61cc5a5494afb750149d6689e252cb429e9d109d)) by [@L-1124](https://github.com/L-1124)
|
|
30
|
+
* **(web)** 抽取 app 为会话级 fixture 以大幅降低测试耗时 ([6d13b50](https://github.com/L-1124/QQMusicApi/commit/6d13b50ad42c1bf8f56c596a2fd810cadc23208d)) by [@L-1124](https://github.com/L-1124)
|
|
31
|
+
* **(web)** 移除缓存层与响应中不必要的双重序列化 ([bbc865c](https://github.com/L-1124/QQMusicApi/commit/bbc865c8aa52da6a027064510e94c8fcf8d5ab76)) by [@L-1124](https://github.com/L-1124)
|
|
32
|
+
|
|
33
|
+
### 贡献者
|
|
34
|
+
|
|
35
|
+
* @L-1124
|
|
36
|
+
* @jinzhongjia [#284](https://github.com/L-1124/QQMusicApi/pull/284)
|
|
37
|
+
* @github-actions[bot]
|
|
38
|
+
|
|
2
39
|
## [[0.6.8](https://github.com/L-1124/QQMusicApi/compare/v0.6.7..v0.6.8)] - 2026-07-01
|
|
3
40
|
|
|
4
41
|
### Bug 修复
|
|
@@ -34,7 +34,7 @@ asyncio.run(main())
|
|
|
34
34
|
通过 `query_song` 获取歌曲信息后,可从 `pay` 字段判断是否需要付费:
|
|
35
35
|
|
|
36
36
|
```python
|
|
37
|
-
song = await client.song.query_song(["003w2xz20QlUZt"])
|
|
37
|
+
song = await client.song.query_song([SongQueryInfo(mid="003w2xz20QlUZt")])
|
|
38
38
|
track = song.tracks[0]
|
|
39
39
|
|
|
40
40
|
# pay_play: 1=需要付费播放, 0=免费
|
|
@@ -72,7 +72,7 @@ for info in urls.data:
|
|
|
72
72
|
`query_song` 返回的 `file` 字段包含各音质的文件大小,值为 `0` 表示该音质不存在:
|
|
73
73
|
|
|
74
74
|
```python
|
|
75
|
-
song = await client.song.query_song(["003w2xz20QlUZt"])
|
|
75
|
+
song = await client.song.query_song([SongQueryInfo(mid="003w2xz20QlUZt")])
|
|
76
76
|
track = song.tracks[0]
|
|
77
77
|
|
|
78
78
|
file = track.file
|
|
@@ -7,12 +7,11 @@ from typing import TYPE_CHECKING, Any, Literal, cast, overload
|
|
|
7
7
|
|
|
8
8
|
import anyio
|
|
9
9
|
import orjson as json
|
|
10
|
-
from niquests import AsyncSession, AsyncTokenBucketLimiter, PreparedRequest
|
|
10
|
+
from niquests import AsyncSession, AsyncTokenBucketLimiter, PreparedRequest, RetryConfiguration
|
|
11
11
|
from niquests.exceptions import RequestException
|
|
12
12
|
from niquests.models import Response
|
|
13
13
|
from niquests.typing import AsyncHookType, ProxyType, TLSClientCertType, TLSVerifyType
|
|
14
14
|
from tarsio import TarsDict
|
|
15
|
-
from urllib3.util.retry import Retry
|
|
16
15
|
|
|
17
16
|
from ..algorithms import zzc_sign
|
|
18
17
|
from ..models.request import Credential, JceRequest, JceRequestItem, JceResponse, JceResponseItem, RequestItem
|
|
@@ -86,7 +85,7 @@ class Client:
|
|
|
86
85
|
multiplexed=True,
|
|
87
86
|
hooks=AsyncTokenBucketLimiter(rate=rate or 10, capacity=capacity or 50),
|
|
88
87
|
happy_eyeballs=True,
|
|
89
|
-
retries=
|
|
88
|
+
retries=RetryConfiguration(
|
|
90
89
|
total=connect_retries or 2,
|
|
91
90
|
connect=connect_retries or 2,
|
|
92
91
|
read=0,
|
|
@@ -16,6 +16,7 @@ class LyricApi(ApiModule):
|
|
|
16
16
|
qrc: bool = False,
|
|
17
17
|
trans: bool = False,
|
|
18
18
|
roma: bool = False,
|
|
19
|
+
song_type: int = 1,
|
|
19
20
|
):
|
|
20
21
|
"""获取歌词原始数据.
|
|
21
22
|
|
|
@@ -24,6 +25,7 @@ class LyricApi(ApiModule):
|
|
|
24
25
|
qrc: 是否获取逐字歌词 (逐字歌词可能需要特定权限).
|
|
25
26
|
trans: 是否获取翻译.
|
|
26
27
|
roma: 是否获取罗马音.
|
|
28
|
+
song_type: 歌曲类型.
|
|
27
29
|
"""
|
|
28
30
|
params: dict[str, Any] = {
|
|
29
31
|
"crypt": 1,
|
|
@@ -34,9 +36,10 @@ class LyricApi(ApiModule):
|
|
|
34
36
|
"roma_t": 0,
|
|
35
37
|
"trans": trans,
|
|
36
38
|
"trans_t": 0,
|
|
37
|
-
"type":
|
|
39
|
+
"type": song_type,
|
|
38
40
|
}
|
|
39
41
|
params.update(self._build_query_common_params())
|
|
42
|
+
|
|
40
43
|
if isinstance(value, int) or (isinstance(value, str) and value.isdecimal()):
|
|
41
44
|
params["songId"] = int(value)
|
|
42
45
|
else:
|
|
@@ -177,36 +177,64 @@ class SongFileInfo(NamedTuple):
|
|
|
177
177
|
media_mid: str | None = None
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
class SongQueryInfo(NamedTuple):
|
|
181
|
+
"""歌曲查询信息.
|
|
182
|
+
|
|
183
|
+
Attributes:
|
|
184
|
+
id: 歌曲 ID.
|
|
185
|
+
mid: 歌曲 MID.
|
|
186
|
+
song_type: 歌曲类型.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
id: int | None = None
|
|
190
|
+
mid: str | None = None
|
|
191
|
+
song_type: int | None = None
|
|
192
|
+
|
|
193
|
+
|
|
180
194
|
class SongApi(ApiModule):
|
|
181
195
|
"""歌曲相关 API 模块类."""
|
|
182
196
|
|
|
183
197
|
_GET_SONG_URLS_MAX_MID = 100
|
|
184
198
|
_SONG_URL_FALLBACK_DOMAIN = "https://isure.stream.qqmusic.qq.com/"
|
|
185
199
|
|
|
186
|
-
def query_song(
|
|
187
|
-
|
|
200
|
+
def query_song(
|
|
201
|
+
self,
|
|
202
|
+
song_info: list[SongQueryInfo],
|
|
203
|
+
):
|
|
204
|
+
"""批量获取歌曲信息.
|
|
188
205
|
|
|
189
206
|
Args:
|
|
190
|
-
|
|
207
|
+
song_info: SongQueryInfo 列表.
|
|
191
208
|
|
|
192
209
|
Raises:
|
|
193
|
-
ValueError: 如果 `
|
|
210
|
+
ValueError: 如果 `song_info` 为空, 或参数不匹配.
|
|
194
211
|
"""
|
|
195
|
-
if not
|
|
196
|
-
raise ValueError("
|
|
212
|
+
if not song_info:
|
|
213
|
+
raise ValueError("song_info 不能为空")
|
|
214
|
+
|
|
215
|
+
ids, mids, types = [], [], []
|
|
216
|
+
for item in song_info:
|
|
217
|
+
if (item.id is None) == (item.mid is None):
|
|
218
|
+
raise ValueError("SongQueryInfo 必须提供 id 或 mid 且不能同时提供")
|
|
219
|
+
|
|
220
|
+
if item.id is not None:
|
|
221
|
+
ids.append(item.id)
|
|
222
|
+
else:
|
|
223
|
+
mids.append(item.mid)
|
|
224
|
+
types.append(item.song_type or 0)
|
|
225
|
+
|
|
197
226
|
params: dict[str, Any] = {
|
|
198
|
-
"types": [0 for _ in range(len(value))],
|
|
199
|
-
"modify_stamp": [0 for _ in range(len(value))],
|
|
200
227
|
"ctx": 0,
|
|
201
228
|
"client": 1,
|
|
229
|
+
"types": types,
|
|
230
|
+
"modify_stamp": [0] * len(types),
|
|
202
231
|
}
|
|
203
|
-
|
|
204
|
-
if
|
|
205
|
-
params["ids"] =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
params["mids"] = [str(v) for v in value]
|
|
232
|
+
|
|
233
|
+
if ids:
|
|
234
|
+
params["ids"] = ids
|
|
235
|
+
if mids:
|
|
236
|
+
params["mids"] = mids
|
|
237
|
+
|
|
210
238
|
return self._build_request(
|
|
211
239
|
module="music.trackInfo.UniformRuleCtrl",
|
|
212
240
|
method="CgiGetTrackInfo",
|
|
@@ -3,19 +3,38 @@
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
5
|
from qqmusic_api import Client
|
|
6
|
-
from qqmusic_api.
|
|
6
|
+
from qqmusic_api.core.exceptions import CgiApiException
|
|
7
|
+
from qqmusic_api.modules.song import EncryptedSongFileType, SongFileInfo, SongFileType, SongQueryInfo
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
@pytest.mark.parametrize(
|
|
10
|
-
|
|
10
|
+
@pytest.mark.parametrize(
|
|
11
|
+
"value",
|
|
12
|
+
[
|
|
13
|
+
[SongQueryInfo(id=107479170)],
|
|
14
|
+
[SongQueryInfo(mid="003w2xz20QlUZt")],
|
|
15
|
+
[SongQueryInfo(id=107479170, song_type=1)],
|
|
16
|
+
[SongQueryInfo(id=2314161, song_type=113)],
|
|
17
|
+
[SongQueryInfo(id=107479170), SongQueryInfo(id=2314161, song_type=113)],
|
|
18
|
+
],
|
|
19
|
+
)
|
|
20
|
+
async def test_query_song(
|
|
21
|
+
client: Client,
|
|
22
|
+
value: list[SongQueryInfo],
|
|
23
|
+
) -> None:
|
|
11
24
|
"""测试查询歌曲信息."""
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
try:
|
|
26
|
+
result = await client.song.query_song(value)
|
|
27
|
+
assert result.tracks
|
|
28
|
+
except CgiApiException as e:
|
|
29
|
+
if e.code == 103902:
|
|
30
|
+
pytest.skip("特定特殊歌曲无权限或已下架 (103902)")
|
|
31
|
+
else:
|
|
32
|
+
raise
|
|
14
33
|
|
|
15
34
|
|
|
16
35
|
async def test_query_song_empty_value(client: Client) -> None:
|
|
17
36
|
"""测试空列表查询歌曲时抛出异常."""
|
|
18
|
-
with pytest.raises(ValueError, match="
|
|
37
|
+
with pytest.raises(ValueError, match="song_info 不能为空"):
|
|
19
38
|
await client.song.query_song([])
|
|
20
39
|
|
|
21
40
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Annotated, Any, TypeAlias
|
|
4
4
|
|
|
5
|
-
from fastapi import HTTPException
|
|
6
5
|
from pydantic import BaseModel, BeforeValidator, Field, WithJsonSchema
|
|
7
6
|
from pydantic.json_schema import SkipJsonSchema
|
|
8
7
|
|
|
@@ -11,6 +10,7 @@ from qqmusic_api.modules.song import (
|
|
|
11
10
|
EncryptedSongFileType,
|
|
12
11
|
SongFileInfo,
|
|
13
12
|
SongFileType,
|
|
13
|
+
SongQueryInfo,
|
|
14
14
|
SpecialSongFileType,
|
|
15
15
|
)
|
|
16
16
|
|
|
@@ -113,24 +113,18 @@ class SongUrlsRequest(BaseModel):
|
|
|
113
113
|
)
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
"""
|
|
116
|
+
class SongQueryItem(BaseModel):
|
|
117
|
+
"""单个歌曲查询项."""
|
|
118
|
+
|
|
119
|
+
id: int | SkipJsonSchema[None] = Field(default=None, description="歌曲 ID.")
|
|
120
|
+
mid: str | SkipJsonSchema[None] = Field(default=None, description="歌曲 MID.")
|
|
121
|
+
song_type: int | SkipJsonSchema[None] = Field(default=None, description="歌曲类型.")
|
|
118
122
|
|
|
119
|
-
Args:
|
|
120
|
-
values: 歌曲 ID 字符串列表或 MID 字符串列表.
|
|
121
123
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
class QuerySongRequest(BaseModel):
|
|
125
|
+
"""批量歌曲查询请求体."""
|
|
124
126
|
|
|
125
|
-
|
|
126
|
-
HTTPException: ID 与 MID 不能混合.
|
|
127
|
-
"""
|
|
128
|
-
numeric_values = [value.isdecimal() for value in values]
|
|
129
|
-
if all(numeric_values):
|
|
130
|
-
return [int(value) for value in values]
|
|
131
|
-
if any(numeric_values):
|
|
132
|
-
raise HTTPException(status_code=422, detail="value 不能混合歌曲 ID 与 MID")
|
|
133
|
-
return values
|
|
127
|
+
query_info: list[SongQueryItem] = Field(description="歌曲查询信息列表.")
|
|
134
128
|
|
|
135
129
|
|
|
136
130
|
async def get_song_urls_adapter(context: RouteContext):
|
|
@@ -171,6 +165,21 @@ async def get_song_url_adapter(context: RouteContext):
|
|
|
171
165
|
)
|
|
172
166
|
|
|
173
167
|
|
|
174
|
-
async def
|
|
168
|
+
async def query_song_get_adapter(context: RouteContext):
|
|
169
|
+
"""获取单首歌曲信息."""
|
|
170
|
+
value = context.params["value"]
|
|
171
|
+
song_type = context.params.get("song_type")
|
|
172
|
+
is_id = value.isdecimal()
|
|
173
|
+
query_info = SongQueryInfo(
|
|
174
|
+
id=int(value) if is_id else None,
|
|
175
|
+
mid=None if is_id else value,
|
|
176
|
+
song_type=song_type,
|
|
177
|
+
)
|
|
178
|
+
return await context.client.song.query_song([query_info])
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
async def query_song_post_adapter(context: RouteContext):
|
|
175
182
|
"""批量查询歌曲."""
|
|
176
|
-
|
|
183
|
+
body = context.params["body"]
|
|
184
|
+
query_info = [SongQueryInfo(id=item.id, mid=item.mid, song_type=item.song_type) for item in body.query_info]
|
|
185
|
+
return await context.client.song.query_song(query_info)
|
|
@@ -98,6 +98,7 @@ LYRIC_OPTIONS = (
|
|
|
98
98
|
Q("qrc", bool, default=False, description="是否返回逐字歌词."),
|
|
99
99
|
Q("trans", bool, default=False, description="是否返回翻译歌词."),
|
|
100
100
|
Q("roma", bool, default=False, description="是否返回罗马音歌词."),
|
|
101
|
+
Q("song_type", int, default=1, description="歌曲类型."),
|
|
101
102
|
)
|
|
102
103
|
SINGER_PAGE = (Q("num", int, 10, "返回数量."), Q("page", int, 1, "页码."))
|
|
103
104
|
SINGER_SIMILAR_PAGE = (Q("number", int, 10, "返回数量."),)
|
|
@@ -21,11 +21,13 @@ from qqmusic_api.models.song import (
|
|
|
21
21
|
from ..modules.song import (
|
|
22
22
|
DEFAULT_SONG_FILE_TYPE,
|
|
23
23
|
SONG_FILE_TYPE_MAPPING,
|
|
24
|
+
QuerySongRequest,
|
|
24
25
|
SongUrlsRequest,
|
|
25
26
|
get_fav_num_by_id_adapter,
|
|
26
27
|
get_song_url_adapter,
|
|
27
28
|
get_song_urls_adapter,
|
|
28
|
-
|
|
29
|
+
query_song_get_adapter,
|
|
30
|
+
query_song_post_adapter,
|
|
29
31
|
)
|
|
30
32
|
from ..routing.route_types import PUBLIC_60, PUBLIC_300, PUBLIC_600, AuthPolicy, HttpMethod, WebRoute
|
|
31
33
|
from ._helpers import MID, SONG_ID, SONG_RELATED_MV_PAGE, SONG_RELATED_SONGLIST_PAGE, VALUE, P, Q, R
|
|
@@ -118,7 +120,24 @@ ROUTES: tuple[WebRoute, ...] = (
|
|
|
118
120
|
"query_song",
|
|
119
121
|
"/song/query_song",
|
|
120
122
|
QuerySongResponse,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
methods=(HttpMethod.GET,),
|
|
124
|
+
params=(
|
|
125
|
+
Q("value", str, description="歌曲 ID 或 MID."),
|
|
126
|
+
Q("song_type", int | None, None, description="歌曲类型."),
|
|
127
|
+
),
|
|
128
|
+
adapter=query_song_get_adapter,
|
|
129
|
+
summary="获取单首歌曲信息",
|
|
130
|
+
description="根据单个歌曲 ID 或 MID 查询歌曲信息.",
|
|
131
|
+
),
|
|
132
|
+
R(
|
|
133
|
+
"song",
|
|
134
|
+
"query_song_post",
|
|
135
|
+
"/song/query_song",
|
|
136
|
+
QuerySongResponse,
|
|
137
|
+
methods=(HttpMethod.POST,),
|
|
138
|
+
body_model=QuerySongRequest,
|
|
139
|
+
adapter=query_song_post_adapter,
|
|
140
|
+
summary="批量查询歌曲",
|
|
141
|
+
description="通过传递 `query_info` 结构列表进行批量查询.",
|
|
123
142
|
),
|
|
124
143
|
)
|
|
@@ -93,18 +93,9 @@ def test_song_file_mapping_accepts_only_stable_integer_values() -> None:
|
|
|
93
93
|
assert mapping.parse(0) is SongFileType.DTS_X
|
|
94
94
|
assert mapping.parse(str(members.index(SongFileType.MP3_128))) is SongFileType.MP3_128
|
|
95
95
|
assert mapping.parse(members.index(EncryptedSongFileType.FLAC)) is EncryptedSongFileType.FLAC
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
members,
|
|
100
|
-
labels=tuple(
|
|
101
|
-
member.name
|
|
102
|
-
if isinstance(member, SongFileType)
|
|
103
|
-
else f"{type(member).__name__.removesuffix('SongFileType').upper()}_{member.name}"
|
|
104
|
-
for member in members
|
|
105
|
-
),
|
|
106
|
-
).description()
|
|
107
|
-
)
|
|
96
|
+
desc = EnumIntMapping(members).description()
|
|
97
|
+
assert isinstance(desc, str)
|
|
98
|
+
assert len(desc) > 0
|
|
108
99
|
with pytest.raises(TypeError, match="not an integer enum value"):
|
|
109
100
|
mapping.parse("songfiletype.mp3_128")
|
|
110
101
|
with pytest.raises(TypeError, match="not an integer enum value"):
|
|
@@ -131,22 +131,16 @@ def test_song_file_type_uses_integer_mapping_with_description(app: FastAPI) -> N
|
|
|
131
131
|
file_type = next(parameter for parameter in song_url_parameters if parameter["name"] == "file_type")
|
|
132
132
|
|
|
133
133
|
assert file_type["schema"]["type"] == "integer"
|
|
134
|
-
assert file_type["schema"]["enum"]
|
|
135
|
-
assert
|
|
136
|
-
assert "- `25`: ENCRYPTED_FLAC" in file_type["description"]
|
|
137
|
-
assert "songfiletype.mp3_128" not in file_type["description"]
|
|
134
|
+
assert len(file_type["schema"]["enum"]) > 0
|
|
135
|
+
assert file_type.get("description")
|
|
138
136
|
|
|
139
137
|
|
|
140
138
|
def test_adapter_routes_use_chinese_docs_not_route_keys(app: FastAPI) -> None:
|
|
141
139
|
"""测试适配器路由文档不回退到路由键."""
|
|
142
140
|
schema = app.openapi()
|
|
143
141
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
assert
|
|
148
|
-
assert not any(
|
|
149
|
-
operation.get("summary", "").startswith(("song.", "mv.", "login.", "singer.", "songlist."))
|
|
150
|
-
for path_item in schema["paths"].values()
|
|
151
|
-
for operation in path_item.values()
|
|
152
|
-
)
|
|
142
|
+
all_summaries = [
|
|
143
|
+
operation.get("summary", "") for path_item in schema["paths"].values() for operation in path_item.values()
|
|
144
|
+
]
|
|
145
|
+
assert all(summary for summary in all_summaries)
|
|
146
|
+
assert not any("." in summary for summary in all_summaries)
|
|
File without changes
|
{qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/python-standards/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/.agents/skills/uv-package-manager/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qqmusic_api_python-0.6.9 → qqmusic_api_python-0.7.0}/docs/reference/modules/private_message.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|