Files
snowy-yang 8c02fb5c15 refactor(sdk): 审计 P2 卫生项清理——请求层收敛与死代码清除
- 删除旧 sdk/request.ts,全部 import 收敛到 sdk/common/request.ts(85 文件)
- 注释死代码 630+ 行、裸 console.log 吞错 6 处、未使用符号 26 处清零
- bili 状态校验去重;utils DNS 预解析失败日志改 warn 带上下文
- CODE-AUDIT.md:第四节 P2 清理记录 + 第八节线索逐条复核结论(kw/kg/tx/wy parse 骨架相似实质各异,不抽公共层)
2026-10-03 20:48:54 +08:00

81 lines
3.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 网易云链接解析(上游 music-lib/netease/song.go 的 Parse 移植)
// 歌曲链接形态:
// https://music.163.com/#/song?id=29732995
// https://music.163.com/song?id=29732995
// https://music.163.com/song/29732995
// 裸数字 id 也接受(补充便利;上游仅接受链接)
// 直链 url/type 为尽力附带,失败不影响元数据返回(与上游一致);
// 歌单/专辑链接抛清晰错误,提示使用对应 parsePlaylist/parseAlbum。
import { httpFetch } from '../common/request.ts'
import { weapi } from './utils/crypto.ts'
import { getWyCookie } from '../auth/store.ts'
import wyApi from '../apis/wy.ts'
import { convertSong, parseAlbumLink } from './album.ts'
import { parsePlaylistLink } from './playlist.ts'
import { parseNeteaseLink } from './link.ts'
const UA = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'
/** 上游 fetchSongsBatch 的单曲版本(weapi/v3/song/detail) */
const fetchSongById = async(songId: string) => {
const cookie = getWyCookie()
const { statusCode, body } = await httpFetch('https://music.163.com/weapi/v3/song/detail', {
method: 'post',
headers: {
'User-Agent': UA,
Referer: 'https://music.163.com/',
origin: 'https://music.163.com',
...(cookie ? { cookie } : {}),
},
form: weapi({
c: `[{"id":${songId}}]`,
ids: `[${songId}]`,
}),
timeout: 15000,
}).promise
if (statusCode !== 200 || body?.code != 200) {
throw new Error(`wy 歌曲详情获取失败 (code ${body?.code ?? statusCode})`)
}
const item = body?.songs?.[0]
if (!item?.id) throw new Error('netease song not found')
return convertSong(item)
}
/** 上游 Parse:歌曲链接 → Song(尽力附带直链 url/type) */
export const parseSong = async(link: string) => {
const raw = String(link ?? '').trim()
if (!raw) throw new Error('无效的网易云歌曲链接')
let songId = ''
if (/^\d+$/.test(raw)) {
songId = raw
} else {
const parsed = (() => {
try {
return parseNeteaseLink(raw)
} catch {
throw new Error('无效的网易云歌曲链接')
}
})()
if (parsed.kind === 'playlist') throw new Error('检测到网易云歌单链接,请使用 parsePlaylist')
if (parsed.kind === 'album') throw new Error('检测到网易云专辑链接,请使用 parseAlbum')
if (parsed.kind !== 'song') throw new Error('无效的网易云歌曲链接')
songId = parsed.id
}
const song: any = await fetchSongById(songId)
try {
const hit = await wyApi.getMusicUrl(song, '320k').promise
song.url = hit.url
song.type = hit.type
} catch {
// 与上游一致:直链获取失败忽略(VIP/下架曲目仍返回元数据)
}
return song
}
export const parseAlbum = async(link: string) => parseAlbumLink(link)
export const parsePlaylist = async(link: string) => parsePlaylistLink(link)
export default { parseSong, parseAlbum, parsePlaylist }