mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-08 08:57:09 +08:00
fix(music): default Douban explore to categories
This commit is contained in:
@@ -29,7 +29,7 @@ MusicExploreSourceParam = Annotated[
|
|||||||
str,
|
str,
|
||||||
Query(pattern="^(musicbrainz|doubanmusic)$"),
|
Query(pattern="^(musicbrainz|doubanmusic)$"),
|
||||||
]
|
]
|
||||||
MusicModeParam = Annotated[str, Query(pattern="^(chart|fresh|tag)$")]
|
MusicModeParam = Annotated[str, Query(pattern="^(chart|fresh)$")]
|
||||||
MusicEntityParam = Annotated[str, Query(pattern="^(recording|album)$")]
|
MusicEntityParam = Annotated[str, Query(pattern="^(recording|album)$")]
|
||||||
MusicRangeParam = Annotated[str, Query(pattern=f"^({'|'.join(LISTENBRAINZ_CHART_RANGES)})$")]
|
MusicRangeParam = Annotated[str, Query(pattern=f"^({'|'.join(LISTENBRAINZ_CHART_RANGES)})$")]
|
||||||
MusicSortParam = Annotated[str, Query(pattern="^listen_count\\.(desc|asc)$")]
|
MusicSortParam = Annotated[str, Query(pattern="^listen_count\\.(desc|asc)$")]
|
||||||
@@ -153,7 +153,7 @@ async def explore_music(
|
|||||||
douban_sort: DoubanMusicSortParam = "U",
|
douban_sort: DoubanMusicSortParam = "U",
|
||||||
_: schemas.TokenPayload = Depends(verify_token),
|
_: schemas.TokenPayload = Depends(verify_token),
|
||||||
) -> list[schemas.MusicInfo]:
|
) -> list[schemas.MusicInfo]:
|
||||||
"""按音乐来源返回可订阅的榜单或新发行候选。"""
|
"""MusicBrainz 返回榜单或新发行,豆瓣音乐固定按官方标签分类浏览。"""
|
||||||
chain = MusicChain()
|
chain = MusicChain()
|
||||||
if media_source != "musicbrainz":
|
if media_source != "musicbrainz":
|
||||||
results = await chain.async_discover(
|
results = await chain.async_discover(
|
||||||
@@ -161,7 +161,7 @@ async def explore_music(
|
|||||||
page=page,
|
page=page,
|
||||||
count=count,
|
count=count,
|
||||||
entity=entity,
|
entity=entity,
|
||||||
mode=mode,
|
mode="tag",
|
||||||
tags=tags,
|
tags=tags,
|
||||||
sort=douban_sort,
|
sort=douban_sort,
|
||||||
)
|
)
|
||||||
|
|||||||
+9
-11
@@ -194,18 +194,16 @@ AniList 榜单、探索、详情、人物和推荐接口优先通过 `anilist-ch
|
|||||||
|
|
||||||
| 方法 | 路径 | 说明 |
|
| 方法 | 路径 | 说明 |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| GET | `/api/v1/media/search` | 当 `type=music` 或 `source=musicbrainz` 时按歌曲、专辑或歌手关键词搜索音乐元数据,参数:`title`、`type`、`count` |
|
| GET | `/api/v1/media/search` | 当 `type=music` 或指定音乐 `media_source` 时按歌曲、专辑或歌手关键词搜索音乐元数据,参数:`title`、`type`、`count`、`media_source` |
|
||||||
| POST | `/api/v1/music/recognize` | 按 `source` + `media_id` 识别音乐详情,请求体:`MusicRecognizeRequest` |
|
| POST | `/api/v1/music/recognize` | 按 `media_source` + `media_id` 识别音乐详情,请求体:`MusicRecognizeRequest` |
|
||||||
| GET | `/api/v1/music/explore` | 按来源浏览音乐;`source=musicbrainz` 支持热门榜单与新发行,`source=theaudiodb` 支持国家/地区趋势专辑或单曲,`source=doubanmusic` 支持豆瓣音乐推荐。参数:`source`、`mode=chart|fresh`、`entity=recording|album`、`country`、`range_name`、`sort_by`、`sort`、`days`、`past`、`future`、`min_listen_count`、`with_cover`、`page`、`count` |
|
| GET | `/api/v1/music/explore` | 按来源浏览音乐;`media_source=musicbrainz` 支持 `mode=chart|fresh` 榜单与新发行,`media_source=doubanmusic` 固定按官方标签分类浏览,使用 `tags` 和 `douban_sort=U|S|R|O` 筛选。其它参数:`entity=recording|album`、`range_name`、`sort_by`、`sort`、`days`、`past`、`future`、`min_listen_count`、`with_cover`、`page`、`count` |
|
||||||
| GET | `/api/v1/music/album/{album_id}` | 按来源专辑 ID 查询专辑详情、完整曲目和发行版本,参数:`source` |
|
| GET | `/api/v1/music/album/{album_id}` | 按来源专辑 ID 查询专辑详情、完整曲目和发行版本,参数:`media_source` |
|
||||||
| GET | `/api/v1/music/album/{album_id}/related` | 按来源查询关联专辑,参数:`source`、`count` |
|
| GET | `/api/v1/music/album/{album_id}/related` | 按来源查询关联专辑,参数:`media_source`、`count` |
|
||||||
| GET | `/api/v1/music/artist/{artist_id}` | 查询艺术家详情;艺术家为只读浏览实体,参数:`source` |
|
| GET | `/api/v1/music/artist/{artist_id}` | 查询艺术家详情;艺术家为只读浏览实体,参数:`media_source` |
|
||||||
| GET | `/api/v1/music/artist/{artist_id}/albums` | 分页查询艺术家的专辑、EP 和单曲,参数:`source`、`page`、`count`、`album_type` |
|
| GET | `/api/v1/music/artist/{artist_id}/albums` | 分页查询艺术家的专辑、EP 和单曲,参数:`media_source`、`page`、`count`、`album_type` |
|
||||||
| GET | `/api/v1/music/artist/{artist_id}/related` | 查询关联艺术家,参数:`source`、`count` |
|
| GET | `/api/v1/music/artist/{artist_id}/related` | 查询关联艺术家,参数:`media_source`、`count` |
|
||||||
| GET | `/api/v1/recommend/music_weekly` | 浏览本周热门音乐,参数:`page`、`count` |
|
| GET | `/api/v1/recommend/music_weekly` | 浏览本周热门音乐,参数:`page`、`count` |
|
||||||
| GET | `/api/v1/recommend/music_theaudiodb_albums` | 浏览 TheAudioDB 热门专辑,参数:`country`、`page`、`count` |
|
| GET | `/api/v1/recommend/music_douban` | 浏览豆瓣音乐新碟榜,参数:`page`、`count` |
|
||||||
| GET | `/api/v1/recommend/music_theaudiodb_tracks` | 浏览 TheAudioDB 热门单曲,参数:`country`、`page`、`count` |
|
|
||||||
| GET | `/api/v1/recommend/music_douban` | 浏览豆瓣音乐推荐,参数:`page`、`count` |
|
|
||||||
|
|
||||||
专辑下载与订阅按“整包”处理:下载层会读取种子文件清单并以专辑 `total_tracks` 校验独立音频文件数量;未确认完整覆盖时不会把专辑订阅销订,也不会把部分曲目报告为完整专辑已入库。音乐刮削遵循 `music` 的标签、封面和歌词策略,歌词通过带有界 TTL/LRU 缓存的 LRCLIB 模块保存为同名 `.lrc` 或 `.txt` 旁挂文件。
|
专辑下载与订阅按“整包”处理:下载层会读取种子文件清单并以专辑 `total_tracks` 校验独立音频文件数量;未确认完整覆盖时不会把专辑订阅销订,也不会把部分曲目报告为完整专辑已入库。音乐刮削遵循 `music` 的标签、封面和歌词策略,歌词通过带有界 TTL/LRU 缓存的 LRCLIB 模块保存为同名 `.lrc` 或 `.txt` 旁挂文件。
|
||||||
|
|
||||||
|
|||||||
@@ -187,18 +187,18 @@ music on configured music-capable media servers; it does not manage playlists.
|
|||||||
|
|
||||||
| Method | Path | Description |
|
| Method | Path | Description |
|
||||||
|--------|------|-------------|
|
|--------|------|-------------|
|
||||||
| GET | `/api/v1/media/search` | Search tracks, albums, or artists with `type=music` or `source=musicbrainz`. Params: `title`, `type`, `count` |
|
| GET | `/api/v1/media/search` | Search tracks, albums, or artists with `type=music` or a music `media_source`. Params: `title`, `type`, `count`, `media_source` |
|
||||||
| POST | `/api/v1/music/recognize` | Resolve music metadata. Body: `source`, `media_id` |
|
| POST | `/api/v1/music/recognize` | Resolve music metadata. Body: `media_source`, `media_id` |
|
||||||
| GET | `/api/v1/music/explore` | Explore music by `source`: MusicBrainz charts/fresh releases, TheAudioDB country trends, or Douban music recommendations. Params: `source`, `mode`, `entity`, `country`, `range_name`, `sort_by`, `sort`, `days`, `past`, `future`, `min_listen_count`, `with_cover`, `page`, `count` |
|
| GET | `/api/v1/music/explore` | Explore by `media_source`: MusicBrainz supports `mode=chart|fresh`; Douban Music always uses official tag categories with `tags` and `douban_sort=U|S|R|O`. Other params: `entity`, `range_name`, `sort_by`, `sort`, `days`, `past`, `future`, `min_listen_count`, `with_cover`, `page`, `count` |
|
||||||
| GET | `/api/v1/music/album/{album_id}` | Album detail with tracks and releases. Params: `source` |
|
| GET | `/api/v1/music/album/{album_id}` | Album detail with tracks and releases. Params: `media_source` |
|
||||||
| GET | `/api/v1/music/album/{album_id}/related` | Related albums for the selected source. Params: `source`, `count` |
|
| GET | `/api/v1/music/album/{album_id}/related` | Related albums for the selected source. Params: `media_source`, `count` |
|
||||||
| GET | `/api/v1/music/artist/{artist_id}` | Browse artist detail. Params: `source` |
|
| GET | `/api/v1/music/artist/{artist_id}` | Browse artist detail. Params: `media_source` |
|
||||||
| GET | `/api/v1/music/artist/{artist_id}/albums` | Browse artist albums/EPs/singles. Params: `source`, `page`, `count`, `album_type` |
|
| GET | `/api/v1/music/artist/{artist_id}/albums` | Browse artist albums/EPs/singles. Params: `media_source`, `page`, `count`, `album_type` |
|
||||||
| GET | `/api/v1/music/artist/{artist_id}/related` | Browse related artists. Params: `source`, `count` |
|
| GET | `/api/v1/music/artist/{artist_id}/related` | Browse related artists. Params: `media_source`, `count` |
|
||||||
|
|
||||||
Music acquisition rules:
|
Music acquisition rules:
|
||||||
|
|
||||||
- Reuse `source`, `media_id`, and `music_type` from search/detail results. Never substitute a same-name entity.
|
- Reuse `media_source`, `media_id`, and `music_type` from search/detail results. Never substitute a same-name entity.
|
||||||
- Subscribe/download one recording as one track. Subscribe/download one album as a complete multi-track pack.
|
- Subscribe/download one recording as one track. Subscribe/download one album as a complete multi-track pack.
|
||||||
- Album torrent validation compares supported audio files with `total_tracks`; incomplete resources do not complete the subscription.
|
- Album torrent validation compares supported audio files with `total_tracks`; incomplete resources do not complete the subscription.
|
||||||
- Artist IDs are never subscription, torrent, download, transfer, or library-existence targets.
|
- Artist IDs are never subscription, torrent, download, transfer, or library-existence targets.
|
||||||
@@ -474,9 +474,7 @@ Streaming search sends `{"type":"heartbeat"}` every 15 seconds without business
|
|||||||
| GET | `/api/v1/recommend/source` | Recommendation data sources |
|
| GET | `/api/v1/recommend/source` | Recommendation data sources |
|
||||||
| GET | `/api/v1/recommend/bangumi_calendar` | Bangumi daily schedule. Params: `page`, `count` |
|
| GET | `/api/v1/recommend/bangumi_calendar` | Bangumi daily schedule. Params: `page`, `count` |
|
||||||
| GET | `/api/v1/recommend/music_weekly` | ListenBrainz weekly site-wide music chart. Params: `page`, `count` |
|
| GET | `/api/v1/recommend/music_weekly` | ListenBrainz weekly site-wide music chart. Params: `page`, `count` |
|
||||||
| GET | `/api/v1/recommend/music_theaudiodb_albums` | TheAudioDB trending albums. Params: `country`, `page`, `count` |
|
| GET | `/api/v1/recommend/music_douban` | Douban new album chart. Params: `page`, `count` |
|
||||||
| GET | `/api/v1/recommend/music_theaudiodb_tracks` | TheAudioDB trending tracks. Params: `country`, `page`, `count` |
|
|
||||||
| GET | `/api/v1/recommend/music_douban` | Douban music recommendations. Params: `page`, `count` |
|
|
||||||
| GET | `/api/v1/recommend/douban_showing` | Douban now showing. Params: `page`, `count` |
|
| GET | `/api/v1/recommend/douban_showing` | Douban now showing. Params: `page`, `count` |
|
||||||
| GET | `/api/v1/recommend/douban_movies` | Douban movies. Params: `sort`, `tags`, `page`, `count` |
|
| GET | `/api/v1/recommend/douban_movies` | Douban movies. Params: `sort`, `tags`, `page`, `count` |
|
||||||
| GET | `/api/v1/recommend/douban_tvs` | Douban TV. Params: `sort`, `tags`, `page`, `count` |
|
| GET | `/api/v1/recommend/douban_tvs` | Douban TV. Params: `sort`, `tags`, `page`, `count` |
|
||||||
|
|||||||
@@ -258,8 +258,8 @@ def test_explore_music_supports_official_fresh_release_mode():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_explore_music_forwards_douban_music_source():
|
def test_explore_music_forces_douban_music_to_tag_browsing():
|
||||||
"""豆瓣音乐探索应走可扩展发现链而不是 ListenBrainz。"""
|
"""豆瓣音乐探索即使收到榜单模式也应固定分类浏览,不与推荐页重复。"""
|
||||||
chain = Mock()
|
chain = Mock()
|
||||||
chain.async_discover = AsyncMock(
|
chain.async_discover = AsyncMock(
|
||||||
return_value=[
|
return_value=[
|
||||||
@@ -277,7 +277,7 @@ def test_explore_music_forwards_douban_music_source():
|
|||||||
explore_music(
|
explore_music(
|
||||||
media_source="doubanmusic",
|
media_source="doubanmusic",
|
||||||
entity="album",
|
entity="album",
|
||||||
mode="tag",
|
mode="chart",
|
||||||
tags="流行,华语",
|
tags="流行,华语",
|
||||||
douban_sort="S",
|
douban_sort="S",
|
||||||
page=2,
|
page=2,
|
||||||
|
|||||||
Reference in New Issue
Block a user