added openjs

This commit is contained in:
lem85930 2023-07-25 20:23:38 +08:00
parent bf76afc6f4
commit e045a91416
27 changed files with 5227 additions and 1073 deletions

34
JN/EXT/OPENJS/README.md Normal file
View File

@ -0,0 +1,34 @@
# CatVodOpen
Open version of catvod.
[🚀TG](https://t.me/catvodapp_offical)
### **Notice**
The open version was originally planned to start in december of last year, but it was delayed due to other matters. So the open version is mainly based on the december version from last year, but will include some bug fixes and core feature merges.
Not being maintained and uncertain whether they will be updated.
**Those who need it can download and use it, and there is no need to provide feedback on any issues.**
### **Limits**
- Only local `assets://` config is supported, and network config is not available.
- Only video&cloud disk module.
- Not supporting sniffing.
- Basic JS interface support.
- No builtin maccms api support.
- etc.
### **Download**
[Release](https://github.com/catvod/CatVodOpen/releases)
- Windows release only test on `windows11`.
- Builtin config `data\flutter_assets\asset\js\config_open.json`
- MacOS only test on `Big Sur` and `Monterey`.
- Builtin config `*.app/Contents/Frameworks/App.framework/Resources/flutter_assets/asset/js/config_open.json`
- iOS only test on `16.0+`.
- Builtin config `*.ipa/Payload/Runner.app/Frameworks/App.framework/flutter_assets/asset/js/config_open.json`

View File

@ -0,0 +1,9 @@
## Debug with any js debugger.
`npm install`
`node test.js`
`node build.js`
**Don't import `wrapper\index.js` direct.**

View File

@ -0,0 +1,8 @@
function __jsEvalReturn() {
return {
isVideoFormat: function (url) {
return !0;
},
};
}
export { __jsEvalReturn };

View File

@ -0,0 +1,61 @@
import fs from 'node:fs';
import path from 'path';
import uglifyjs from 'uglify-js';
const copySpider = ['app', 'kunyu77_open', 'alist_open'];
const root = process.cwd();
const src = path.join(root);
const out = path.join(root, 'dist');
function minify(s, d) {
var jsContent = fs.readFileSync(s).toString();
jsContent = jsContent.replace('./lib/cat.js', 'assets://js/lib/cat.js');
jsContent = jsContent.replace('./cat.js', 'assets://js/lib/cat.js');
jsContent = uglifyjs.minify(jsContent, {
mangle: false,
});
fs.writeFileSync(d, jsContent.code);
}
function listAllFiles(dirPath, arrayOfFiles) {
var files = fs.readdirSync(dirPath);
arrayOfFiles = arrayOfFiles || [];
files.forEach(function (file) {
if (fs.statSync(dirPath + '/' + file).isDirectory()) {
arrayOfFiles = listAllFiles(dirPath + '/' + file, arrayOfFiles);
} else {
arrayOfFiles.push(path.join(dirPath, '/', file));
}
});
return arrayOfFiles;
}
function src2Out() {
if (fs.existsSync(out)) fs.rmSync(out, { recursive: true, force: true });
fs.mkdirSync(out, { recursive: true });
const libSrc = path.join(src, 'lib');
const libOut = path.join(out, 'lib');
fs.mkdirSync(libOut, { recursive: true });
const libs = listAllFiles(libSrc);
for (let index = 0; index < libs.length; index++) {
const element = libs[index];
const relative = path.relative(libSrc, element);
minify(element, path.join(libOut, relative));
}
for (const sp of copySpider) {
minify(path.join(src, sp + '.js'), path.join(out, sp + '.js'));
}
}
src2Out();
fs.copyFileSync(path.join(src, 'config_open.json'), path.join(out, 'config_open.json'));
console.log('done');

View File

@ -0,0 +1,70 @@
{
"video": {
"sites": [
{
"key": "kunyu77",
"name": "琨娱七七",
"type": 3,
"api": "assets://js/kunyu77_open.js"
}
]
},
"pan": {
"sites": [
{
"key": "alist",
"name": "Alist",
"type": 40,
"api": "assets://js/alist_open.js",
"ext": [
{
"name": "🙋丫仙女",
"server": "http://alist.xiaoya.pro/",
"startPage": "/",
"showAll": false,
"search": true,
"headers": {
"Authorization": ""
},
"params": {
"/abc": {
"password": "123"
},
"/abc/abc": {
"password": "123"
}
}
},
{
"name": "🐋一只鱼",
"server": "https://alist.youte.ml"
},
{
"name": "🌊七米蓝",
"server": "https://al.chirmyram.com"
},
{
"name": "🐉神族九帝",
"server": "https://alist.shenzjd.com"
},
{
"name": "☃️姬路白雪",
"server": "https://pan.jlbx.xyz"
},
{
"name": "✨星梦",
"server": "https://pan.bashroot.top"
},
{
"name": "💢repl",
"server": "https://ali.liucn.repl.co"
},
{
"name": "💦讯维云盘",
"server": "https://pan.xwbeta.com"
}
]
}
]
}
}

View File

@ -1,166 +1,166 @@
import { Crypto, load, _, jinja2 } from './lib/cat.js'; import { Crypto, load, _, jinja2 } from './lib/cat.js';
let key = 'duboku'; let key = 'duboku';
let url = 'https://u.duboku.io'; let url = 'https://u.duboku.io';
let siteKey = ''; let siteKey = '';
let siteType = 0; let siteType = 0;
const UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'; const UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1';
async function request(reqUrl, agentSp) { async function request(reqUrl, agentSp) {
let res = await req(reqUrl, { let res = await req(reqUrl, {
method: 'get', method: 'get',
headers: { headers: {
'User-Agent': agentSp || UA, 'User-Agent': agentSp || UA,
'Referer': url 'Referer': url
}, },
}); });
return res.content; return res.content;
} }
// cfg = {skey: siteKey, ext: extend} // cfg = {skey: siteKey, ext: extend}
async function init(cfg) { async function init(cfg) {
siteKey = cfg.skey; siteKey = cfg.skey;
siteType = cfg.stype; siteType = cfg.stype;
} }
async function home(filter) { async function home(filter) {
const html = await request(url); const html = await request(url);
const $ = load(html); const $ = load(html);
const class_parse = $('ul.nav-list > li > a[href*=vodtype]'); const class_parse = $('ul.nav-list > li > a[href*=vodtype]');
let classes = []; let classes = [];
classes = _.map(class_parse, (cls) => { classes = _.map(class_parse, (cls) => {
let typeId = cls.attribs['href']; let typeId = cls.attribs['href'];
typeId = typeId.substring(typeId.lastIndexOf('/') + 1).replace('.html',''); typeId = typeId.substring(typeId.lastIndexOf('/') + 1).replace('.html','');
return { return {
type_id: typeId, type_id: typeId,
type_name: cls.children[0].data, type_name: cls.children[0].data,
}; };
}); });
let filterObj = { let filterObj = {
"2":[{"key":"cateId","name":"类型","value":[{"n":"全部","v":"2"},{"n":"陆剧","v":"13"},{"n":"日韩剧","v":"15"},{"n":"短剧","v":"21"},{"n":"台泰剧","v":"14"},{"n":"港剧","v":"20"}]},{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"内地","v":"内地"},{"n":"韩国","v":"韩国"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"美国","v":"美国"},{"n":"英国","v":"英国"},{"n":"巴西","v":"巴西"},{"n":"泰国","v":"泰国"},{"n":"法国","v":"法国"},{"n":"日本","v":"日本"},{"n":"荷兰","v":"荷兰"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"韩语","v":"韩语"},{"n":"泰语","v":"泰语"},{"n":"法语","v":"法语"},{"n":"日语","v":"日语"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "2":[{"key":"cateId","name":"类型","value":[{"n":"全部","v":"2"},{"n":"陆剧","v":"13"},{"n":"日韩剧","v":"15"},{"n":"短剧","v":"21"},{"n":"台泰剧","v":"14"},{"n":"港剧","v":"20"}]},{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"内地","v":"内地"},{"n":"韩国","v":"韩国"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"美国","v":"美国"},{"n":"英国","v":"英国"},{"n":"巴西","v":"巴西"},{"n":"泰国","v":"泰国"},{"n":"法国","v":"法国"},{"n":"日本","v":"日本"},{"n":"荷兰","v":"荷兰"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"韩语","v":"韩语"},{"n":"泰语","v":"泰语"},{"n":"法语","v":"法语"},{"n":"日语","v":"日语"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"3":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"真人秀","v":"真人秀"},{"n":"选秀","v":"选秀"},{"n":"竞演","v":"竞演"},{"n":"情感","v":"情感"},{"n":"访谈","v":"访谈"},{"n":"播报","v":"播报"},{"n":"旅游","v":"旅游"},{"n":"音乐","v":"音乐"},{"n":"美食","v":"美食"},{"n":"纪实","v":"纪实"},{"n":"曲艺","v":"曲艺"},{"n":"生活","v":"生活"},{"n":"游戏互动","v":"游戏互动"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"内地","v":"内地"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"韩国","v":"韩国"},{"n":"美国","v":"美国"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"闽南语","v":"闽南语"},{"n":"韩语","v":"韩语"},{"n":"日语","v":"日语"},{"n":"其它","v":"其它"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "3":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"真人秀","v":"真人秀"},{"n":"选秀","v":"选秀"},{"n":"竞演","v":"竞演"},{"n":"情感","v":"情感"},{"n":"访谈","v":"访谈"},{"n":"播报","v":"播报"},{"n":"旅游","v":"旅游"},{"n":"音乐","v":"音乐"},{"n":"美食","v":"美食"},{"n":"纪实","v":"纪实"},{"n":"曲艺","v":"曲艺"},{"n":"生活","v":"生活"},{"n":"游戏互动","v":"游戏互动"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"内地","v":"内地"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"韩国","v":"韩国"},{"n":"美国","v":"美国"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"闽南语","v":"闽南语"},{"n":"韩语","v":"韩语"},{"n":"日语","v":"日语"},{"n":"其它","v":"其它"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"4":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"玄幻","v":"玄幻"},{"n":"武侠","v":"武侠"},{"n":"情感","v":"情感"},{"n":"科幻","v":"科幻"},{"n":"热血","v":"热血"},{"n":"推理","v":"推理"},{"n":"搞笑","v":"搞笑"},{"n":"冒险","v":"冒险"},{"n":"萝莉","v":"萝莉"},{"n":"校园","v":"校园"},{"n":"动作","v":"动作"},{"n":"机战","v":"机战"},{"n":"运动","v":"运动"},{"n":"战争","v":"战争"},{"n":"少年","v":"少年"},{"n":"少女","v":"少女"},{"n":"社会","v":"社会"},{"n":"亲子","v":"亲子"},{"n":"益智","v":"益智"},{"n":"励志","v":"励志"},{"n":"其他","v":"其他"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"国产","v":"国产"},{"n":"日本","v":"日本"},{"n":"美国","v":"美国"},{"n":"法国","v":"法国"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"闽南语","v":"闽南语"},{"n":"韩语","v":"韩语"},{"n":"日语","v":"日语"},{"n":"其它","v":"其它"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "4":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"玄幻","v":"玄幻"},{"n":"武侠","v":"武侠"},{"n":"情感","v":"情感"},{"n":"科幻","v":"科幻"},{"n":"热血","v":"热血"},{"n":"推理","v":"推理"},{"n":"搞笑","v":"搞笑"},{"n":"冒险","v":"冒险"},{"n":"萝莉","v":"萝莉"},{"n":"校园","v":"校园"},{"n":"动作","v":"动作"},{"n":"机战","v":"机战"},{"n":"运动","v":"运动"},{"n":"战争","v":"战争"},{"n":"少年","v":"少年"},{"n":"少女","v":"少女"},{"n":"社会","v":"社会"},{"n":"亲子","v":"亲子"},{"n":"益智","v":"益智"},{"n":"励志","v":"励志"},{"n":"其他","v":"其他"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"国产","v":"国产"},{"n":"日本","v":"日本"},{"n":"美国","v":"美国"},{"n":"法国","v":"法国"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"闽南语","v":"闽南语"},{"n":"韩语","v":"韩语"},{"n":"日语","v":"日语"},{"n":"其它","v":"其它"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"13":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "13":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"15":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"韩国","v":"韩国"},{"n":"日本","v":"日本"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "15":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"韩国","v":"韩国"},{"n":"日本","v":"日本"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"21":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "21":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"14":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"台湾","v":"台湾"},{"n":"泰国","v":"泰国"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}], "14":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"台湾","v":"台湾"},{"n":"泰国","v":"泰国"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}],
"20":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}] "20":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"悬疑","v":"悬疑"},{"n":"武侠","v":"武侠"},{"n":"科幻","v":"科幻"},{"n":"都市","v":"都市"},{"n":"爱情","v":"爱情"},{"n":"古装","v":"古装"},{"n":"战争","v":"战争"},{"n":"青春","v":"青春"},{"n":"偶像","v":"偶像"},{"n":"喜剧","v":"喜剧"},{"n":"家庭","v":"家庭"},{"n":"犯罪","v":"犯罪"},{"n":"奇幻","v":"奇幻"},{"n":"剧情","v":"剧情"},{"n":"乡村","v":"乡村"},{"n":"年代","v":"年代"},{"n":"警匪","v":"警匪"},{"n":"谍战","v":"谍战"},{"n":"冒险","v":"冒险"},{"n":"罪案","v":"罪案"},{"n":"宫廷","v":"宫廷"},{"n":"BL","v":"BL"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"by","name":"排序","value":[{"n":"时间","v":"time"},{"n":"人气","v":"hits"},{"n":"评分","v":"score"}]}]
}; };
return JSON.stringify({ return JSON.stringify({
class: classes, class: classes,
filters: filterObj, filters: filterObj,
}); });
} }
async function homeVod() { async function homeVod() {
const link = url + '/vodshow/2--hits---------.html'; const link = url + '/vodshow/2--hits---------.html';
const html = await request(link); const html = await request(link);
const $ = load(html); const $ = load(html);
const items = $('div.myui-panel_bd > ul.myui-vodlist > li'); const items = $('div.myui-panel_bd > ul.myui-vodlist > li');
let videos = _.map(items, (item) => { let videos = _.map(items, (item) => {
const it = $(item).find('a:first')[0]; const it = $(item).find('a:first')[0];
const remarks = $($(item).find('span.pic-text')[0]).text().trim(); const remarks = $($(item).find('span.pic-text')[0]).text().trim();
return { return {
vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'), vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'),
vod_name: it.attribs.title, vod_name: it.attribs.title,
vod_pic: it.attribs['data-original'], vod_pic: it.attribs['data-original'],
vod_remarks: remarks || '', vod_remarks: remarks || '',
}; };
}); });
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
async function category(tid, pg, filter, extend) { async function category(tid, pg, filter, extend) {
if (pg <= 0) pg = 1; if (pg <= 0) pg = 1;
const link = url + '/vodshow/' + (extend.CateId || tid) + '-'+(extend.area || '')+'-'+(extend.by || 'time')+'-'+(extend.class || '')+'-'+(extend.lang || '')+'-'+(extend.letter || '')+'---' + (`${pg}`) + '---'+(extend.year || '')+'.html'; const link = url + '/vodshow/' + (extend.CateId || tid) + '-'+(extend.area || '')+'-'+(extend.by || 'time')+'-'+(extend.class || '')+'-'+(extend.lang || '')+'-'+(extend.letter || '')+'---' + (`${pg}`) + '---'+(extend.year || '')+'.html';
const html = await request(link); const html = await request(link);
const $ = load(html); const $ = load(html);
const items = $('div.myui-panel_bd > ul.myui-vodlist > li'); const items = $('div.myui-panel_bd > ul.myui-vodlist > li');
let videos = _.map(items, (item) => { let videos = _.map(items, (item) => {
const it = $(item).find('a:first')[0]; const it = $(item).find('a:first')[0];
const remarks = $($(item).find('span.pic-text')[0]).text().trim(); const remarks = $($(item).find('span.pic-text')[0]).text().trim();
return { return {
vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'), vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'),
vod_name: it.attribs.title, vod_name: it.attribs.title,
vod_pic: it.attribs['data-original'], vod_pic: it.attribs['data-original'],
vod_remarks: remarks || '', vod_remarks: remarks || '',
}; };
}); });
const hasMore = $('ul.myui-page > li > a:contains(下一页)').length > 0; const hasMore = $('ul.myui-page > li > a:contains(下一页)').length > 0;
const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg);
return JSON.stringify({ return JSON.stringify({
page: parseInt(pg), page: parseInt(pg),
pagecount: pgCount, pagecount: pgCount,
limit: 24, limit: 24,
total: 24 * pgCount, total: 24 * pgCount,
list: videos, list: videos,
}); });
} }
async function detail(id) { async function detail(id) {
const html = await request(url + '/voddetail/' + id + '.html'); const html = await request(url + '/voddetail/' + id + '.html');
const $ = load(html); const $ = load(html);
let vod = { let vod = {
vod_id: id, vod_id: id,
vod_name: $('h1:first').text().trim(), vod_name: $('h1:first').text().trim(),
vod_type: $('.myui-content__detail p:first a').text(), vod_type: $('.myui-content__detail p:first a').text(),
vod_actor: $('.myui-content__detail p:nth-child(5)').text().replace('主演:',''), vod_actor: $('.myui-content__detail p:nth-child(5)').text().replace('主演:',''),
vod_director: $('.myui-content__detail p:nth-child(6)').text().replace('导演:',''), vod_director: $('.myui-content__detail p:nth-child(6)').text().replace('导演:',''),
vod_pic: $('div.myui-content__thumb img:first').attr('data-original'), vod_pic: $('div.myui-content__thumb img:first').attr('data-original'),
vod_remarks :$('#rating:first span').text().replace(/\s{2,}/g, ' '), vod_remarks :$('#rating:first span').text().replace(/\s{2,}/g, ' '),
vod_content: $('span.data').text().trim(), vod_content: $('span.data').text().trim(),
}; };
const playlist = _.map($('ul.sort-list > li > a'), (it) => { const playlist = _.map($('ul.sort-list > li > a'), (it) => {
return it.children[0].data + '$' + it.attribs.href.replace(/\/vodplay\/(.*).html/g, '$1'); return it.children[0].data + '$' + it.attribs.href.replace(/\/vodplay\/(.*).html/g, '$1');
}); });
vod.vod_play_from = key; vod.vod_play_from = key;
vod.vod_play_url = playlist.join('#'); vod.vod_play_url = playlist.join('#');
return JSON.stringify({ return JSON.stringify({
list: [vod], list: [vod],
}); });
} }
async function play(flag, id, flags) { async function play(flag, id, flags) {
const link = url + '/vodplay/' + id + '.html'; const link = url + '/vodplay/' + id + '.html';
const html = await request(link); const html = await request(link);
const $ = load(html); const $ = load(html);
const js = JSON.parse($('script:contains(player_)').html().replace('var player_data=','')); const js = JSON.parse($('script:contains(player_)').html().replace('var player_data=',''));
const playUrl = js.url.replace('index.m3u8','hls\/index.m3u8'); const playUrl = js.url.replace('index.m3u8','hls\/index.m3u8');
return JSON.stringify({ return JSON.stringify({
parse: 0, parse: 0,
url: playUrl, url: playUrl,
}); });
} }
async function search(wd, quick) { async function search(wd, quick) {
let data = JSON.parse(await request(url + '/index.php/ajax/suggest?mid=1&wd=' + wd)).list; let data = JSON.parse(await request(url + '/index.php/ajax/suggest?mid=1&wd=' + wd)).list;
let videos = []; let videos = [];
for (const vod of data) { for (const vod of data) {
videos.push({ videos.push({
vod_id: vod.id, vod_id: vod.id,
vod_name: vod.name, vod_name: vod.name,
vod_pic: vod.pic, vod_pic: vod.pic,
vod_remarks: '', vod_remarks: '',
}); });
} }
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
export function __jsEvalReturn() { export function __jsEvalReturn() {
return { return {
init: init, init: init,
home: home, home: home,
homeVod: homeVod, homeVod: homeVod,
category: category, category: category,
detail: detail, detail: detail,
play: play, play: play,
search: search, search: search,
}; };
} }

View File

@ -1,203 +1,203 @@
import { Crypto, load, _ } from './lib/cat.js'; import { Crypto, load, _ } from './lib/cat.js';
let key = 'ikanbot'; let key = 'ikanbot';
let url = 'https://www.ikanbot.com'; let url = 'https://www.ikanbot.com';
let siteKey = ''; let siteKey = '';
let siteType = 0; let siteType = 0;
const UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'; const UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1';
async function request(reqUrl, agentSp) { async function request(reqUrl, agentSp) {
let res = await req(reqUrl, { let res = await req(reqUrl, {
method: 'get', method: 'get',
headers: { headers: {
'User-Agent': agentSp || UA, 'User-Agent': agentSp || UA,
}, },
}); });
return res.content; return res.content;
} }
// cfg = {skey: siteKey, ext: extend} // cfg = {skey: siteKey, ext: extend}
async function init(cfg) { async function init(cfg) {
siteKey = cfg.skey; siteKey = cfg.skey;
siteType = cfg.stype; siteType = cfg.stype;
} }
function getClass($) { function getClass($) {
const nav = $('ul.nav-pills:eq(1) > li > a'); const nav = $('ul.nav-pills:eq(1) > li > a');
let tags = { let tags = {
key: 'tag', key: 'tag',
name: '标签', name: '标签',
value: _.map(nav, (n) => { value: _.map(nav, (n) => {
return { n: n.children[0].data, v: n.attribs.href }; return { n: n.children[0].data, v: n.attribs.href };
}), }),
}; };
tags['init'] = tags.value[0].v; tags['init'] = tags.value[0].v;
const title = $('title:first').text().split('-')[0].substring(2); const title = $('title:first').text().split('-')[0].substring(2);
return { cls: { type_id: tags.value[0].v, type_name: title }, tags: [tags] }; return { cls: { type_id: tags.value[0].v, type_name: title }, tags: [tags] };
} }
async function home(filter) { async function home(filter) {
let classes = []; let classes = [];
let filterObj = {}; let filterObj = {};
for (const cate of ['/hot/index-movie-热门.html', '/hot/index-tv-热门.html']) { for (const cate of ['/hot/index-movie-热门.html', '/hot/index-tv-热门.html']) {
const html = await request(url + cate); const html = await request(url + cate);
const $ = load(html); const $ = load(html);
const { cls, tags } = getClass($); const { cls, tags } = getClass($);
classes.push(cls); classes.push(cls);
filterObj[cls.type_id] = tags; filterObj[cls.type_id] = tags;
} }
return JSON.stringify({ return JSON.stringify({
class: classes, class: classes,
filters: filterObj, filters: filterObj,
}); });
} }
async function homeVod() { async function homeVod() {
return '{}'; return '{}';
} }
async function category(tid, pg, filter, extend) { async function category(tid, pg, filter, extend) {
if (pg <= 0) pg = 1; if (pg <= 0) pg = 1;
const link = url + (extend.tag || tid).replace('.html', pg > 1 ? `-p-${pg}.html` : '.html'); const link = url + (extend.tag || tid).replace('.html', pg > 1 ? `-p-${pg}.html` : '.html');
const html = await request(link); const html = await request(link);
const $ = load(html); const $ = load(html);
const items = $('div.v-list a.item'); const items = $('div.v-list a.item');
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {}); var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
let videos = _.map(items, (item) => { let videos = _.map(items, (item) => {
const img = $(item).find('img:first')[0]; const img = $(item).find('img:first')[0];
return { return {
vod_id: item.attribs.href, vod_id: item.attribs.href,
vod_name: img.attribs.alt, vod_name: img.attribs.alt,
vod_pic: jsBase + base64Encode(img.attribs['data-src']), vod_pic: jsBase + base64Encode(img.attribs['data-src']),
vod_remarks: '', vod_remarks: '',
}; };
}); });
const hasMore = $('div.page-more > a:contains(下一页)').length > 0; const hasMore = $('div.page-more > a:contains(下一页)').length > 0;
const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg);
return JSON.stringify({ return JSON.stringify({
page: parseInt(pg), page: parseInt(pg),
pagecount: pgCount, pagecount: pgCount,
limit: 24, limit: 24,
total: 24 * pgCount, total: 24 * pgCount,
list: videos, list: videos,
}); });
} }
async function detail(id) { async function detail(id) {
const html = await request(url + id); const html = await request(url + id);
const $ = load(html); const $ = load(html);
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {}); var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
const detail = $('div.detail > .meta'); const detail = $('div.detail > .meta');
let vod = { let vod = {
vod_id: id, vod_id: id,
vod_pic: jsBase + base64Encode($('div.item-root > img')[0].attribs['data-src']), vod_pic: jsBase + base64Encode($('div.item-root > img')[0].attribs['data-src']),
vod_remarks: '', vod_remarks: '',
}; };
for (const info of detail) { for (const info of detail) {
if ($(info).hasClass('title')) { if ($(info).hasClass('title')) {
vod.vod_name = info.children[0].data; vod.vod_name = info.children[0].data;
} else if ($(info).hasClass('year')) { } else if ($(info).hasClass('year')) {
vod.vod_area = info.children[0].data; vod.vod_area = info.children[0].data;
} else if ($(info).hasClass('country')) { } else if ($(info).hasClass('country')) {
vod.vod_area = info.children[0].data; vod.vod_area = info.children[0].data;
} else if ($(info).hasClass('celebrity')) { } else if ($(info).hasClass('celebrity')) {
vod.vod_actor = info.children[0].data; vod.vod_actor = info.children[0].data;
} }
} }
const res = await req(url + '/api/getResN?videoId=' + id.substring(id.lastIndexOf('/') + 1) + '&mtype=2', { const res = await req(url + '/api/getResN?videoId=' + id.substring(id.lastIndexOf('/') + 1) + '&mtype=2', {
headers: { headers: {
Referer: url, Referer: url,
'User-Agent': UA, 'User-Agent': UA,
}, },
}); });
const list = JSON.parse(res.content).data.list; const list = JSON.parse(res.content).data.list;
let playlist = {}; let playlist = {};
for (const l of list) { for (const l of list) {
const flagData = JSON.parse(l.resData); const flagData = JSON.parse(l.resData);
for (const f of flagData) { for (const f of flagData) {
const from = f.flag; const from = f.flag;
const urls = f.url; const urls = f.url;
if (!from || !urls) continue; if (!from || !urls) continue;
if (playlist[from]) continue; if (playlist[from]) continue;
playlist[from] = urls; playlist[from] = urls;
} }
} }
vod.vod_play_from = _.keys(playlist).join('$$$'); vod.vod_play_from = _.keys(playlist).join('$$$');
vod.vod_play_url = _.values(playlist).join('$$$'); vod.vod_play_url = _.values(playlist).join('$$$');
return JSON.stringify({ return JSON.stringify({
list: [vod], list: [vod],
}); });
} }
function base64Encode(text) { function base64Encode(text) {
return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text)); return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text));
} }
function base64Decode(text) { function base64Decode(text) {
return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text)); return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
} }
async function proxy(segments, headers) { async function proxy(segments, headers) {
let what = segments[0]; let what = segments[0];
let url = base64Decode(segments[1]); let url = base64Decode(segments[1]);
if (what == 'img') { if (what == 'img') {
var resp = await req(url, { var resp = await req(url, {
buffer: 2, buffer: 2,
headers: { headers: {
Referer: url, Referer: url,
'User-Agent': UA, 'User-Agent': UA,
}, },
}); });
return JSON.stringify({ return JSON.stringify({
code: resp.code, code: resp.code,
buffer: 2, buffer: 2,
content: resp.content, content: resp.content,
headers: resp.headers, headers: resp.headers,
}); });
} }
return JSON.stringify({ return JSON.stringify({
code: 500, code: 500,
content: '', content: '',
}); });
} }
async function play(flag, id, flags) { async function play(flag, id, flags) {
return JSON.stringify({ return JSON.stringify({
parse: 0, parse: 0,
url: id, url: id,
}); });
} }
async function search(wd, quick) { async function search(wd, quick) {
const html = await request(url + '/search?q=' + wd); const html = await request(url + '/search?q=' + wd);
const $ = load(html); const $ = load(html);
const items = $('div.media > div.media-left > a'); const items = $('div.media > div.media-left > a');
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {}); var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
let videos = _.map(items, (item) => { let videos = _.map(items, (item) => {
const img = $(item).find('img:first')[0]; const img = $(item).find('img:first')[0];
return { return {
vod_id: item.attribs.href, vod_id: item.attribs.href,
vod_name: img.attribs.alt, vod_name: img.attribs.alt,
vod_pic: jsBase + base64Encode(img.attribs['data-src']), vod_pic: jsBase + base64Encode(img.attribs['data-src']),
vod_remarks: '', vod_remarks: '',
}; };
}); });
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
export function __jsEvalReturn() { export function __jsEvalReturn() {
return { return {
init: init, init: init,
home: home, home: home,
homeVod: homeVod, homeVod: homeVod,
category: category, category: category,
detail: detail, detail: detail,
play: play, play: play,
proxy: proxy, proxy: proxy,
search: search, search: search,
}; };
} }

View File

@ -1,364 +1,364 @@
import { Crypto, dayjs, jinja2, _ } from './lib/cat.js'; import { Crypto, dayjs, jinja2, _ } from './lib/cat.js';
let key = 'kkys'; let key = 'kkys';
let url = 'https://api1.baibaipei.com:8899'; let url = 'https://api1.baibaipei.com:8899';
let device = {}; let device = {};
let siteKey = ''; let siteKey = '';
let siteType = 0; let siteType = 0;
async function request(reqUrl, postData, agentSp, get) { async function request(reqUrl, postData, agentSp, get) {
let ts = dayjs().valueOf().toString(); let ts = dayjs().valueOf().toString();
let rand = randStr(32); let rand = randStr(32);
let sign = Crypto.MD5('abcdexxxdd2daklmn25129_' + ts + '_' + rand) let sign = Crypto.MD5('abcdexxxdd2daklmn25129_' + ts + '_' + rand)
.toString() .toString()
.toLowerCase(); .toLowerCase();
let headers = { let headers = {
'user-agent': agentSp || device.ua, 'user-agent': agentSp || device.ua,
}; };
if (reqUrl.includes('baibaipei')) { if (reqUrl.includes('baibaipei')) {
headers['device-id'] = device.id; headers['device-id'] = device.id;
headers['push-token'] = ''; headers['push-token'] = '';
headers['sign'] = sign; headers['sign'] = sign;
headers['time'] = ts; headers['time'] = ts;
headers['md5'] = rand; headers['md5'] = rand;
headers['version'] = '2.1.0'; headers['version'] = '2.1.0';
headers['system-model'] = device.model; headers['system-model'] = device.model;
headers['system-brand'] = device.brand; headers['system-brand'] = device.brand;
headers['system-version'] = device.release; headers['system-version'] = device.release;
} }
let res = await req(reqUrl, { let res = await req(reqUrl, {
method: get ? 'get' : 'post', method: get ? 'get' : 'post',
headers: headers, headers: headers,
data: postData || {}, data: postData || {},
postType: get ? '' : 'form', postType: get ? '' : 'form',
}); });
let content = res.content; let content = res.content;
// console.log(content); // console.log(content);
return content; return content;
} }
async function init(cfg) { async function init(cfg) {
siteKey = cfg.skey; siteKey = cfg.skey;
siteType = cfg.stype; siteType = cfg.stype;
var deviceKey = 'device'; var deviceKey = 'device';
var deviceInfo = await local.get(key, deviceKey); var deviceInfo = await local.get(key, deviceKey);
if (deviceInfo.length > 0) { if (deviceInfo.length > 0) {
try { try {
device = JSON.parse(deviceInfo); device = JSON.parse(deviceInfo);
} catch (error) {} } catch (error) {}
} }
if (_.isEmpty(device)) { if (_.isEmpty(device)) {
device = randDevice(); device = randDevice();
device.id = randStr(33).toLowerCase(); device.id = randStr(33).toLowerCase();
device.ua = 'okhttp/4.1.0'; device.ua = 'okhttp/4.1.0';
await local.set(key, deviceKey, JSON.stringify(device)); await local.set(key, deviceKey, JSON.stringify(device));
} }
} }
async function home(filter) { async function home(filter) {
// await req('https://www.facebook.com', {}); // await req('https://www.facebook.com', {});
let data = JSON.parse(await request(url + '/api.php/Index/getTopVideoCategory')).data; let data = JSON.parse(await request(url + '/api.php/Index/getTopVideoCategory')).data;
let classes = []; let classes = [];
let filterObj = {}; let filterObj = {};
for (const type of data) { for (const type of data) {
let typeName = type.nav_name; let typeName = type.nav_name;
if (typeName == '推荐') continue; if (typeName == '推荐') continue;
let typeId = type.nav_type_id.toString(); let typeId = type.nav_type_id.toString();
classes.push({ classes.push({
type_id: typeId, type_id: typeId,
type_name: typeName, type_name: typeName,
}); });
if (!filter) continue; if (!filter) continue;
try { try {
let filterAll = []; let filterAll = [];
let filterData = JSON.parse(await request(url + '/api.php/Video/getFilterType', { type: typeId })).data; let filterData = JSON.parse(await request(url + '/api.php/Video/getFilterType', { type: typeId })).data;
for (let key of Object.keys(filterData)) { for (let key of Object.keys(filterData)) {
let itemValues = filterData[key]; let itemValues = filterData[key];
if (key === 'plot') key = 'class'; if (key === 'plot') key = 'class';
let typeExtendName = ''; let typeExtendName = '';
switch (key) { switch (key) {
case 'class': case 'class':
typeExtendName = '类型'; typeExtendName = '类型';
break; break;
case 'area': case 'area':
typeExtendName = '地区'; typeExtendName = '地区';
break; break;
case 'lang': case 'lang':
typeExtendName = '语言'; typeExtendName = '语言';
break; break;
case 'year': case 'year':
typeExtendName = '年代'; typeExtendName = '年代';
break; break;
case 'sort': case 'sort':
typeExtendName = '排序'; typeExtendName = '排序';
break; break;
} }
if (typeExtendName.length === 0) continue; if (typeExtendName.length === 0) continue;
let newTypeExtend = { let newTypeExtend = {
key: key, key: key,
name: typeExtendName, name: typeExtendName,
}; };
let newTypeExtendKV = []; let newTypeExtendKV = [];
for (let j = 0; j < itemValues.length; j++) { for (let j = 0; j < itemValues.length; j++) {
const name = itemValues[j]; const name = itemValues[j];
let value = key === 'sort' ? j + '' : name === '全部' ? '0' : name; let value = key === 'sort' ? j + '' : name === '全部' ? '0' : name;
newTypeExtendKV.push({ n: name, v: value }); newTypeExtendKV.push({ n: name, v: value });
} }
newTypeExtend['init'] = key === 'sort' ? '1' : newTypeExtendKV[0]['v']; newTypeExtend['init'] = key === 'sort' ? '1' : newTypeExtendKV[0]['v'];
newTypeExtend.value = newTypeExtendKV; newTypeExtend.value = newTypeExtendKV;
filterAll.push(newTypeExtend); filterAll.push(newTypeExtend);
} }
if (!_.isEmpty(filterAll)) { if (!_.isEmpty(filterAll)) {
filterObj[typeId] = filterAll; filterObj[typeId] = filterAll;
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
} }
// console.log(await homeVod()); // console.log(await homeVod());
// console.log(classes); // console.log(classes);
// console.log(filterObj); // console.log(filterObj);
return JSON.stringify({ return JSON.stringify({
class: classes, class: classes,
filters: filterObj, filters: filterObj,
}); });
} }
async function homeVod() { async function homeVod() {
let jsonArray = JSON.parse(await request(url + '/api.php/Index/getHomePage', { type: 1, p: 1 })).data.video; let jsonArray = JSON.parse(await request(url + '/api.php/Index/getHomePage', { type: 1, p: 1 })).data.video;
let videos = []; let videos = [];
for (const item of jsonArray) { for (const item of jsonArray) {
if (item.title.styleType !== 0) continue; if (item.title.styleType !== 0) continue;
for (const vObj of item.list) { for (const vObj of item.list) {
videos.push({ videos.push({
vod_id: vObj.vod_id, vod_id: vObj.vod_id,
vod_name: vObj.vod_name, vod_name: vObj.vod_name,
vod_pic: vObj.vod_pic, vod_pic: vObj.vod_pic,
vod_remarks: vObj.vod_remarks || vObj.vod_score || '', vod_remarks: vObj.vod_remarks || vObj.vod_score || '',
}); });
} }
} }
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
async function category(tid, pg, filter, extend) { async function category(tid, pg, filter, extend) {
if (pg == 0) pg = 1; if (pg == 0) pg = 1;
let reqUrl = url + '/api.php/Video/getFilterVideoList'; let reqUrl = url + '/api.php/Video/getFilterVideoList';
var formData = JSON.parse( var formData = JSON.parse(
jinja2( jinja2(
`{ `{
"type": "{{tid}}", "type": "{{tid}}",
"p": "{{pg}}", "p": "{{pg}}",
"area": "{{ext.area|default(0)}}", "area": "{{ext.area|default(0)}}",
"year": "{{ext.year|default(0)}}", "year": "{{ext.year|default(0)}}",
"sort": "{{ext.sort|default(0)}}", "sort": "{{ext.sort|default(0)}}",
"class": "{{ext.class|default(0)}}" "class": "{{ext.class|default(0)}}"
}`, }`,
{ ext: extend, tid: tid, pg: pg } { ext: extend, tid: tid, pg: pg }
) )
); );
console.log(formData); console.log(formData);
let data = JSON.parse(await request(reqUrl, formData)).data; let data = JSON.parse(await request(reqUrl, formData)).data;
let videos = []; let videos = [];
for (const vod of data.data) { for (const vod of data.data) {
videos.push({ videos.push({
vod_id: vod.vod_id, vod_id: vod.vod_id,
vod_name: vod.vod_name, vod_name: vod.vod_name,
vod_pic: vod.vod_pic, vod_pic: vod.vod_pic,
vod_remarks: vod.vod_remarks || vod.vod_score || '', vod_remarks: vod.vod_remarks || vod.vod_score || '',
}); });
} }
return JSON.stringify({ return JSON.stringify({
page: parseInt(data.current_page), page: parseInt(data.current_page),
pagecount: parseInt(data.last_page), pagecount: parseInt(data.last_page),
limit: parseInt(data.per_page), limit: parseInt(data.per_page),
total: parseInt(data.total), total: parseInt(data.total),
list: videos, list: videos,
}); });
} }
async function detail(id) { async function detail(id) {
let data = JSON.parse(await request(url + '/api.php/Video/getVideoInfo', { video_id: id })).data.video; let data = JSON.parse(await request(url + '/api.php/Video/getVideoInfo', { video_id: id })).data.video;
let vod = { let vod = {
vod_id: data.vod_id, vod_id: data.vod_id,
vod_name: data.vod_name, vod_name: data.vod_name,
vod_pic: data.vod_pic, vod_pic: data.vod_pic,
type_name: data.vod_class, type_name: data.vod_class,
vod_year: data.vod_year, vod_year: data.vod_year,
vod_area: data.vod_area, vod_area: data.vod_area,
vod_remarks: data.vod_remarks || '', vod_remarks: data.vod_remarks || '',
vod_actor: data.vod_actor, vod_actor: data.vod_actor,
vod_director: data.vod_director, vod_director: data.vod_director,
vod_content: data.vod_content.trim(), vod_content: data.vod_content.trim(),
}; };
let playlist = {}; let playlist = {};
for (const item of data.vod_play) { for (const item of data.vod_play) {
let from = item.playerForm; let from = item.playerForm;
if (from === 'jp') continue; if (from === 'jp') continue;
if (from === 'xg') continue; if (from === 'xg') continue;
let urls = []; let urls = [];
for (const u of item.url) { for (const u of item.url) {
urls.push(formatPlayUrl(vod.vod_name, u.title) + '$' + u.play_url); urls.push(formatPlayUrl(vod.vod_name, u.title) + '$' + u.play_url);
} }
if (!playlist.hasOwnProperty(from) && urls.length > 0) { if (!playlist.hasOwnProperty(from) && urls.length > 0) {
playlist[from] = urls; playlist[from] = urls;
} }
} }
parse = data.parse || []; parse = data.parse || [];
vod.vod_play_from = _.keys(playlist).join('$$$'); vod.vod_play_from = _.keys(playlist).join('$$$');
let urls = _.values(playlist); let urls = _.values(playlist);
let vod_play_url = []; let vod_play_url = [];
for (const urlist of urls) { for (const urlist of urls) {
vod_play_url.push(urlist.join('#')); vod_play_url.push(urlist.join('#'));
} }
vod.vod_play_url = vod_play_url.join('$$$'); vod.vod_play_url = vod_play_url.join('$$$');
return JSON.stringify({ return JSON.stringify({
list: [vod], list: [vod],
}); });
} }
var parse = []; var parse = [];
async function play(flag, id, flags) { async function play(flag, id, flags) {
try { try {
if (id.indexOf('youku') >= 0 || id.indexOf('iqiyi') >= 0 || id.indexOf('v.qq.com') >= 0 || id.indexOf('pptv') >= 0 || id.indexOf('le.com') >= 0 || id.indexOf('1905.com') >= 0 || id.indexOf('mgtv') >= 0) { if (id.indexOf('youku') >= 0 || id.indexOf('iqiyi') >= 0 || id.indexOf('v.qq.com') >= 0 || id.indexOf('pptv') >= 0 || id.indexOf('le.com') >= 0 || id.indexOf('1905.com') >= 0 || id.indexOf('mgtv') >= 0) {
if (parse.length > 0) { if (parse.length > 0) {
for (let index = 0; index < parse.length; index++) { for (let index = 0; index < parse.length; index++) {
try { try {
const p = parse[index]; const p = parse[index];
let res = await req(p + id, { let res = await req(p + id, {
headers: { 'user-agent': 'okhttp/4.1.0' }, headers: { 'user-agent': 'okhttp/4.1.0' },
}); });
var result = jsonParse(id, JSON.parse(res.content)); var result = jsonParse(id, JSON.parse(res.content));
if (result.url) { if (result.url) {
result.parse = 0; result.parse = 0;
return JSON.stringify(result); return JSON.stringify(result);
} }
} catch (error) {} } catch (error) {}
} }
} }
} }
if (id.indexOf('jqq-') >= 0) { if (id.indexOf('jqq-') >= 0) {
var jqqHeader = await request(url + '/jqqheader.json', null, null, true); var jqqHeader = await request(url + '/jqqheader.json', null, null, true);
var jqqHeaders = JSON.parse(jqqHeader); var jqqHeaders = JSON.parse(jqqHeader);
var ids = id.split('-'); var ids = id.split('-');
var jxJqq = await req('https://api.juquanquanapp.com/app/drama/detail?dramaId=' + ids[1] + '&episodeSid=' + ids[2] + '&quality=LD', { headers: jqqHeaders }); var jxJqq = await req('https://api.juquanquanapp.com/app/drama/detail?dramaId=' + ids[1] + '&episodeSid=' + ids[2] + '&quality=LD', { headers: jqqHeaders });
var jqqInfo = JSON.parse(jxJqq.content); var jqqInfo = JSON.parse(jxJqq.content);
if (jqqInfo.data.playInfo.url) { if (jqqInfo.data.playInfo.url) {
return JSON.stringify({ return JSON.stringify({
parse: 0, parse: 0,
playUrl: '', playUrl: '',
url: jqqInfo.data.playInfo.url, url: jqqInfo.data.playInfo.url,
}); });
} }
} }
let res = await request(url + '/video.php', { url: id }); let res = await request(url + '/video.php', { url: id });
var result = jsonParse(id, JSON.parse(res).data); var result = jsonParse(id, JSON.parse(res).data);
if (result.url) { if (result.url) {
result.parse = 0; result.parse = 0;
return JSON.stringify(result); return JSON.stringify(result);
} }
return JSON.stringify({ return JSON.stringify({
parse: 0, parse: 0,
playUrl: '', playUrl: '',
url: id, url: id,
}); });
} catch (e) { } catch (e) {
console.log(e); console.log(e);
return JSON.stringify({ return JSON.stringify({
parse: 0, parse: 0,
url: id, url: id,
}); });
} }
} }
async function search(wd, quick) { async function search(wd, quick) {
let data = JSON.parse(await request(url + '/api.php/Search/getSearch', { key: wd, type_id: 0, p: 1 })).data; let data = JSON.parse(await request(url + '/api.php/Search/getSearch', { key: wd, type_id: 0, p: 1 })).data;
let videos = []; let videos = [];
for (const vod of data.data) { for (const vod of data.data) {
videos.push({ videos.push({
vod_id: vod.vod_id, vod_id: vod.vod_id,
vod_name: vod.vod_name, vod_name: vod.vod_name,
vod_pic: vod.vod_pic, vod_pic: vod.vod_pic,
vod_remarks: vod.vod_remarks || vod.vod_score || '', vod_remarks: vod.vod_remarks || vod.vod_score || '',
}); });
} }
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
const charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789'; const charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
function randStr(len, withNum) { function randStr(len, withNum) {
var _str = ''; var _str = '';
let containsNum = withNum === undefined ? true : withNum; let containsNum = withNum === undefined ? true : withNum;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11); let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
_str += charStr[idx]; _str += charStr[idx];
} }
return _str; return _str;
} }
function randDevice() { function randDevice() {
return { return {
brand: 'Huawei', brand: 'Huawei',
model: 'HUAWEI Mate 20', model: 'HUAWEI Mate 20',
release: '10', release: '10',
buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(), buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
}; };
} }
function formatPlayUrl(src, name) { function formatPlayUrl(src, name) {
return name return name
.trim() .trim()
.replaceAll(src, '') .replaceAll(src, '')
.replace(/<|>|《|》/g, '') .replace(/<|>|《|》/g, '')
.replace(/\$|#/g, ' ') .replace(/\$|#/g, ' ')
.trim(); .trim();
} }
function jsonParse(input, json) { function jsonParse(input, json) {
try { try {
let url = json.url ?? ''; let url = json.url ?? '';
if (url.startsWith('//')) { if (url.startsWith('//')) {
url = 'https:' + url; url = 'https:' + url;
} }
if (!url.startsWith('http')) { if (!url.startsWith('http')) {
return {}; return {};
} }
let headers = json['headers'] || {}; let headers = json['headers'] || {};
let ua = (json['user-agent'] || '').trim(); let ua = (json['user-agent'] || '').trim();
if (ua.length > 0) { if (ua.length > 0) {
headers['User-Agent'] = ua; headers['User-Agent'] = ua;
} }
let referer = (json['referer'] || '').trim(); let referer = (json['referer'] || '').trim();
if (referer.length > 0) { if (referer.length > 0) {
headers['Referer'] = referer; headers['Referer'] = referer;
} }
_.keys(headers).forEach((hk) => { _.keys(headers).forEach((hk) => {
if (!headers[hk]) delete headers[hk]; if (!headers[hk]) delete headers[hk];
}); });
return { return {
header: headers, header: headers,
url: url, url: url,
}; };
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
return {}; return {};
} }
export function __jsEvalReturn() { export function __jsEvalReturn() {
return { return {
init: init, init: init,
home: home, home: home,
homeVod: homeVod, homeVod: homeVod,
category: category, category: category,
detail: detail, detail: detail,
play: play, play: play,
search: search, search: search,
}; };
} }

View File

@ -1,341 +1,341 @@
import { Crypto, dayjs, jinja2, Uri, _ } from './lib/cat.js'; import { Crypto, dayjs, jinja2, Uri, _ } from './lib/cat.js';
let key = 'kunyu77'; let key = 'kunyu77';
let url = 'http://api.tyun77.cn'; let url = 'http://api.tyun77.cn';
let device = {}; let device = {};
let timeOffset = 0; let timeOffset = 0;
let siteKey = ''; let siteKey = '';
let siteType = 0; let siteType = 0;
async function request(reqUrl, agentSp) { async function request(reqUrl, agentSp) {
let sj = dayjs().unix() - timeOffset; let sj = dayjs().unix() - timeOffset;
let uri = new Uri(reqUrl); let uri = new Uri(reqUrl);
uri.addQueryParam('pcode', '010110005'); uri.addQueryParam('pcode', '010110005');
uri.addQueryParam('version', '2.1.6'); uri.addQueryParam('version', '2.1.6');
uri.addQueryParam('devid', device.id); uri.addQueryParam('devid', device.id);
uri.addQueryParam('package', 'com.sevenVideo.app.android'); uri.addQueryParam('package', 'com.sevenVideo.app.android');
uri.addQueryParam('sys', 'android'); uri.addQueryParam('sys', 'android');
uri.addQueryParam('sysver', device.release); uri.addQueryParam('sysver', device.release);
uri.addQueryParam('brand', device.brand); uri.addQueryParam('brand', device.brand);
uri.addQueryParam('model', device.model.replaceAll(' ', '_')); uri.addQueryParam('model', device.model.replaceAll(' ', '_'));
uri.addQueryParam('sj', sj); uri.addQueryParam('sj', sj);
let keys = []; let keys = [];
for (var i = 0; i < uri.queryPairs.length; i++) { for (var i = 0; i < uri.queryPairs.length; i++) {
keys.push(uri.queryPairs[i][0]); keys.push(uri.queryPairs[i][0]);
} }
keys = _.sortBy(keys, function (name) { keys = _.sortBy(keys, function (name) {
return name; return name;
}); });
let tkSrc = uri.path(); let tkSrc = uri.path();
for (let k of keys) { for (let k of keys) {
let v = uri.getQueryParamValue(k); let v = uri.getQueryParamValue(k);
v = encodeURIComponent(v); v = encodeURIComponent(v);
tkSrc += v; tkSrc += v;
} }
tkSrc += sj; tkSrc += sj;
tkSrc += 'XSpeUFjJ'; tkSrc += 'XSpeUFjJ';
console.log(tkSrc); console.log(tkSrc);
let tk = Crypto.MD5(tkSrc).toString().toLowerCase(); let tk = Crypto.MD5(tkSrc).toString().toLowerCase();
console.log(tk); console.log(tk);
let header = { let header = {
'user-agent': agentSp || 'okhttp/3.12.0', 'user-agent': agentSp || 'okhttp/3.12.0',
t: sj, t: sj,
TK: tk, TK: tk,
}; };
let res = await req(uri.toString(), { let res = await req(uri.toString(), {
headers: header, headers: header,
}); });
let serverTime = res.headers.date; // dart all response header key is lowercase let serverTime = res.headers.date; // dart all response header key is lowercase
let content = res.content; let content = res.content;
let serverTimeS = dayjs(serverTime).unix(); let serverTimeS = dayjs(serverTime).unix();
timeOffset = dayjs().unix() - serverTimeS; timeOffset = dayjs().unix() - serverTimeS;
// console.log(content); // console.log(content);
return content; return content;
} }
async function init(cfg) { async function init(cfg) {
siteKey = cfg.skey; siteKey = cfg.skey;
siteType = cfg.stype; siteType = cfg.stype;
var deviceKey = 'device'; var deviceKey = 'device';
var deviceInfo = await local.get(key, deviceKey); var deviceInfo = await local.get(key, deviceKey);
if (deviceInfo.length > 0) { if (deviceInfo.length > 0) {
try { try {
device = JSON.parse(deviceInfo); device = JSON.parse(deviceInfo);
} catch (error) {} } catch (error) {}
} }
if (_.isEmpty(device)) { if (_.isEmpty(device)) {
device = randDevice(); device = randDevice();
device.id = randStr(32).toLowerCase(); device.id = randStr(32).toLowerCase();
device.ua = 'Dalvik/2.1.0 (Linux; U; Android ' + device.release + '; ' + device.model + ' Build/' + device.buildId + ')'; device.ua = 'Dalvik/2.1.0 (Linux; U; Android ' + device.release + '; ' + device.model + ' Build/' + device.buildId + ')';
await local.set(key, deviceKey, JSON.stringify(device)); await local.set(key, deviceKey, JSON.stringify(device));
} }
await request(url + '/api.php/provide/getDomain'); await request(url + '/api.php/provide/getDomain');
await request(url + '/api.php/provide/config'); await request(url + '/api.php/provide/config');
await request(url + '/api.php/provide/checkUpgrade'); await request(url + '/api.php/provide/checkUpgrade');
await request(url + '/api.php/provide/channel'); await request(url + '/api.php/provide/channel');
} }
async function home(filter) { async function home(filter) {
let data = JSON.parse(await request(url + '/api.php/provide/filter')).data; let data = JSON.parse(await request(url + '/api.php/provide/filter')).data;
let classes = []; let classes = [];
let filterObj = {}; let filterObj = {};
let filterAll = []; let filterAll = [];
for (const key in data) { for (const key in data) {
classes.push({ classes.push({
type_id: key, type_id: key,
type_name: data[key][0].cat, type_name: data[key][0].cat,
}); });
if (!filter) continue; if (!filter) continue;
try { try {
let typeId = key.toString(); let typeId = key.toString();
if (_.isEmpty(filterAll)) { if (_.isEmpty(filterAll)) {
let filterData = JSON.parse(await request(url + '/api.php/provide/searchFilter?type_id=0&pagenum=1&pagesize=1')).data.conditions; let filterData = JSON.parse(await request(url + '/api.php/provide/searchFilter?type_id=0&pagenum=1&pagesize=1')).data.conditions;
// console.log(filterData); // console.log(filterData);
// 年份 // 年份
let year = { let year = {
key: 'year', key: 'year',
name: '年份', name: '年份',
init: '', init: '',
}; };
let yearValues = []; let yearValues = [];
yearValues.push({ n: '全部', v: '' }); yearValues.push({ n: '全部', v: '' });
filterData.y.forEach((e) => { filterData.y.forEach((e) => {
yearValues.push({ n: e.name, v: e.value }); yearValues.push({ n: e.name, v: e.value });
}); });
year['value'] = yearValues; year['value'] = yearValues;
// 地区 // 地区
let area = { let area = {
key: 'area', key: 'area',
name: '地区', name: '地区',
init: '', init: '',
}; };
let areaValues = []; let areaValues = [];
areaValues.push({ n: '全部', v: '' }); areaValues.push({ n: '全部', v: '' });
filterData.a.forEach((e) => { filterData.a.forEach((e) => {
areaValues.push({ n: e.name, v: e.value }); areaValues.push({ n: e.name, v: e.value });
}); });
area['value'] = areaValues; area['value'] = areaValues;
// 类型 // 类型
let type = { let type = {
key: 'category', key: 'category',
name: '类型', name: '类型',
init: '', init: '',
}; };
let typeValues = []; let typeValues = [];
typeValues.push({ n: '全部', v: '' }); typeValues.push({ n: '全部', v: '' });
filterData.scat.forEach((e) => { filterData.scat.forEach((e) => {
typeValues.push({ n: e.name, v: e.value }); typeValues.push({ n: e.name, v: e.value });
}); });
type['value'] = typeValues; type['value'] = typeValues;
filterAll.push(year, area, type); filterAll.push(year, area, type);
} }
if (!_.isEmpty(filterAll)) { if (!_.isEmpty(filterAll)) {
filterObj[typeId] = filterAll; filterObj[typeId] = filterAll;
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
} }
// console.log(classes); // console.log(classes);
// console.log(filterObj); // console.log(filterObj);
return JSON.stringify({ return JSON.stringify({
class: classes, class: classes,
filters: filterObj, filters: filterObj,
}); });
} }
async function homeVod() { async function homeVod() {
let data = JSON.parse(await request(url + '/api.php/provide/homeBlock?type_id=0')).data; let data = JSON.parse(await request(url + '/api.php/provide/homeBlock?type_id=0')).data;
let blocks = data.blocks; let blocks = data.blocks;
let videos = []; let videos = [];
for (const block of blocks) { for (const block of blocks) {
let name = block.block_name; let name = block.block_name;
if (name.indexOf('热播') >= 0) continue; if (name.indexOf('热播') >= 0) continue;
let contents = block.contents; let contents = block.contents;
for (const content of contents) { for (const content of contents) {
videos.push({ videos.push({
vod_id: content.id, vod_id: content.id,
vod_name: content.title, vod_name: content.title,
vod_pic: content.videoCover, vod_pic: content.videoCover,
vod_remarks: content.msg, vod_remarks: content.msg,
}); });
} }
} }
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
async function category(tid, pg, filter, extend) { async function category(tid, pg, filter, extend) {
let reqUrl = url + '/api.php/provide/searchFilter?type_id=' + tid + '&pagenum=' + pg + '&pagesize=24&'; let reqUrl = url + '/api.php/provide/searchFilter?type_id=' + tid + '&pagenum=' + pg + '&pagesize=24&';
reqUrl += jinja2('year={{ext.year}}&category={{ext.category}}&area={{ext.area}}', { ext: extend }); reqUrl += jinja2('year={{ext.year}}&category={{ext.category}}&area={{ext.area}}', { ext: extend });
let data = JSON.parse(await request(reqUrl)).data; let data = JSON.parse(await request(reqUrl)).data;
let videos = []; let videos = [];
for (const vod of data.result) { for (const vod of data.result) {
videos.push({ videos.push({
vod_id: vod.id, vod_id: vod.id,
vod_name: vod.title, vod_name: vod.title,
vod_pic: vod.videoCover, vod_pic: vod.videoCover,
vod_remarks: vod.msg, vod_remarks: vod.msg,
}); });
} }
return JSON.stringify({ return JSON.stringify({
page: parseInt(data.page), page: parseInt(data.page),
pagecount: data.pagesize, pagecount: data.pagesize,
limit: 24, limit: 24,
total: data.total, total: data.total,
list: videos, list: videos,
}); });
} }
async function detail(id) { async function detail(id) {
let data = JSON.parse(await request(url + '/api.php/provide/videoDetail?ids=' + id)).data; let data = JSON.parse(await request(url + '/api.php/provide/videoDetail?ids=' + id)).data;
console.log(data); console.log(data);
let vod = { let vod = {
vod_id: data.id, vod_id: data.id,
vod_name: data.videoName, vod_name: data.videoName,
vod_pic: data.videoCover, vod_pic: data.videoCover,
type_name: data.subCategory, type_name: data.subCategory,
vod_year: data.year, vod_year: data.year,
vod_area: data.area, vod_area: data.area,
vod_remarks: data.msg, vod_remarks: data.msg,
vod_actor: data.actor, vod_actor: data.actor,
vod_director: data.director, vod_director: data.director,
vod_content: data.brief.trim(), vod_content: data.brief.trim(),
}; };
let episodes = JSON.parse(await request(url + '/api.php/provide/videoPlaylist?ids=' + id)).data.episodes; let episodes = JSON.parse(await request(url + '/api.php/provide/videoPlaylist?ids=' + id)).data.episodes;
let playlist = {}; let playlist = {};
for (const episode of episodes) { for (const episode of episodes) {
let playurls = episode.playurls; let playurls = episode.playurls;
for (const playurl of playurls) { for (const playurl of playurls) {
let from = playurl.playfrom; let from = playurl.playfrom;
let t = formatPlayUrl(vod.vod_name, playurl.title); let t = formatPlayUrl(vod.vod_name, playurl.title);
if (t.length == 0) t = playurl.title.trim(); if (t.length == 0) t = playurl.title.trim();
if (!playlist.hasOwnProperty(from)) { if (!playlist.hasOwnProperty(from)) {
playlist[from] = []; playlist[from] = [];
} }
playlist[from].push(t + '$' + playurl.playurl); playlist[from].push(t + '$' + playurl.playurl);
} }
} }
vod.vod_play_from = _.keys(playlist).join('$$$'); vod.vod_play_from = _.keys(playlist).join('$$$');
let urls = _.values(playlist); let urls = _.values(playlist);
let vod_play_url = []; let vod_play_url = [];
for (const urlist of urls) { for (const urlist of urls) {
vod_play_url.push(urlist.join('#')); vod_play_url.push(urlist.join('#'));
} }
vod.vod_play_url = vod_play_url.join('$$$'); vod.vod_play_url = vod_play_url.join('$$$');
return JSON.stringify({ return JSON.stringify({
list: [vod], list: [vod],
}); });
} }
async function play(flag, id, flags) { async function play(flag, id, flags) {
try { try {
let data = JSON.parse(await request(url + '/api.php/provide/parserUrl?url=' + id + '&retryNum=0')).data; let data = JSON.parse(await request(url + '/api.php/provide/parserUrl?url=' + id + '&retryNum=0')).data;
let playHeader = data.playHeader; let playHeader = data.playHeader;
let jxUrl = data.url; let jxUrl = data.url;
let res = await req(jxUrl, { let res = await req(jxUrl, {
headers: { headers: {
'user-agent': 'okhttp/3.12.0', 'user-agent': 'okhttp/3.12.0',
}, },
}); });
let result = jsonParse(id, JSON.parse(res.content)); let result = jsonParse(id, JSON.parse(res.content));
result['parse'] = 0; result['parse'] = 0;
if (playHeader) { if (playHeader) {
result.header = _.merge(result.header, playHeader); result.header = _.merge(result.header, playHeader);
} }
return JSON.stringify(result); return JSON.stringify(result);
} catch (e) { } catch (e) {
return JSON.stringify({ return JSON.stringify({
parse: 0, parse: 0,
url: id, url: id,
}); });
} }
} }
async function search(wd, quick) { async function search(wd, quick) {
let data = JSON.parse(await request(url + '/api.php/provide/searchVideo?searchName=' + wd + '&pg=1', 'okhttp/3.12.0')).data; let data = JSON.parse(await request(url + '/api.php/provide/searchVideo?searchName=' + wd + '&pg=1', 'okhttp/3.12.0')).data;
let videos = []; let videos = [];
for (const vod of data) { for (const vod of data) {
videos.push({ videos.push({
vod_id: vod.id, vod_id: vod.id,
vod_name: vod.videoName, vod_name: vod.videoName,
vod_pic: vod.videoCover, vod_pic: vod.videoCover,
vod_remarks: vod.msg, vod_remarks: vod.msg,
}); });
} }
return JSON.stringify({ return JSON.stringify({
list: videos, list: videos,
}); });
} }
const charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789'; const charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
function randStr(len, withNum) { function randStr(len, withNum) {
var _str = ''; var _str = '';
let containsNum = withNum === undefined ? true : withNum; let containsNum = withNum === undefined ? true : withNum;
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11); let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
_str += charStr[idx]; _str += charStr[idx];
} }
return _str; return _str;
} }
function randDevice() { function randDevice() {
return { return {
brand: 'Huawei', brand: 'Huawei',
model: 'HUAWEI Mate 20', model: 'HUAWEI Mate 20',
release: '10', release: '10',
buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(), buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
}; };
} }
function formatPlayUrl(src, name) { function formatPlayUrl(src, name) {
return name return name
.trim() .trim()
.replaceAll(src, '') .replaceAll(src, '')
.replace(/<|>|《|》/g, '') .replace(/<|>|《|》/g, '')
.replace(/\$|#/g, ' ') .replace(/\$|#/g, ' ')
.trim(); .trim();
} }
function jsonParse(input, json) { function jsonParse(input, json) {
try { try {
let url = json.url ?? ''; let url = json.url ?? '';
if (url.startsWith('//')) { if (url.startsWith('//')) {
url = 'https:' + url; url = 'https:' + url;
} }
if (!url.startsWith('http')) { if (!url.startsWith('http')) {
return {}; return {};
} }
let headers = json['headers'] || {}; let headers = json['headers'] || {};
let ua = (json['user-agent'] || '').trim(); let ua = (json['user-agent'] || '').trim();
if (ua.length > 0) { if (ua.length > 0) {
headers['User-Agent'] = ua; headers['User-Agent'] = ua;
} }
let referer = (json['referer'] || '').trim(); let referer = (json['referer'] || '').trim();
if (referer.length > 0) { if (referer.length > 0) {
headers['Referer'] = referer; headers['Referer'] = referer;
} }
return { return {
header: headers, header: headers,
url: url, url: url,
}; };
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
return {}; return {};
} }
export function __jsEvalReturn() { export function __jsEvalReturn() {
return { return {
init: init, init: init,
home: home, home: home,
homeVod: homeVod, homeVod: homeVod,
category: category, category: category,
detail: detail, detail: detail,
play: play, play: play,
search: search, search: search,
}; };
} }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,47 @@
function compareTwoStrings(first, second) {
if ((first = first.replace(/\s+/g, '')) === (second = second.replace(/\s+/g, ''))) return 1;
if (first.length < 2 || second.length < 2) return 0;
var firstBigrams = new Map();
for (let i = 0; i < first.length - 1; i++) {
var bigram = first.substring(i, i + 2),
count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) + 1 : 1;
firstBigrams.set(bigram, count);
}
let intersectionSize = 0;
for (let i = 0; i < second.length - 1; i++) {
const bigram = second.substring(i, i + 2),
count = firstBigrams.has(bigram) ? firstBigrams.get(bigram) : 0;
0 < count && (firstBigrams.set(bigram, count - 1), intersectionSize++);
}
return (2 * intersectionSize) / (first.length + second.length - 2);
}
function findBestMatch(mainString, targetStrings) {
var ratings = [];
let bestMatchIndex = 0;
for (let i = 0; i < targetStrings.length; i++) {
var currentTargetString = targetStrings[i],
currentRating = compareTwoStrings(mainString, currentTargetString);
ratings.push({ target: currentTargetString, rating: currentRating }), currentRating > ratings[bestMatchIndex].rating && (bestMatchIndex = i);
}
return { ratings: ratings, bestMatch: ratings[bestMatchIndex], bestMatchIndex: bestMatchIndex };
}
function lcs(str1, str2) {
if (!str1 || !str2) return { length: 0, sequence: '', offset: 0 };
for (var sequence = '', str1Length = str1.length, str2Length = str2.length, num = new Array(str1Length), maxlen = 0, lastSubsBegin = 0, i = 0; i < str1Length; i++) {
for (var subArray = new Array(str2Length), j = 0; j < str2Length; j++) subArray[j] = 0;
num[i] = subArray;
}
for (var thisSubsBegin = null, i = 0; i < str1Length; i++) for (j = 0; j < str2Length; j++) str1[i] !== str2[j] ? (num[i][j] = 0) : ((num[i][j] = 0 === i || 0 === j ? 1 : 1 + num[i - 1][j - 1]), num[i][j] > maxlen && ((maxlen = num[i][j]), lastSubsBegin === (thisSubsBegin = i - num[i][j] + 1) ? (sequence += str1[i]) : ((lastSubsBegin = thisSubsBegin), (sequence = ''), (sequence += str1.substr(lastSubsBegin, i + 1 - lastSubsBegin)))));
return { length: maxlen, sequence: sequence, offset: thisSubsBegin };
}
function findBestLCS(mainString, targetStrings) {
var results = [];
let bestMatchIndex = 0;
for (let i = 0; i < targetStrings.length; i++) {
var currentTargetString = targetStrings[i],
currentLCS = lcs(mainString, currentTargetString);
results.push({ target: currentTargetString, lcs: currentLCS }), currentLCS.length > results[bestMatchIndex].lcs.length && (bestMatchIndex = i);
}
return { allLCS: results, bestMatch: results[bestMatchIndex], bestMatchIndex: bestMatchIndex };
}
export { compareTwoStrings, findBestMatch, findBestLCS };

342
JN/EXT/OPENJS/open/package-lock.json generated Normal file
View File

@ -0,0 +1,342 @@
{
"name": "CatVodOpenJSSpider",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "CatVodOpenJSSpider",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"axios": "^1.4.0",
"qs": "^6.11.2"
},
"devDependencies": {
"@types/node": "^20.1.5",
"uglify-js": "^3.17.4"
}
},
"node_modules/@types/node": {
"version": "20.4.2",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.4.2.tgz",
"integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
"dev": true
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"node_modules/get-intrinsic": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g=="
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/qs": {
"version": "6.11.2",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.2.tgz",
"integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
}
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"node_modules/uglify-js": {
"version": "3.17.4",
"resolved": "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.17.4.tgz",
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
"dev": true,
"bin": {
"uglifyjs": "bin/uglifyjs"
},
"engines": {
"node": ">=0.8.0"
}
}
},
"dependencies": {
"@types/node": {
"version": "20.4.2",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-20.4.2.tgz",
"integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"get-intrinsic": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g=="
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"qs": {
"version": "6.11.2",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.2.tgz",
"integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
"requires": {
"side-channel": "^1.0.4"
}
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"uglify-js": {
"version": "3.17.4",
"resolved": "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.17.4.tgz",
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
"dev": true
}
}
}

View File

@ -0,0 +1,21 @@
{
"name": "CatVodOpenJSSpider",
"version": "1.0.0",
"description": "",
"main": "app.js",
"type": "module",
"directories": {
"lib": "lib"
},
"scripts": {},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.4.0",
"qs": "^6.11.2"
},
"devDependencies": {
"@types/node": "^20.1.5",
"uglify-js": "^3.17.4"
}
}

View File

@ -0,0 +1,9 @@
import {} from './wrapper/index.js';
// import { test } from './testVideo.js';
import { test } from './testAlist.js';
(async function () {
await test();
debugger;
})();

View File

@ -0,0 +1,72 @@
import { __jsEvalReturn } from './alist_open.js';
var spider = __jsEvalReturn();
async function test() {
await spider.init({
skey: 'siteKey',
ext: [
{
name: '🙋丫仙女',
server: 'http://v.elizen.me/',
startPage: '/',
showAll: false,
search: true,
headers: {
Authorization: '',
},
params: {
'/abc': {
password: '123',
},
'/abc/abc': {
password: '123',
},
},
},
{
name: '🐋一只鱼',
server: 'https://alist.youte.ml',
},
{
name: '🌊七米蓝',
server: 'https://al.chirmyram.com',
},
{
name: '🐉神族九帝',
server: 'https://alist.shenzjd.com',
},
{
name: '☃️姬路白雪',
server: 'https://pan.jlbx.xyz',
},
{
name: '✨星梦',
server: 'https://pan.bashroot.top',
},
{
name: '💢repl',
server: 'https://ali.liucn.repl.co',
},
{
name: '💦讯维云盘',
server: 'https://pan.xwbeta.com',
},
],
});
var files = JSON.parse(await spider.dir('/'));
console.log(files);
files = JSON.parse(await spider.dir(files.list[0].path));
console.log(files);
// files = JSON.parse(await spider.dir('/🙋丫仙女/电视剧/欧美/4K/00 漫威衍生美剧/L 猎鹰与冬兵4K2021【美剧】豆瓣评分7.5/'));
// console.log(files);
var fileInfo = JSON.parse(await spider.file('/💦讯维云盘/热播短剧/傲世神尊/01.mp4'));
console.log(fileInfo);
}
export { test };

View File

@ -0,0 +1,51 @@
import { __jsEvalReturn } from './kunyu77_open.js';
var spider = __jsEvalReturn();
async function test() {
var spType = null;
var spVid = null;
spType = '2';
// spVid = '95873';
await spider.init({ skey: 'siteKey', ext: '' });
var classes = JSON.parse(await spider.home(true));
console.log(classes);
var homeVod = JSON.parse(await spider.homeVod());
console.log(homeVod);
if (classes.class && classes.class.length > 0) {
var page = JSON.parse(await spider.category(spType || classes.class[0].type_id, 0, undefined, {}));
console.log(page);
if (page.list && page.list.length > 0) {
for (const k in page.list) {
if (k >= 5) break;
var detail = JSON.parse(await spider.detail(spVid || page.list[k].vod_id));
console.log(detail);
if (detail.list && detail.list.length > 0) {
var pFlag = detail.list[0].vod_play_from.split('$$$');
var pUrls = detail.list[0].vod_play_url.split('$$$');
if (pFlag.length > 0 && pUrls.length > 0) {
for (const i in pFlag) {
var flag = pFlag[i];
var urls = pUrls[i].split('#');
if (urls.length > 0) {
var url = urls[0].split('$')[1];
console.log(flag, url);
var playUrl = await spider.play(flag, url, []);
console.log(playUrl);
}
}
}
}
if (spVid) break;
}
}
}
var search = JSON.parse(await spider.search('奥特曼'));
console.log(search);
search = JSON.parse(await spider.search('喜欢'));
console.log(search);
}
export { test };

View File

@ -0,0 +1,266 @@
// !!!!! Do not use in release mode. Just a native inject fake wrapper for test spider. !!!!!
// !!!!! Do not use in release mode. Just a native inject fake wrapper for test spider. !!!!!
// !!!!! Do not use in release mode. Just a native inject fake wrapper for test spider. !!!!!
import axios from 'axios';
import crypto from 'crypto';
import https from 'https';
import fs from 'node:fs';
import qs from 'qs';
import { Uri, _ } from '../lib/cat.js';
const confs = {};
function initLocalStorage(storage) {
if (!_.has(confs, storage)) {
if (!fs.existsSync('local')) {
fs.mkdirSync('local');
}
const storagePath = 'local/js_' + storage;
if (!fs.existsSync(storagePath)) {
fs.writeFileSync(storagePath, '{}');
confs[storage] = {};
} else {
confs[storage] = JSON.parse(fs.readFileSync(storagePath).toString());
}
}
}
function localGet(storage, key) {
initLocalStorage(storage);
return _.get(confs[storage], key, '');
}
function localSet(storage, key, value) {
initLocalStorage(storage);
confs[storage][key] = value;
fs.writeFileSync('local/js_' + storage, JSON.stringify(confs[storage]));
}
async function request(url, opt) {
try {
var data = opt ? opt.data || null : null;
var postType = opt ? opt.postType || null : null;
var returnBuffer = opt ? opt.buffer || 0 : 0;
var timeout = opt ? opt.timeout || 5000 : 5000;
var headers = opt ? opt.headers || {} : {};
if (postType == 'form') {
headers['Content-Type'] = 'application/x-www-form-urlencoded';
if (data != null) {
data = qs.stringify(data, { encode: false });
}
}
let respType = returnBuffer == 1 || returnBuffer == 2 ? 'arraybuffer' : undefined;
var resp = await axios(url, {
responseType: respType,
method: opt ? opt.method || 'get' : 'get',
headers: headers,
data: data,
timeout: timeout,
httpsAgent: https.Agent({
rejectUnauthorized: false,
}),
});
var data = resp.data;
var resHeader = {};
for (const hks of resp.headers) {
var v = hks[1];
resHeader[hks[0]] = Array.isArray(v) ? (v.length == 1 ? v[0] : v) : v;
}
if (!returnBuffer) {
if (typeof data === 'object') {
data = JSON.stringify(data);
}
} else if (returnBuffer == 1) {
return { code: resp.status, headers: resHeader, content: data };
} else if (returnBuffer == 2) {
return { code: resp.status, headers: resHeader, content: data.toString('base64') };
}
return { code: resp.status, headers: resHeader, content: data };
} catch (error) {
console.error(error);
}
return { headers: {}, content: '' };
}
function base64EncodeBuf(buff, urlsafe = false) {
return buff.toString(urlsafe ? 'base64url' : 'base64');
}
function base64Encode(text, urlsafe = false) {
return base64EncodeBuf(Buffer.from(text, 'utf8'), urlsafe);
}
function base64DecodeBuf(text) {
return Buffer.from(text, 'base64');
}
function base64Decode(text) {
return base64DecodeBuf(text).toString('utf8');
}
function md5(text) {
return crypto.createHash('md5').update(Buffer.from(text, 'utf8')).digest('hex');
}
function aes(mode, encrypt, input, inBase64, key, iv, outBase64) {
if (iv.length == 0) iv = null;
try {
if (mode.startsWith('AES/CBC')) {
switch (key.length) {
case 16:
mode = 'aes-128-cbc';
break;
case 32:
mode = 'aes-256-cbc';
break;
}
} else if (mode.startsWith('AES/ECB')) {
switch (key.length) {
case 16:
mode = 'aes-128-ecb';
break;
case 32:
mode = 'aes-256-ecb';
break;
}
}
const inBuf = inBase64 ? base64DecodeBuf(input) : Buffer.from(input, 'utf8');
let keyBuf = Buffer.from(key);
if (keyBuf.length < 16) keyBuf = Buffer.concat([keyBuf], 16);
let ivBuf = iv == null ? Buffer.alloc(0) : Buffer.from(iv);
if (iv != null && ivBuf.length < 16) ivBuf = Buffer.concat([ivBuf], 16);
const cipher = encrypt ? crypto.createCipheriv(mode, keyBuf, ivBuf) : crypto.createDecipheriv(mode, keyBuf, ivBuf);
const outBuf = Buffer.concat([cipher.update(inBuf), cipher.final()]);
return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
} catch (error) {
console.log(error);
}
return '';
}
function des(mode, encrypt, input, inBase64, key, iv, outBase64) {
try {
if (mode.startsWith('DESede/CBC')) {
// https://stackoverflow.com/questions/29831300/convert-desede-ecb-nopadding-algorithm-written-in-java-into-nodejs-using-crypto
switch (key.length) {
case 16:
mode = 'des-ede-cbc';
break;
case 24:
mode = 'des-ede3-cbc';
break;
}
}
const inBuf = inBase64 ? base64DecodeBuf(input) : Buffer.from(input, 'utf8');
let keyBuf = Buffer.from(key);
if (keyBuf.length < 16) keyBuf = Buffer.concat([keyBuf], 16);
let ivBuf = iv == null ? Buffer.alloc(0) : Buffer.from(iv);
if (iv != null && ivBuf.length < 8) ivBuf = Buffer.concat([ivBuf], 8);
const cipher = encrypt ? crypto.createCipheriv(mode, keyBuf, ivBuf) : crypto.createDecipheriv(mode, keyBuf, ivBuf);
const outBuf = Buffer.concat([cipher.update(inBuf), cipher.final()]);
return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
} catch (error) {
console.log(error);
}
return '';
}
// pkcs8 only
function rsa(mode, pub, encrypt, input, inBase64, key, outBase64) {
try {
let pd = undefined;
const keyObj = pub ? crypto.createPublicKey(key) : crypto.createPrivateKey(key);
if (!keyObj.asymmetricKeyDetails || !keyObj.asymmetricKeyDetails.modulusLength) return '';
const moduleLen = keyObj.asymmetricKeyDetails.modulusLength;
let blockLen = moduleLen / 8;
switch (mode) {
case 'RSA/PKCS1':
pd = crypto.constants.RSA_PKCS1_PADDING;
blockLen = encrypt ? blockLen - 11 : blockLen;
break;
case 'RSA/None/NoPadding':
pd = crypto.constants.RSA_NO_PADDING;
break;
case 'RSA/None/OAEPPadding':
pd = crypto.constants.RSA_PKCS1_OAEP_PADDING;
blockLen = encrypt ? blockLen - 41 : blockLen;
break;
default:
throw Error('not support ' + mode);
}
let inBuf = inBase64 ? base64DecodeBuf(input) : Buffer.from(input, 'utf8');
let bufIdx = 0;
let outBuf = Buffer.alloc(0);
while (bufIdx < inBuf.length) {
const bufEndIdx = Math.min(bufIdx + blockLen, inBuf.length);
let tmpInBuf = inBuf.subarray(bufIdx, bufEndIdx);
if (pd == crypto.constants.RSA_NO_PADDING) {
if (tmpInBuf.length < blockLen) {
tmpInBuf = Buffer.concat([Buffer.alloc(128 - tmpInBuf.length), tmpInBuf]);
}
}
let tmpBuf;
if (pub) {
tmpBuf = encrypt ? crypto.publicEncrypt({ key: keyObj, padding: pd }, tmpInBuf) : crypto.publicDecrypt({ key: keyObj, padding: pd }, tmpInBuf);
} else {
tmpBuf = encrypt ? crypto.privateEncrypt({ key: keyObj, padding: pd }, tmpInBuf) : crypto.privateDecrypt({ key: keyObj, padding: pd }, tmpInBuf);
}
bufIdx = bufEndIdx;
outBuf = Buffer.concat([outBuf, tmpBuf]);
}
return outBase64 ? base64EncodeBuf(outBuf) : outBuf.toString('utf8');
} catch (error) {
console.log(error);
}
return '';
}
var charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
function randStr(len, withNum) {
var _str = '';
let containsNum = withNum === undefined ? true : withNum;
for (var i = 0; i < len; i++) {
let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
_str += charStr[idx];
}
return _str;
}
globalThis.local = {
get: async function (storage, key) {
return localGet(storage, key);
},
set: async function (storage, key, val) {
localSet(storage, key, val);
},
};
globalThis.md5X = md5;
globalThis.rsaX = rsa;
globalThis.aesX = aes;
globalThis.desX = des;
globalThis.req = request;
globalThis.url2Proxy = async function (type, url, headers) {
let hd = Object.keys(headers).length == 0 ? '_' : encodeURIComponent(JSON.stringify(headers));
let uri = new Uri(url);
let path = uri.path();
path = path.substring(path.lastIndexOf('/'));
let ext = path.indexOf('.') >= 0 ? path.substring(path.indexOf('.')) : '.bin';
return 'http://127.0.0.1:13333/up/' + randStr(6) + '/' + type + '/' + hd + '/' + encodeURIComponent(url) + '/' + ext;
};
globalThis.js2Proxy = async function (dynamic, siteType, site, url, headers) {
let hd = Object.keys(headers).length == 0 ? '_' : encodeURIComponent(JSON.stringify(headers));
return (dynamic ? 'js2p://_WEB_/' : 'http://127.0.0.1:13333/jp/') + randStr(6) + '/' + siteType + '/' + site + '/' + hd + '/' + encodeURIComponent(url);
};
export default {};

View File

@ -0,0 +1,11 @@
## Standalone windows & macos sniffer server base on electron.
`npm install`
`npm run start`
`curl http://127.0.0.1:8887/?url=https://v.qq.com/x/page/i3038urj2mt.html`
`curl http://127.0.0.1:8887/?url=http://www.mgtv.com/v/1/290346/f/3664551.html`
`curl http://127.0.0.1:8887/?url=https://555dy.cc/vodplay/414521-1-1.html`

View File

@ -0,0 +1,43 @@
<html>
<script src="./jquery.min.js"></script>
<body>
<input type="text" id="port" value="8887" />
<button id="start" onclick="start()">Start</button>
<button id="stop" onclick="stop()">Stop</button>
</body>
<script>
msg_center.on((event, msg) => {
console.log(msg);
switch (msg.code) {
case 100:
$('#port')[0].value = msg.cfg.port;
break;
case 200:
$('#start').hide();
$('#stop').show();
break;
case 201:
$('#start').show();
$('#stop').hide();
break;
default:
break;
}
});
function start() {
const port = $('#port')[0].value;
msg_center.send({ code: 200, cfg: { port: port } });
}
function stop() {
msg_center.send({ code: 201 });
}
$('#start').show();
$('#stop').hide();
msg_center.send({ code: 100 });
</script>
</html>

View File

@ -0,0 +1,8 @@
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('msg_center', {
send: (...args) => ipcRenderer.send('msg', ...args),
on: (fn) => {
ipcRenderer.on('msg', (event, ...args) => fn(event, ...args));
},
});

View File

@ -0,0 +1,182 @@
const os = require('os');
const { app, session, BrowserWindow, ipcMain } = require('electron');
const pie = require('puppeteer-in-electron');
const puppeteer = require('puppeteer-core');
const http = require('http');
const Store = require('electron-store');
const store = new Store();
const urlRegex = 'http((?!http).){12,}?\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)\\?.*|http((?!http).){12,}\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)|http((?!http).)*?video/tos*';
async function trySniffer(url) {
const promise = new Promise(async (resolve, reject) => {
try {
let timeout = setTimeout(() => {
timeout = null;
resolve({ code: 500 });
page.close();
}, 15000);
const browser = await pie.connect(app, puppeteer);
const window = new BrowserWindow({
show: false,
});
// window.webContents.openDevTools();
const page = await pie.getPage(browser, window);
await page.setRequestInterception(true);
page.on('request', (req) => {
if (!timeout) req.abort().catch((err) => console.error(err));
var reqUrl = req.url();
if (reqUrl.match(urlRegex)) {
if (reqUrl.indexOf('url=http') < 0 && reqUrl.indexOf('v=http') < 0 && reqUrl.indexOf('.css') < 0 && reqUrl.indexOf('.html') < 0) {
console.log(req.headers());
console.log(reqUrl);
const headers = req.headers();
const header = {};
if (headers['referer']) header['referer'] = headers['referer'];
if (headers['user-agent']) header['user-agent'] = headers['user-agent'];
resolve({ code: 200, url: reqUrl, header: header });
req.abort().catch((err) => console.error(err));
clearTimeout(timeout);
timeout = null;
page.close();
return;
}
}
if (req.isInterceptResolutionHandled()) return;
if (req.resourceType() == 'image') req.abort().catch((err) => console.error(err));
else req.continue().catch((err) => console.error(err));
});
await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1');
await page.goto(url).catch((err) => {});
} catch (e) {
console.error(e);
resolve({ code: 500 });
}
});
return promise;
}
pie.initialize(app);
let httpServer = null;
const httpServerSockets = new Set();
const createMain = async () => {
// await session.defaultSession.clearCache();
const mainWindow = new BrowserWindow({
show: false,
width: 480,
resizable: false,
height: 300,
webPreferences: {
preload: __dirname + '/config.js',
},
});
mainWindow.removeMenu();
const defaultPort = 8889;
function startServer() {
if (httpServer) {
return;
}
httpServerSockets.clear();
const requestListener = async function (req, res) {
if (!req.url.startsWith('/?url=')) {
res.writeHead(500);
res.end('Url must /?url=http*****');
return;
}
const sniffUrl = req.url.substring(6).trim();
const result = await trySniffer(sniffUrl);
res.writeHead(200);
res.end(JSON.stringify(result));
};
httpServer = http.createServer(requestListener);
const port = store.get('port', defaultPort);
store.set('port', port);
httpServer.on('error', (e) => {
httpServer = null;
mainWindow.webContents.send('msg', {
code: 201,
});
});
httpServer.on('connection', (socket) => {
httpServerSockets.add(socket);
httpServer.once('close', () => {
httpServerSockets.delete(socket);
});
});
httpServer.listen(port, '0.0.0.0', () => {
console.log(`Server is running on`);
console.log(`\thttp://127.0.0.1:${port}`);
const interfaces = os.networkInterfaces();
for (let intf in interfaces) {
for (let i in interfaces[intf]) {
let address = interfaces[intf][i];
if (address.family === 'IPv4' && !address.internal) {
console.log(`\thttp://${address.address}:${port}`);
}
}
}
mainWindow.webContents.send('msg', {
code: 200,
});
});
}
function stopServer() {
if (httpServer) {
for (const socket of httpServerSockets) {
socket.destroy();
httpServerSockets.delete(socket);
}
httpServer.close();
httpServerSockets.clear();
httpServer = null;
}
mainWindow.webContents.send('msg', {
code: 201,
});
}
// mainWindow.webContents.openDevTools();
ipcMain.on('msg', async (event, msg) => {
switch (msg.code) {
case 100: {
const port = store.get('port', defaultPort);
mainWindow.webContents.send('msg', {
code: 100,
cfg: {
port: port,
},
});
startServer();
break;
}
case 200: {
const port = msg.cfg.port;
store.set('port', port);
startServer();
break;
}
case 201:
stopServer();
break;
default:
break;
}
console.log(msg);
});
await mainWindow.loadFile(__dirname + '/config.html');
mainWindow.show();
};
app.whenReady().then(() => {
createMain();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});

2
JN/EXT/OPENJS/sniffer/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2893
JN/EXT/OPENJS/sniffer/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
{
"name": "sniffer",
"version": "1.0.0",
"description": "CatVodeOpen sniffer",
"main": "index.js",
"scripts": {
"start": "electron index.js"
},
"author": "Simon",
"license": "ISC",
"devDependencies": {},
"build": {
"win": {
"target": "dir",
"icon": "./app_icon.ico"
}
},
"dependencies": {
"electron": "^21.2.2",
"puppeteer-core": "^19.2.2",
"puppeteer-in-electron": "^3.0.5",
"electron-store": "^8.1.0"
}
}