drpyS.js 55 KB

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