Files
sg/open/91live_zb.js
2026-08-14 11:23:32 +02:00

268 lines
9.7 KiB
JavaScript

/*
@header({
searchable: 1,
filterable: 1,
quickSearch: 1,
title: '91电视[直]',
lang: 'cat',
})
*/
import { Crypto as CryptoJS } from 'assets://js/lib/cat.js';
let host = 'http://sj.91kds.cn';
let siteName = '91电视', siteKey = '', siteType = 0;
let UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Chrome/126.0.0.0 Safari/537.36)";
const headers = {
'User-Agent': UA,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
};
function init(cfg) {
siteName = cfg.skey?.split('_')[1] || cfg.skey || '91电视';
siteKey = cfg.skey;
siteType = cfg.stype;
if (cfg && typeof cfg === 'string') {
host = cfg;
} else if (cfg && typeof cfg === 'object') {
let ext = cfg.ext;
if (ext && typeof ext === 'object' && Object.keys(ext).length) {
host = ext.host || ext.hosturl || ext.url || ext.site;
}
}
}
function safeJSONParse(str, defaultValue = {}) {
if (!str || typeof str === 'object') return str || defaultValue;
try {
return JSON.parse(str);
} catch {
return defaultValue;
}
}
async function request(url, options = {}) {
const reqHeaders = { ...headers, ...options.headers };
let postType = reqHeaders['Content-Type']?.includes('json') ? 'json' :
reqHeaders['Content-Type']?.includes('form') ? 'form' : '';
try {
const response = await req(url, {
method: options.method || 'GET',
headers: reqHeaders,
data: options.data,
postType: postType,
timeout: options.timeout || 15000
});
return response?.content || response?.data || response;
} catch {
return null;
}
}
async function home(filter) {
const classes = [
{ type_id: "央视", type_name: "央视" }, { type_id: "卫视", type_name: "卫视" },
{ type_id: "高清", type_name: "高清" }, { type_id: "4K", type_name: "4K" },
{ type_id: "影视", type_name: "影视" }, { type_id: "体育", type_name: "体育" },
{ type_id: "动漫", type_name: "动漫" }, { type_id: "财经", type_name: "财经" },
{ type_id: "综艺", type_name: "综艺" }, { type_id: "教育", type_name: "教育" },
{ type_id: "新闻", type_name: "新闻" }, { type_id: "纪录", type_name: "纪录" },
{ type_id: "国际", type_name: "国际" }, { type_id: "网络", type_name: "网络" },
{ type_id: "购物", type_name: "购物" }, { type_id: "虎牙", type_name: "虎牙" }
];
const filters = {};
classes.forEach(cls => { filters[cls.type_id] = []; });
return JSON.stringify({ class: classes, filters: filters });
}
async function homeVod() {
return await category('湖北', 1, null, {});
}
async function category(tid, pg, filter, extend) {
try {
const url = `${host}/api/get_channel.php?id=${tid}`;
const html = await request(url);
if (!html || !html.includes('ename')) {
return JSON.stringify({ list: [], page: 1, pagecount: 1, limit: 20, total: 0 });
}
const list = safeJSONParse(html);
const nwtime = Math.floor(Date.now() / 1000);
const videos = list.map(item => {
const enamee = item.ename;
const srcKey = enamee + "com.jiaoxiang.fangnaleahkajfkahlajjaflfakhfakfbuyaozaigaolefuquqikangbuzhu2.3.4fu:ck:92:92:ff" + nwtime + "20240918";
const sign = CryptoJS.MD5(srcKey).toString();
const detailUrl = `http://sjapi1.91kds.cn/api/get_source.php?ename=${enamee}&app=com.jiaoxiang.fangnale&version=2.3.4&mac=fu:ck:92:92:ff&nwtime=${nwtime}&sign=${sign}&ev=20240918`;
return {
vod_id: detailUrl + '@' + item.name,
vod_name: item.name,
vod_pic: item.icon,
vod_remarks: '直播'
};
});
return JSON.stringify({ list: videos, page: 1, pagecount: 1, limit: 20, total: videos.length });
} catch (e) {
return JSON.stringify({ list: [], page: 1, pagecount: 1, limit: 20, total: 0 });
}
}
async function detail(id) {
try {
const [purl, vod_name] = id.split('@');
const html = await request(purl);
const data = safeJSONParse(html);
const vod = {
vod_id: purl,
vod_name: vod_name || data.name || data.title || "直播频道",
vod_pic: data.icon || "",
vod_content: data.desc || "暂无简介",
vod_remarks: "直播"
};
let list = data.liveSource || [];
let names = data.liveSourceName || [];
let playFrom = [];
let playUrl = [];
let seen = new Set();
let lineCounter = 1;
list.forEach((item, j) => {
let rawInput = item;
let inputUrl = rawInput.replace(/^kdsvod:\/\//, '');
let urlName = names[j] || '线路' + lineCounter;
if (inputUrl.includes('pwd=jsdecode') && inputUrl.includes('id=')) {
let parts = inputUrl.split('?');
let baseUrl = parts[0];
let queryStr = parts[1] || '';
let queryObj = {};
queryStr.split('&').forEach(kv => {
let t = kv.split('=');
if (t[0]) queryObj[t[0]] = decodeURIComponent(t[1] || '');
});
let id = queryObj['id'];
let bt = queryObj['bt'] || null;
let coreKey = (bt || '') + '_' + id;
if (seen.has(coreKey)) return;
seen.add(coreKey);
let params = {
app: 'com.jiaoxiang.fangnale',
version: '2.3.4',
mac: 'fu:ck:92:92:ff',
utk: '',
nwtime: Math.floor(Date.now() / 1000),
ev: '20250113'
};
let appendStr = 'ahkajfkahlajjaflfakhfakfbuyaozaigaolefuquqikangbuzhu';
let signStr = id;
Object.keys(params).forEach(key => {
if (key === 'tmk') return;
if (key === 'app') signStr += params[key] + appendStr;
else signStr += params[key];
});
params.sign = CryptoJS.MD5(signStr).toString();
let finalQuery = [];
if (bt !== null) finalQuery.push('bt=' + bt);
finalQuery.push('id=' + id);
Object.keys(params).forEach(k => {
finalQuery.push(k + '=' + encodeURIComponent(params[k]));
});
let finalUrl = baseUrl + '?' + finalQuery.join('&');
let lineName = '线路' + lineCounter;
playFrom.push(lineName);
playUrl.push(urlName + '$' + finalUrl);
lineCounter++;
} else {
let videoUrl;
if (inputUrl.startsWith('htmlplay://')) {
videoUrl = inputUrl.replace('htmlplay://', '').split('#')[0];
} else {
videoUrl = inputUrl;
}
let urlKey = videoUrl.split('?')[0];
if (seen.has(urlKey)) return;
seen.add(urlKey);
let referer = '';
if (inputUrl.includes('@@referer=')) {
let tmp = inputUrl.split('@@referer=');
videoUrl = tmp[0];
referer = tmp[1] || '';
}
let lineName = '线路' + lineCounter;
if (referer) {
let playObj = JSON.stringify({ url: videoUrl, header: { Referer: referer } });
playFrom.push(lineName);
playUrl.push(urlName + '$' + playObj);
} else {
playFrom.push(lineName);
playUrl.push(urlName + '$' + videoUrl);
}
lineCounter++;
}
});
vod.vod_play_from = playFrom.join('$$$');
vod.vod_play_url = playUrl.join('$$$');
return JSON.stringify({ list: [vod] });
} catch (e) {
return JSON.stringify({ list: [] });
}
}
async function play(flag, id, flags) {
return JSON.stringify({ parse: 0, url: id, header: {} });
}
async function search(wd, quick, pg = "1") {
try {
const nwtime = Math.floor(Date.now() / 1000);
const srcKey = "4954af3c86d8bc0b766afee71503d860" + nwtime + "f8dd806a73202456eb6e782c1c4aecfc";
const sign = CryptoJS.MD5(srcKey).toString();
const searchUrl = `${host}/api/get_search.php?id=${encodeURIComponent(wd)}`;
const html = await request(searchUrl);
if (!html || !html.includes('ename')) {
return JSON.stringify({ list: [], page: parseInt(pg), pagecount: 0, limit: 20, total: 0 });
}
const list = safeJSONParse(html);
const videos = list.map(item => ({
vod_id: `${host}/api/get_source.php?ename=${item.ename}@${item.name}`,
vod_name: item.name,
vod_pic: item.icon,
vod_remarks: item.path || ''
}));
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 function __jsEvalReturn() {
return { init, home, homeVod, category, detail, play, search };
}