refactor(api)!: 平台 id 回退——joox/5sing/bili/apple 恢复全名,目录对齐 bd/mg
- 撤销 3381e9b/1b972ec 中 jx/5s/bl/ap 四个短码,恢复 joox/5sing/bili/apple; qian→bd、migu→mg 保留 - 目录与文件对齐保留的新 id:sdk/qian/→sdk/bd/、sdk/migu/→sdk/mg/、 sdk/apis/qian.ts→bd.ts、migu.ts→mg.ts、src/http/migu-stream.ts→mg-stream.ts (规则改为「目录=对外 id」,聚合入口的模块变量同步更名;music.migu.cn 等域名、 上游 music-lib 对照注释、miguGet 等功能标识符不动) - 对外 id 全表:kw kg tx wy qs xm me qt lr mg bd joox 5sing bili apple **破坏性变更**:joox/5sing/bili/apple 四平台的 URL、/sources 返回与 data/auth.json 凭据键恢复全名,已存短码键的登录态需重新登录。 验证:typecheck ✓、pnpm test 112/112 ✓
This commit is contained in:
1 parent
8c02fb5c15
commit
e1357dd412
50 files changed
+178
-178
No files matched your search
@@ -0,0 +1,63 @@
|
||||
// 咪咕音乐平台模块 —— 搜索 / 取流(多档候选 + Z3D 解密标注)/ 歌词 / 封面 / 专辑 / 歌单 / 链接解析
|
||||
// 上游对应:music-lib/migu/(migu.go、song.go、lyric.go、album.go、playlist.go、download.go)
|
||||
// 匿名面(2026-10-02 实测):搜索、PQ(128k mp3) 取流、歌词、封面、专辑曲目、歌单曲目均可用;
|
||||
// HQ/SQ/ZQ 各档需登录 Cookie(接口返回「登录后免费试听」)。
|
||||
import mgApi from '../apis/mg.ts'
|
||||
import musicSearch from './musicSearch.ts'
|
||||
import lyric, { contentIdOf } from './lyric.ts'
|
||||
import album from './album.ts'
|
||||
import playlist from './playlist.ts'
|
||||
import { fetchSongDetail, miguSongLink } from './util.ts'
|
||||
|
||||
const mg = {
|
||||
musicSearch,
|
||||
getMusicUrl(songInfo: any, type: string) {
|
||||
return mgApi.getMusicUrl(songInfo, type)
|
||||
},
|
||||
getLyric(songInfo: any) {
|
||||
return lyric.getLyric(songInfo)
|
||||
},
|
||||
getPic(songInfo: any) {
|
||||
return (async() => {
|
||||
if (songInfo?.img) return songInfo.img
|
||||
const contentID = contentIdOf(songInfo)
|
||||
if (!contentID) return null
|
||||
const item = await fetchSongDetail(contentID)
|
||||
const { pickMiguImage, normalizeMiguImageURL, firstNonEmpty } = await import('./util.ts')
|
||||
return normalizeMiguImageURL(firstNonEmpty(
|
||||
pickMiguImage(item.imgItems), pickMiguImage(item.albumImgs), item.img1, item.img2, item.img3,
|
||||
)) || null
|
||||
})()
|
||||
},
|
||||
getMusicInfo(songInfo: any) {
|
||||
const contentID = contentIdOf(songInfo)
|
||||
if (!contentID) return Promise.reject(new Error('migu 歌曲 id 无效'))
|
||||
return fetchSongDetail(contentID)
|
||||
},
|
||||
album,
|
||||
playlist,
|
||||
parse: {
|
||||
parseSong: async(link: string) => parseSong(link),
|
||||
parseAlbum: album.parseAlbumLink,
|
||||
parsePlaylist: playlist.parsePlaylistLink,
|
||||
},
|
||||
getMusicDetailPageUrl(songInfo: any) {
|
||||
const extra = songInfo?.extra ?? {}
|
||||
return String(extra.link ?? '') || miguSongLink(contentIdOf(songInfo))
|
||||
},
|
||||
}
|
||||
|
||||
/** 歌曲链接解析:https://music.migu.cn/v3/music/song/<contentId>(含裸 contentId) */
|
||||
export const parseSong = async(link: string) => {
|
||||
const raw = String(link ?? '')
|
||||
const m = raw.match(/music\.migu\.cn\/v3\/music\/song\/(\d+)/) || raw.match(/^(\d{6,})$/)
|
||||
if (!m) throw new Error('无效的咪咕歌曲链接')
|
||||
const contentID = m[1]!
|
||||
const item = await fetchSongDetail(contentID)
|
||||
const { convertItemToSong } = await import('./util.ts')
|
||||
const song = convertItemToSong(item, true)
|
||||
if (!song) throw new Error('该歌曲没有可用格式')
|
||||
return song
|
||||
}
|
||||
|
||||
export default mg
|
||||
Reference in new issue
Block a user