340 lines
11 KiB
JavaScript
340 lines
11 KiB
JavaScript
/*
|
|
@header({
|
|
searchable: 1,
|
|
filterable: 1,
|
|
quickSearch: 1,
|
|
title: '围观短剧',
|
|
lang: 'cat'
|
|
})
|
|
*/
|
|
|
|
let siteName = '围观短剧';
|
|
let siteKey = '';
|
|
let siteType = 0;
|
|
|
|
let UA = "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36";
|
|
|
|
let rule = {
|
|
host: 'https://api.drama.9ddm.com',
|
|
tagsUrl: '/drama/home/shortVideoTags?version_code=1500&os_type=1',
|
|
searchUrl: '/drama/home/search?version_code=1500&os_type=1',
|
|
detailUrl: '/drama/home/shortVideoDetail?version_code=1500&os_type=1'
|
|
};
|
|
|
|
const DEFAULT_HEADERS = {
|
|
'User-Agent': UA,
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
};
|
|
|
|
function init(cfg) {
|
|
try {
|
|
siteName = (cfg.skey?.split('_')[1] || cfg.skey) || (cfg.key?.split('_')[1] || cfg.key) || '围观短剧';
|
|
siteKey = cfg.skey;
|
|
siteType = cfg.stype;
|
|
console.log(`【${siteName}】初始化完成`);
|
|
} catch (e) {
|
|
console.log(`【${siteName}】初始化失败: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
function safeJSONParse(str, defaultValue = {}) {
|
|
if (!str) return defaultValue;
|
|
if (typeof str === 'object') return str;
|
|
try {
|
|
return JSON.parse(str);
|
|
} catch (e) {
|
|
console.log(`【${siteName}】JSON解析失败: ${e.message}`);
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
// 通用请求函数
|
|
async function request(url, options = {}) {
|
|
console.log(`【${siteName}】${options.method || 'GET'} ${url.split('?')[0]}`);
|
|
|
|
const baseOptions = {
|
|
method: options.method || 'GET',
|
|
headers: { ...DEFAULT_HEADERS, ...options.headers },
|
|
timeout: options.timeout || 15000
|
|
};
|
|
|
|
let dataStr = '';
|
|
const requestData = options.body || options.data;
|
|
if (requestData) {
|
|
dataStr = typeof requestData === 'string' ? requestData : JSON.stringify(requestData);
|
|
baseOptions.headers['Content-Type'] = baseOptions.headers['Content-Type'] || 'application/json';
|
|
}
|
|
|
|
for (let key of ['data', 'body']) {
|
|
try {
|
|
const reqOptions = { ...baseOptions, [key]: dataStr };
|
|
const response = await req(url, reqOptions);
|
|
const content = response?.content || response?.data || response;
|
|
|
|
if (!content) continue;
|
|
|
|
const data = typeof content === 'object' ? content : safeJSONParse(content);
|
|
|
|
if (data?.code && data.code !== 200) continue;
|
|
|
|
console.log(`【${siteName}】${key}成功: ${JSON.stringify(data).substring(0, 300)}`);
|
|
return data;
|
|
} catch (e) {
|
|
console.log(`【${siteName}】${key}异常: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
console.log(`【${siteName}】全部失败`);
|
|
return null;
|
|
}
|
|
|
|
async function home() {
|
|
let classes = [{ type_name: '全部', type_id: '全部' }];
|
|
let filters = { '全部': [] };
|
|
|
|
const data = await request(`${rule.host}${rule.tagsUrl}`);
|
|
|
|
if (data && data.code === 200) {
|
|
// 分类
|
|
if (data.audiences && Array.isArray(data.audiences)) {
|
|
const audienceClasses = data.audiences.map(audience => ({
|
|
type_name: audience,
|
|
type_id: audience
|
|
}));
|
|
classes.push(...audienceClasses);
|
|
|
|
// 为每个分类创建筛选
|
|
for (const audience of data.audiences) {
|
|
filters[audience] = [];
|
|
|
|
if (data.tags && Array.isArray(data.tags) && data.tags.length > 0) {
|
|
const tagValues = [{ n: '全部', v: '' }];
|
|
data.tags.forEach(tag => {
|
|
if (tag) tagValues.push({ n: tag, v: tag });
|
|
});
|
|
if (tagValues.length > 1) {
|
|
filters[audience].push({ key: 'tag', name: '标签', value: tagValues });
|
|
}
|
|
}
|
|
|
|
if (data.orders && Array.isArray(data.orders) && data.orders.length > 0) {
|
|
const orderValues = data.orders.map(order => ({ n: order, v: order }));
|
|
filters[audience].push({ key: 'order', name: '排序', value: orderValues });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return JSON.stringify({ class: classes, filters: filters });
|
|
}
|
|
|
|
async function homeVod() {
|
|
try {
|
|
const result = await category('全部', 1, {}, {});
|
|
const data = typeof result === 'string' ? safeJSONParse(result) : result;
|
|
const list = (data && data.list) ? data.list.slice(0, 12) : [];
|
|
return JSON.stringify({ list: list });
|
|
} catch (e) {
|
|
console.log(`【${siteName}】homeVod失败: ${e.message}`);
|
|
return JSON.stringify({ list: [] });
|
|
}
|
|
}
|
|
|
|
async function category(tid, pg, filter, extend) {
|
|
const videos = [];
|
|
const page = pg || 1;
|
|
|
|
const tag = (extend && extend.tag) ? extend.tag : "";
|
|
const order = (extend && extend.order) ? extend.order : "";
|
|
|
|
const orderMap = { "最热": "hot", "最新": "new", "热度": "hot", "时间": "new" };
|
|
let orderValue = orderMap[order] || "";
|
|
|
|
const postData = {
|
|
audience: tid === '全部' ? "" : tid,
|
|
page: page,
|
|
pageSize: 30,
|
|
searchWord: "",
|
|
subject: tag,
|
|
order: orderValue
|
|
};
|
|
|
|
console.log(`【${siteName}】分类请求: tid=${tid}, tag=${tag}, order=${order}`);
|
|
|
|
const data = await request(`${rule.host}${rule.searchUrl}`, {
|
|
method: 'POST',
|
|
body: postData
|
|
});
|
|
|
|
if (data && data.code === 200 && data.data && Array.isArray(data.data)) {
|
|
for (const it of data.data) {
|
|
if (it && it.oneId) {
|
|
videos.push({
|
|
vod_id: String(it.oneId),
|
|
vod_name: it.title || '未知标题',
|
|
vod_pic: it.vertPoster || it.horizonPoster || '',
|
|
vod_remarks: `集数:${it.episodeCount || 0} 播放:${it.viewCount || 0}`,
|
|
vod_content: it.description || '',
|
|
vod_year: it.publishDate || ''
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
console.log(`【${siteName}】分类数据异常:`, data?.code);
|
|
}
|
|
|
|
console.log(`【${siteName}】分类获取到 ${videos.length} 条数据`);
|
|
|
|
return JSON.stringify({
|
|
list: videos,
|
|
page: page,
|
|
pagecount: page + 1,
|
|
limit: videos.length,
|
|
total: videos.length * (page + 1)
|
|
});
|
|
}
|
|
|
|
async function detail(id) {
|
|
if (!id) return JSON.stringify({ list: [] });
|
|
|
|
const url = `${rule.host}${rule.detailUrl}&oneId=${encodeURIComponent(id)}&page=1&pageSize=1000`;
|
|
const data = await request(url);
|
|
|
|
if (data && data.code === 200 && data.data && Array.isArray(data.data)) {
|
|
const episodes = data.data.filter(ep => ep);
|
|
const firstEpisode = episodes[0] || {};
|
|
|
|
const playItems = [];
|
|
for (let i = 0; i < episodes.length; i++) {
|
|
const episode = episodes[i];
|
|
let playSetting = episode.playSetting || episode.videoClarityList || [];
|
|
|
|
if (typeof playSetting === 'string') {
|
|
playSetting = safeJSONParse(playSetting, []);
|
|
}
|
|
if (!Array.isArray(playSetting)) playSetting = [];
|
|
|
|
const clarityInfo = {};
|
|
for (const item of playSetting) {
|
|
if (item && item.url && item.name) {
|
|
clarityInfo[item.name] = item.url;
|
|
}
|
|
}
|
|
|
|
if (Object.keys(clarityInfo).length > 0) {
|
|
const episodeNum = episode.playOrder || episode.episodeNumber || (i + 1);
|
|
playItems.push(`第${episodeNum}集$${JSON.stringify(clarityInfo)}`);
|
|
}
|
|
}
|
|
|
|
const playUrl = playItems.join('#');
|
|
if (!playUrl) return JSON.stringify({ list: [] });
|
|
|
|
const vod = {
|
|
vod_id: String(id),
|
|
vod_name: firstEpisode.title || '未知剧名',
|
|
vod_pic: firstEpisode.vertPoster || firstEpisode.horizonPoster || '',
|
|
vod_remarks: `共${episodes.length}集`,
|
|
vod_content: firstEpisode.description || '',
|
|
vod_play_from: '围观短剧',
|
|
vod_play_url: playUrl
|
|
};
|
|
|
|
return JSON.stringify({ list: [vod] });
|
|
}
|
|
|
|
return JSON.stringify({ list: [] });
|
|
}
|
|
|
|
async function play(flag, id, flags) {
|
|
let clarityInfo = {};
|
|
|
|
try {
|
|
if (typeof id === 'object') {
|
|
clarityInfo = id;
|
|
} else if (typeof id === 'string') {
|
|
clarityInfo = safeJSONParse(id, {});
|
|
}
|
|
} catch (e) {
|
|
return JSON.stringify({ parse: 0, url: id || '', msg: '播放参数错误' });
|
|
}
|
|
|
|
const clarityOrder = ['4K', '超清', '1080P', '高清', '720P', '流畅', '480P'];
|
|
const urls = [];
|
|
const added = new Set();
|
|
|
|
for (const clarity of clarityOrder) {
|
|
const url = clarityInfo[clarity];
|
|
if (url && typeof url === 'string' && url.startsWith('http') && !added.has(clarity)) {
|
|
urls.push(clarity, url);
|
|
added.add(clarity);
|
|
}
|
|
}
|
|
|
|
if (urls.length > 0) {
|
|
return JSON.stringify({
|
|
parse: 0,
|
|
url: urls,
|
|
header: { 'User-Agent': UA }
|
|
});
|
|
}
|
|
|
|
if (typeof id === 'string' && id.startsWith('http')) {
|
|
return JSON.stringify({ parse: 0, url: id, header: { 'User-Agent': UA } });
|
|
}
|
|
|
|
return JSON.stringify({ parse: 0, url: '', msg: '暂无可用播放地址' });
|
|
}
|
|
|
|
async function search(wd, quick, pg) {
|
|
if (!wd || wd.trim() === '') {
|
|
return JSON.stringify({ list: [], page: 1 });
|
|
}
|
|
|
|
const page = pg || 1;
|
|
const postData = {
|
|
audience: "",
|
|
page: page,
|
|
pageSize: 30,
|
|
searchWord: wd,
|
|
subject: ""
|
|
};
|
|
|
|
const data = await request(`${rule.host}${rule.searchUrl}`, {
|
|
method: 'POST',
|
|
body: postData,
|
|
timeout: 8000
|
|
});
|
|
|
|
let videos = [];
|
|
if (data && data.code === 200 && data.data && Array.isArray(data.data)) {
|
|
videos = data.data.filter(it => it && it.oneId).map(it => ({
|
|
vod_id: String(it.oneId),
|
|
vod_name: it.title || '未知标题',
|
|
vod_pic: it.vertPoster || it.horizonPoster || '',
|
|
vod_remarks: `集数:${it.episodeCount || 0} 播放:${it.viewCount || 0}`,
|
|
vod_content: it.description || ''
|
|
}));
|
|
}
|
|
|
|
return JSON.stringify({
|
|
list: videos,
|
|
page: page,
|
|
pagecount: videos.length === 30 ? page + 1 : page,
|
|
limit: videos.length,
|
|
total: videos.length * page
|
|
});
|
|
}
|
|
|
|
export function __jsEvalReturn() {
|
|
return {
|
|
init: init,
|
|
home: home,
|
|
homeVod: homeVod,
|
|
category: category,
|
|
detail: detail,
|
|
play: play,
|
|
search: search
|
|
};
|
|
} |