feat(sdk): 新增咪咕/千千/JOOX/哔哩哔哩/5sing/Apple Music 六平台
平台注册表由 9 个扩到 15 个,同时补齐 sdk/types.ts 的类型与 OpenAPI 文档里的能力位声明。 - migu:命中 Z3D/I3D 加密候选时不返回直链,改由服务端解密代理出流, SDK 侧只负责登记票据,避免客户端拿到无法播放的密文 - apple:只提供 preview 试听片段(完整曲为 DRM),标 noAggregate 排除在跨平台精确匹配之外,防止用它顶掉其它平台的可播结果 - 其余平台按既有 PlatformModule 约定实现搜索/专辑/歌单/歌词 为什么合并成一次提交:六平台共用同一份注册表与能力位声明, 拆开会产生互相引用、单独无法通过类型检查的中间态。
This commit is contained in:
1 parent
47ce651f46
commit
33b96f92c4
54 files changed
+6161
-5
No files matched your search
@@ -0,0 +1,77 @@
|
||||
// Apple Music 专辑(上游 apple.go 的 SearchAlbum / ParseAlbum / GetAlbumSongs)
|
||||
// 详情:amp-api /v1/catalog/<sf>/albums/<id>?extend=extendedAssetUrls
|
||||
// → data[0].relationships.tracks.data[](>300 首时分页,next 由 fetchAllTrackResources 跟进)
|
||||
// 链接:extractAppleID(link, 'album'),支持裸数字 id 与 /us/album/<slug>/<id> 链接。
|
||||
import {
|
||||
appleAmpGet,
|
||||
appleAlbumToPlaylist,
|
||||
appleSongFromCatalog,
|
||||
extractAppleID,
|
||||
fetchAllTrackResources,
|
||||
getAppleConfig,
|
||||
} from './util.ts'
|
||||
|
||||
export { searchAlbum } from './musicSearch.ts'
|
||||
|
||||
import { searchAlbum } from './musicSearch.ts'
|
||||
|
||||
/** 专辑详情(page/limit 在完整曲目上切片,与其它平台 getAlbumDetail 契约一致) */
|
||||
export const getAlbumDetail = async(rawId: string, page = 1, limit = 50) => {
|
||||
const albumId = extractAppleID(String(rawId ?? ''), 'album')
|
||||
if (!albumId) throw new Error(`invalid apple music album id/link: ${rawId}`)
|
||||
|
||||
const cfg = getAppleConfig()
|
||||
const body: any = await appleAmpGet(`/v1/catalog/${cfg.storefront}/albums/${albumId}`, { extend: 'extendedAssetUrls' })
|
||||
const album = (body?.data ?? [])[0]
|
||||
if (!album) throw new Error(`apple album not found: ${albumId}`)
|
||||
|
||||
const tracks = await fetchAllTrackResources(album?.relationships?.tracks)
|
||||
const songs = tracks.map((track: any) => appleSongFromCatalog(track, albumId))
|
||||
|
||||
const p = Math.max(1, Number(page) || 1)
|
||||
const l = Math.max(1, Number(limit) || 50)
|
||||
const summary = appleAlbumToPlaylist(album)
|
||||
// 上游 fetchPlaylistDetail 的做法:接口未给 trackCount 时以实际曲目数补齐
|
||||
if (!summary.trackCount || songs.length > summary.trackCount) summary.trackCount = songs.length
|
||||
|
||||
return {
|
||||
source: 'apple' as const,
|
||||
info: {
|
||||
id: albumId,
|
||||
name: summary.name,
|
||||
img: summary.cover,
|
||||
desc: summary.description,
|
||||
author: summary.creator,
|
||||
link: summary.link,
|
||||
trackCount: summary.trackCount,
|
||||
releaseDate: summary.extra?.release_date || '',
|
||||
recordLabel: summary.extra?.record_label || '',
|
||||
},
|
||||
list: songs.slice((p - 1) * l, (p - 1) * l + l),
|
||||
page: p,
|
||||
limit: l,
|
||||
total: songs.length,
|
||||
}
|
||||
}
|
||||
|
||||
/** 上游 GetAlbumSongs:只返回曲目数组 */
|
||||
export const getAlbumSongs = async(id: string): Promise<any[]> => {
|
||||
const { list } = await getAlbumDetail(id, 1, 100000)
|
||||
return list
|
||||
}
|
||||
|
||||
/** 上游 ParseAlbum:专辑链接 → 详情(曲目全量,不分页) */
|
||||
export const parseAlbumLink = async(link: string) => {
|
||||
const detail = await getAlbumDetail(link, 1, 100000)
|
||||
return {
|
||||
source: 'apple' as const,
|
||||
id: detail.info.id,
|
||||
info: detail.info,
|
||||
list: detail.list,
|
||||
page: 1,
|
||||
limit: Math.max(detail.total, 1),
|
||||
total: detail.total,
|
||||
}
|
||||
}
|
||||
|
||||
export default { getAlbumDetail, getAlbumSongs, searchAlbum, parseAlbumLink }
|
||||
Reference in new issue
Block a user