qqmusic-api-python 0.8.1__tar.gz → 0.8.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.
Files changed (236) hide show
  1. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/PKG-INFO +1 -1
  2. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/release-notes.md +26 -0
  3. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/pyproject.toml +0 -1
  4. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/__init__.py +1 -1
  5. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/singer.py +76 -14
  6. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/singer.py +111 -16
  7. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_singer.py +44 -6
  8. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/typing/test_client_typing.py +7 -3
  9. qqmusic_api_python-0.8.2/uv.lock +2243 -0
  10. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/README.md +1 -1
  11. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/config.example.toml +0 -12
  12. qqmusic_api_python-0.8.2/web/requirements.txt +1565 -0
  13. qqmusic_api_python-0.8.2/web/run.py +39 -0
  14. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/app.py +0 -30
  15. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/config.py +0 -14
  16. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/login.py +0 -1
  17. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/mv.py +0 -10
  18. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/_helpers.py +1 -37
  19. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/mv.py +3 -5
  20. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/singer.py +8 -0
  21. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/adapter_registry.py +0 -5
  22. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/route_types.py +1 -3
  23. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/router_factory.py +3 -5
  24. qqmusic_api_python-0.8.1/uv.lock +0 -2083
  25. qqmusic_api_python-0.8.1/web/requirements.txt +0 -1407
  26. qqmusic_api_python-0.8.1/web/run.py +0 -105
  27. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.agents/skills/pydantic/SKILL.md +0 -0
  28. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.agents/skills/python-standards/SKILL.md +0 -0
  29. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.agents/skills/uv-package-manager/SKILL.md +0 -0
  30. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.dockerignore +0 -0
  31. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  32. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  33. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
  34. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  35. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/renovate.json +0 -0
  36. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/workflows/checking.yaml +0 -0
  37. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/workflows/docs.yml +0 -0
  38. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/workflows/release.yml +0 -0
  39. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.github/workflows/testing.yml +0 -0
  40. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.gitignore +0 -0
  41. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/.markdownlint-cli2.yaml +0 -0
  42. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/AGENTS.md +0 -0
  43. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/CLAUDE.md +0 -0
  44. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/LICENSE +0 -0
  45. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/README.md +0 -0
  46. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/assets/qq-music.svg +0 -0
  47. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/cliff.toml +0 -0
  48. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/coding.md +0 -0
  49. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/contributing.md +0 -0
  50. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/index.md +0 -0
  51. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/core/client.md +0 -0
  52. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/core/exception.md +0 -0
  53. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/core/pagination.md +0 -0
  54. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/core/request.md +0 -0
  55. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/core/versioning.md +0 -0
  56. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/album.md +0 -0
  57. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/base.md +0 -0
  58. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/comment.md +0 -0
  59. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/helper.md +0 -0
  60. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/login.md +0 -0
  61. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/lyric.md +0 -0
  62. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/mv.md +0 -0
  63. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/private_message.md +0 -0
  64. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/recommend.md +0 -0
  65. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/request.md +0 -0
  66. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/search.md +0 -0
  67. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/singer.md +0 -0
  68. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/song.md +0 -0
  69. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/songlist.md +0 -0
  70. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/sound_power.md +0 -0
  71. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/top.md +0 -0
  72. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/model/user.md +0 -0
  73. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/album.md +0 -0
  74. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/comment.md +0 -0
  75. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/helper.md +0 -0
  76. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/helper_utils.md +0 -0
  77. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/login.md +0 -0
  78. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/login_utils.md +0 -0
  79. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/lyric.md +0 -0
  80. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/mv.md +0 -0
  81. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/private_message.md +0 -0
  82. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/recommend.md +0 -0
  83. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/search.md +0 -0
  84. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/singer.md +0 -0
  85. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/song.md +0 -0
  86. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/songlist.md +0 -0
  87. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/sound_power.md +0 -0
  88. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/top.md +0 -0
  89. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/reference/modules/user.md +0 -0
  90. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/client.md +0 -0
  91. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/credential.md +0 -0
  92. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/download.md +0 -0
  93. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/error-handling.md +0 -0
  94. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/login.md +0 -0
  95. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/pagination.md +0 -0
  96. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/start.md +0 -0
  97. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/docs/tutorial/web.md +0 -0
  98. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/download_song.py +0 -0
  99. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/get_all_sheets.py +0 -0
  100. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/phone_login.py +0 -0
  101. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/private_message.py +0 -0
  102. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/qrcode_login.py +0 -0
  103. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/sound_power.py +0 -0
  104. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/examples/upload_file.py +0 -0
  105. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/prek.toml +0 -0
  106. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/algorithms/__init__.py +0 -0
  107. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/algorithms/sign.py +0 -0
  108. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/algorithms/tripledes.py +0 -0
  109. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/__init__.py +0 -0
  110. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/client.py +0 -0
  111. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/endpoint.py +0 -0
  112. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/engine.py +0 -0
  113. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/exceptions.py +0 -0
  114. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/executor.py +0 -0
  115. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/pagination.py +0 -0
  116. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/request.py +0 -0
  117. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/response.py +0 -0
  118. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/transport.py +0 -0
  119. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/core/versioning.py +0 -0
  120. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/__init__.py +0 -0
  121. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/_validator.py +0 -0
  122. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/album.py +0 -0
  123. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/base.py +0 -0
  124. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/comment.py +0 -0
  125. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/helper.py +0 -0
  126. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/login.py +0 -0
  127. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/lyric.py +0 -0
  128. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/mv.py +0 -0
  129. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/private_message.py +0 -0
  130. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/recommend.py +0 -0
  131. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/request.py +0 -0
  132. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/search.py +0 -0
  133. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/song.py +0 -0
  134. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/songlist.py +0 -0
  135. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/sound_power.py +0 -0
  136. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/top.py +0 -0
  137. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/models/user.py +0 -0
  138. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/__init__.py +0 -0
  139. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/_base.py +0 -0
  140. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/album.py +0 -0
  141. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/comment.py +0 -0
  142. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/helper.py +0 -0
  143. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/helper_utils.py +0 -0
  144. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/login.py +0 -0
  145. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/login_utils.py +0 -0
  146. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/lyric.py +0 -0
  147. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/mv.py +0 -0
  148. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/private_message.py +0 -0
  149. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/recommend.py +0 -0
  150. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/search.py +0 -0
  151. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/song.py +0 -0
  152. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/songlist.py +0 -0
  153. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/sound_power.py +0 -0
  154. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/top.py +0 -0
  155. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/modules/user.py +0 -0
  156. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/py.typed +0 -0
  157. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/utils/__init__.py +0 -0
  158. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/utils/android_session.py +0 -0
  159. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/utils/common.py +0 -0
  160. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/utils/device.py +0 -0
  161. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/utils/mqtt.py +0 -0
  162. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/qqmusic_api/utils/qimei.py +0 -0
  163. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/scripts/ag-1.py +0 -0
  164. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/conftest.py +0 -0
  165. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/kernel_contract.py +0 -0
  166. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_album.py +0 -0
  167. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_android_session.py +0 -0
  168. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_client.py +0 -0
  169. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_comment.py +0 -0
  170. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_device.py +0 -0
  171. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_endpoint.py +0 -0
  172. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_engine.py +0 -0
  173. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_executor.py +0 -0
  174. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_login.py +0 -0
  175. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_login_engine.py +0 -0
  176. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_login_utils.py +0 -0
  177. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_lyric.py +0 -0
  178. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_mv.py +0 -0
  179. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_pagination.py +0 -0
  180. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_private_message.py +0 -0
  181. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_qimei.py +0 -0
  182. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_recommend.py +0 -0
  183. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_response.py +0 -0
  184. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_search.py +0 -0
  185. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_song.py +0 -0
  186. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_songlist.py +0 -0
  187. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_sound_power.py +0 -0
  188. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_top.py +0 -0
  189. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_transport.py +0 -0
  190. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/test_user.py +0 -0
  191. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/typing/test_build_request.py +0 -0
  192. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/tests/typing/test_endpoint_typing.py +0 -0
  193. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/.gitignore +0 -0
  194. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/Dockerfile +0 -0
  195. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/accounts.example.toml +0 -0
  196. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/docker-compose.example.yml +0 -0
  197. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/__init__.py +0 -0
  198. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/auth.py +0 -0
  199. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/cache.py +0 -0
  200. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/coalesce.py +0 -0
  201. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/credential_pool.py +0 -0
  202. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/credential_store.py +0 -0
  203. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/deps.py +0 -0
  204. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/error_mapping.py +0 -0
  205. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/response.py +0 -0
  206. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/core/security.py +0 -0
  207. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/__init__.py +0 -0
  208. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/comment.py +0 -0
  209. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/singer.py +0 -0
  210. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/song.py +0 -0
  211. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/modules/songlist.py +0 -0
  212. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/__init__.py +0 -0
  213. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/album.py +0 -0
  214. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/comment.py +0 -0
  215. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/login.py +0 -0
  216. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/lyric.py +0 -0
  217. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/recommend.py +0 -0
  218. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/search.py +0 -0
  219. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/song.py +0 -0
  220. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/songlist.py +0 -0
  221. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/sound_power.py +0 -0
  222. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/top.py +0 -0
  223. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routes/user.py +0 -0
  224. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/__init__.py +0 -0
  225. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/docstrings.py +0 -0
  226. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/executor.py +0 -0
  227. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/modules.py +0 -0
  228. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/src/routing/params.py +0 -0
  229. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/conftest.py +0 -0
  230. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/test_web_core.py +0 -0
  231. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/test_web_docstrings.py +0 -0
  232. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/test_web_engine_services.py +0 -0
  233. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/test_web_enums.py +0 -0
  234. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/test_web_route_validation.py +0 -0
  235. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/web/tests/test_web_routes.py +0 -0
  236. {qqmusic_api_python-0.8.1 → qqmusic_api_python-0.8.2}/zensical.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: qqmusic-api-python
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: QQ音乐API封装库
5
5
  Project-URL: documentation, https://l-1124.github.io/QQMusicApi/
