added openjs
This commit is contained in:
parent
bf76afc6f4
commit
e045a91416
34
JN/EXT/OPENJS/README.md
Normal file
34
JN/EXT/OPENJS/README.md
Normal 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`
|
9
JN/EXT/OPENJS/open/README.md
Normal file
9
JN/EXT/OPENJS/open/README.md
Normal 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.**
|
8
JN/EXT/OPENJS/open/app.js
Normal file
8
JN/EXT/OPENJS/open/app.js
Normal file
@ -0,0 +1,8 @@
|
||||
function __jsEvalReturn() {
|
||||
return {
|
||||
isVideoFormat: function (url) {
|
||||
return !0;
|
||||
},
|
||||
};
|
||||
}
|
||||
export { __jsEvalReturn };
|
61
JN/EXT/OPENJS/open/build.js
Normal file
61
JN/EXT/OPENJS/open/build.js
Normal 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');
|
70
JN/EXT/OPENJS/open/config_open.json
Normal file
70
JN/EXT/OPENJS/open/config_open.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -1,166 +1,166 @@
|
||||
import { Crypto, load, _, jinja2 } from './lib/cat.js';
|
||||
|
||||
let key = 'duboku';
|
||||
let url = 'https://u.duboku.io';
|
||||
let siteKey = '';
|
||||
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';
|
||||
|
||||
async function request(reqUrl, agentSp) {
|
||||
let res = await req(reqUrl, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'User-Agent': agentSp || UA,
|
||||
'Referer': url
|
||||
},
|
||||
});
|
||||
return res.content;
|
||||
}
|
||||
|
||||
// cfg = {skey: siteKey, ext: extend}
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
const html = await request(url);
|
||||
const $ = load(html);
|
||||
const class_parse = $('ul.nav-list > li > a[href*=vodtype]');
|
||||
let classes = [];
|
||||
classes = _.map(class_parse, (cls) => {
|
||||
let typeId = cls.attribs['href'];
|
||||
typeId = typeId.substring(typeId.lastIndexOf('/') + 1).replace('.html','');
|
||||
return {
|
||||
type_id: typeId,
|
||||
type_name: cls.children[0].data,
|
||||
};
|
||||
});
|
||||
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"}]}],
|
||||
"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"}]}],
|
||||
"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"}]}],
|
||||
"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"}]}],
|
||||
"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({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
const link = url + '/vodshow/2--hits---------.html';
|
||||
const html = await request(link);
|
||||
const $ = load(html);
|
||||
const items = $('div.myui-panel_bd > ul.myui-vodlist > li');
|
||||
let videos = _.map(items, (item) => {
|
||||
const it = $(item).find('a:first')[0];
|
||||
const remarks = $($(item).find('span.pic-text')[0]).text().trim();
|
||||
return {
|
||||
vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'),
|
||||
vod_name: it.attribs.title,
|
||||
vod_pic: it.attribs['data-original'],
|
||||
vod_remarks: remarks || '',
|
||||
};
|
||||
});
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
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 html = await request(link);
|
||||
const $ = load(html);
|
||||
const items = $('div.myui-panel_bd > ul.myui-vodlist > li');
|
||||
let videos = _.map(items, (item) => {
|
||||
const it = $(item).find('a:first')[0];
|
||||
const remarks = $($(item).find('span.pic-text')[0]).text().trim();
|
||||
return {
|
||||
vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'),
|
||||
vod_name: it.attribs.title,
|
||||
vod_pic: it.attribs['data-original'],
|
||||
vod_remarks: remarks || '',
|
||||
};
|
||||
});
|
||||
const hasMore = $('ul.myui-page > li > a:contains(下一页)').length > 0;
|
||||
const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg);
|
||||
return JSON.stringify({
|
||||
page: parseInt(pg),
|
||||
pagecount: pgCount,
|
||||
limit: 24,
|
||||
total: 24 * pgCount,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const html = await request(url + '/voddetail/' + id + '.html');
|
||||
const $ = load(html);
|
||||
let vod = {
|
||||
vod_id: id,
|
||||
vod_name: $('h1:first').text().trim(),
|
||||
vod_type: $('.myui-content__detail p:first a').text(),
|
||||
vod_actor: $('.myui-content__detail p:nth-child(5)').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_remarks :$('#rating:first span').text().replace(/\s{2,}/g, ' '),
|
||||
vod_content: $('span.data').text().trim(),
|
||||
};
|
||||
const playlist = _.map($('ul.sort-list > li > a'), (it) => {
|
||||
return it.children[0].data + '$' + it.attribs.href.replace(/\/vodplay\/(.*).html/g, '$1');
|
||||
});
|
||||
vod.vod_play_from = key;
|
||||
vod.vod_play_url = playlist.join('#');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
const link = url + '/vodplay/' + id + '.html';
|
||||
const html = await request(link);
|
||||
const $ = load(html);
|
||||
const js = JSON.parse($('script:contains(player_)').html().replace('var player_data=',''));
|
||||
const playUrl = js.url.replace('index.m3u8','hls\/index.m3u8');
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: playUrl,
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, quick) {
|
||||
let data = JSON.parse(await request(url + '/index.php/ajax/suggest?mid=1&wd=' + wd)).list;
|
||||
let videos = [];
|
||||
for (const vod of data) {
|
||||
videos.push({
|
||||
vod_id: vod.id,
|
||||
vod_name: vod.name,
|
||||
vod_pic: vod.pic,
|
||||
vod_remarks: '',
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
};
|
||||
import { Crypto, load, _, jinja2 } from './lib/cat.js';
|
||||
|
||||
let key = 'duboku';
|
||||
let url = 'https://u.duboku.io';
|
||||
let siteKey = '';
|
||||
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';
|
||||
|
||||
async function request(reqUrl, agentSp) {
|
||||
let res = await req(reqUrl, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'User-Agent': agentSp || UA,
|
||||
'Referer': url
|
||||
},
|
||||
});
|
||||
return res.content;
|
||||
}
|
||||
|
||||
// cfg = {skey: siteKey, ext: extend}
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
const html = await request(url);
|
||||
const $ = load(html);
|
||||
const class_parse = $('ul.nav-list > li > a[href*=vodtype]');
|
||||
let classes = [];
|
||||
classes = _.map(class_parse, (cls) => {
|
||||
let typeId = cls.attribs['href'];
|
||||
typeId = typeId.substring(typeId.lastIndexOf('/') + 1).replace('.html','');
|
||||
return {
|
||||
type_id: typeId,
|
||||
type_name: cls.children[0].data,
|
||||
};
|
||||
});
|
||||
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"}]}],
|
||||
"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"}]}],
|
||||
"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"}]}],
|
||||
"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"}]}],
|
||||
"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({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
const link = url + '/vodshow/2--hits---------.html';
|
||||
const html = await request(link);
|
||||
const $ = load(html);
|
||||
const items = $('div.myui-panel_bd > ul.myui-vodlist > li');
|
||||
let videos = _.map(items, (item) => {
|
||||
const it = $(item).find('a:first')[0];
|
||||
const remarks = $($(item).find('span.pic-text')[0]).text().trim();
|
||||
return {
|
||||
vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'),
|
||||
vod_name: it.attribs.title,
|
||||
vod_pic: it.attribs['data-original'],
|
||||
vod_remarks: remarks || '',
|
||||
};
|
||||
});
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
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 html = await request(link);
|
||||
const $ = load(html);
|
||||
const items = $('div.myui-panel_bd > ul.myui-vodlist > li');
|
||||
let videos = _.map(items, (item) => {
|
||||
const it = $(item).find('a:first')[0];
|
||||
const remarks = $($(item).find('span.pic-text')[0]).text().trim();
|
||||
return {
|
||||
vod_id: it.attribs.href.replace(/.*?\/voddetail\/(.*).html/g, '$1'),
|
||||
vod_name: it.attribs.title,
|
||||
vod_pic: it.attribs['data-original'],
|
||||
vod_remarks: remarks || '',
|
||||
};
|
||||
});
|
||||
const hasMore = $('ul.myui-page > li > a:contains(下一页)').length > 0;
|
||||
const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg);
|
||||
return JSON.stringify({
|
||||
page: parseInt(pg),
|
||||
pagecount: pgCount,
|
||||
limit: 24,
|
||||
total: 24 * pgCount,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const html = await request(url + '/voddetail/' + id + '.html');
|
||||
const $ = load(html);
|
||||
let vod = {
|
||||
vod_id: id,
|
||||
vod_name: $('h1:first').text().trim(),
|
||||
vod_type: $('.myui-content__detail p:first a').text(),
|
||||
vod_actor: $('.myui-content__detail p:nth-child(5)').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_remarks :$('#rating:first span').text().replace(/\s{2,}/g, ' '),
|
||||
vod_content: $('span.data').text().trim(),
|
||||
};
|
||||
const playlist = _.map($('ul.sort-list > li > a'), (it) => {
|
||||
return it.children[0].data + '$' + it.attribs.href.replace(/\/vodplay\/(.*).html/g, '$1');
|
||||
});
|
||||
vod.vod_play_from = key;
|
||||
vod.vod_play_url = playlist.join('#');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
const link = url + '/vodplay/' + id + '.html';
|
||||
const html = await request(link);
|
||||
const $ = load(html);
|
||||
const js = JSON.parse($('script:contains(player_)').html().replace('var player_data=',''));
|
||||
const playUrl = js.url.replace('index.m3u8','hls\/index.m3u8');
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: playUrl,
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, quick) {
|
||||
let data = JSON.parse(await request(url + '/index.php/ajax/suggest?mid=1&wd=' + wd)).list;
|
||||
let videos = [];
|
||||
for (const vod of data) {
|
||||
videos.push({
|
||||
vod_id: vod.id,
|
||||
vod_name: vod.name,
|
||||
vod_pic: vod.pic,
|
||||
vod_remarks: '',
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
};
|
||||
}
|
@ -1,203 +1,203 @@
|
||||
import { Crypto, load, _ } from './lib/cat.js';
|
||||
|
||||
let key = 'ikanbot';
|
||||
let url = 'https://www.ikanbot.com';
|
||||
let siteKey = '';
|
||||
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';
|
||||
|
||||
async function request(reqUrl, agentSp) {
|
||||
let res = await req(reqUrl, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'User-Agent': agentSp || UA,
|
||||
},
|
||||
});
|
||||
return res.content;
|
||||
}
|
||||
|
||||
// cfg = {skey: siteKey, ext: extend}
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
}
|
||||
|
||||
function getClass($) {
|
||||
const nav = $('ul.nav-pills:eq(1) > li > a');
|
||||
let tags = {
|
||||
key: 'tag',
|
||||
name: '标签',
|
||||
value: _.map(nav, (n) => {
|
||||
return { n: n.children[0].data, v: n.attribs.href };
|
||||
}),
|
||||
};
|
||||
tags['init'] = tags.value[0].v;
|
||||
const title = $('title:first').text().split('-')[0].substring(2);
|
||||
return { cls: { type_id: tags.value[0].v, type_name: title }, tags: [tags] };
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
let classes = [];
|
||||
let filterObj = {};
|
||||
for (const cate of ['/hot/index-movie-热门.html', '/hot/index-tv-热门.html']) {
|
||||
const html = await request(url + cate);
|
||||
const $ = load(html);
|
||||
const { cls, tags } = getClass($);
|
||||
classes.push(cls);
|
||||
filterObj[cls.type_id] = tags;
|
||||
}
|
||||
return JSON.stringify({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
return '{}';
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
if (pg <= 0) pg = 1;
|
||||
const link = url + (extend.tag || tid).replace('.html', pg > 1 ? `-p-${pg}.html` : '.html');
|
||||
const html = await request(link);
|
||||
const $ = load(html);
|
||||
const items = $('div.v-list a.item');
|
||||
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
|
||||
let videos = _.map(items, (item) => {
|
||||
const img = $(item).find('img:first')[0];
|
||||
return {
|
||||
vod_id: item.attribs.href,
|
||||
vod_name: img.attribs.alt,
|
||||
vod_pic: jsBase + base64Encode(img.attribs['data-src']),
|
||||
vod_remarks: '',
|
||||
};
|
||||
});
|
||||
const hasMore = $('div.page-more > a:contains(下一页)').length > 0;
|
||||
const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg);
|
||||
return JSON.stringify({
|
||||
page: parseInt(pg),
|
||||
pagecount: pgCount,
|
||||
limit: 24,
|
||||
total: 24 * pgCount,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const html = await request(url + id);
|
||||
const $ = load(html);
|
||||
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
|
||||
const detail = $('div.detail > .meta');
|
||||
let vod = {
|
||||
vod_id: id,
|
||||
vod_pic: jsBase + base64Encode($('div.item-root > img')[0].attribs['data-src']),
|
||||
vod_remarks: '',
|
||||
};
|
||||
for (const info of detail) {
|
||||
if ($(info).hasClass('title')) {
|
||||
vod.vod_name = info.children[0].data;
|
||||
} else if ($(info).hasClass('year')) {
|
||||
vod.vod_area = info.children[0].data;
|
||||
} else if ($(info).hasClass('country')) {
|
||||
vod.vod_area = info.children[0].data;
|
||||
} else if ($(info).hasClass('celebrity')) {
|
||||
vod.vod_actor = info.children[0].data;
|
||||
}
|
||||
}
|
||||
|
||||
const res = await req(url + '/api/getResN?videoId=' + id.substring(id.lastIndexOf('/') + 1) + '&mtype=2', {
|
||||
headers: {
|
||||
Referer: url,
|
||||
'User-Agent': UA,
|
||||
},
|
||||
});
|
||||
const list = JSON.parse(res.content).data.list;
|
||||
let playlist = {};
|
||||
for (const l of list) {
|
||||
const flagData = JSON.parse(l.resData);
|
||||
for (const f of flagData) {
|
||||
const from = f.flag;
|
||||
const urls = f.url;
|
||||
if (!from || !urls) continue;
|
||||
if (playlist[from]) continue;
|
||||
playlist[from] = urls;
|
||||
}
|
||||
}
|
||||
vod.vod_play_from = _.keys(playlist).join('$$$');
|
||||
vod.vod_play_url = _.values(playlist).join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
function base64Encode(text) {
|
||||
return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text));
|
||||
}
|
||||
|
||||
function base64Decode(text) {
|
||||
return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
|
||||
}
|
||||
|
||||
async function proxy(segments, headers) {
|
||||
let what = segments[0];
|
||||
let url = base64Decode(segments[1]);
|
||||
if (what == 'img') {
|
||||
var resp = await req(url, {
|
||||
buffer: 2,
|
||||
headers: {
|
||||
Referer: url,
|
||||
'User-Agent': UA,
|
||||
},
|
||||
});
|
||||
return JSON.stringify({
|
||||
code: resp.code,
|
||||
buffer: 2,
|
||||
content: resp.content,
|
||||
headers: resp.headers,
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
code: 500,
|
||||
content: '',
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: id,
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, quick) {
|
||||
const html = await request(url + '/search?q=' + wd);
|
||||
const $ = load(html);
|
||||
const items = $('div.media > div.media-left > a');
|
||||
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
|
||||
let videos = _.map(items, (item) => {
|
||||
const img = $(item).find('img:first')[0];
|
||||
return {
|
||||
vod_id: item.attribs.href,
|
||||
vod_name: img.attribs.alt,
|
||||
vod_pic: jsBase + base64Encode(img.attribs['data-src']),
|
||||
vod_remarks: '',
|
||||
};
|
||||
});
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
proxy: proxy,
|
||||
search: search,
|
||||
};
|
||||
}
|
||||
import { Crypto, load, _ } from './lib/cat.js';
|
||||
|
||||
let key = 'ikanbot';
|
||||
let url = 'https://www.ikanbot.com';
|
||||
let siteKey = '';
|
||||
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';
|
||||
|
||||
async function request(reqUrl, agentSp) {
|
||||
let res = await req(reqUrl, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
'User-Agent': agentSp || UA,
|
||||
},
|
||||
});
|
||||
return res.content;
|
||||
}
|
||||
|
||||
// cfg = {skey: siteKey, ext: extend}
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
}
|
||||
|
||||
function getClass($) {
|
||||
const nav = $('ul.nav-pills:eq(1) > li > a');
|
||||
let tags = {
|
||||
key: 'tag',
|
||||
name: '标签',
|
||||
value: _.map(nav, (n) => {
|
||||
return { n: n.children[0].data, v: n.attribs.href };
|
||||
}),
|
||||
};
|
||||
tags['init'] = tags.value[0].v;
|
||||
const title = $('title:first').text().split('-')[0].substring(2);
|
||||
return { cls: { type_id: tags.value[0].v, type_name: title }, tags: [tags] };
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
let classes = [];
|
||||
let filterObj = {};
|
||||
for (const cate of ['/hot/index-movie-热门.html', '/hot/index-tv-热门.html']) {
|
||||
const html = await request(url + cate);
|
||||
const $ = load(html);
|
||||
const { cls, tags } = getClass($);
|
||||
classes.push(cls);
|
||||
filterObj[cls.type_id] = tags;
|
||||
}
|
||||
return JSON.stringify({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
return '{}';
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
if (pg <= 0) pg = 1;
|
||||
const link = url + (extend.tag || tid).replace('.html', pg > 1 ? `-p-${pg}.html` : '.html');
|
||||
const html = await request(link);
|
||||
const $ = load(html);
|
||||
const items = $('div.v-list a.item');
|
||||
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
|
||||
let videos = _.map(items, (item) => {
|
||||
const img = $(item).find('img:first')[0];
|
||||
return {
|
||||
vod_id: item.attribs.href,
|
||||
vod_name: img.attribs.alt,
|
||||
vod_pic: jsBase + base64Encode(img.attribs['data-src']),
|
||||
vod_remarks: '',
|
||||
};
|
||||
});
|
||||
const hasMore = $('div.page-more > a:contains(下一页)').length > 0;
|
||||
const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg);
|
||||
return JSON.stringify({
|
||||
page: parseInt(pg),
|
||||
pagecount: pgCount,
|
||||
limit: 24,
|
||||
total: 24 * pgCount,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const html = await request(url + id);
|
||||
const $ = load(html);
|
||||
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
|
||||
const detail = $('div.detail > .meta');
|
||||
let vod = {
|
||||
vod_id: id,
|
||||
vod_pic: jsBase + base64Encode($('div.item-root > img')[0].attribs['data-src']),
|
||||
vod_remarks: '',
|
||||
};
|
||||
for (const info of detail) {
|
||||
if ($(info).hasClass('title')) {
|
||||
vod.vod_name = info.children[0].data;
|
||||
} else if ($(info).hasClass('year')) {
|
||||
vod.vod_area = info.children[0].data;
|
||||
} else if ($(info).hasClass('country')) {
|
||||
vod.vod_area = info.children[0].data;
|
||||
} else if ($(info).hasClass('celebrity')) {
|
||||
vod.vod_actor = info.children[0].data;
|
||||
}
|
||||
}
|
||||
|
||||
const res = await req(url + '/api/getResN?videoId=' + id.substring(id.lastIndexOf('/') + 1) + '&mtype=2', {
|
||||
headers: {
|
||||
Referer: url,
|
||||
'User-Agent': UA,
|
||||
},
|
||||
});
|
||||
const list = JSON.parse(res.content).data.list;
|
||||
let playlist = {};
|
||||
for (const l of list) {
|
||||
const flagData = JSON.parse(l.resData);
|
||||
for (const f of flagData) {
|
||||
const from = f.flag;
|
||||
const urls = f.url;
|
||||
if (!from || !urls) continue;
|
||||
if (playlist[from]) continue;
|
||||
playlist[from] = urls;
|
||||
}
|
||||
}
|
||||
vod.vod_play_from = _.keys(playlist).join('$$$');
|
||||
vod.vod_play_url = _.values(playlist).join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
function base64Encode(text) {
|
||||
return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text));
|
||||
}
|
||||
|
||||
function base64Decode(text) {
|
||||
return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
|
||||
}
|
||||
|
||||
async function proxy(segments, headers) {
|
||||
let what = segments[0];
|
||||
let url = base64Decode(segments[1]);
|
||||
if (what == 'img') {
|
||||
var resp = await req(url, {
|
||||
buffer: 2,
|
||||
headers: {
|
||||
Referer: url,
|
||||
'User-Agent': UA,
|
||||
},
|
||||
});
|
||||
return JSON.stringify({
|
||||
code: resp.code,
|
||||
buffer: 2,
|
||||
content: resp.content,
|
||||
headers: resp.headers,
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
code: 500,
|
||||
content: '',
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: id,
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, quick) {
|
||||
const html = await request(url + '/search?q=' + wd);
|
||||
const $ = load(html);
|
||||
const items = $('div.media > div.media-left > a');
|
||||
var jsBase = await js2Proxy(true, siteType, siteKey, 'img/', {});
|
||||
let videos = _.map(items, (item) => {
|
||||
const img = $(item).find('img:first')[0];
|
||||
return {
|
||||
vod_id: item.attribs.href,
|
||||
vod_name: img.attribs.alt,
|
||||
vod_pic: jsBase + base64Encode(img.attribs['data-src']),
|
||||
vod_remarks: '',
|
||||
};
|
||||
});
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
proxy: proxy,
|
||||
search: search,
|
||||
};
|
||||
}
|
@ -1,364 +1,364 @@
|
||||
import { Crypto, dayjs, jinja2, _ } from './lib/cat.js';
|
||||
|
||||
let key = 'kkys';
|
||||
let url = 'https://api1.baibaipei.com:8899';
|
||||
let device = {};
|
||||
let siteKey = '';
|
||||
let siteType = 0;
|
||||
|
||||
async function request(reqUrl, postData, agentSp, get) {
|
||||
let ts = dayjs().valueOf().toString();
|
||||
let rand = randStr(32);
|
||||
let sign = Crypto.MD5('abcdexxxdd2daklmn25129_' + ts + '_' + rand)
|
||||
.toString()
|
||||
.toLowerCase();
|
||||
let headers = {
|
||||
'user-agent': agentSp || device.ua,
|
||||
};
|
||||
if (reqUrl.includes('baibaipei')) {
|
||||
headers['device-id'] = device.id;
|
||||
headers['push-token'] = '';
|
||||
headers['sign'] = sign;
|
||||
headers['time'] = ts;
|
||||
headers['md5'] = rand;
|
||||
headers['version'] = '2.1.0';
|
||||
headers['system-model'] = device.model;
|
||||
headers['system-brand'] = device.brand;
|
||||
headers['system-version'] = device.release;
|
||||
}
|
||||
let res = await req(reqUrl, {
|
||||
method: get ? 'get' : 'post',
|
||||
headers: headers,
|
||||
data: postData || {},
|
||||
postType: get ? '' : 'form',
|
||||
});
|
||||
|
||||
let content = res.content;
|
||||
// console.log(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
var deviceKey = 'device';
|
||||
var deviceInfo = await local.get(key, deviceKey);
|
||||
if (deviceInfo.length > 0) {
|
||||
try {
|
||||
device = JSON.parse(deviceInfo);
|
||||
} catch (error) {}
|
||||
}
|
||||
if (_.isEmpty(device)) {
|
||||
device = randDevice();
|
||||
device.id = randStr(33).toLowerCase();
|
||||
device.ua = 'okhttp/4.1.0';
|
||||
await local.set(key, deviceKey, JSON.stringify(device));
|
||||
}
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
// await req('https://www.facebook.com', {});
|
||||
let data = JSON.parse(await request(url + '/api.php/Index/getTopVideoCategory')).data;
|
||||
let classes = [];
|
||||
let filterObj = {};
|
||||
for (const type of data) {
|
||||
let typeName = type.nav_name;
|
||||
if (typeName == '推荐') continue;
|
||||
let typeId = type.nav_type_id.toString();
|
||||
classes.push({
|
||||
type_id: typeId,
|
||||
type_name: typeName,
|
||||
});
|
||||
if (!filter) continue;
|
||||
try {
|
||||
let filterAll = [];
|
||||
let filterData = JSON.parse(await request(url + '/api.php/Video/getFilterType', { type: typeId })).data;
|
||||
for (let key of Object.keys(filterData)) {
|
||||
let itemValues = filterData[key];
|
||||
if (key === 'plot') key = 'class';
|
||||
let typeExtendName = '';
|
||||
switch (key) {
|
||||
case 'class':
|
||||
typeExtendName = '类型';
|
||||
break;
|
||||
case 'area':
|
||||
typeExtendName = '地区';
|
||||
break;
|
||||
case 'lang':
|
||||
typeExtendName = '语言';
|
||||
break;
|
||||
case 'year':
|
||||
typeExtendName = '年代';
|
||||
break;
|
||||
case 'sort':
|
||||
typeExtendName = '排序';
|
||||
break;
|
||||
}
|
||||
if (typeExtendName.length === 0) continue;
|
||||
let newTypeExtend = {
|
||||
key: key,
|
||||
name: typeExtendName,
|
||||
};
|
||||
let newTypeExtendKV = [];
|
||||
for (let j = 0; j < itemValues.length; j++) {
|
||||
const name = itemValues[j];
|
||||
let value = key === 'sort' ? j + '' : name === '全部' ? '0' : name;
|
||||
newTypeExtendKV.push({ n: name, v: value });
|
||||
}
|
||||
newTypeExtend['init'] = key === 'sort' ? '1' : newTypeExtendKV[0]['v'];
|
||||
newTypeExtend.value = newTypeExtendKV;
|
||||
filterAll.push(newTypeExtend);
|
||||
}
|
||||
if (!_.isEmpty(filterAll)) {
|
||||
filterObj[typeId] = filterAll;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
// console.log(await homeVod());
|
||||
// console.log(classes);
|
||||
// console.log(filterObj);
|
||||
return JSON.stringify({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
let jsonArray = JSON.parse(await request(url + '/api.php/Index/getHomePage', { type: 1, p: 1 })).data.video;
|
||||
let videos = [];
|
||||
for (const item of jsonArray) {
|
||||
if (item.title.styleType !== 0) continue;
|
||||
for (const vObj of item.list) {
|
||||
videos.push({
|
||||
vod_id: vObj.vod_id,
|
||||
vod_name: vObj.vod_name,
|
||||
vod_pic: vObj.vod_pic,
|
||||
vod_remarks: vObj.vod_remarks || vObj.vod_score || '',
|
||||
});
|
||||
}
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
if (pg == 0) pg = 1;
|
||||
let reqUrl = url + '/api.php/Video/getFilterVideoList';
|
||||
var formData = JSON.parse(
|
||||
jinja2(
|
||||
`{
|
||||
"type": "{{tid}}",
|
||||
"p": "{{pg}}",
|
||||
"area": "{{ext.area|default(0)}}",
|
||||
"year": "{{ext.year|default(0)}}",
|
||||
"sort": "{{ext.sort|default(0)}}",
|
||||
"class": "{{ext.class|default(0)}}"
|
||||
}`,
|
||||
{ ext: extend, tid: tid, pg: pg }
|
||||
)
|
||||
);
|
||||
console.log(formData);
|
||||
let data = JSON.parse(await request(reqUrl, formData)).data;
|
||||
let videos = [];
|
||||
for (const vod of data.data) {
|
||||
videos.push({
|
||||
vod_id: vod.vod_id,
|
||||
vod_name: vod.vod_name,
|
||||
vod_pic: vod.vod_pic,
|
||||
vod_remarks: vod.vod_remarks || vod.vod_score || '',
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
page: parseInt(data.current_page),
|
||||
pagecount: parseInt(data.last_page),
|
||||
limit: parseInt(data.per_page),
|
||||
total: parseInt(data.total),
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
let data = JSON.parse(await request(url + '/api.php/Video/getVideoInfo', { video_id: id })).data.video;
|
||||
let vod = {
|
||||
vod_id: data.vod_id,
|
||||
vod_name: data.vod_name,
|
||||
vod_pic: data.vod_pic,
|
||||
type_name: data.vod_class,
|
||||
vod_year: data.vod_year,
|
||||
vod_area: data.vod_area,
|
||||
vod_remarks: data.vod_remarks || '',
|
||||
vod_actor: data.vod_actor,
|
||||
vod_director: data.vod_director,
|
||||
vod_content: data.vod_content.trim(),
|
||||
};
|
||||
let playlist = {};
|
||||
for (const item of data.vod_play) {
|
||||
let from = item.playerForm;
|
||||
if (from === 'jp') continue;
|
||||
if (from === 'xg') continue;
|
||||
let urls = [];
|
||||
for (const u of item.url) {
|
||||
urls.push(formatPlayUrl(vod.vod_name, u.title) + '$' + u.play_url);
|
||||
}
|
||||
if (!playlist.hasOwnProperty(from) && urls.length > 0) {
|
||||
playlist[from] = urls;
|
||||
}
|
||||
}
|
||||
parse = data.parse || [];
|
||||
vod.vod_play_from = _.keys(playlist).join('$$$');
|
||||
let urls = _.values(playlist);
|
||||
let vod_play_url = [];
|
||||
for (const urlist of urls) {
|
||||
vod_play_url.push(urlist.join('#'));
|
||||
}
|
||||
vod.vod_play_url = vod_play_url.join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
var parse = [];
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
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 (parse.length > 0) {
|
||||
for (let index = 0; index < parse.length; index++) {
|
||||
try {
|
||||
const p = parse[index];
|
||||
let res = await req(p + id, {
|
||||
headers: { 'user-agent': 'okhttp/4.1.0' },
|
||||
});
|
||||
var result = jsonParse(id, JSON.parse(res.content));
|
||||
if (result.url) {
|
||||
result.parse = 0;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id.indexOf('jqq-') >= 0) {
|
||||
var jqqHeader = await request(url + '/jqqheader.json', null, null, true);
|
||||
var jqqHeaders = JSON.parse(jqqHeader);
|
||||
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 jqqInfo = JSON.parse(jxJqq.content);
|
||||
if (jqqInfo.data.playInfo.url) {
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
playUrl: '',
|
||||
url: jqqInfo.data.playInfo.url,
|
||||
});
|
||||
}
|
||||
}
|
||||
let res = await request(url + '/video.php', { url: id });
|
||||
var result = jsonParse(id, JSON.parse(res).data);
|
||||
if (result.url) {
|
||||
result.parse = 0;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
playUrl: '',
|
||||
url: id,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 videos = [];
|
||||
for (const vod of data.data) {
|
||||
videos.push({
|
||||
vod_id: vod.vod_id,
|
||||
vod_name: vod.vod_name,
|
||||
vod_pic: vod.vod_pic,
|
||||
vod_remarks: vod.vod_remarks || vod.vod_score || '',
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
function randDevice() {
|
||||
return {
|
||||
brand: 'Huawei',
|
||||
model: 'HUAWEI Mate 20',
|
||||
release: '10',
|
||||
buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
function formatPlayUrl(src, name) {
|
||||
return name
|
||||
.trim()
|
||||
.replaceAll(src, '')
|
||||
.replace(/<|>|《|》/g, '')
|
||||
.replace(/\$|#/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function jsonParse(input, json) {
|
||||
try {
|
||||
let url = json.url ?? '';
|
||||
if (url.startsWith('//')) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
if (!url.startsWith('http')) {
|
||||
return {};
|
||||
}
|
||||
let headers = json['headers'] || {};
|
||||
let ua = (json['user-agent'] || '').trim();
|
||||
if (ua.length > 0) {
|
||||
headers['User-Agent'] = ua;
|
||||
}
|
||||
let referer = (json['referer'] || '').trim();
|
||||
if (referer.length > 0) {
|
||||
headers['Referer'] = referer;
|
||||
}
|
||||
_.keys(headers).forEach((hk) => {
|
||||
if (!headers[hk]) delete headers[hk];
|
||||
});
|
||||
return {
|
||||
header: headers,
|
||||
url: url,
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
};
|
||||
}
|
||||
import { Crypto, dayjs, jinja2, _ } from './lib/cat.js';
|
||||
|
||||
let key = 'kkys';
|
||||
let url = 'https://api1.baibaipei.com:8899';
|
||||
let device = {};
|
||||
let siteKey = '';
|
||||
let siteType = 0;
|
||||
|
||||
async function request(reqUrl, postData, agentSp, get) {
|
||||
let ts = dayjs().valueOf().toString();
|
||||
let rand = randStr(32);
|
||||
let sign = Crypto.MD5('abcdexxxdd2daklmn25129_' + ts + '_' + rand)
|
||||
.toString()
|
||||
.toLowerCase();
|
||||
let headers = {
|
||||
'user-agent': agentSp || device.ua,
|
||||
};
|
||||
if (reqUrl.includes('baibaipei')) {
|
||||
headers['device-id'] = device.id;
|
||||
headers['push-token'] = '';
|
||||
headers['sign'] = sign;
|
||||
headers['time'] = ts;
|
||||
headers['md5'] = rand;
|
||||
headers['version'] = '2.1.0';
|
||||
headers['system-model'] = device.model;
|
||||
headers['system-brand'] = device.brand;
|
||||
headers['system-version'] = device.release;
|
||||
}
|
||||
let res = await req(reqUrl, {
|
||||
method: get ? 'get' : 'post',
|
||||
headers: headers,
|
||||
data: postData || {},
|
||||
postType: get ? '' : 'form',
|
||||
});
|
||||
|
||||
let content = res.content;
|
||||
// console.log(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
var deviceKey = 'device';
|
||||
var deviceInfo = await local.get(key, deviceKey);
|
||||
if (deviceInfo.length > 0) {
|
||||
try {
|
||||
device = JSON.parse(deviceInfo);
|
||||
} catch (error) {}
|
||||
}
|
||||
if (_.isEmpty(device)) {
|
||||
device = randDevice();
|
||||
device.id = randStr(33).toLowerCase();
|
||||
device.ua = 'okhttp/4.1.0';
|
||||
await local.set(key, deviceKey, JSON.stringify(device));
|
||||
}
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
// await req('https://www.facebook.com', {});
|
||||
let data = JSON.parse(await request(url + '/api.php/Index/getTopVideoCategory')).data;
|
||||
let classes = [];
|
||||
let filterObj = {};
|
||||
for (const type of data) {
|
||||
let typeName = type.nav_name;
|
||||
if (typeName == '推荐') continue;
|
||||
let typeId = type.nav_type_id.toString();
|
||||
classes.push({
|
||||
type_id: typeId,
|
||||
type_name: typeName,
|
||||
});
|
||||
if (!filter) continue;
|
||||
try {
|
||||
let filterAll = [];
|
||||
let filterData = JSON.parse(await request(url + '/api.php/Video/getFilterType', { type: typeId })).data;
|
||||
for (let key of Object.keys(filterData)) {
|
||||
let itemValues = filterData[key];
|
||||
if (key === 'plot') key = 'class';
|
||||
let typeExtendName = '';
|
||||
switch (key) {
|
||||
case 'class':
|
||||
typeExtendName = '类型';
|
||||
break;
|
||||
case 'area':
|
||||
typeExtendName = '地区';
|
||||
break;
|
||||
case 'lang':
|
||||
typeExtendName = '语言';
|
||||
break;
|
||||
case 'year':
|
||||
typeExtendName = '年代';
|
||||
break;
|
||||
case 'sort':
|
||||
typeExtendName = '排序';
|
||||
break;
|
||||
}
|
||||
if (typeExtendName.length === 0) continue;
|
||||
let newTypeExtend = {
|
||||
key: key,
|
||||
name: typeExtendName,
|
||||
};
|
||||
let newTypeExtendKV = [];
|
||||
for (let j = 0; j < itemValues.length; j++) {
|
||||
const name = itemValues[j];
|
||||
let value = key === 'sort' ? j + '' : name === '全部' ? '0' : name;
|
||||
newTypeExtendKV.push({ n: name, v: value });
|
||||
}
|
||||
newTypeExtend['init'] = key === 'sort' ? '1' : newTypeExtendKV[0]['v'];
|
||||
newTypeExtend.value = newTypeExtendKV;
|
||||
filterAll.push(newTypeExtend);
|
||||
}
|
||||
if (!_.isEmpty(filterAll)) {
|
||||
filterObj[typeId] = filterAll;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
// console.log(await homeVod());
|
||||
// console.log(classes);
|
||||
// console.log(filterObj);
|
||||
return JSON.stringify({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
let jsonArray = JSON.parse(await request(url + '/api.php/Index/getHomePage', { type: 1, p: 1 })).data.video;
|
||||
let videos = [];
|
||||
for (const item of jsonArray) {
|
||||
if (item.title.styleType !== 0) continue;
|
||||
for (const vObj of item.list) {
|
||||
videos.push({
|
||||
vod_id: vObj.vod_id,
|
||||
vod_name: vObj.vod_name,
|
||||
vod_pic: vObj.vod_pic,
|
||||
vod_remarks: vObj.vod_remarks || vObj.vod_score || '',
|
||||
});
|
||||
}
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
if (pg == 0) pg = 1;
|
||||
let reqUrl = url + '/api.php/Video/getFilterVideoList';
|
||||
var formData = JSON.parse(
|
||||
jinja2(
|
||||
`{
|
||||
"type": "{{tid}}",
|
||||
"p": "{{pg}}",
|
||||
"area": "{{ext.area|default(0)}}",
|
||||
"year": "{{ext.year|default(0)}}",
|
||||
"sort": "{{ext.sort|default(0)}}",
|
||||
"class": "{{ext.class|default(0)}}"
|
||||
}`,
|
||||
{ ext: extend, tid: tid, pg: pg }
|
||||
)
|
||||
);
|
||||
console.log(formData);
|
||||
let data = JSON.parse(await request(reqUrl, formData)).data;
|
||||
let videos = [];
|
||||
for (const vod of data.data) {
|
||||
videos.push({
|
||||
vod_id: vod.vod_id,
|
||||
vod_name: vod.vod_name,
|
||||
vod_pic: vod.vod_pic,
|
||||
vod_remarks: vod.vod_remarks || vod.vod_score || '',
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
page: parseInt(data.current_page),
|
||||
pagecount: parseInt(data.last_page),
|
||||
limit: parseInt(data.per_page),
|
||||
total: parseInt(data.total),
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
let data = JSON.parse(await request(url + '/api.php/Video/getVideoInfo', { video_id: id })).data.video;
|
||||
let vod = {
|
||||
vod_id: data.vod_id,
|
||||
vod_name: data.vod_name,
|
||||
vod_pic: data.vod_pic,
|
||||
type_name: data.vod_class,
|
||||
vod_year: data.vod_year,
|
||||
vod_area: data.vod_area,
|
||||
vod_remarks: data.vod_remarks || '',
|
||||
vod_actor: data.vod_actor,
|
||||
vod_director: data.vod_director,
|
||||
vod_content: data.vod_content.trim(),
|
||||
};
|
||||
let playlist = {};
|
||||
for (const item of data.vod_play) {
|
||||
let from = item.playerForm;
|
||||
if (from === 'jp') continue;
|
||||
if (from === 'xg') continue;
|
||||
let urls = [];
|
||||
for (const u of item.url) {
|
||||
urls.push(formatPlayUrl(vod.vod_name, u.title) + '$' + u.play_url);
|
||||
}
|
||||
if (!playlist.hasOwnProperty(from) && urls.length > 0) {
|
||||
playlist[from] = urls;
|
||||
}
|
||||
}
|
||||
parse = data.parse || [];
|
||||
vod.vod_play_from = _.keys(playlist).join('$$$');
|
||||
let urls = _.values(playlist);
|
||||
let vod_play_url = [];
|
||||
for (const urlist of urls) {
|
||||
vod_play_url.push(urlist.join('#'));
|
||||
}
|
||||
vod.vod_play_url = vod_play_url.join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
var parse = [];
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
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 (parse.length > 0) {
|
||||
for (let index = 0; index < parse.length; index++) {
|
||||
try {
|
||||
const p = parse[index];
|
||||
let res = await req(p + id, {
|
||||
headers: { 'user-agent': 'okhttp/4.1.0' },
|
||||
});
|
||||
var result = jsonParse(id, JSON.parse(res.content));
|
||||
if (result.url) {
|
||||
result.parse = 0;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id.indexOf('jqq-') >= 0) {
|
||||
var jqqHeader = await request(url + '/jqqheader.json', null, null, true);
|
||||
var jqqHeaders = JSON.parse(jqqHeader);
|
||||
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 jqqInfo = JSON.parse(jxJqq.content);
|
||||
if (jqqInfo.data.playInfo.url) {
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
playUrl: '',
|
||||
url: jqqInfo.data.playInfo.url,
|
||||
});
|
||||
}
|
||||
}
|
||||
let res = await request(url + '/video.php', { url: id });
|
||||
var result = jsonParse(id, JSON.parse(res).data);
|
||||
if (result.url) {
|
||||
result.parse = 0;
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
playUrl: '',
|
||||
url: id,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 videos = [];
|
||||
for (const vod of data.data) {
|
||||
videos.push({
|
||||
vod_id: vod.vod_id,
|
||||
vod_name: vod.vod_name,
|
||||
vod_pic: vod.vod_pic,
|
||||
vod_remarks: vod.vod_remarks || vod.vod_score || '',
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
function randDevice() {
|
||||
return {
|
||||
brand: 'Huawei',
|
||||
model: 'HUAWEI Mate 20',
|
||||
release: '10',
|
||||
buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
function formatPlayUrl(src, name) {
|
||||
return name
|
||||
.trim()
|
||||
.replaceAll(src, '')
|
||||
.replace(/<|>|《|》/g, '')
|
||||
.replace(/\$|#/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function jsonParse(input, json) {
|
||||
try {
|
||||
let url = json.url ?? '';
|
||||
if (url.startsWith('//')) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
if (!url.startsWith('http')) {
|
||||
return {};
|
||||
}
|
||||
let headers = json['headers'] || {};
|
||||
let ua = (json['user-agent'] || '').trim();
|
||||
if (ua.length > 0) {
|
||||
headers['User-Agent'] = ua;
|
||||
}
|
||||
let referer = (json['referer'] || '').trim();
|
||||
if (referer.length > 0) {
|
||||
headers['Referer'] = referer;
|
||||
}
|
||||
_.keys(headers).forEach((hk) => {
|
||||
if (!headers[hk]) delete headers[hk];
|
||||
});
|
||||
return {
|
||||
header: headers,
|
||||
url: url,
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
};
|
||||
}
|
@ -1,341 +1,341 @@
|
||||
import { Crypto, dayjs, jinja2, Uri, _ } from './lib/cat.js';
|
||||
|
||||
let key = 'kunyu77';
|
||||
let url = 'http://api.tyun77.cn';
|
||||
let device = {};
|
||||
let timeOffset = 0;
|
||||
let siteKey = '';
|
||||
let siteType = 0;
|
||||
|
||||
async function request(reqUrl, agentSp) {
|
||||
let sj = dayjs().unix() - timeOffset;
|
||||
let uri = new Uri(reqUrl);
|
||||
uri.addQueryParam('pcode', '010110005');
|
||||
uri.addQueryParam('version', '2.1.6');
|
||||
uri.addQueryParam('devid', device.id);
|
||||
uri.addQueryParam('package', 'com.sevenVideo.app.android');
|
||||
uri.addQueryParam('sys', 'android');
|
||||
uri.addQueryParam('sysver', device.release);
|
||||
uri.addQueryParam('brand', device.brand);
|
||||
uri.addQueryParam('model', device.model.replaceAll(' ', '_'));
|
||||
uri.addQueryParam('sj', sj);
|
||||
let keys = [];
|
||||
for (var i = 0; i < uri.queryPairs.length; i++) {
|
||||
keys.push(uri.queryPairs[i][0]);
|
||||
}
|
||||
keys = _.sortBy(keys, function (name) {
|
||||
return name;
|
||||
});
|
||||
let tkSrc = uri.path();
|
||||
for (let k of keys) {
|
||||
let v = uri.getQueryParamValue(k);
|
||||
v = encodeURIComponent(v);
|
||||
tkSrc += v;
|
||||
}
|
||||
tkSrc += sj;
|
||||
tkSrc += 'XSpeUFjJ';
|
||||
console.log(tkSrc);
|
||||
let tk = Crypto.MD5(tkSrc).toString().toLowerCase();
|
||||
console.log(tk);
|
||||
let header = {
|
||||
'user-agent': agentSp || 'okhttp/3.12.0',
|
||||
t: sj,
|
||||
TK: tk,
|
||||
};
|
||||
let res = await req(uri.toString(), {
|
||||
headers: header,
|
||||
});
|
||||
|
||||
let serverTime = res.headers.date; // dart all response header key is lowercase
|
||||
let content = res.content;
|
||||
let serverTimeS = dayjs(serverTime).unix();
|
||||
timeOffset = dayjs().unix() - serverTimeS;
|
||||
// console.log(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
var deviceKey = 'device';
|
||||
var deviceInfo = await local.get(key, deviceKey);
|
||||
if (deviceInfo.length > 0) {
|
||||
try {
|
||||
device = JSON.parse(deviceInfo);
|
||||
} catch (error) {}
|
||||
}
|
||||
if (_.isEmpty(device)) {
|
||||
device = randDevice();
|
||||
device.id = randStr(32).toLowerCase();
|
||||
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 request(url + '/api.php/provide/getDomain');
|
||||
await request(url + '/api.php/provide/config');
|
||||
await request(url + '/api.php/provide/checkUpgrade');
|
||||
await request(url + '/api.php/provide/channel');
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/filter')).data;
|
||||
let classes = [];
|
||||
let filterObj = {};
|
||||
let filterAll = [];
|
||||
for (const key in data) {
|
||||
classes.push({
|
||||
type_id: key,
|
||||
type_name: data[key][0].cat,
|
||||
});
|
||||
if (!filter) continue;
|
||||
try {
|
||||
let typeId = key.toString();
|
||||
if (_.isEmpty(filterAll)) {
|
||||
let filterData = JSON.parse(await request(url + '/api.php/provide/searchFilter?type_id=0&pagenum=1&pagesize=1')).data.conditions;
|
||||
// console.log(filterData);
|
||||
// 年份
|
||||
let year = {
|
||||
key: 'year',
|
||||
name: '年份',
|
||||
init: '',
|
||||
};
|
||||
let yearValues = [];
|
||||
yearValues.push({ n: '全部', v: '' });
|
||||
filterData.y.forEach((e) => {
|
||||
yearValues.push({ n: e.name, v: e.value });
|
||||
});
|
||||
year['value'] = yearValues;
|
||||
// 地区
|
||||
let area = {
|
||||
key: 'area',
|
||||
name: '地区',
|
||||
init: '',
|
||||
};
|
||||
let areaValues = [];
|
||||
areaValues.push({ n: '全部', v: '' });
|
||||
filterData.a.forEach((e) => {
|
||||
areaValues.push({ n: e.name, v: e.value });
|
||||
});
|
||||
area['value'] = areaValues;
|
||||
// 类型
|
||||
let type = {
|
||||
key: 'category',
|
||||
name: '类型',
|
||||
init: '',
|
||||
};
|
||||
let typeValues = [];
|
||||
typeValues.push({ n: '全部', v: '' });
|
||||
filterData.scat.forEach((e) => {
|
||||
typeValues.push({ n: e.name, v: e.value });
|
||||
});
|
||||
type['value'] = typeValues;
|
||||
|
||||
filterAll.push(year, area, type);
|
||||
}
|
||||
if (!_.isEmpty(filterAll)) {
|
||||
filterObj[typeId] = filterAll;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
// console.log(classes);
|
||||
// console.log(filterObj);
|
||||
return JSON.stringify({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/homeBlock?type_id=0')).data;
|
||||
let blocks = data.blocks;
|
||||
let videos = [];
|
||||
for (const block of blocks) {
|
||||
let name = block.block_name;
|
||||
if (name.indexOf('热播') >= 0) continue;
|
||||
let contents = block.contents;
|
||||
for (const content of contents) {
|
||||
videos.push({
|
||||
vod_id: content.id,
|
||||
vod_name: content.title,
|
||||
vod_pic: content.videoCover,
|
||||
vod_remarks: content.msg,
|
||||
});
|
||||
}
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
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 });
|
||||
let data = JSON.parse(await request(reqUrl)).data;
|
||||
let videos = [];
|
||||
for (const vod of data.result) {
|
||||
videos.push({
|
||||
vod_id: vod.id,
|
||||
vod_name: vod.title,
|
||||
vod_pic: vod.videoCover,
|
||||
vod_remarks: vod.msg,
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
page: parseInt(data.page),
|
||||
pagecount: data.pagesize,
|
||||
limit: 24,
|
||||
total: data.total,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/videoDetail?ids=' + id)).data;
|
||||
console.log(data);
|
||||
let vod = {
|
||||
vod_id: data.id,
|
||||
vod_name: data.videoName,
|
||||
vod_pic: data.videoCover,
|
||||
type_name: data.subCategory,
|
||||
vod_year: data.year,
|
||||
vod_area: data.area,
|
||||
vod_remarks: data.msg,
|
||||
vod_actor: data.actor,
|
||||
vod_director: data.director,
|
||||
vod_content: data.brief.trim(),
|
||||
};
|
||||
let episodes = JSON.parse(await request(url + '/api.php/provide/videoPlaylist?ids=' + id)).data.episodes;
|
||||
let playlist = {};
|
||||
for (const episode of episodes) {
|
||||
let playurls = episode.playurls;
|
||||
for (const playurl of playurls) {
|
||||
let from = playurl.playfrom;
|
||||
let t = formatPlayUrl(vod.vod_name, playurl.title);
|
||||
if (t.length == 0) t = playurl.title.trim();
|
||||
if (!playlist.hasOwnProperty(from)) {
|
||||
playlist[from] = [];
|
||||
}
|
||||
playlist[from].push(t + '$' + playurl.playurl);
|
||||
}
|
||||
}
|
||||
vod.vod_play_from = _.keys(playlist).join('$$$');
|
||||
let urls = _.values(playlist);
|
||||
let vod_play_url = [];
|
||||
for (const urlist of urls) {
|
||||
vod_play_url.push(urlist.join('#'));
|
||||
}
|
||||
vod.vod_play_url = vod_play_url.join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
try {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/parserUrl?url=' + id + '&retryNum=0')).data;
|
||||
let playHeader = data.playHeader;
|
||||
let jxUrl = data.url;
|
||||
let res = await req(jxUrl, {
|
||||
headers: {
|
||||
'user-agent': 'okhttp/3.12.0',
|
||||
},
|
||||
});
|
||||
let result = jsonParse(id, JSON.parse(res.content));
|
||||
result['parse'] = 0;
|
||||
if (playHeader) {
|
||||
result.header = _.merge(result.header, playHeader);
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
} catch (e) {
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 videos = [];
|
||||
for (const vod of data) {
|
||||
videos.push({
|
||||
vod_id: vod.id,
|
||||
vod_name: vod.videoName,
|
||||
vod_pic: vod.videoCover,
|
||||
vod_remarks: vod.msg,
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
function randDevice() {
|
||||
return {
|
||||
brand: 'Huawei',
|
||||
model: 'HUAWEI Mate 20',
|
||||
release: '10',
|
||||
buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
function formatPlayUrl(src, name) {
|
||||
return name
|
||||
.trim()
|
||||
.replaceAll(src, '')
|
||||
.replace(/<|>|《|》/g, '')
|
||||
.replace(/\$|#/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function jsonParse(input, json) {
|
||||
try {
|
||||
let url = json.url ?? '';
|
||||
if (url.startsWith('//')) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
if (!url.startsWith('http')) {
|
||||
return {};
|
||||
}
|
||||
let headers = json['headers'] || {};
|
||||
let ua = (json['user-agent'] || '').trim();
|
||||
if (ua.length > 0) {
|
||||
headers['User-Agent'] = ua;
|
||||
}
|
||||
let referer = (json['referer'] || '').trim();
|
||||
if (referer.length > 0) {
|
||||
headers['Referer'] = referer;
|
||||
}
|
||||
return {
|
||||
header: headers,
|
||||
url: url,
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
};
|
||||
}
|
||||
import { Crypto, dayjs, jinja2, Uri, _ } from './lib/cat.js';
|
||||
|
||||
let key = 'kunyu77';
|
||||
let url = 'http://api.tyun77.cn';
|
||||
let device = {};
|
||||
let timeOffset = 0;
|
||||
let siteKey = '';
|
||||
let siteType = 0;
|
||||
|
||||
async function request(reqUrl, agentSp) {
|
||||
let sj = dayjs().unix() - timeOffset;
|
||||
let uri = new Uri(reqUrl);
|
||||
uri.addQueryParam('pcode', '010110005');
|
||||
uri.addQueryParam('version', '2.1.6');
|
||||
uri.addQueryParam('devid', device.id);
|
||||
uri.addQueryParam('package', 'com.sevenVideo.app.android');
|
||||
uri.addQueryParam('sys', 'android');
|
||||
uri.addQueryParam('sysver', device.release);
|
||||
uri.addQueryParam('brand', device.brand);
|
||||
uri.addQueryParam('model', device.model.replaceAll(' ', '_'));
|
||||
uri.addQueryParam('sj', sj);
|
||||
let keys = [];
|
||||
for (var i = 0; i < uri.queryPairs.length; i++) {
|
||||
keys.push(uri.queryPairs[i][0]);
|
||||
}
|
||||
keys = _.sortBy(keys, function (name) {
|
||||
return name;
|
||||
});
|
||||
let tkSrc = uri.path();
|
||||
for (let k of keys) {
|
||||
let v = uri.getQueryParamValue(k);
|
||||
v = encodeURIComponent(v);
|
||||
tkSrc += v;
|
||||
}
|
||||
tkSrc += sj;
|
||||
tkSrc += 'XSpeUFjJ';
|
||||
console.log(tkSrc);
|
||||
let tk = Crypto.MD5(tkSrc).toString().toLowerCase();
|
||||
console.log(tk);
|
||||
let header = {
|
||||
'user-agent': agentSp || 'okhttp/3.12.0',
|
||||
t: sj,
|
||||
TK: tk,
|
||||
};
|
||||
let res = await req(uri.toString(), {
|
||||
headers: header,
|
||||
});
|
||||
|
||||
let serverTime = res.headers.date; // dart all response header key is lowercase
|
||||
let content = res.content;
|
||||
let serverTimeS = dayjs(serverTime).unix();
|
||||
timeOffset = dayjs().unix() - serverTimeS;
|
||||
// console.log(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
var deviceKey = 'device';
|
||||
var deviceInfo = await local.get(key, deviceKey);
|
||||
if (deviceInfo.length > 0) {
|
||||
try {
|
||||
device = JSON.parse(deviceInfo);
|
||||
} catch (error) {}
|
||||
}
|
||||
if (_.isEmpty(device)) {
|
||||
device = randDevice();
|
||||
device.id = randStr(32).toLowerCase();
|
||||
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 request(url + '/api.php/provide/getDomain');
|
||||
await request(url + '/api.php/provide/config');
|
||||
await request(url + '/api.php/provide/checkUpgrade');
|
||||
await request(url + '/api.php/provide/channel');
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/filter')).data;
|
||||
let classes = [];
|
||||
let filterObj = {};
|
||||
let filterAll = [];
|
||||
for (const key in data) {
|
||||
classes.push({
|
||||
type_id: key,
|
||||
type_name: data[key][0].cat,
|
||||
});
|
||||
if (!filter) continue;
|
||||
try {
|
||||
let typeId = key.toString();
|
||||
if (_.isEmpty(filterAll)) {
|
||||
let filterData = JSON.parse(await request(url + '/api.php/provide/searchFilter?type_id=0&pagenum=1&pagesize=1')).data.conditions;
|
||||
// console.log(filterData);
|
||||
// 年份
|
||||
let year = {
|
||||
key: 'year',
|
||||
name: '年份',
|
||||
init: '',
|
||||
};
|
||||
let yearValues = [];
|
||||
yearValues.push({ n: '全部', v: '' });
|
||||
filterData.y.forEach((e) => {
|
||||
yearValues.push({ n: e.name, v: e.value });
|
||||
});
|
||||
year['value'] = yearValues;
|
||||
// 地区
|
||||
let area = {
|
||||
key: 'area',
|
||||
name: '地区',
|
||||
init: '',
|
||||
};
|
||||
let areaValues = [];
|
||||
areaValues.push({ n: '全部', v: '' });
|
||||
filterData.a.forEach((e) => {
|
||||
areaValues.push({ n: e.name, v: e.value });
|
||||
});
|
||||
area['value'] = areaValues;
|
||||
// 类型
|
||||
let type = {
|
||||
key: 'category',
|
||||
name: '类型',
|
||||
init: '',
|
||||
};
|
||||
let typeValues = [];
|
||||
typeValues.push({ n: '全部', v: '' });
|
||||
filterData.scat.forEach((e) => {
|
||||
typeValues.push({ n: e.name, v: e.value });
|
||||
});
|
||||
type['value'] = typeValues;
|
||||
|
||||
filterAll.push(year, area, type);
|
||||
}
|
||||
if (!_.isEmpty(filterAll)) {
|
||||
filterObj[typeId] = filterAll;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
// console.log(classes);
|
||||
// console.log(filterObj);
|
||||
return JSON.stringify({
|
||||
class: classes,
|
||||
filters: filterObj,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/homeBlock?type_id=0')).data;
|
||||
let blocks = data.blocks;
|
||||
let videos = [];
|
||||
for (const block of blocks) {
|
||||
let name = block.block_name;
|
||||
if (name.indexOf('热播') >= 0) continue;
|
||||
let contents = block.contents;
|
||||
for (const content of contents) {
|
||||
videos.push({
|
||||
vod_id: content.id,
|
||||
vod_name: content.title,
|
||||
vod_pic: content.videoCover,
|
||||
vod_remarks: content.msg,
|
||||
});
|
||||
}
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
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 });
|
||||
let data = JSON.parse(await request(reqUrl)).data;
|
||||
let videos = [];
|
||||
for (const vod of data.result) {
|
||||
videos.push({
|
||||
vod_id: vod.id,
|
||||
vod_name: vod.title,
|
||||
vod_pic: vod.videoCover,
|
||||
vod_remarks: vod.msg,
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
page: parseInt(data.page),
|
||||
pagecount: data.pagesize,
|
||||
limit: 24,
|
||||
total: data.total,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/videoDetail?ids=' + id)).data;
|
||||
console.log(data);
|
||||
let vod = {
|
||||
vod_id: data.id,
|
||||
vod_name: data.videoName,
|
||||
vod_pic: data.videoCover,
|
||||
type_name: data.subCategory,
|
||||
vod_year: data.year,
|
||||
vod_area: data.area,
|
||||
vod_remarks: data.msg,
|
||||
vod_actor: data.actor,
|
||||
vod_director: data.director,
|
||||
vod_content: data.brief.trim(),
|
||||
};
|
||||
let episodes = JSON.parse(await request(url + '/api.php/provide/videoPlaylist?ids=' + id)).data.episodes;
|
||||
let playlist = {};
|
||||
for (const episode of episodes) {
|
||||
let playurls = episode.playurls;
|
||||
for (const playurl of playurls) {
|
||||
let from = playurl.playfrom;
|
||||
let t = formatPlayUrl(vod.vod_name, playurl.title);
|
||||
if (t.length == 0) t = playurl.title.trim();
|
||||
if (!playlist.hasOwnProperty(from)) {
|
||||
playlist[from] = [];
|
||||
}
|
||||
playlist[from].push(t + '$' + playurl.playurl);
|
||||
}
|
||||
}
|
||||
vod.vod_play_from = _.keys(playlist).join('$$$');
|
||||
let urls = _.values(playlist);
|
||||
let vod_play_url = [];
|
||||
for (const urlist of urls) {
|
||||
vod_play_url.push(urlist.join('#'));
|
||||
}
|
||||
vod.vod_play_url = vod_play_url.join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [vod],
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
try {
|
||||
let data = JSON.parse(await request(url + '/api.php/provide/parserUrl?url=' + id + '&retryNum=0')).data;
|
||||
let playHeader = data.playHeader;
|
||||
let jxUrl = data.url;
|
||||
let res = await req(jxUrl, {
|
||||
headers: {
|
||||
'user-agent': 'okhttp/3.12.0',
|
||||
},
|
||||
});
|
||||
let result = jsonParse(id, JSON.parse(res.content));
|
||||
result['parse'] = 0;
|
||||
if (playHeader) {
|
||||
result.header = _.merge(result.header, playHeader);
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
} catch (e) {
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 videos = [];
|
||||
for (const vod of data) {
|
||||
videos.push({
|
||||
vod_id: vod.id,
|
||||
vod_name: vod.videoName,
|
||||
vod_pic: vod.videoCover,
|
||||
vod_remarks: vod.msg,
|
||||
});
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
function randDevice() {
|
||||
return {
|
||||
brand: 'Huawei',
|
||||
model: 'HUAWEI Mate 20',
|
||||
release: '10',
|
||||
buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
function formatPlayUrl(src, name) {
|
||||
return name
|
||||
.trim()
|
||||
.replaceAll(src, '')
|
||||
.replace(/<|>|《|》/g, '')
|
||||
.replace(/\$|#/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function jsonParse(input, json) {
|
||||
try {
|
||||
let url = json.url ?? '';
|
||||
if (url.startsWith('//')) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
if (!url.startsWith('http')) {
|
||||
return {};
|
||||
}
|
||||
let headers = json['headers'] || {};
|
||||
let ua = (json['user-agent'] || '').trim();
|
||||
if (ua.length > 0) {
|
||||
headers['User-Agent'] = ua;
|
||||
}
|
||||
let referer = (json['referer'] || '').trim();
|
||||
if (referer.length > 0) {
|
||||
headers['Referer'] = referer;
|
||||
}
|
||||
return {
|
||||
header: headers,
|
||||
url: url,
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
};
|
||||
}
|
1
JN/EXT/OPENJS/open/lib/cat.js
Normal file
1
JN/EXT/OPENJS/open/lib/cat.js
Normal file
File diff suppressed because one or more lines are too long
47
JN/EXT/OPENJS/open/lib/similarity.js
Normal file
47
JN/EXT/OPENJS/open/lib/similarity.js
Normal 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
342
JN/EXT/OPENJS/open/package-lock.json
generated
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
21
JN/EXT/OPENJS/open/package.json
Normal file
21
JN/EXT/OPENJS/open/package.json
Normal 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"
|
||||
}
|
||||
}
|
9
JN/EXT/OPENJS/open/test.js
Normal file
9
JN/EXT/OPENJS/open/test.js
Normal 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;
|
||||
})();
|
72
JN/EXT/OPENJS/open/testAlist.js
Normal file
72
JN/EXT/OPENJS/open/testAlist.js
Normal 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 猎鹰与冬兵4K(2021)【美剧】豆瓣评分:7.5/'));
|
||||
// console.log(files);
|
||||
|
||||
var fileInfo = JSON.parse(await spider.file('/💦讯维云盘/热播短剧/傲世神尊/01.mp4'));
|
||||
console.log(fileInfo);
|
||||
|
||||
}
|
||||
|
||||
export { test };
|
51
JN/EXT/OPENJS/open/testVideo.js
Normal file
51
JN/EXT/OPENJS/open/testVideo.js
Normal 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 };
|
266
JN/EXT/OPENJS/open/wrapper/index.js
Normal file
266
JN/EXT/OPENJS/open/wrapper/index.js
Normal 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 {};
|
11
JN/EXT/OPENJS/sniffer/README.md
Normal file
11
JN/EXT/OPENJS/sniffer/README.md
Normal 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`
|
43
JN/EXT/OPENJS/sniffer/config.html
Normal file
43
JN/EXT/OPENJS/sniffer/config.html
Normal 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>
|
8
JN/EXT/OPENJS/sniffer/config.js
Normal file
8
JN/EXT/OPENJS/sniffer/config.js
Normal 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));
|
||||
},
|
||||
});
|
182
JN/EXT/OPENJS/sniffer/index.js
Normal file
182
JN/EXT/OPENJS/sniffer/index.js
Normal 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
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
2893
JN/EXT/OPENJS/sniffer/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
JN/EXT/OPENJS/sniffer/package.json
Normal file
24
JN/EXT/OPENJS/sniffer/package.json
Normal 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"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user