added openjs

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

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

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

File diff suppressed because one or more lines are too long

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

File diff suppressed because it is too large Load Diff

View File

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