6
6
  Project-URL: homepage, https://l-1124.github.io/QQMusicApi/
@@ -1,4 +1,30 @@
1
1
 
2
+ ## [[0.8.1](https://github.com/L-1124/QQMusicApi/compare/v0.8.0..v0.8.1)] - 2026-10-04
3
+
4
+ ### Bug 修复
5
+
6
+ * **(core)** 为传输层增加默认请求超时 ([86a2716](https://github.com/L-1124/QQMusicApi/commit/86a2716eddde166edcacfe511d4b9f2090f6a2bd)) by [@L-1124](https://github.com/L-1124)
7
+ * **(web)** 手机验证码路由改为 POST 提交 ([b714255](https://github.com/L-1124/QQMusicApi/commit/b714255b2a9dbef535e709659fd029b49856bbf6)) by [@L-1124](https://github.com/L-1124)
8
+ * **(web)** 参数校验失败响应返回错误详情 ([dee7e18](https://github.com/L-1124/QQMusicApi/commit/dee7e187c26a45b973759f56c7445da635e04740)) by [@L-1124](https://github.com/L-1124)
9
+
10
+ ### 功能更新
11
+
12
+ * **(core)** 新增 Credential.is_valid 并收编登录态判断 ([415b3ae](https://github.com/L-1124/QQMusicApi/commit/415b3aef6e3f3b7fc5092653f22c1ce0d5dc31d5)) by [@L-1124](https://github.com/L-1124)
13
+ * **(core)** 补充 py.typed 类型标记 ([2136321](https://github.com/L-1124/QQMusicApi/commit/2136321cf19796e0738f6b91243a650dd99f76a2)) by [@L-1124](https://github.com/L-1124)
14
+
15
+ ### 功能重构
16
+
17
+ * **(web)** 复用 Credential.is_valid 移除重复登录态判断 ([f8ec18d](https://github.com/L-1124/QQMusicApi/commit/f8ec18dcf9a559988ff141972b704861a3a5ef5e)) by [@L-1124](https://github.com/L-1124)
18
+
19
+ ### 文档更新
20
+
21
+ * 修正刷新凭证示例与 Web 服务启动说明 ([83e743b](https://github.com/L-1124/QQMusicApi/commit/83e743b52219471ddb399e21d6a003273f2c0bd2)) by [@L-1124](https://github.com/L-1124)
22
+
23
+ ### 贡献者
24
+
25
+ * @L-1124
26
+ * @github-actions[bot]
27
+
2
28
  ## [[0.8.0](https://github.com/L-1124/QQMusicApi/compare/v0.7.3..v0.8.0)] - 2026-10-04
3
29
 
4
30
  ### Bug 修复
@@ -86,7 +86,6 @@ web = [
86
86
  "fastapi>=0.136.1",
87
87
  "griffe>=2.0.2",
88
88
  "pydantic-settings[toml]>=2.14.0",
89
- "loguru>=0.7.3",
90
89
  "uvicorn>=0.46.0",
91
90
  ]
92
91
 
@@ -23,7 +23,7 @@ from .core.exceptions import (
23
23
  from .core.versioning import Platform
24
24
  from .models.request import Credential
25
25
 
26
- __version__ = "0.8.1"
26
+ __version__ = "0.8.2"
27
27
 
28
28
  __all__ = [
29
29
  "ApiDataError",
@@ -234,6 +234,74 @@ class VideoBrief(MV):
234
234
  icon_type: int = 0
235
235
 
236
236
 
237
+ class TabFilterItem(Response):
238
+ """Tab 筛选条目 (专辑类型 / 视频标签).
239
+
240
+ Attributes:
241
+ id: 筛选项 ID.
242
+ title: 筛选项名称.
243
+ """
244
+
245
+ id: int = Field(default=-1, validation_alias=AliasChoices("ID", "id"))
246
+ title: str = Field(default="", validation_alias=AliasChoices("Title", "name"))
247
+
248
+
249
+ class TabFilterList(Response):
250
+ """服务端下发的 Tab 筛选列表.
251
+
252
+ Attributes:
253
+ default_id: 默认选中项 ID.
254
+ items: 筛选项列表.
255
+ """
256
+
257
+ default_id: int = Field(default=0, validation_alias="DefaultID")
258
+ items: Annotated[list[TabFilterItem], NoneToEmptyList] = Field(default_factory=list, validation_alias="ItemList")
259
+
260
+
261
+ class SongTabInfo(Response):
262
+ """歌曲 Tab 内容.
263
+
264
+ Attributes:
265
+ songs: 歌曲列表.
266
+ tag_info_list: 歌曲标签信息列表 (客户端原样透传).
267
+ """
268
+
269
+ songs: Annotated[list[Song], NoneToEmptyList] = Field(
270
+ default_factory=list, json_schema_extra={"jsonpath": "$.List[*]"}
271
+ )
272
+ tag_info_list: Annotated[list[dict[str, Any]], NoneToEmptyList] = Field(
273
+ default_factory=list, validation_alias="SongTagInfoList"
274
+ )
275
+
276
+
277
+ class AlbumTabInfo(Response):
278
+ """专辑 Tab 内容.
279
+
280
+ Attributes:
281
+ type_list: 服务端下发的专辑分类筛选列表.
282
+ albums: 专辑列表.
283
+ """
284
+
285
+ type_list: TabFilterList = Field(default_factory=TabFilterList, validation_alias="TypeList")
286
+ albums: Annotated[list[AlbumBrief], NoneToEmptyList] = Field(
287
+ default_factory=list, json_schema_extra={"jsonpath": "$.AlbumList[*]"}
288
+ )
289
+
290
+
291
+ class VideoTabInfo(Response):
292
+ """视频 Tab 内容.
293
+
294
+ Attributes:
295
+ videos: 视频列表.
296
+ tag_list: 服务端下发的视频标签筛选列表.
297
+ """
298
+
299
+ videos: Annotated[list[VideoBrief], NoneToEmptyList] = Field(
300
+ default_factory=list, json_schema_extra={"jsonpath": "$.VideoList[*]"}
301
+ )
302
+ tag_list: Annotated[list[TabFilterItem], NoneToEmptyList] = Field(default_factory=list, validation_alias="TagList")
303
+
304
+
237
305
  class HomepageTabDetailResponse(Response):
238
306
  """歌手主页标签详情响应.
239
307
 
@@ -241,12 +309,12 @@ class HomepageTabDetailResponse(Response):
241
309
  tab_id: 当前标签页 ID.
242
310
  has_more: 是否还有更多结果.
243
311
  need_show_tab: 是否需要展示标签.
244
- order: 排序值.
312
+ order: 服务端归一化后的排序值.
245
313
  tab_list: 标签页元信息列表.
246
- introduction_tab: 简介标签内容.
247
- song_tab: 歌曲标签内容.
248
- album_tab: 专辑标签内容.
249
- video_tab: 视频标签内容.
314
+ song_tab: 歌曲 Tab 内容.
315
+ album_tab: 专辑 Tab 内容.
316
+ video_tab: 视频 Tab 内容.
317
+ introduction_tab: 简介 Tab 内容.
250
318
  """
251
319
 
252
320
  tab_id: str = Field(default="", validation_alias="TabID")
@@ -254,19 +322,13 @@ class HomepageTabDetailResponse(Response):
254
322
  need_show_tab: int = Field(default=0, validation_alias="NeedShowTab")
255
323
  order: int = Field(default=0, validation_alias="Order")
256
324
  tab_list: Annotated[list[TabMeta], NoneToEmptyList] = Field(default_factory=list, validation_alias="TabList")
325
+ song_tab: SongTabInfo = Field(default_factory=SongTabInfo, validation_alias="SongTab")
326
+ album_tab: AlbumTabInfo = Field(default_factory=AlbumTabInfo, validation_alias="AlbumTab")
327
+ video_tab: VideoTabInfo = Field(default_factory=VideoTabInfo, validation_alias="VideoTab")
257
328
  introduction_tab: Annotated[list[dict[str, Any]], NoneToEmptyList] = Field(
258
329
  default_factory=list,
259
330
  json_schema_extra={"jsonpath": "$.IntroductionTab.List"},
260
331
  )
261
- song_tab: Annotated[list[Song], NoneToEmptyList] = Field(
262
- default_factory=list, json_schema_extra={"jsonpath": "$.SongTab.List[*]"}
263
- )
264
- album_tab: Annotated[list[AlbumBrief], NoneToEmptyList] = Field(
265
- default_factory=list, json_schema_extra={"jsonpath": "$.AlbumTab.AlbumList[*]"}
266
- )
267
- video_tab: Annotated[list[VideoBrief], NoneToEmptyList] = Field(
268
- default_factory=list, json_schema_extra={"jsonpath": "$.VideoTab.VideoList[*]"}
269
- )
270
332
 
271
333
 
272
334
  class HomepageHeaderResponse(Response):
@@ -1,9 +1,9 @@
1
1
  """歌手相关 API."""
2
2
 
3
3
  from enum import Enum, IntEnum
4
- from typing import cast
4
+ from typing import Any, Literal, TypedDict, cast, overload
5
5
 
6
- from ..core import Platform
6
+ from ..core import PaginatedCgiRequest, Platform
7
7
  from ..core.endpoint import CgiRequestData, cgi_endpoint
8
8
  from ..core.pagination import (
9
9
  MultiFieldContinuationStrategy,
@@ -91,6 +91,17 @@ class TabType(Enum):
91
91
  self.tab_name = tab_name
92
92
 
93
93
 
94
+ class OrderType(IntEnum):
95
+ """歌手主页条目排序类型.
96
+
97
+ + LATEST: 最新 / 按时间排序 (0)
98
+ + HOT: 最热 / 按热度排序 (1)
99
+ """
100
+
101
+ LATEST = 0
102
+ HOT = 1
103
+
104
+
94
105
  class IndexType(IntEnum):
95
106
  """首字母索引枚举."""
96
107
 
@@ -124,6 +135,30 @@ class IndexType(IntEnum):
124
135
  HASH = 27
125
136
 
126
137
 
138
+ class AlbumExtension(TypedDict):
139
+ """专辑 Tab 扩展参数.
140
+
141
+ Attributes:
142
+ IsNeedFilterType: 是否下发分类筛选列表.
143
+ FilterType: 分类筛选值.
144
+ """
145
+
146
+ IsNeedFilterType: int
147
+ FilterType: int
148
+
149
+
150
+ class VideoExtension(TypedDict):
151
+ """视频 Tab 扩展参数.
152
+
153
+ Attributes:
154
+ TagID: 视频标签筛选值.
155
+ IsNeedTagList: 是否下发标签列表.
156
+ """
157
+
158
+ TagID: int
159
+ IsNeedTagList: int
160
+
161
+
127
162
  class SingerApi(ApiModule):
128
163
  """歌手相关 API."""
129
164
 
@@ -224,6 +259,38 @@ class SingerApi(ApiModule):
224
259
  param={"SingerMid": mid},
225
260
  )
226
261
 
262
+ @overload
263
+ def get_tab_detail(
264
+ self,
265
+ mid: str,
266
+ tab_type: Literal[TabType.VIDEO],
267
+ page: int = 1,
268
+ num: int = 10,
269
+ order: OrderType | int = OrderType.LATEST,
270
+ extension: VideoExtension | None = None,
271
+ ) -> PaginatedCgiRequest[HomepageTabDetailResponse]: ...
272
+
273
+ @overload
274
+ def get_tab_detail(
275
+ self,
276
+ mid: str,
277
+ tab_type: Literal[TabType.ALBUM],
278
+ page: int = 1,
279
+ num: int = 10,
280
+ order: OrderType | int = OrderType.LATEST,
281
+ extension: AlbumExtension | None = None,
282
+ ) -> PaginatedCgiRequest[HomepageTabDetailResponse]: ...
283
+
284
+ @overload
285
+ def get_tab_detail(
286
+ self,
287
+ mid: str,
288
+ tab_type: TabType,
289
+ page: int = 1,
290
+ num: int = 10,
291
+ order: OrderType | int = OrderType.LATEST,
292
+ ) -> PaginatedCgiRequest[HomepageTabDetailResponse]: ...
293
+
227
294
  @cgi_endpoint(
228
295
  key="singer.get_tab_detail",
229
296
  module="music.UnifiedHomepage.UnifiedHomepageSrv",
@@ -237,6 +304,8 @@ class SingerApi(ApiModule):
237
304
  tab_type: TabType,
238
305
  page: int = 1,
239
306
  num: int = 10,
307
+ order: OrderType | int = OrderType.LATEST,
308
+ extension: VideoExtension | AlbumExtension | None = None,
240
309
  ) -> CgiRequestData:
241
310
  """获取歌手主页特定 Tab 的详情原始数据.
242
311
 
@@ -245,16 +314,21 @@ class SingerApi(ApiModule):
245
314
  tab_type: Tab 类型.
246
315
  page: 页码.
247
316
  num: 返回数量.
317
+ order: 排序方式 (最新 / 最热).
318
+ extension: Tab 请求扩展参数.
248
319
  """
320
+ param: dict[str, Any] = {
321
+ "SingerMid": mid,
322
+ "IsQueryTabDetail": 1,
323
+ "TabID": tab_type.tab_id,
324
+ "PageNum": page - 1,
325
+ "PageSize": num,
326
+ "Order": int(order),
327
+ }
328
+ if extension:
329
+ param[tab_type.value[1].replace("Tab", "") + "Extension"] = extension
249
330
  return CgiRequestData(
250
- param={
251
- "SingerMid": mid,
252
- "IsQueryTabDetail": 1,
253
- "TabID": tab_type.tab_id,
254
- "PageNum": page - 1,
255
- "PageSize": num,
256
- "Order": 0,
257
- },
331
+ param=param,
258
332
  pager_strategy=PageStrategy[HomepageTabDetailResponse](
259
333
  page_key="PageNum",
260
334
  page_size=num,
@@ -324,16 +398,23 @@ class SingerApi(ApiModule):
324
398
  response_model=SingerSongListResponse,
325
399
  item_type=Song,
326
400
  )
327
- def get_songs_list(self, mid: str, num: int = 10, page: int = 1) -> CgiRequestData:
401
+ def get_songs_list(
402
+ self,
403
+ mid: str,
404
+ num: int = 10,
405
+ page: int = 1,
406
+ order: OrderType | int = OrderType.HOT,
407
+ ) -> CgiRequestData:
328
408
  """获取歌手的歌曲列表.
329
409
 
330
410
  Args:
331
411
  mid: 歌手 MID.
332
412
  num: 返回歌曲数量.
333
413
  page: 分页页码.
414
+ order: 排序方式.
334
415
  """
335
416
  return CgiRequestData(
336
- param={"singerMid": mid, "order": 1, "number": num, "begin": (page - 1) * num},
417
+ param={"singerMid": mid, "order": int(order), "number": num, "begin": (page - 1) * num},
337
418
  pager_strategy=OffsetStrategy[SingerSongListResponse](
338
419
  offset_key="begin",
339
420
  page_size_key="number",
@@ -350,16 +431,23 @@ class SingerApi(ApiModule):
350
431
  response_model=SingerAlbumListResponse,
351
432
  item_type=AlbumBrief,
352
433
  )
353
- def get_album_list(self, mid: str, num: int = 10, page: int = 1) -> CgiRequestData:
434
+ def get_album_list(
435
+ self,
436
+ mid: str,
437
+ num: int = 10,
438
+ page: int = 1,
439
+ order: OrderType | int = OrderType.HOT,
440
+ ) -> CgiRequestData:
354
441
  """获取歌手的专辑列表.
355
442
 
356
443
  Args:
357
444
  mid: 歌手 MID.
358
445
  num: 返回专辑数量.
359
446
  page: 分页页码.
447
+ order: 排序方式.
360
448
  """
361
449
  return CgiRequestData(
362
- param={"singerMid": mid, "order": 1, "number": num, "begin": (page - 1) * num},
450
+ param={"singerMid": mid, "order": int(order), "number": num, "begin": (page - 1) * num},
363
451
  pager_strategy=OffsetStrategy[SingerAlbumListResponse](
364
452
  offset_key="begin",
365
453
  page_size_key="number",
@@ -376,16 +464,23 @@ class SingerApi(ApiModule):
376
464
  response_model=SingerMvListResponse,
377
465
  item_type=VideoBrief,
378
466
  )
379
- def get_mv_list(self, mid: str, num: int = 10, page: int = 1) -> CgiRequestData:
467
+ def get_mv_list(
468
+ self,
469
+ mid: str,
470
+ num: int = 10,
471
+ page: int = 1,
472
+ order: OrderType | int = OrderType.HOT,
473
+ ) -> CgiRequestData:
380
474
  """获取歌手 MV 列表数据.
381
475
 
382
476
  Args:
383
477
  mid: 歌手 MID.
384
478
  num: 返回数量.
385
479
  page: 分页页码.
480
+ order: 排序方式.
386
481
  """
387
482
  return CgiRequestData(
388
- param={"singermid": mid, "order": 1, "count": num, "start": (page - 1) * num},
483
+ param={"singermid": mid, "order": order, "count": num, "start": (page - 1) * num},
389
484
  pager_strategy=OffsetStrategy[SingerMvListResponse](
390
485
  offset_key="start",
391
486
  page_size_key="count",
@@ -82,8 +82,20 @@ async def test_get_tab_detail_song(client: Client) -> None:
82
82
  page=1,
83
83
  num=10,
84
84
  )
85
- assert result.song_tab is not None
86
- assert result.song_tab
85
+ assert result.song_tab.songs
86
+
87
+
88
+ async def test_get_tab_detail_song_with_order(client: Client) -> None:
89
+ """测试使用排序参数获取歌手歌曲 Tab 模型."""
90
+ result = await client.singer.get_tab_detail(
91
+ mid="0025NhlN2yWrP4",
92
+ tab_type=TabType.SONG,
93
+ page=1,
94
+ num=5,
95
+ order=1,
96
+ )
97
+ assert result.song_tab.songs
98
+ assert result.order == 1
87
99
 
88
100
 
89
101
  async def test_get_tab_detail_album(client: Client) -> None:
@@ -94,8 +106,21 @@ async def test_get_tab_detail_album(client: Client) -> None:
94
106
  page=1,
95
107
  num=10,
96
108
  )
97
- assert result.album_tab is not None
98
- assert result.album_tab
109
+ assert result.album_tab.albums
110
+ assert result.album_tab.type_list.default_id == 0
111
+
112
+
113
+ async def test_get_tab_detail_album_with_filter(client: Client) -> None:
114
+ """测试携带分类筛选参数获取歌手专辑 Tab, 服务端返回筛选列表."""
115
+ result = await client.singer.get_tab_detail(
116
+ mid="000GGDys0yA0Nk",
117
+ tab_type=TabType.ALBUM,
118
+ page=1,
119
+ num=5,
120
+ extension={"IsNeedFilterType": 1, "FilterType": 2},
121
+ )
122
+ assert result.album_tab.type_list.items
123
+ assert {item.id for item in result.album_tab.type_list.items} == {0, 1, 2, 3, 4}
99
124
 
100
125
 
101
126
  async def test_get_tab_detail_video(client: Client) -> None:
@@ -106,8 +131,19 @@ async def test_get_tab_detail_video(client: Client) -> None:
106
131
  page=1,
107
132
  num=10,
108
133
  )
109
- assert result.video_tab is not None
110
- assert result.video_tab
134
+ assert result.video_tab.videos
135
+
136
+
137
+ async def test_get_tab_detail_video_with_tag(client: Client) -> None:
138
+ """测试携带标签参数获取歌手视频 Tab, 服务端返回标签列表."""
139
+ result = await client.singer.get_tab_detail(
140
+ mid="000GGDys0yA0Nk",
141
+ tab_type=TabType.VIDEO,
142
+ page=1,
143
+ num=5,
144
+ extension={"TagID": 0, "IsNeedTagList": 1},
145
+ )
146
+ assert result.video_tab.tag_list
111
147
 
112
148
 
113
149
  async def test_get_desc(client: Client) -> None:
@@ -149,6 +185,7 @@ async def test_get_songs_list_with_params(client: Client) -> None:
149
185
  mid="0025NhlN2yWrP4",
150
186
  num=10,
151
187
  page=2,
188
+ order=1,
152
189
  )
153
190
  assert result.song_list
154
191
  assert len(result.song_list) <= result.total_num
@@ -167,6 +204,7 @@ async def test_get_album_list_with_params(client: Client) -> None:
167
204
  mid="0025NhlN2yWrP4",
168
205
  num=10,
169
206
  page=2,
207
+ order=1,
170
208
  )
171
209
  assert result.album_list
172
210
 
@@ -35,7 +35,7 @@ from qqmusic_api.models.songlist import GetSonglistDetailResponse
35
35
  from qqmusic_api.models.top import TopDetailResponse
36
36
  from qqmusic_api.models.user import DislikeListData, RelationUser, UserRelationListResponse
37
37
  from qqmusic_api.modules.search import SearchType
38
- from qqmusic_api.modules.singer import TabType
38
+ from qqmusic_api.modules.singer import OrderType, TabType
39
39
  from qqmusic_api.modules.song import SongFileInfo
40
40
 
41
41
  pytestmark = pytest.mark.core
@@ -105,11 +105,15 @@ def test_client_facade_pure_paginated_types():
105
105
  tab_req = client.singer.get_tab_detail("001BLpXF2DyJe2", TabType.SONG)
106
106
  assert_type(tab_req, PaginatedCgiRequest[HomepageTabDetailResponse])
107
107
 
108
+ tab_song_req = client.singer.get_tab_detail("001BLpXF2DyJe2", TabType.SONG, order=OrderType.HOT)
109
+ assert_type(tab_song_req, PaginatedCgiRequest[HomepageTabDetailResponse])
110
+
111
+ tab_album_req = client.singer.get_tab_detail("001BLpXF2DyJe2", TabType.ALBUM, order=OrderType.LATEST)
112
+ assert_type(tab_album_req, PaginatedCgiRequest[HomepageTabDetailResponse])
108
113
  tab_annotated: PaginatedCgiRequest[HomepageTabDetailResponse] = client.singer.get_tab_detail(
109
- "001BLpXF2DyJe2", TabType.SONG
114
+ "001BLpXF2DyJe2", TabType.SONG, order=0
110
115
  )
111
116
  assert_type(tab_annotated, PaginatedCgiRequest[HomepageTabDetailResponse])
112
-
113
117
  general_req = client.search.general_search("周杰伦")
114
118
  assert_type(general_req, PaginatedCgiRequest[GeneralSearchResponse])
115
119