drpyS.js 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536
  1. import {readFile} from 'fs/promises';
  2. import {existsSync, readFileSync, writeFileSync, mkdirSync} from 'fs';
  3. import {fileURLToPath} from "url";
  4. import {createRequire} from 'module';
  5. import {XMLHttpRequest} from 'xmlhttprequest';
  6. import path from "path";
  7. import vm from 'vm';
  8. import WebSocket, {WebSocketServer} from 'ws';
  9. import zlib from 'zlib';
  10. import JSONbig from 'json-bigint';
  11. import * as minizlib from 'minizlib';
  12. import '../libs_drpy/es6-extend.js'
  13. import {getSitesMap} from "../utils/sites-map.js";
  14. import * as utils from '../utils/utils.js';
  15. import * as misc from '../utils/misc.js';
  16. import COOKIE from '../utils/cookieManager.js';
  17. import {ENV} from '../utils/env.js';
  18. import {Quark} from "../utils/quark.js";
  19. import {UC} from "../utils/uc.js";
  20. import {Ali} from "../utils/ali.js";
  21. import {Cloud} from "../utils/cloud.js";
  22. import {Yun} from "../utils/yun.js";
  23. import {Pan} from "../utils/pan123.js";
  24. import AIS from '../utils/ais.js';
  25. // const { req } = await import('../utils/req.js');
  26. import {gbkTool} from '../libs_drpy/gbk.js'
  27. // import {atob, btoa, base64Encode, base64Decode, md5} from "../libs_drpy/crypto-util.js";
  28. import {base64Decode, base64Encode, md5, rc4, rc4_decode, rc4Decrypt, rc4Encrypt} from "../libs_drpy/crypto-util.js";
  29. import {getContentType, getMimeType} from "../utils/mime-type.js";
  30. import {getParsesDict} from "../utils/file.js";
  31. import {getFirstLetter} from "../utils/pinyin-tool.js";
  32. import "../utils/random-http-ua.js";
  33. import template from '../libs_drpy/template.js'
  34. import batchExecute from '../libs_drpy/batchExecute.js';
  35. import '../libs_drpy/abba.js'
  36. import '../libs_drpy/drpyInject.js'
  37. import '../libs_drpy/crypto-js.js';
  38. import '../libs_drpy/jsencrypt.js';
  39. import '../libs_drpy/node-rsa.js';
  40. import '../libs_drpy/pako.min.js';
  41. import '../libs_drpy/json5.js'
  42. import '../libs_drpy/jinja.js'
  43. // import '../libs_drpy/jsonpathplus.min.js'
  44. import '../libs_drpy/drpyCustom.js'
  45. import '../libs_drpy/moduleLoader.js'
  46. // import '../libs_drpy/crypto-js-wasm.js'
  47. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  48. const _data_path = path.join(__dirname, '../data');
  49. const _config_path = path.join(__dirname, '../config');
  50. globalThis.misc = misc;
  51. globalThis.utils = utils;
  52. globalThis.COOKIE = COOKIE;
  53. globalThis.ENV = ENV;
  54. globalThis._ENV = process.env;
  55. globalThis.Quark = Quark;
  56. globalThis.UC = UC;
  57. globalThis.Ali = Ali;
  58. globalThis.Cloud = Cloud;
  59. globalThis.Yun = Yun;
  60. globalThis.Pan = Pan;
  61. globalThis.require = createRequire(import.meta.url);
  62. globalThis._fetch = fetch;
  63. globalThis.XMLHttpRequest = XMLHttpRequest;
  64. globalThis.WebSocket = WebSocket;
  65. globalThis.WebSocketServer = WebSocketServer;
  66. globalThis.zlib = zlib;
  67. globalThis.JSONbig = JSONbig;
  68. globalThis.JsonBig = JSONbig({storeAsString: true});
  69. globalThis.minizlib = minizlib;
  70. globalThis.AIS = AIS;
  71. globalThis.pathLib = {
  72. basename: path.basename,
  73. extname: path.extname,
  74. readFile: function (filename) {
  75. let _file_path = path.join(_data_path, filename);
  76. const resolvedPath = path.resolve(_data_path, _file_path); // 将路径解析为绝对路径
  77. if (!resolvedPath.startsWith(_data_path)) {
  78. log(`no access for read ${_file_path}`)
  79. return '';
  80. }
  81. // 检查文件是否存在
  82. if (!existsSync(resolvedPath)) {
  83. log(`file not found for read ${resolvedPath}`)
  84. return '';
  85. }
  86. return readFileSync(resolvedPath, 'utf8')
  87. },
  88. writeFile: function (filename, text) {
  89. let _file_path = path.join(_data_path, filename);
  90. const resolvedPath = path.resolve(_data_path, _file_path); // 将路径解析为绝对路径
  91. if (!resolvedPath.startsWith(_data_path)) {
  92. log(`no access for read ${_file_path}`)
  93. return '';
  94. }
  95. try {
  96. const dirPath = path.dirname(resolvedPath);
  97. // 检查目录是否存在,不存在则创建
  98. if (!existsSync(dirPath)) {
  99. mkdirSync(dirPath, {recursive: true});
  100. }
  101. writeFileSync(resolvedPath, text, 'utf8');
  102. return true
  103. } catch (e) {
  104. log(`failed for saveFile ${_file_path} error:${e.message}`);
  105. return false
  106. }
  107. },
  108. };
  109. const {sleep, sleepSync, computeHash, deepCopy, urljoin, urljoin2, joinUrl, naturalSort, $js} = utils;
  110. const es6JsPath = path.join(__dirname, '../libs_drpy/es6-extend.js');
  111. // 读取扩展代码
  112. const es6_extend_code = readFileSync(es6JsPath, 'utf8');
  113. const reqJsPath = path.join(__dirname, '../libs_drpy/req-extend.js');
  114. // 读取网络请求扩展代码
  115. const req_extend_code = readFileSync(reqJsPath, 'utf8');
  116. // 缓存已初始化的模块和文件 hash 值
  117. const moduleCache = new Map();
  118. const ruleObjectCache = new Map();
  119. const jxCache = new Map();
  120. let pupWebview = null;
  121. if (typeof fetchByHiker === 'undefined') { // 判断是海阔直接放弃导入puppeteer
  122. try {
  123. // 尝试动态导入模块puppeteerHelper
  124. const {puppeteerHelper} = await import('../utils/headless-util.js'); // 使用动态 import
  125. pupWebview = new puppeteerHelper();
  126. console.log('puppeteerHelper imported successfully');
  127. } catch (error) {
  128. // console.log('Failed to import puppeteerHelper:', error);
  129. console.log(`Failed to import puppeteerHelper:${error.message}`);
  130. }
  131. }
  132. globalThis.pupWebview = pupWebview;
  133. try {
  134. if (typeof fetchByHiker !== 'undefined' && typeof globalThis.import === 'function') {
  135. await globalThis.import('../libs_drpy/crypto-js-wasm.js'); // 海阔放在globalThis里去动态引入
  136. } else {
  137. await import('../libs_drpy/crypto-js-wasm.js'); // 使用动态 import规避海阔报错无法运行问题
  138. }
  139. globalThis.CryptoJSW = CryptoJSWasm;
  140. } catch (error) {
  141. // console.log('Failed to import puppeteerHelper:', error);
  142. console.log(`Failed to import CryptoJSWasm:${error.message}`);
  143. globalThis.CryptoJSW = {
  144. loadAllWasm: async function () {
  145. },
  146. // MD5: async function (str) {
  147. // return md5(str)
  148. // },
  149. ...CryptoJS
  150. };
  151. }
  152. let simplecc = null;
  153. try {
  154. const simWasm = await import('simplecc-wasm'); // 使用动态 import
  155. simplecc = simWasm.simplecc;
  156. console.log('simplecc imported successfully');
  157. } catch (error) {
  158. // console.log('Failed to import puppeteerHelper:', error);
  159. console.log(`Failed to import simplecc:${error.message}`);
  160. }
  161. globalThis.simplecc = simplecc;
  162. let DataBase = null;
  163. let database = null;
  164. try {
  165. if (typeof fetchByHiker !== 'undefined' && typeof globalThis.import === 'function') {
  166. const sqliteUtil = await globalThis.import('../utils/database.js'); // 海阔放在globalThis里去动态引入
  167. DataBase = sqliteUtil.DataBase;
  168. database = sqliteUtil.database;
  169. } else {
  170. const sqliteUtil = await import('../utils/database.js'); // 使用动态 import
  171. DataBase = sqliteUtil.DataBase;
  172. database = sqliteUtil.database;
  173. }
  174. console.log('sqlite3 database imported successfully');
  175. } catch (error) {
  176. console.log(`Failed to import sqlite3:${error.message}`);
  177. }
  178. globalThis.DataBase = DataBase;
  179. globalThis.database = database;
  180. export async function getSandbox(env = {}) {
  181. const {getProxyUrl, hostUrl, fServer} = env;
  182. // (可选) 加载所有 wasm 文件
  183. await CryptoJSW.loadAllWasm();
  184. const utilsSanbox = {
  185. sleep,
  186. sleepSync,
  187. utils,
  188. misc,
  189. computeHash,
  190. deepCopy,
  191. urljoin,
  192. urljoin2,
  193. joinUrl,
  194. naturalSort,
  195. $js,
  196. $,
  197. pupWebview,
  198. getProxyUrl,
  199. hostUrl,
  200. fServer,
  201. getContentType, getMimeType, getParsesDict, getFirstLetter
  202. };
  203. const drpySanbox = {
  204. jsp,
  205. pdfh,
  206. pd,
  207. pdfa,
  208. jsoup,
  209. pdfl,
  210. pjfh,
  211. pj,
  212. pjfa,
  213. pq,
  214. local,
  215. md5X,
  216. rsaX,
  217. aesX,
  218. desX,
  219. req,
  220. _fetch,
  221. XMLHttpRequest,
  222. simplecc,
  223. AIS,
  224. batchFetch,
  225. JSProxyStream,
  226. JSFile,
  227. js2Proxy,
  228. log,
  229. print,
  230. jsonToCookie,
  231. cookieToJson,
  232. runMain,
  233. };
  234. const drpyCustomSanbox = {
  235. MOBILE_UA,
  236. PC_UA,
  237. UA,
  238. UC_UA,
  239. IOS_UA,
  240. RULE_CK,
  241. CATE_EXCLUDE,
  242. TAB_EXCLUDE,
  243. OCR_RETRY,
  244. OCR_API,
  245. nodata,
  246. SPECIAL_URL,
  247. setResult,
  248. setHomeResult,
  249. setResult2,
  250. urlDeal,
  251. tellIsJx,
  252. urlencode,
  253. encodeUrl,
  254. uint8ArrayToBase64,
  255. Utf8ArrayToStr,
  256. gzip,
  257. ungzip,
  258. encodeStr,
  259. decodeStr,
  260. getCryptoJS,
  261. RSA,
  262. fixAdM3u8Ai,
  263. forceOrder,
  264. getQuery,
  265. stringify,
  266. dealJson,
  267. OcrApi,
  268. getHome,
  269. buildUrl,
  270. keysToLowerCase,
  271. parseQueryString,
  272. encodeIfContainsSpecialChars,
  273. objectToQueryString,
  274. };
  275. const libsSanbox = {
  276. matchesAll,
  277. cut,
  278. gbkTool,
  279. CryptoJS,
  280. CryptoJSW,
  281. JSEncrypt,
  282. NODERSA,
  283. pako,
  284. JSON5,
  285. jinja,
  286. template,
  287. batchExecute,
  288. atob,
  289. btoa,
  290. base64Encode,
  291. base64Decode,
  292. md5,
  293. rc4Encrypt,
  294. rc4Decrypt,
  295. rc4,
  296. rc4_decode,
  297. randomUa,
  298. jsonpath,
  299. hlsParser,
  300. axios,
  301. axiosX,
  302. URL,
  303. pathLib,
  304. qs,
  305. Buffer,
  306. URLSearchParams,
  307. COOKIE,
  308. ENV,
  309. _ENV,
  310. Quark,
  311. UC,
  312. Ali,
  313. Cloud,
  314. Yun,
  315. Pan,
  316. DataBase,
  317. database,
  318. require,
  319. WebSocket,
  320. WebSocketServer,
  321. zlib,
  322. JSONbig,
  323. JsonBig,
  324. minizlib,
  325. };
  326. // 创建一个沙箱上下文,注入需要的全局变量和函数
  327. const sandbox = {
  328. console, // 将 console 注入沙箱,便于调试
  329. // eval, // 直接引入原生 eval(不要这样用,环境是隔离的会导致执行不符合预期,需要包装)
  330. WebAssembly, // 允许使用原生 WebAssembly(这里即使不引用也可以在沙箱里用这个变量。写在这里骗骗自己吧)
  331. setTimeout, // 注入定时器方法
  332. setInterval,
  333. clearTimeout,
  334. clearInterval,
  335. module: {}, // 模块支持
  336. exports: {}, // 模块支持
  337. rule: {}, // 用于存放导出的 rule 对象
  338. jx: {},// 用于存放导出的 解析 对象
  339. lazy: async function () {
  340. }, // 用于导出解析的默认函数
  341. _asyncGetRule: null,
  342. _asyncGetLazy: null,
  343. ...utilsSanbox,
  344. ...drpySanbox,
  345. ...drpyCustomSanbox,
  346. ...libsSanbox,
  347. };
  348. // 创建一个上下文
  349. const context = vm.createContext(sandbox);
  350. // 注入扩展代码到沙箱中
  351. const polyfillsScript = new vm.Script(es6_extend_code);
  352. polyfillsScript.runInContext(context);
  353. // 设置沙箱到全局 $
  354. sandbox.$.setSandbox(sandbox);
  355. /*
  356. if (typeof fetchByHiker !== 'undefined') { // 临时解决海阔不支持eval问题,但是这个eval存在作用域问题,跟非海阔环境的有很大区别,属于残废版本
  357. sandbox.eval = function (code) {
  358. const evalScript = new vm.Script(code);
  359. return evalScript.runInContext(context);
  360. };
  361. }
  362. */
  363. return {
  364. sandbox,
  365. context
  366. }
  367. }
  368. /**
  369. * 初始化模块:加载并执行模块文件,存储初始化后的 rule 对象
  370. * 如果存在 `预处理` 属性且为函数,会在缓存前执行
  371. * @param {string} filePath - 模块文件路径
  372. * @param env
  373. * @param refresh 强制清除缓存
  374. * @returns {Promise<object>} - 返回初始化后的模块对象
  375. */
  376. export async function init(filePath, env = {}, refresh) {
  377. try {
  378. // 读取文件内容
  379. const fileContent = await readFile(filePath, 'utf-8');
  380. // 计算文件的 hash 值
  381. const fileHash = computeHash(fileContent);
  382. const moduleName = path.basename(filePath, '.js');
  383. let moduleExt = env.ext || '';
  384. // log('moduleName:', moduleName);
  385. // log('moduleExt:', moduleExt);
  386. let SitesMap = getSitesMap(_config_path);
  387. // log('SitesMap:', SitesMap);
  388. if (moduleExt && SitesMap[moduleName]) {
  389. try {
  390. moduleExt = ungzip(moduleExt);
  391. } catch (e) {
  392. log(`[${moduleName}] ungzip解密moduleExt失败: ${e.message}`);
  393. }
  394. if (!SitesMap[moduleName].find(i => i.queryStr === moduleExt) && !SitesMap[moduleName].find(i => i.queryObject.params === moduleExt)) {
  395. throw new Error("moduleExt is wrong!")
  396. }
  397. }
  398. let hashMd5 = md5(filePath + '#pAq#' + moduleExt);
  399. // 检查缓存:是否有文件且未刷新且文件 hash 未变化
  400. if (moduleCache.has(hashMd5) && !refresh) {
  401. const cached = moduleCache.get(hashMd5);
  402. if (cached.hash === fileHash) {
  403. // log(`Module ${filePath} already initialized and unchanged, returning cached instance.`);
  404. return cached.moduleObject;
  405. }
  406. }
  407. log(`Loading module: ${filePath}`);
  408. let t1 = utils.getNowTime();
  409. const {sandbox, context} = await getSandbox(env);
  410. // 执行文件内容,将其放入沙箱中
  411. const js_code = getOriginalJs(fileContent);
  412. // console.log('js_code:', js_code.slice(5000));
  413. const js_code_wrapper = `
  414. _asyncGetRule = (async function() {
  415. ${js_code}
  416. return rule;
  417. })();
  418. `;
  419. const ruleScript = new vm.Script(js_code_wrapper);
  420. // ruleScript.runInContext(context);
  421. // const result = await ruleScript.runInContext(context);
  422. const executeWithTimeout = (script, context, timeout) => {
  423. return Promise.race([
  424. new Promise((_, reject) =>
  425. setTimeout(() => reject(new Error('Code execution timed out')), timeout)
  426. ),
  427. new Promise((resolve, reject) => {
  428. try {
  429. const result = script.runInContext(context); // 同步运行脚本
  430. if (result && typeof result.then === 'function') {
  431. // 如果结果是 Promise,则等待其解析
  432. result.then(resolve).catch(reject);
  433. } else {
  434. // 如果结果是非异步值,直接返回
  435. resolve(result);
  436. }
  437. } catch (error) {
  438. reject(error);
  439. }
  440. })
  441. ]);
  442. };
  443. const result = await executeWithTimeout(ruleScript, context, 30000);
  444. // console.log('result:', result);
  445. // sandbox.rule = await sandbox._asyncGetRule;
  446. sandbox.rule = result;
  447. // rule注入完毕后添加自定义req扩展request方法进入规则,这个代码里可以直接获取rule的任意对象,而且还是独立隔离的
  448. const reqExtendScript = new vm.Script(req_extend_code);
  449. reqExtendScript.runInContext(context);
  450. // 访问沙箱中的 rule 对象。不进行deepCopy了,避免初始化或者预处理对rule.xxx进行修改后,在其他函数里使用却没生效问题
  451. // const moduleObject = utils.deepCopy(sandbox.rule);
  452. const rule = sandbox.rule;
  453. if (moduleExt) { // 传了参数才覆盖rule参数,否则取rule内置
  454. // log('moduleExt:', moduleExt);
  455. if (moduleExt.startsWith('../json')) {
  456. rule.params = urljoin(env.jsonUrl, moduleExt.slice(8));
  457. } else {
  458. rule.params = moduleExt
  459. }
  460. }
  461. await initParse(rule, env, vm, context);
  462. // otherScript放入到initParse去执行
  463. // const otherScript = new vm.Script(`
  464. // globalThis.jsp = new jsoup(rule.host||'');
  465. // globalThis.pdfh = pdfh;
  466. // globalThis.pd = pd;
  467. // globalThis.pdfa = pdfa;
  468. // globalThis.HOST = rule.host||'';
  469. // `);
  470. // otherScript.runInContext(context);
  471. let t2 = utils.getNowTime();
  472. const moduleObject = utils.deepCopy(rule);
  473. moduleObject.cost = t2 - t1;
  474. // console.log(`${filePath} headers:`, moduleObject.headers);
  475. // 缓存模块和文件的 hash 值
  476. moduleCache.set(hashMd5, {moduleObject, hash: fileHash});
  477. return moduleObject;
  478. } catch (error) {
  479. console.log(`Error in drpy.init :${filePath}`, error);
  480. throw new Error(`Failed to initialize module:${error.message}`);
  481. }
  482. }
  483. export async function getRuleObject(filePath, env, refresh) {
  484. try {
  485. // 读取文件内容
  486. const fileContent = await readFile(filePath, 'utf-8');
  487. // 计算文件的 hash 值
  488. const fileHash = computeHash(fileContent);
  489. // 检查缓存:是否有文件且未刷新且文件 hash 未变化
  490. if (ruleObjectCache.has(filePath) && !refresh) {
  491. const cached = ruleObjectCache.get(filePath);
  492. if (cached.hash === fileHash) {
  493. // log(`Module ${filePath} already initialized and unchanged, returning cached instance.`);
  494. return cached.ruleObject;
  495. }
  496. }
  497. log(`Loading RuleObject: ${filePath} fileSize:${fileContent.length}`);
  498. let t1 = utils.getNowTime();
  499. const {sandbox, context} = await getSandbox(env);
  500. const js_code = getOriginalJs(fileContent);
  501. const js_code_wrapper = `
  502. _asyncGetRule = (async function() {
  503. ${js_code}
  504. return rule;
  505. })();
  506. `;
  507. const ruleScript = new vm.Script(js_code_wrapper);
  508. ruleScript.runInContext(context);
  509. sandbox.rule = await sandbox._asyncGetRule;
  510. const rule = sandbox.rule;
  511. let t2 = utils.getNowTime();
  512. const ruleObject = deepCopy(rule);
  513. // 设置可搜索、可筛选、可快搜等属性
  514. ruleObject.searchable = ruleObject.hasOwnProperty('searchable') ? Number(ruleObject.searchable) : 0;
  515. ruleObject.filterable = ruleObject.hasOwnProperty('filterable') ? Number(ruleObject.filterable) : 0;
  516. ruleObject.quickSearch = ruleObject.hasOwnProperty('quickSearch') ? Number(ruleObject.quickSearch) : 0;
  517. ruleObject.cost = t2 - t1;
  518. // console.log(`${filePath} headers:`, moduleObject.headers);
  519. // 缓存模块和文件的 hash 值
  520. ruleObjectCache.set(filePath, {ruleObject, hash: fileHash});
  521. return ruleObject
  522. } catch (error) {
  523. console.log(`${filePath} Error in drpy.getRuleObject:${error.message}`);
  524. return {}
  525. }
  526. }
  527. export async function initJx(filePath, env, refresh) {
  528. try {
  529. // 读取文件内容
  530. const fileContent = await readFile(filePath, 'utf-8');
  531. // 计算文件的 hash 值
  532. const fileHash = computeHash(fileContent);
  533. let hashMd5 = md5(filePath + '#pAq#' + (env === {} ? 0 : 1));
  534. // 检查缓存:是否有文件且未刷新且文件 hash 未变化
  535. if (jxCache.has(hashMd5) && !refresh) {
  536. const cached = jxCache.get(hashMd5);
  537. if (cached.hash === fileHash) {
  538. // log(`Module ${filePath} already initialized and unchanged, returning cached instance.`);
  539. return cached.jxObj;
  540. }
  541. }
  542. log(`Loading jx: ${filePath}, hash:${hashMd5}`);
  543. let t1 = utils.getNowTime();
  544. const {sandbox, context} = await getSandbox(env);
  545. // 执行文件内容,将其放入沙箱中
  546. const js_code = getOriginalJs(fileContent);
  547. const js_code_wrapper = `
  548. _asyncGetLazy = (async function() {
  549. ${js_code}
  550. return {jx,lazy};
  551. })();
  552. `;
  553. const ruleScript = new vm.Script(js_code_wrapper);
  554. ruleScript.runInContext(context);
  555. const jxResult = await sandbox._asyncGetLazy;
  556. sandbox.lazy = jxResult.lazy;
  557. sandbox.jx = jxResult.jx;
  558. const reqExtendScript = new vm.Script(req_extend_code);
  559. reqExtendScript.runInContext(context);
  560. let t2 = utils.getNowTime();
  561. const jxObj = {...sandbox.jx, lazy: sandbox.lazy};
  562. const cost = t2 - t1;
  563. console.log(`加载解析:${filePath} 耗时 ${cost}毫秒`)
  564. jxCache.set(hashMd5, {jxObj, hash: fileHash});
  565. return jxObj;
  566. } catch (error) {
  567. console.log(`Error in drpy.initJx:${filePath}`, error);
  568. throw new Error(`Failed to initialize jx:${error.message}`);
  569. }
  570. }
  571. /**
  572. * 使用临时的上下文调用异步方法,确保每次调用时的上下文 (this) 是独立的。
  573. * 这样可以避免多个请求之间共享状态,确保数据的隔离性。
  574. *
  575. * @param rule 规则本身
  576. * @param {Function} method - 要调用的异步方法,通常是对象上的方法(例如:moduleObject[method])
  577. * @param {Object} injectVars - 用作临时上下文的变量,通常包含一些动态的参数(如:input, MY_URL等)
  578. * @param {Array} args - 传递给方法的参数列表,会在方法调用时使用
  579. *
  580. * @returns {Promise} - 返回异步方法执行的结果,通常是 `await method.apply(...)` 调用的结果
  581. */
  582. async function invokeWithInjectVars(rule, method, injectVars, args) {
  583. // return await moduleObject[method].apply(Object.assign(injectVars, moduleObject), args);
  584. // 这里不使用 bind 或者直接修改原方法,而是通过 apply 临时注入 injectVars 作为 `this` 上下文
  585. // 这样每次调用时,方法内部的 `this` 会指向 `injectVars`,避免了共享状态,确保数据的隔离性。
  586. let thisProxy = new Proxy(injectVars, {
  587. get(injectVars, key) {
  588. return injectVars[key] || rule[key]
  589. },
  590. set(injectVars, key, value) {
  591. rule[key] = value;
  592. injectVars[key] = value;
  593. }
  594. });
  595. let result = {};
  596. let error = null;
  597. try {
  598. result = await method.apply(thisProxy, args);
  599. } catch (e) {
  600. error = e;
  601. }
  602. if (!['推荐'].includes(injectVars['method']) && error) {
  603. throw error
  604. }
  605. // let result = await method.apply(injectVars, args); // 使用 apply 临时注入 injectVars 作为上下文,并执行方法
  606. switch (injectVars['method']) {
  607. case '推荐':
  608. if (error) {
  609. log('error:', error);
  610. error = null;
  611. result = [];
  612. }
  613. break;
  614. case 'class_parse':
  615. result = await homeParseAfter(result, rule.类型, rule.hikerListCol, rule.hikerClassListCol, injectVars);
  616. break;
  617. case '一级':
  618. result = await cateParseAfter(rule, result, args[1]);
  619. console.log(`一级 ${injectVars.input} 执行完毕,结果为:`, JSON.stringify(result.list.slice(0, 2)));
  620. break;
  621. case '二级':
  622. result = await detailParseAfter(result);
  623. break;
  624. case '搜索':
  625. result = await searchParseAfter(rule, result, args[2]);
  626. console.log(`搜索 ${injectVars.input} 执行完毕,结果为:`, JSON.stringify(result.list.slice(0, 2)));
  627. break;
  628. case 'lazy':
  629. result = await playParseAfter(rule, result, args[1], args[0]);
  630. console.log(`免嗅 ${injectVars.input} 执行完毕,结果为:`, JSON.stringify(result));
  631. break;
  632. case 'proxy_rule':
  633. break;
  634. case 'action':
  635. break;
  636. default:
  637. console.log(`invokeWithInjectVars: ${injectVars['method']}`);
  638. break;
  639. }
  640. if (error) {
  641. throw error
  642. }
  643. return result
  644. }
  645. /**
  646. * 调用模块的指定方法
  647. * @param {string} filePath - 模块文件路径
  648. * @param env 全局的环境变量-针对本规则,如代理地址
  649. * @param {string} method - 要调用的属性方法名称
  650. * @param args - 传递给方法的普通参数
  651. * @param {object} injectVars - 需要注入的变量(如 input 和 MY_URL)
  652. * @returns {Promise<any>} - 方法调用的返回值
  653. */
  654. async function invokeMethod(filePath, env, method, args = [], injectVars = {}) {
  655. const moduleObject = await init(filePath, env); // 确保模块已初始化
  656. switch (method) {
  657. case 'get_rule':
  658. return moduleObject;
  659. case 'class_parse':
  660. injectVars = await homeParse(moduleObject, ...args);
  661. if (!injectVars) {
  662. return {}
  663. }
  664. break
  665. case '推荐':
  666. injectVars = await homeVodParse(moduleObject, ...args);
  667. if (!injectVars) {
  668. return {}
  669. }
  670. break
  671. case '一级':
  672. injectVars = await cateParse(moduleObject, ...args);
  673. if (!injectVars) {
  674. return {}
  675. }
  676. break
  677. case '二级':
  678. injectVars = await detailParse(moduleObject, ...args);
  679. if (!injectVars) {
  680. return {}
  681. }
  682. break;
  683. case '搜索':
  684. injectVars = await searchParse(moduleObject, ...args);
  685. if (!injectVars) {
  686. return {}
  687. }
  688. break;
  689. case 'lazy':
  690. injectVars = await playParse(moduleObject, ...args);
  691. if (!injectVars) {
  692. return {}
  693. }
  694. break;
  695. case 'proxy_rule':
  696. injectVars = await proxyParse(moduleObject, ...args);
  697. if (!injectVars) {
  698. return {}
  699. }
  700. break;
  701. }
  702. injectVars['method'] = method;
  703. // 环境变量扩展进入this区域
  704. Object.assign(injectVars, env);
  705. if (method === 'lazy') {
  706. const tmpLazyFunction = async function () {
  707. let {input} = this;
  708. return input
  709. };
  710. if (moduleObject[method] && typeof moduleObject[method] === 'function') {
  711. try {
  712. return await invokeWithInjectVars(moduleObject, moduleObject[method], injectVars, args);
  713. } catch (e) {
  714. let playUrl = injectVars.input || '';
  715. log(`执行免嗅代码发送了错误: ${e.message},原始链接为:${playUrl}`);
  716. if (SPECIAL_URL.test(playUrl) || /^(push:)/.test(playUrl) || playUrl.startsWith('http')) {
  717. return await invokeWithInjectVars(moduleObject, tmpLazyFunction, injectVars, args);
  718. } else {
  719. throw e
  720. }
  721. }
  722. } else if (!moduleObject[method]) {// 新增特性,可以不写lazy属性
  723. return await invokeWithInjectVars(moduleObject, tmpLazyFunction, injectVars, args);
  724. }
  725. } else if (moduleObject[method] && typeof moduleObject[method] === 'function') {
  726. // console.log('injectVars:', injectVars);
  727. return await invokeWithInjectVars(moduleObject, moduleObject[method], injectVars, args);
  728. } else if (!moduleObject[method] && method === 'class_parse') { // 新增特性,可以不写class_parse属性
  729. const tmpClassFunction = async function () {
  730. };
  731. return await invokeWithInjectVars(moduleObject, tmpClassFunction, injectVars, args);
  732. } else {
  733. if (['推荐', '一级', '搜索'].includes(method)) {
  734. return []
  735. } else if (['二级'].includes(method)) {
  736. return {}
  737. } else if (['lazy'].includes(method)) {
  738. // console.log(injectVars);
  739. return {
  740. parse: 1,
  741. url: injectVars.input,
  742. header: moduleObject.headers && Object.keys(moduleObject.headers).length > 0 ? moduleObject.headers : undefined
  743. }
  744. } else { // class_parse一定要有,这样即使不返回数据都能自动取class_name和class_url的内容
  745. throw new Error(`Method ${method} not found in module ${filePath}`);
  746. }
  747. }
  748. }
  749. async function initParse(rule, env, vm, context) {
  750. rule.host = (rule.host || '').rstrip('/');
  751. // 检查并执行 `hostJs` 方法
  752. if (typeof rule.hostJs === 'function') {
  753. log('Executing hostJs...');
  754. try {
  755. let HOST = await rule.hostJs.apply({input: rule.host, MY_URL: rule.host, HOST: rule.host});
  756. if (HOST) {
  757. rule.host = HOST.rstrip('/');
  758. log(`已动态设置规则【${rule.title}】的host为: ${rule.host}`);
  759. }
  760. } catch (e) {
  761. log(`hostJs执行错误:${e.message}`);
  762. }
  763. }
  764. let rule_cate_excludes = (rule.cate_exclude || '').split('|').filter(it => it.trim());
  765. let rule_tab_excludes = (rule.tab_exclude || '').split('|').filter(it => it.trim());
  766. rule_cate_excludes = rule_cate_excludes.concat(CATE_EXCLUDE.split('|').filter(it => it.trim()));
  767. rule_tab_excludes = rule_tab_excludes.concat(TAB_EXCLUDE.split('|').filter(it => it.trim()));
  768. rule.cate_exclude = rule_cate_excludes.join('|');
  769. rule.tab_exclude = rule_tab_excludes.join('|');
  770. rule.类型 = rule.类型 || '影视'; // 影视|听书|漫画|小说
  771. rule.url = rule.url || '';
  772. rule.double = rule.double || false;
  773. rule.homeUrl = rule.homeUrl || '';
  774. rule.detailUrl = rule.detailUrl || '';
  775. rule.searchUrl = rule.searchUrl || '';
  776. rule.homeUrl = rule.host && rule.homeUrl ? urljoin(rule.host, rule.homeUrl) : (rule.homeUrl || rule.host);
  777. rule.homeUrl = jinja.render(rule.homeUrl, {rule: rule});
  778. rule.detailUrl = rule.host && rule.detailUrl ? urljoin(rule.host, rule.detailUrl) : rule.detailUrl;
  779. rule.二级访问前 = rule.二级访问前 || '';
  780. if (rule.url.includes('[') && rule.url.includes(']')) {
  781. let u1 = rule.url.split('[')[0]
  782. let u2 = rule.url.split('[')[1].split(']')[0]
  783. rule.url = rule.host && rule.url ? urljoin(rule.host, u1) + '[' + urljoin(rule.host, u2) + ']' : rule.url;
  784. } else {
  785. rule.url = rule.host && rule.url ? urljoin(rule.host, rule.url) : rule.url;
  786. }
  787. if (rule.searchUrl.includes('[') && rule.searchUrl.includes(']') && !rule.searchUrl.includes('#')) {
  788. let u1 = rule.searchUrl.split('[')[0]
  789. let u2 = rule.searchUrl.split('[')[1].split(']')[0]
  790. rule.searchUrl = rule.host && rule.searchUrl ? urljoin(rule.host, u1) + '[' + urljoin(rule.host, u2) + ']' : rule.searchUrl;
  791. } else {
  792. rule.searchUrl = rule.host && rule.searchUrl ? urljoin(rule.host, rule.searchUrl) : rule.searchUrl;
  793. }
  794. rule.timeout = rule.timeout || 5000;
  795. rule.encoding = rule.编码 || rule.encoding || 'utf-8';
  796. rule.search_encoding = rule.搜索编码 || rule.search_encoding || '';
  797. rule.图片来源 = rule.图片来源 || '';
  798. rule.图片替换 = rule.图片替换 || '';
  799. rule.play_json = rule.hasOwnProperty('play_json') ? rule.play_json : [];
  800. rule.pagecount = rule.hasOwnProperty('pagecount') ? rule.pagecount : {};
  801. rule.proxy_rule = rule.hasOwnProperty('proxy_rule') ? rule.proxy_rule : '';
  802. if (!rule.hasOwnProperty('sniffer')) { // 默认关闭辅助嗅探
  803. rule.sniffer = false;
  804. }
  805. rule.sniffer = rule.hasOwnProperty('sniffer') ? rule.sniffer : '';
  806. rule.sniffer = !!(rule.sniffer && rule.sniffer !== '0' && rule.sniffer !== 'false');
  807. rule.isVideo = rule.hasOwnProperty('isVideo') ? rule.isVideo : '';
  808. if (rule.sniffer && !rule.isVideo) { // 默认辅助嗅探自动增强嗅探规则
  809. rule.isVideo = '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*|http((?!http).)*?obj/tos*';
  810. }
  811. rule.tab_remove = rule.hasOwnProperty('tab_remove') ? rule.tab_remove : [];
  812. rule.tab_order = rule.hasOwnProperty('tab_order') ? rule.tab_order : [];
  813. rule.tab_rename = rule.hasOwnProperty('tab_rename') ? rule.tab_rename : {};
  814. if (rule.headers && typeof (rule.headers) === 'object') {
  815. try {
  816. let header_keys = Object.keys(rule.headers);
  817. for (let k of header_keys) {
  818. if (k.toLowerCase() === 'user-agent') {
  819. let v = rule.headers[k];
  820. console.log(v);
  821. if (['MOBILE_UA', 'PC_UA', 'UC_UA', 'IOS_UA', 'UA'].includes(v)) {
  822. rule.headers[k] = eval(v);
  823. log(rule.headers[k])
  824. }
  825. } else if (k.toLowerCase() === 'cookie') {
  826. let v = rule.headers[k];
  827. if (v && v.startsWith('http')) {
  828. console.log(v);
  829. try {
  830. v = fetch(v);
  831. console.log(v);
  832. rule.headers[k] = v;
  833. } catch (e) {
  834. console.log(`从${v}获取cookie发生错误:${e.message}`);
  835. }
  836. }
  837. }
  838. }
  839. } catch (e) {
  840. console.log(`处理headers发生错误:${e.message}`);
  841. }
  842. } else {
  843. rule.headers = {}
  844. }
  845. // 新版放入规则内部
  846. rule.oheaders = deepCopy(rule.headers);
  847. rule.rule_fetch_params = {'headers': rule.headers, 'timeout': rule.timeout, 'encoding': rule.encoding};
  848. const originalScript = new vm.Script(`
  849. globalThis.oheaders = rule.oheaders
  850. globalThis.rule_fetch_params = rule.rule_fetch_params;
  851. `);
  852. originalScript.runInContext(context);
  853. // 检查并执行 `预处理` 方法
  854. if (typeof rule.预处理 === 'function') {
  855. log('Executing 预处理...');
  856. await rule.预处理(env);
  857. }
  858. const otherScript = new vm.Script(`
  859. globalThis.jsp = new jsoup(rule.host||'');
  860. globalThis.pdfh = pdfh;
  861. globalThis.pd = pd;
  862. globalThis.pdfa = pdfa;
  863. globalThis.HOST = rule.host||'';
  864. `);
  865. otherScript.runInContext(context);
  866. return rule
  867. }
  868. async function homeParse(rule) {
  869. let url = rule.homeUrl;
  870. if (typeof (rule.filter) === 'string' && rule.filter.trim().length > 0) {
  871. try {
  872. let filter_json = ungzip(rule.filter.trim());
  873. // log(filter_json);
  874. rule.filter = JSON.parse(filter_json);
  875. } catch (e) {
  876. log(`[${rule.title}] filter ungzip或格式化解密出错: ${e.message}`);
  877. rule.filter = {};
  878. }
  879. }
  880. let classes = [];
  881. if (rule.class_name && rule.class_url) {
  882. let names = rule.class_name.split('&');
  883. let urls = rule.class_url.split('&');
  884. let cnt = Math.min(names.length, urls.length);
  885. for (let i = 0; i < cnt; i++) {
  886. classes.push({
  887. 'type_id': urls[i],
  888. 'type_name': names[i],
  889. 'type_flag': rule['class_flag'],
  890. });
  891. }
  892. }
  893. const jsp = new jsoup(url);
  894. return {
  895. TYPE: 'home',
  896. input: url,
  897. MY_URL: url,
  898. HOST: rule.host,
  899. classes: classes,
  900. filters: rule.filter,
  901. cate_exclude: rule.cate_exclude,
  902. home_flag: rule.home_flag,
  903. fetch_params: deepCopy(rule.rule_fetch_params),
  904. jsp: jsp,
  905. pdfh: jsp.pdfh.bind(jsp),
  906. pdfa: jsp.pdfa.bind(jsp),
  907. pd: jsp.pd.bind(jsp),
  908. pjfh: jsp.pjfh.bind(jsp),
  909. pjfa: jsp.pjfa.bind(jsp),
  910. pj: jsp.pj.bind(jsp),
  911. }
  912. }
  913. async function homeParseAfter(d, _type, hikerListCol, hikerClassListCol, injectVars) {
  914. if (!d) {
  915. d = {};
  916. }
  917. d.type = _type || '影视';
  918. if (hikerListCol) {
  919. d.hikerListCol = hikerListCol;
  920. }
  921. if (hikerClassListCol) {
  922. d.hikerClassListCol = hikerClassListCol;
  923. }
  924. const {
  925. classes,
  926. filters,
  927. cate_exclude,
  928. home_flag,
  929. } = injectVars;
  930. if (!Array.isArray(d.class)) {
  931. d.class = classes;
  932. }
  933. if (!d.filters) {
  934. d.filters = filters;
  935. }
  936. if (!d.list) {
  937. d.list = [];
  938. }
  939. if (!d.type_flag && home_flag) {
  940. d.type_flag = home_flag;
  941. }
  942. d.class = d.class.filter(it => !cate_exclude || !(new RegExp(cate_exclude).test(it.type_name)));
  943. return d
  944. }
  945. async function homeVodParse(rule) {
  946. let url = rule.homeUrl;
  947. const jsp = new jsoup(url);
  948. return {
  949. TYPE: 'home',
  950. input: url,
  951. MY_URL: url,
  952. HOST: rule.host,
  953. double: rule.double,
  954. fetch_params: deepCopy(rule.rule_fetch_params),
  955. jsp: jsp,
  956. pdfh: jsp.pdfh.bind(jsp),
  957. pdfa: jsp.pdfa.bind(jsp),
  958. pd: jsp.pd.bind(jsp),
  959. pjfh: jsp.pjfh.bind(jsp),
  960. pjfa: jsp.pjfa.bind(jsp),
  961. pj: jsp.pj.bind(jsp),
  962. }
  963. }
  964. async function cateParse(rule, tid, pg, filter, extend) {
  965. log(tid, pg, filter, extend);
  966. let url = rule.url.replaceAll('fyclass', tid);
  967. if (pg === 1 && url.includes('[') && url.includes(']')) {
  968. url = url.split('[')[1].split(']')[0];
  969. } else if (pg > 1 && url.includes('[') && url.includes(']')) {
  970. url = url.split('[')[0];
  971. }
  972. if (rule.filter_url) {
  973. if (!/fyfilter/.test(url)) {
  974. if (!url.endsWith('&') && !rule.filter_url.startsWith('&')) {
  975. url += '&'
  976. }
  977. url += rule.filter_url;
  978. } else {
  979. url = url.replace('fyfilter', rule.filter_url);
  980. }
  981. url = url.replaceAll('fyclass', tid);
  982. let fl = filter ? extend : {};
  983. if (rule.filter_def && typeof (rule.filter_def) === 'object') {
  984. try {
  985. if (Object.keys(rule.filter_def).length > 0 && rule.filter_def.hasOwnProperty(tid)) {
  986. let self_fl_def = rule.filter_def[tid];
  987. if (self_fl_def && typeof (self_fl_def) === 'object') {
  988. let fl_def = deepCopy(self_fl_def);
  989. fl = Object.assign(fl_def, fl);
  990. }
  991. }
  992. } catch (e) {
  993. log(`合并不同分类对应的默认筛选出错:${e.message}`);
  994. }
  995. }
  996. let new_url;
  997. new_url = jinja.render(url, {fl: fl, fyclass: tid});
  998. url = new_url;
  999. }
  1000. if (/fypage/.test(url)) {
  1001. if (url.includes('(') && url.includes(')')) {
  1002. let url_rep = url.match(/.*?\((.*)\)/)[1];
  1003. let cnt_page = url_rep.replaceAll('fypage', pg);
  1004. let cnt_pg = eval(cnt_page);
  1005. url = url.replaceAll(url_rep, cnt_pg).replaceAll('(', '').replaceAll(')', '');
  1006. } else {
  1007. url = url.replaceAll('fypage', pg);
  1008. }
  1009. }
  1010. const jsp = new jsoup(url);
  1011. return {
  1012. MY_CATE: tid,
  1013. MY_FL: extend,
  1014. TYPE: 'cate',
  1015. input: url,
  1016. MY_URL: url,
  1017. HOST: rule.host,
  1018. MY_PAGE: pg,
  1019. fetch_params: deepCopy(rule.rule_fetch_params),
  1020. jsp: jsp,
  1021. pdfh: jsp.pdfh.bind(jsp),
  1022. pdfa: jsp.pdfa.bind(jsp),
  1023. pd: jsp.pd.bind(jsp),
  1024. pjfh: jsp.pjfh.bind(jsp),
  1025. pjfa: jsp.pjfa.bind(jsp),
  1026. pj: jsp.pj.bind(jsp),
  1027. }
  1028. }
  1029. async function cateParseAfter(rule, d, pg) {
  1030. return d.length < 1 ? nodata : {
  1031. 'page': parseInt(pg),
  1032. 'pagecount': 9999,
  1033. 'limit': Number(rule.limit) || 20,
  1034. 'total': 999999,
  1035. 'list': d,
  1036. }
  1037. }
  1038. async function detailParse(rule, ids) {
  1039. let vid = ids[0].toString();
  1040. let orId = vid;
  1041. let fyclass = '';
  1042. log('orId:' + orId);
  1043. if (vid.indexOf('$') > -1) {
  1044. let tmp = vid.split('$');
  1045. fyclass = tmp[0];
  1046. vid = tmp[1];
  1047. }
  1048. let detailUrl = vid.split('@@')[0];
  1049. let url;
  1050. if (!detailUrl.startsWith('http') && !detailUrl.includes('/')) {
  1051. url = rule.detailUrl.replaceAll('fyid', detailUrl).replaceAll('fyclass', fyclass);
  1052. } else if (detailUrl.includes('/')) {
  1053. url = urljoin(rule.homeUrl, detailUrl);
  1054. } else {
  1055. url = detailUrl
  1056. }
  1057. const jsp = new jsoup(url);
  1058. return {
  1059. TYPE: 'detail',
  1060. input: url,
  1061. vid: vid,
  1062. orId: orId,
  1063. fyclass: fyclass,
  1064. MY_URL: url,
  1065. HOST: rule.host,
  1066. fetch_params: deepCopy(rule.rule_fetch_params),
  1067. jsp: jsp,
  1068. pdfh: jsp.pdfh.bind(jsp),
  1069. pdfa: jsp.pdfa.bind(jsp),
  1070. pd: jsp.pd.bind(jsp),
  1071. pdfl: jsp.pdfl.bind(jsp), // 二级绑定pdfl函数
  1072. pjfh: jsp.pjfh.bind(jsp),
  1073. pjfa: jsp.pjfa.bind(jsp),
  1074. pj: jsp.pj.bind(jsp),
  1075. }
  1076. }
  1077. async function detailParseAfter(vod) {
  1078. return {
  1079. list: [vod]
  1080. }
  1081. }
  1082. async function searchParse(rule, wd, quick, pg) {
  1083. if (rule.search_encoding) {
  1084. if (rule.search_encoding.toLowerCase() !== 'utf-8') {
  1085. // 按搜索编码进行编码
  1086. wd = encodeStr(wd, rule.search_encoding);
  1087. }
  1088. } else if (rule.encoding && rule.encoding.toLowerCase() !== 'utf-8') {
  1089. // 按全局编码进行编码
  1090. wd = encodeStr(wd, rule.encoding);
  1091. }
  1092. if (!rule.searchUrl) {
  1093. return
  1094. }
  1095. if (rule.searchNoPage && Number(pg) > 1) {
  1096. // 关闭搜索分页
  1097. return '{}'
  1098. }
  1099. let url = rule.searchUrl.replaceAll('**', wd);
  1100. if (pg === 1 && url.includes('[') && url.includes(']') && !url.includes('#')) {
  1101. url = url.split('[')[1].split(']')[0];
  1102. } else if (pg > 1 && url.includes('[') && url.includes(']') && !url.includes('#')) {
  1103. url = url.split('[')[0];
  1104. }
  1105. if (/fypage/.test(url)) {
  1106. if (url.includes('(') && url.includes(')')) {
  1107. let url_rep = url.match(/.*?\((.*)\)/)[1];
  1108. let cnt_page = url_rep.replaceAll('fypage', pg);
  1109. let cnt_pg = eval(cnt_page);
  1110. url = url.replaceAll(url_rep, cnt_pg).replaceAll('(', '').replaceAll(')', '');
  1111. } else {
  1112. url = url.replaceAll('fypage', pg);
  1113. }
  1114. }
  1115. const jsp = new jsoup(url);
  1116. return {
  1117. TYPE: 'search',
  1118. MY_PAGE: pg,
  1119. KEY: wd,
  1120. input: url,
  1121. MY_URL: url,
  1122. HOST: rule.host,
  1123. detailUrl: rule.detailUrl || '',
  1124. fetch_params: deepCopy(rule.rule_fetch_params),
  1125. jsp: jsp,
  1126. pdfh: jsp.pdfh.bind(jsp),
  1127. pdfa: jsp.pdfa.bind(jsp),
  1128. pd: jsp.pd.bind(jsp),
  1129. pjfh: jsp.pjfh.bind(jsp),
  1130. pjfa: jsp.pjfa.bind(jsp),
  1131. pj: jsp.pj.bind(jsp),
  1132. }
  1133. }
  1134. async function searchParseAfter(rule, d, pg) {
  1135. return {
  1136. 'page': parseInt(pg),
  1137. 'pagecount': 9999,
  1138. 'limit': Number(rule.limit) || 20,
  1139. 'total': 999999,
  1140. 'list': d,
  1141. }
  1142. }
  1143. async function playParse(rule, flag, id, flags) {
  1144. let url = id;
  1145. if (!/http/.test(url)) {
  1146. try {
  1147. url = base64Decode(url);
  1148. log('[playParse]: id is base64 data');
  1149. } catch (e) {
  1150. }
  1151. }
  1152. url = decodeURIComponent(url);
  1153. if (!/^http/.test(url)) {
  1154. url = id;
  1155. }
  1156. if (id !== url) {
  1157. log(`[playParse]: ${id} => ${url}`);
  1158. } else {
  1159. log(`[playParse]: ${url}`);
  1160. }
  1161. const jsp = new jsoup(url);
  1162. return {
  1163. TYPE: 'play',
  1164. MY_FLAG: flag,
  1165. flag: flag,
  1166. input: url,
  1167. MY_URL: url,
  1168. HOST: rule.host,
  1169. fetch_params: deepCopy(rule.rule_fetch_params),
  1170. jsp: jsp,
  1171. pdfh: jsp.pdfh.bind(jsp),
  1172. pdfa: jsp.pdfa.bind(jsp),
  1173. pd: jsp.pd.bind(jsp),
  1174. pjfh: jsp.pjfh.bind(jsp),
  1175. pjfa: jsp.pjfa.bind(jsp),
  1176. pj: jsp.pj.bind(jsp),
  1177. }
  1178. }
  1179. async function playParseAfter(rule, obj, playUrl, flag) {
  1180. let common_play = {
  1181. parse: SPECIAL_URL.test(playUrl) || /^(push:)/.test(playUrl) ? 0 : 1,
  1182. url: playUrl,
  1183. flag: flag,
  1184. jx: tellIsJx(playUrl)
  1185. };
  1186. let lazy_play;
  1187. if (!rule.play_parse || !rule.lazy) {
  1188. lazy_play = common_play;
  1189. } else if (rule.play_parse && rule.lazy && typeof (rule.lazy) === 'function') {
  1190. try {
  1191. lazy_play = typeof (obj) === 'object' ? obj : {
  1192. parse: SPECIAL_URL.test(obj) || /^(push:)/.test(obj) ? 0 : 1,
  1193. jx: tellIsJx(obj),
  1194. url: obj
  1195. };
  1196. } catch (e) {
  1197. log(`js免嗅错误:${e.message}`);
  1198. lazy_play = common_play;
  1199. }
  1200. } else {
  1201. lazy_play = common_play;
  1202. }
  1203. if (Array.isArray(rule.play_json) && rule.play_json.length > 0) { // 数组情况判断长度大于0
  1204. let web_url = lazy_play.url;
  1205. for (let pjson of rule.play_json) {
  1206. if (pjson.re && (pjson.re === '*' || web_url.match(new RegExp(pjson.re)))) {
  1207. if (pjson.json && typeof (pjson.json) === 'object') {
  1208. let base_json = pjson.json;
  1209. lazy_play = Object.assign(lazy_play, base_json);
  1210. break;
  1211. }
  1212. }
  1213. }
  1214. } else if (rule.play_json && !Array.isArray(rule.play_json)) { // 其他情况 非[] 判断true/false
  1215. let base_json = {
  1216. jx: 1,
  1217. parse: 1,
  1218. };
  1219. lazy_play = Object.assign(lazy_play, base_json);
  1220. } else if (!rule.play_json) { // 不解析传0
  1221. let base_json = {
  1222. jx: 0,
  1223. parse: 1,
  1224. };
  1225. lazy_play = Object.assign(lazy_play, base_json);
  1226. }
  1227. return lazy_play
  1228. }
  1229. async function proxyParse(rule, params) {
  1230. // log('proxyParse:', params);
  1231. return {
  1232. TYPE: 'proxy',
  1233. input: params.url || '',
  1234. MY_URL: params.url || '',
  1235. }
  1236. }
  1237. export async function home(filePath, env, filter = 1) {
  1238. return await invokeMethod(filePath, env, 'class_parse', [filter], {
  1239. input: '$.homeUrl',
  1240. MY_URL: '$.homeUrl'
  1241. });
  1242. }
  1243. export async function homeVod(filePath, env) {
  1244. return await invokeMethod(filePath, env, '推荐', [], {
  1245. input: '$.homeUrl',
  1246. MY_URL: '$.homeUrl'
  1247. });
  1248. }
  1249. export async function cate(filePath, env, tid, pg = 1, filter = 1, extend = {}) {
  1250. return await invokeMethod(filePath, env, '一级', [tid, pg, filter, extend], {
  1251. input: '$.url',
  1252. MY_URL: '$.url'
  1253. });
  1254. }
  1255. export async function detail(filePath, env, ids) {
  1256. if (!Array.isArray(ids)) throw new Error('Parameter "ids" must be an array');
  1257. return await invokeMethod(filePath, env, '二级', [ids], {
  1258. input: `${ids[0]}`,
  1259. MY_URL: `${ids[0]}`
  1260. });
  1261. }
  1262. export async function search(filePath, env, wd, quick = 0, pg = 1) {
  1263. return await invokeMethod(filePath, env, '搜索', [wd, quick, pg], {
  1264. input: '$.searchUrl',
  1265. MY_URL: '$.searchUrl'
  1266. });
  1267. }
  1268. export async function play(filePath, env, flag, id, flags) {
  1269. flags = flags || [];
  1270. if (!Array.isArray(flags)) throw new Error('Parameter "flags" must be an array');
  1271. return await invokeMethod(filePath, env, 'lazy', [flag, id, flags], {
  1272. input: `${id}`,
  1273. MY_URL: `${id}`,
  1274. });
  1275. }
  1276. export async function proxy(filePath, env, params) {
  1277. params = params || {};
  1278. try {
  1279. return await invokeMethod(filePath, env, 'proxy_rule', [deepCopy(params)], {
  1280. input: `${params.url}`,
  1281. MY_URL: `${params.url}`,
  1282. });
  1283. } catch (e) {
  1284. return [500, 'text/plain', '代理规则错误:' + e.message]
  1285. }
  1286. }
  1287. export async function action(filePath, env, action, value) {
  1288. try {
  1289. return await invokeMethod(filePath, env, 'action', [action, value], {});
  1290. } catch (e) {
  1291. return '动作规则错误:' + e.message
  1292. }
  1293. }
  1294. export async function getRule(filePath, env) {
  1295. return await invokeMethod(filePath, env, 'get_rule', [], {});
  1296. }
  1297. export async function jx(filePath, env, params) {
  1298. params = params || {};
  1299. try {
  1300. const jxObj = await initJx(filePath, env); // 确保模块已初始化
  1301. const lazy = await jxObj.lazy;
  1302. const result = await lazy(params.url || '', params);
  1303. // log(`[jx]: ${JSON.stringify(result)}`);
  1304. return result;
  1305. } catch (e) {
  1306. return {code: 404, url: '', msg: `${filePath} 代理解析错误:${e.message}`, cost: ''}
  1307. }
  1308. }
  1309. export async function getJx(filePath) {
  1310. try {
  1311. // 确保模块已初始化
  1312. const jxObj = await initJx(filePath, {});
  1313. // console.log('jxObj:', jxObj);
  1314. return jxObj;
  1315. } catch (e) {
  1316. return {code: 403, error: `${filePath} 获取代理信息错误:${e.message}`}
  1317. }
  1318. }
  1319. /**
  1320. * 获取加密前的原始的js源文本
  1321. * @param js_code
  1322. */
  1323. export function getOriginalJs(js_code) {
  1324. let current_match = /var rule|[\u4E00-\u9FA5]+|function|let |var |const |\(|\)|"|'/;
  1325. if (current_match.test(js_code)) {
  1326. return js_code
  1327. }
  1328. let rsa_private_key = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqin/jUpqM6+fgYP/oMqj9zcdHMM0mEZXLeTyixIJWP53lzJV2N2E3OP6BBpUmq2O1a9aLnTIbADBaTulTNiOnVGoNG58umBnupnbmmF8iARbDp2mTzdMMeEgLdrfXS6Y3VvazKYALP8EhEQykQVarexR78vRq7ltY3quXx7cgI0ROfZz5Sw3UOLQJ+VoWmwIxu9AMEZLVzFDQN93hzuzs3tNyHK6xspBGB7zGbwCg+TKi0JeqPDrXxYUpAz1cQ/MO+Da0WgvkXnvrry8NQROHejdLVOAslgr6vYthH9bKbsGyNY3H+P12kcxo9RAcVveONnZbcMyxjtF5dWblaernAgMBAAECggEAGdEHlSEPFmAr5PKqKrtoi6tYDHXdyHKHC5tZy4YV+Pp+a6gxxAiUJejx1hRqBcWSPYeKne35BM9dgn5JofgjI5SKzVsuGL6bxl3ayAOu+xXRHWM9f0t8NHoM5fdd0zC3g88dX3fb01geY2QSVtcxSJpEOpNH3twgZe6naT2pgiq1S4okpkpldJPo5GYWGKMCHSLnKGyhwS76gF8bTPLoay9Jxk70uv6BDUMlA4ICENjmsYtd3oirWwLwYMEJbSFMlyJvB7hjOjR/4RpT4FPnlSsIpuRtkCYXD4jdhxGlvpXREw97UF2wwnEUnfgiZJ2FT/MWmvGGoaV/CfboLsLZuQKBgQDTNZdJrs8dbijynHZuuRwvXvwC03GDpEJO6c1tbZ1s9wjRyOZjBbQFRjDgFeWs9/T1aNBLUrgsQL9c9nzgUziXjr1Nmu52I0Mwxi13Km/q3mT+aQfdgNdu6ojsI5apQQHnN/9yMhF6sNHg63YOpH+b+1bGRCtr1XubuLlumKKscwKBgQDOtQ2lQjMtwsqJmyiyRLiUOChtvQ5XI7B2mhKCGi8kZ+WEAbNQcmThPesVzW+puER6D4Ar4hgsh9gCeuTaOzbRfZ+RLn3Aksu2WJEzfs6UrGvm6DU1INn0z/tPYRAwPX7sxoZZGxqML/z+/yQdf2DREoPdClcDa2Lmf1KpHdB+vQKBgBXFCVHz7a8n4pqXG/HvrIMJdEpKRwH9lUQS/zSPPtGzaLpOzchZFyQQBwuh1imM6Te+VPHeldMh3VeUpGxux39/m+160adlnRBS7O7CdgSsZZZ/dusS06HAFNraFDZf1/VgJTk9BeYygX+AZYu+0tReBKSs9BjKSVJUqPBIVUQXAoGBAJcZ7J6oVMcXxHxwqoAeEhtvLcaCU9BJK36XQ/5M67ceJ72mjJC6/plUbNukMAMNyyi62gO6I9exearecRpB/OGIhjNXm99Ar59dAM9228X8gGfryLFMkWcO/fNZzb6lxXmJ6b2LPY3KqpMwqRLTAU/zy+ax30eFoWdDHYa4X6e1AoGAfa8asVGOJ8GL9dlWufEeFkDEDKO9ww5GdnpN+wqLwePWqeJhWCHad7bge6SnlylJp5aZXl1+YaBTtOskC4Whq9TP2J+dNIgxsaF5EFZQJr8Xv+lY9lu0CruYOh9nTNF9x3nubxJgaSid/7yRPfAGnsJRiknB5bsrCvgsFQFjJVs=';
  1329. let decode_content = '';
  1330. function aes_decrypt(data) {
  1331. // log(data);
  1332. let key = CryptoJS.enc.Hex.parse("686A64686E780A0A0A0A0A0A0A0A0A0A");
  1333. let iv = CryptoJS.enc.Hex.parse("647A797964730A0A0A0A0A0A0A0A0A0A");
  1334. let ciphertext = CryptoJS.enc.Base64.parse(data);
  1335. let decrypted = CryptoJS.AES.decrypt({ciphertext: ciphertext}, key, {
  1336. iv: iv,
  1337. mode: CryptoJS.mode.CBC,
  1338. padding: CryptoJS.pad.Pkcs7
  1339. }).toString(CryptoJS.enc.Utf8);
  1340. // log(decrypted);
  1341. return decrypted;
  1342. }
  1343. let error_log = false;
  1344. function logger(text) {
  1345. // console.log('[logger]:', text);
  1346. if (error_log) {
  1347. log(text);
  1348. }
  1349. }
  1350. let decode_funcs = [
  1351. (text) => {
  1352. try {
  1353. return ungzip(text)
  1354. } catch (e) {
  1355. logger('非gzip加密');
  1356. return ''
  1357. }
  1358. },
  1359. (text) => {
  1360. try {
  1361. return base64Decode(text)
  1362. } catch (e) {
  1363. logger('非b64加密');
  1364. return ''
  1365. }
  1366. },
  1367. (text) => {
  1368. try {
  1369. return aes_decrypt(text)
  1370. } catch (e) {
  1371. logger('非aes加密');
  1372. return ''
  1373. }
  1374. },
  1375. (text) => {
  1376. try {
  1377. return RSA.decode(text, rsa_private_key, null)
  1378. } catch (e) {
  1379. logger('非rsa加密');
  1380. return ''
  1381. }
  1382. },
  1383. // (text) => {
  1384. // try {
  1385. // return NODERSA.decryptRSAWithPrivateKey(text, RSA.getPrivateKey(rsa_private_key).replace(/RSA /g, ''), {
  1386. // options: {
  1387. // environment: "browser",
  1388. // encryptionScheme: 'pkcs1',
  1389. // b: '1024'
  1390. // }
  1391. // });
  1392. // } catch (e) {
  1393. // log(e.message);
  1394. // return ''
  1395. // }
  1396. // },
  1397. ]
  1398. let func_index = 0
  1399. while (!current_match.test(decode_content)) {
  1400. decode_content = decode_funcs[func_index](js_code);
  1401. func_index++;
  1402. if (func_index >= decode_funcs.length) {
  1403. break;
  1404. }
  1405. }
  1406. return decode_content
  1407. }
  1408. export const jsEncoder = {
  1409. base64Encode,
  1410. gzip,
  1411. aes_encrypt: function (data) {
  1412. // 定义密钥和初始向量,必须与解密时一致
  1413. let key = CryptoJS.enc.Hex.parse("686A64686E780A0A0A0A0A0A0A0A0A0A");
  1414. let iv = CryptoJS.enc.Hex.parse("647A797964730A0A0A0A0A0A0A0A0A0A");
  1415. // 使用AES加密
  1416. let encrypted = CryptoJS.AES.encrypt(data, key, {
  1417. iv: iv,
  1418. mode: CryptoJS.mode.CBC,
  1419. padding: CryptoJS.pad.Pkcs7
  1420. });
  1421. // 返回Base64编码的加密结果
  1422. return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
  1423. // 返回完整的加密结果(包括 IV 和其他元数据)
  1424. // return encrypted.toString(); // Base64 格式
  1425. },
  1426. rsa_encode: function (text) {
  1427. let rsa_private_key = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqin/jUpqM6+fgYP/oMqj9zcdHMM0mEZXLeTyixIJWP53lzJV2N2E3OP6BBpUmq2O1a9aLnTIbADBaTulTNiOnVGoNG58umBnupnbmmF8iARbDp2mTzdMMeEgLdrfXS6Y3VvazKYALP8EhEQykQVarexR78vRq7ltY3quXx7cgI0ROfZz5Sw3UOLQJ+VoWmwIxu9AMEZLVzFDQN93hzuzs3tNyHK6xspBGB7zGbwCg+TKi0JeqPDrXxYUpAz1cQ/MO+Da0WgvkXnvrry8NQROHejdLVOAslgr6vYthH9bKbsGyNY3H+P12kcxo9RAcVveONnZbcMyxjtF5dWblaernAgMBAAECggEAGdEHlSEPFmAr5PKqKrtoi6tYDHXdyHKHC5tZy4YV+Pp+a6gxxAiUJejx1hRqBcWSPYeKne35BM9dgn5JofgjI5SKzVsuGL6bxl3ayAOu+xXRHWM9f0t8NHoM5fdd0zC3g88dX3fb01geY2QSVtcxSJpEOpNH3twgZe6naT2pgiq1S4okpkpldJPo5GYWGKMCHSLnKGyhwS76gF8bTPLoay9Jxk70uv6BDUMlA4ICENjmsYtd3oirWwLwYMEJbSFMlyJvB7hjOjR/4RpT4FPnlSsIpuRtkCYXD4jdhxGlvpXREw97UF2wwnEUnfgiZJ2FT/MWmvGGoaV/CfboLsLZuQKBgQDTNZdJrs8dbijynHZuuRwvXvwC03GDpEJO6c1tbZ1s9wjRyOZjBbQFRjDgFeWs9/T1aNBLUrgsQL9c9nzgUziXjr1Nmu52I0Mwxi13Km/q3mT+aQfdgNdu6ojsI5apQQHnN/9yMhF6sNHg63YOpH+b+1bGRCtr1XubuLlumKKscwKBgQDOtQ2lQjMtwsqJmyiyRLiUOChtvQ5XI7B2mhKCGi8kZ+WEAbNQcmThPesVzW+puER6D4Ar4hgsh9gCeuTaOzbRfZ+RLn3Aksu2WJEzfs6UrGvm6DU1INn0z/tPYRAwPX7sxoZZGxqML/z+/yQdf2DREoPdClcDa2Lmf1KpHdB+vQKBgBXFCVHz7a8n4pqXG/HvrIMJdEpKRwH9lUQS/zSPPtGzaLpOzchZFyQQBwuh1imM6Te+VPHeldMh3VeUpGxux39/m+160adlnRBS7O7CdgSsZZZ/dusS06HAFNraFDZf1/VgJTk9BeYygX+AZYu+0tReBKSs9BjKSVJUqPBIVUQXAoGBAJcZ7J6oVMcXxHxwqoAeEhtvLcaCU9BJK36XQ/5M67ceJ72mjJC6/plUbNukMAMNyyi62gO6I9exearecRpB/OGIhjNXm99Ar59dAM9228X8gGfryLFMkWcO/fNZzb6lxXmJ6b2LPY3KqpMwqRLTAU/zy+ax30eFoWdDHYa4X6e1AoGAfa8asVGOJ8GL9dlWufEeFkDEDKO9ww5GdnpN+wqLwePWqeJhWCHad7bge6SnlylJp5aZXl1+YaBTtOskC4Whq9TP2J+dNIgxsaF5EFZQJr8Xv+lY9lu0CruYOh9nTNF9x3nubxJgaSid/7yRPfAGnsJRiknB5bsrCvgsFQFjJVs=';
  1428. return RSA.encode(text, rsa_private_key, null);
  1429. }
  1430. };
  1431. export const jsDecoder = {
  1432. base64Decode,
  1433. ungzip,
  1434. aes_decrypt: function (data) {
  1435. let key = CryptoJS.enc.Hex.parse("686A64686E780A0A0A0A0A0A0A0A0A0A");
  1436. let iv = CryptoJS.enc.Hex.parse("647A797964730A0A0A0A0A0A0A0A0A0A");
  1437. let ciphertext = CryptoJS.enc.Base64.parse(data);
  1438. let decrypted = CryptoJS.AES.decrypt({ciphertext: ciphertext}, key, {
  1439. iv: iv,
  1440. mode: CryptoJS.mode.CBC,
  1441. padding: CryptoJS.pad.Pkcs7
  1442. }).toString(CryptoJS.enc.Utf8);
  1443. return decrypted;
  1444. },
  1445. rsa_decode: function (text) {
  1446. let rsa_private_key = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqin/jUpqM6+fgYP/oMqj9zcdHMM0mEZXLeTyixIJWP53lzJV2N2E3OP6BBpUmq2O1a9aLnTIbADBaTulTNiOnVGoNG58umBnupnbmmF8iARbDp2mTzdMMeEgLdrfXS6Y3VvazKYALP8EhEQykQVarexR78vRq7ltY3quXx7cgI0ROfZz5Sw3UOLQJ+VoWmwIxu9AMEZLVzFDQN93hzuzs3tNyHK6xspBGB7zGbwCg+TKi0JeqPDrXxYUpAz1cQ/MO+Da0WgvkXnvrry8NQROHejdLVOAslgr6vYthH9bKbsGyNY3H+P12kcxo9RAcVveONnZbcMyxjtF5dWblaernAgMBAAECggEAGdEHlSEPFmAr5PKqKrtoi6tYDHXdyHKHC5tZy4YV+Pp+a6gxxAiUJejx1hRqBcWSPYeKne35BM9dgn5JofgjI5SKzVsuGL6bxl3ayAOu+xXRHWM9f0t8NHoM5fdd0zC3g88dX3fb01geY2QSVtcxSJpEOpNH3twgZe6naT2pgiq1S4okpkpldJPo5GYWGKMCHSLnKGyhwS76gF8bTPLoay9Jxk70uv6BDUMlA4ICENjmsYtd3oirWwLwYMEJbSFMlyJvB7hjOjR/4RpT4FPnlSsIpuRtkCYXD4jdhxGlvpXREw97UF2wwnEUnfgiZJ2FT/MWmvGGoaV/CfboLsLZuQKBgQDTNZdJrs8dbijynHZuuRwvXvwC03GDpEJO6c1tbZ1s9wjRyOZjBbQFRjDgFeWs9/T1aNBLUrgsQL9c9nzgUziXjr1Nmu52I0Mwxi13Km/q3mT+aQfdgNdu6ojsI5apQQHnN/9yMhF6sNHg63YOpH+b+1bGRCtr1XubuLlumKKscwKBgQDOtQ2lQjMtwsqJmyiyRLiUOChtvQ5XI7B2mhKCGi8kZ+WEAbNQcmThPesVzW+puER6D4Ar4hgsh9gCeuTaOzbRfZ+RLn3Aksu2WJEzfs6UrGvm6DU1INn0z/tPYRAwPX7sxoZZGxqML/z+/yQdf2DREoPdClcDa2Lmf1KpHdB+vQKBgBXFCVHz7a8n4pqXG/HvrIMJdEpKRwH9lUQS/zSPPtGzaLpOzchZFyQQBwuh1imM6Te+VPHeldMh3VeUpGxux39/m+160adlnRBS7O7CdgSsZZZ/dusS06HAFNraFDZf1/VgJTk9BeYygX+AZYu+0tReBKSs9BjKSVJUqPBIVUQXAoGBAJcZ7J6oVMcXxHxwqoAeEhtvLcaCU9BJK36XQ/5M67ceJ72mjJC6/plUbNukMAMNyyi62gO6I9exearecRpB/OGIhjNXm99Ar59dAM9228X8gGfryLFMkWcO/fNZzb6lxXmJ6b2LPY3KqpMwqRLTAU/zy+ax30eFoWdDHYa4X6e1AoGAfa8asVGOJ8GL9dlWufEeFkDEDKO9ww5GdnpN+wqLwePWqeJhWCHad7bge6SnlylJp5aZXl1+YaBTtOskC4Whq9TP2J+dNIgxsaF5EFZQJr8Xv+lY9lu0CruYOh9nTNF9x3nubxJgaSid/7yRPfAGnsJRiknB5bsrCvgsFQFjJVs=';
  1447. return RSA.decode(text, rsa_private_key, null);
  1448. }
  1449. };
  1450. /**
  1451. * 执行main函数
  1452. * 示例 function main(text){return gzip(text)}
  1453. * @param main_func_code
  1454. * @param arg
  1455. */
  1456. export async function runMain(main_func_code, arg) {
  1457. let mainFunc = async function () {
  1458. return ''
  1459. };
  1460. try {
  1461. eval(main_func_code + '\nmainFunc=main;');
  1462. return mainFunc(arg);
  1463. } catch (e) {
  1464. log(`执行main_func_code发生了错误:${e.message}`);
  1465. return ''
  1466. }
  1467. }