feat(music): add TheAudioDB and Douban discovery

This commit is contained in:
jxxghp
2026-08-12 10:50:13 +08:00
parent a1dd259143
commit d1028a6902
15 changed files with 769 additions and 20 deletions

View File

@@ -133,6 +133,7 @@ async def clear_music_recognition_cache(
async def explore_music(
page: PageParam = 1,
count: CountParam = 30,
source: MusicSourceParam = "musicbrainz",
mode: MusicModeParam = "chart",
entity: MusicEntityParam = "recording",
range_name: MusicRangeParam = "this_month",
@@ -143,11 +144,20 @@ async def explore_music(
future: bool = True,
min_listen_count: Annotated[int, Query(ge=0)] = 0,
with_cover: bool = False,
country: Annotated[str, Query(pattern="^[A-Za-z]{2}$")] = "us",
_: schemas.TokenPayload = Depends(verify_token),
) -> list[schemas.MusicInfo]:
""" ListenBrainz 官方热门榜单或新发行两种模式返回可订阅的音乐候选。"""
"""音乐来源返回可订阅的榜单或新发行候选。"""
chain = MusicChain()
if mode == "fresh":
if source != "musicbrainz":
results = await chain.async_discover(
source=source,
page=page,
count=count,
entity=entity,
country=country,
)
elif mode == "fresh":
results = await chain.async_fresh_releases(
days=days,
sort=sort,
@@ -167,6 +177,8 @@ async def explore_music(
with_cover=with_cover,
entity=entity,
)
if source != "musicbrainz" and with_cover:
results = [info for info in results if info.cover_url or info.poster_path]
return [_serialize_music(info) for info in results]
@@ -187,6 +199,26 @@ async def music_album(
return _serialize_album(info)
@router.get(
"/album/{album_id}/related",
summary="查询关联音乐专辑",
response_model=list[schemas.MusicInfo],
)
async def music_album_related(
album_id: str,
count: CountParam = 24,
source: MusicSourceParam = "musicbrainz",
_: schemas.TokenPayload = Depends(verify_token),
) -> list[schemas.MusicInfo]:
"""按来源和专辑 ID 返回可继续浏览的关联专辑。"""
results = await MusicChain().async_album_related(
source=source,
media_id=album_id,
count=count,
)
return [_serialize_music(info) for info in results]
@router.get(
"/artist/{artist_id}/albums",
summary="查询艺术家的专辑列表",

View File

@@ -74,6 +74,58 @@ async def music_weekly(
return await RecommendChain().async_music_weekly(page=page, count=count)
@router.get(
"/music_theaudiodb_albums",
summary="TheAudioDB 热门专辑",
response_model=List[schemas.MusicInfo],
)
async def music_theaudiodb_albums(
page: Optional[int] = 1,
count: Optional[int] = 30,
country: str = "us",
_: schemas.TokenPayload = Depends(verify_token),
) -> Any:
"""浏览 TheAudioDB 指定国家或地区的热门专辑。"""
return await RecommendChain().async_music_theaudiodb_albums(
page=page,
count=count,
country=country,
)
@router.get(
"/music_theaudiodb_tracks",
summary="TheAudioDB 热门单曲",
response_model=List[schemas.MusicInfo],
)
async def music_theaudiodb_tracks(
page: Optional[int] = 1,
count: Optional[int] = 30,
country: str = "us",
_: schemas.TokenPayload = Depends(verify_token),
) -> Any:
"""浏览 TheAudioDB 指定国家或地区的热门单曲。"""
return await RecommendChain().async_music_theaudiodb_tracks(
page=page,
count=count,
country=country,
)
@router.get(
"/music_douban",
summary="豆瓣音乐推荐",
response_model=List[schemas.MusicInfo],
)
async def music_douban(
page: Optional[int] = 1,
count: Optional[int] = 30,
_: schemas.TokenPayload = Depends(verify_token),
) -> Any:
"""浏览豆瓣音乐推荐合集。"""
return await RecommendChain().async_music_douban(page=page, count=count)
@router.get(
"/douban_showing", summary="豆瓣正在热映", response_model=List[schemas.MediaInfo]
)

View File

@@ -613,7 +613,7 @@ async def subscribe_history(
current_user: User = Depends(get_current_active_user_async),
) -> Any:
"""
查询电影/电视剧订阅历史
查询电影电视剧或音乐订阅历史
"""
if current_user.is_superuser:
histories = await SubscribeHistory.async_list_by_type(