Files
2026-06-29 03:41:14 +00:00

261 lines
7.0 KiB
JavaScript

/*
@header({
searchable: 1,
filterable: 1,
quickSearch: 1,
title: '喜马拉雅[听]',
lang: 'cat',
})
*/
let host = 'https://m.ximalaya.com';
let searchHost = 'https://api.cenguigui.cn';
let UA = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36'
};
// ==================== 日志开关 ====================
let DEBUG = 0; // 0=关闭日志, 1=开启日志
function dlog(...args) {
if (DEBUG !== 1) return;
console.log(...args);
}
async function request(url, obj) {
if (!obj) {
obj = {
headers: UA,
timeout: 5000
}
}
const response = await req(url, obj);
return response.content;
}
async function init(cfg) {
dlog(`cfg参数类型: ${typeof cfg}, 值:`, cfg);
// 统一处理为字符串配置
if (cfg && typeof cfg === 'string') {
host = cfg;
} else if (cfg && typeof cfg === 'object') {
// 优先从对象中提取配置
ext = cfg.ext
host = ext.host || ext.hosturl || ext.url || ext.site ;
// 设置应用需要的属性
cfg.skey = '';
cfg.stype = '3';
}
dlog(`host: ${host}`);
}
async function home(filter) {
const classNames = '有声书&儿童&音乐&相声&娱乐&广播剧&历史&外语';
const classUrls = 'youshengshu&ertong&yinyue&xiangsheng&yule&guangbojv&lishi&waiyu';
const names = classNames.split('&');
const urls = classUrls.split('&');
const classes = [];
for (let i = 0; i < names.length && i < urls.length; i++) {
classes.push({
type_id: urls[i],
type_name: names[i]
});
}
const filters = {};
classes.forEach(cls => {
filters[cls.type_id] = [];
});
return JSON.stringify({ class: classes, filters: filters });
}
async function homeVod() {
return JSON.stringify({ list: [] });
}
async function category(tid, pg, filter, extend) {
try {
const url = `${host}/m-revision/page/category/queryCategoryAlbumsByPage?sort=0&pageSize=50&page=${pg || 1}&categoryCode=${tid}`;
const html = await request(url);
if (!html) {
return JSON.stringify({
list: [],
page: pg || 1,
pagecount: 1,
limit: 50,
total: 0
});
}
const data = JSON.parse(html).data.albumBriefDetailInfos;
const videos = [];
data.forEach(it => {
const vip = it.albumInfo.albumVipPayType;
// 只显示免费内容
if (vip === 0) {
const id = `http://mobile.ximalaya.com/mobile/others/ca/album/track/${it.id}/true/0/200?albumId=${it.id}`;
videos.push({
vod_id: id,
vod_name: it.albumInfo.title,
vod_pic: `http://imagev2.xmcdn.com/${it.albumInfo.cover}`,
vod_remarks: '免费'
});
}
});
return JSON.stringify({
list: videos,
page: pg || 1,
pagecount: 10, // 假设有10页
limit: 50,
total: videos.length
});
} catch (e) {
return JSON.stringify({
list: [],
page: pg || 1,
pagecount: 1,
limit: 50,
total: 0
});
}
}
async function detail(id) {
try {
const urls = [];
// 解析专辑ID
const albumIdMatch = id.match(/albumId=(\d+)/);
const albumId = albumIdMatch ? albumIdMatch[1] : '';
// 获取第一页数据
const html = await request(id);
const json = JSON.parse(html);
const album = json.album;
let data = json.tracks.list;
const maxPageId = json.tracks.maxPageId;
// 处理第一页数据
data.forEach(it => {
urls.push(`${it.title}$${it.playPathAacv164}`);
});
// 获取后续分页数据
if (maxPageId > 1) {
for (let j = 2; j <= maxPageId; j++) {
const pageUrl = id.replace('/0/', `/${j}/`);
try {
const pageHtml = await request(pageUrl);
const pageJson = JSON.parse(pageHtml);
const pageData = pageJson.tracks.list;
pageData.forEach(it => {
urls.push(`${it.title}$${it.playPathAacv164}`);
});
} catch (e) {
dlog(`获取分页数据失败: ${pageUrl}`);
}
}
}
const vod = {
vod_id: id,
vod_name: album.title || '暂无名称',
vod_pic: album.coverLarge || '暂无图片',
vod_content: album.intro || '暂无简介',
vod_remarks: `共${urls.length}集`,
vod_play_from: '喜马拉雅',
vod_play_url: urls.join('#')
};
return JSON.stringify({ list: [vod] });
} catch (e) {
dlog(`detail函数错误: ${e.message}`);
return JSON.stringify({ list: [] });
}
}
async function play(flag, id, flags) {
try {
// 直接播放音频URL
return JSON.stringify({
parse: 0,
jx: 0,
url: id,
header: {}
});
} catch (e) {
return JSON.stringify({
parse: 0,
jx: 0,
url: ["错误", "播放地址获取失败"],
header: {}
});
}
}
async function search(wd, quick, pg = "1") {
try {
const url = `${searchHost}/api/music/ximalaya.php?name=${encodeURIComponent(wd)}`;
const html = await request(url);
if (!html) {
return JSON.stringify({
list: [],
page: parseInt(pg),
pagecount: 0,
limit: 20,
total: 0
});
}
const data = JSON.parse(html).data;
const videos = data.map(it => {
const id = `http://mobile.ximalaya.com/mobile/others/ca/album/track/${it.albumId}/true/0/200?albumId=${it.albumId}`;
return {
vod_id: id,
vod_name: it.title,
vod_pic: it.cover,
vod_remarks: '喜马拉雅'
};
});
return JSON.stringify({
list: videos,
page: parseInt(pg),
pagecount: 1,
limit: 20,
total: videos.length
});
} catch (e) {
return JSON.stringify({
list: [],
page: parseInt(pg),
pagecount: 0,
limit: 20,
total: 0
});
}
}
export default {
init: init,
home: home,
homeVod: homeVod,
category: category,
detail: detail,
play: play,
search: search
};