- 删除旧 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 骨架相似实质各异,不抽公共层)
57 lines
2.2 KiB
TypeScript
57 lines
2.2 KiB
TypeScript
// 喜马拉雅搜索(web 通道)
|
|
// 接口: https://www.ximalaya.com/revision/search?core=track&kw=&page=&rows=&spellchecker=true&condition=relation&device=web
|
|
// 实测(2026-10-02)匿名可用(注意:同参数的 /revision/search/main 与 /search/main 会命中
|
|
// risk invalid 风控,本端点 + condition=relation&device=web 不受影响)
|
|
// 返回 data.result.response.docs[],字段 id/title/duration(秒)/nickname/album_id/album_title/
|
|
// album_cover_path/is_paid/is_trailer
|
|
import { httpFetch } from '../common/request.ts'
|
|
import { formatPlayTime } from '../index.ts'
|
|
import { XM_UA } from './sign.ts'
|
|
|
|
const SEARCH_URL = 'https://www.ximalaya.com/revision/search'
|
|
|
|
const normalizeCover = (path: unknown): string | null => {
|
|
if (!path) return null
|
|
const s = String(path)
|
|
return s.startsWith('http') ? s : `https://imagev2.xmcdn.com/${s}`
|
|
}
|
|
|
|
export const search = (keyword: string, page = 1, limit = 20) => {
|
|
const params = new URLSearchParams({
|
|
core: 'track', kw: keyword, page: String(page), rows: String(limit),
|
|
spellchecker: 'true', condition: 'relation', device: 'web',
|
|
})
|
|
return httpFetch(`${SEARCH_URL}?${params.toString()}`, {
|
|
headers: { 'User-Agent': XM_UA, Accept: 'application/json, text/plain, */*', Referer: 'https://www.ximalaya.com/' },
|
|
timeout: 15000,
|
|
}).promise.then(({ statusCode, body }: any) => {
|
|
if (statusCode != 200 || body?.ret != 200) throw new Error(body?.msg || '搜索失败')
|
|
const docs = body?.data?.result?.response?.docs ?? []
|
|
const total = Number(body?.data?.result?.response?.numFound ?? docs.length)
|
|
const allPage = Math.ceil(total / limit) || page
|
|
return {
|
|
allPage,
|
|
total,
|
|
limit,
|
|
source: 'xm' as const,
|
|
list: docs.map((item: any) => ({
|
|
songmid: String(item.id),
|
|
name: item.title || '',
|
|
singer: item.nickname || '',
|
|
albumId: item.album_id ? String(item.album_id) : '',
|
|
albumName: item.album_title || '',
|
|
interval: item.duration ? formatPlayTime(Number(item.duration)) : 0,
|
|
payPlay: Boolean(item.is_paid),
|
|
img: normalizeCover(item.album_cover_path),
|
|
lrc: '',
|
|
lrcx: '',
|
|
types: [],
|
|
_types: {},
|
|
disabled: false,
|
|
})),
|
|
}
|
|
})
|
|
}
|
|
|
|
export default { search }
|