对话1.txt 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. 我基于你的代码做了一些调整,接下来请更新记忆:
  2. 1. index2.js
  3. import Fastify from 'fastify';
  4. import * as drpy from './libs/drpy.js';
  5. import path from 'path';
  6. import {fileURLToPath} from 'url';
  7. const fastify = Fastify({logger: true});
  8. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  9. console.log('__dirname:', __dirname);
  10. // 动态加载模块并根据 query 执行不同逻辑
  11. fastify.get('/api/:module', async (request, reply) => {
  12. const moduleName = request.params.module;
  13. const query = request.query; // 获取 query 参数
  14. const modulePath = path.join(__dirname, 'js', `${moduleName}.js`);
  15. try {
  16. // 根据 query 参数决定执行逻辑
  17. if ('play' in query) {
  18. // 处理播放逻辑
  19. const result = await drpy.play(modulePath);
  20. return reply.send(result);
  21. }
  22. if ('ac' in query && 't' in query) {
  23. // 分类逻辑
  24. const result = await drpy.cate(modulePath);
  25. return reply.send(result);
  26. }
  27. if ('ac' in query && 'ids' in query) {
  28. // 详情逻辑
  29. const result = await drpy.detail(modulePath);
  30. return reply.send(result);
  31. }
  32. if ('wd' in query) {
  33. // 搜索逻辑
  34. const result = await drpy.search(modulePath);
  35. return reply.send(result);
  36. }
  37. if ('refresh' in query) {
  38. // 强制刷新初始化逻辑
  39. const refreshedObject = await drpy.init(modulePath, true);
  40. return reply.send(refreshedObject);
  41. }
  42. // 默认逻辑,返回 home + homeVod 接口
  43. const result_home = await drpy.home(modulePath);
  44. const result_homeVod = await drpy.homeVod(modulePath);
  45. const result = {
  46. class: result_home,
  47. list: result_homeVod
  48. }
  49. reply.send(result);
  50. } catch (error) {
  51. console.log('Error processing request:', error);
  52. reply.status(500).send({error: `Failed to process request for module ${moduleName}: ${error.message}`});
  53. }
  54. });
  55. // 启动服务
  56. const start = async () => {
  57. try {
  58. await fastify.listen(5757);
  59. console.log('Server listening at http://localhost:5757');
  60. } catch (err) {
  61. fastify.log.error(err);
  62. process.exit(1);
  63. }
  64. };
  65. start();
  66. 2. libs/drpy.js
  67. import * as utils from '../utils/utils.js'; // 使用 import 引入工具类
  68. import {readFile} from 'fs/promises';
  69. import vm from 'vm'; // Node.js 的 vm 模块
  70. const {req} = await import('../utils/req.js');
  71. const {sleep, sleepSync} = await import('../utils/utils.js');
  72. // 缓存已初始化的模块
  73. const moduleCache = new Map();
  74. /**
  75. * 初始化模块:加载并执行模块文件,存储初始化后的 rule 对象
  76. * 如果存在 `预处理` 属性且为函数,会在缓存前执行
  77. * @param {string} filePath - 模块文件路径
  78. * @param refresh 强制清除缓存
  79. * @returns {Promise<object>} - 返回初始化后的模块对象
  80. */
  81. export async function init(filePath, refresh) {
  82. if (moduleCache.has(filePath) && !refresh) {
  83. console.log(`Module ${filePath} already initialized, returning cached instance.`);
  84. return moduleCache.get(filePath);
  85. }
  86. try {
  87. let t1 = utils.getNowTime();
  88. // 读取 JS 文件的内容
  89. const fileContent = await readFile(filePath, 'utf-8');
  90. // 创建一个沙箱上下文,注入需要的全局变量和函数
  91. const sandbox = {
  92. console,
  93. req,
  94. sleep,
  95. sleepSync,
  96. utils,
  97. rule: {}, // 用于存放导出的 rule 对象
  98. };
  99. // 创建一个上下文
  100. const context = vm.createContext(sandbox);
  101. // 执行文件内容,将其放入沙箱中
  102. const script = new vm.Script(fileContent);
  103. script.runInContext(context);
  104. // 访问沙箱中的 rule 对象
  105. const moduleObject = utils.deepCopy(sandbox.rule);
  106. // 检查并执行 `预处理` 方法
  107. if (typeof moduleObject.预处理 === 'function') {
  108. console.log('Executing preprocessing...');
  109. await moduleObject.预处理();
  110. }
  111. // 缓存初始化后的模块
  112. moduleCache.set(filePath, moduleObject);
  113. let t2 = utils.getNowTime();
  114. moduleObject.cost = t2 - t1;
  115. return moduleObject;
  116. } catch (error) {
  117. console.log('Error in drpy.init:', error);
  118. throw new Error('Failed to initialize module');
  119. }
  120. }
  121. /**
  122. * 调用模块的指定方法
  123. * @param {string} filePath - 模块文件路径
  124. * @param {string} method - 要调用的属性方法名称
  125. * @returns {Promise<any>} - 方法调用的返回值
  126. */
  127. async function invokeMethod(filePath, method) {
  128. const moduleObject = await init(filePath); // 确保模块已初始化
  129. if (moduleObject[method] && typeof moduleObject[method] === 'function') {
  130. return await moduleObject[method](); // 调用对应的方法
  131. } else {
  132. throw new Error(`Method ${method} not found in module ${filePath}`);
  133. }
  134. }
  135. // 各种接口调用方法
  136. export async function home(filePath) {
  137. return await invokeMethod(filePath, 'class_parse');
  138. }
  139. export async function homeVod(filePath) {
  140. return await invokeMethod(filePath, '推荐');
  141. }
  142. export async function cate(filePath) {
  143. return await invokeMethod(filePath, '一级');
  144. }
  145. export async function detail(filePath) {
  146. return await invokeMethod(filePath, '二级');
  147. }
  148. export async function search(filePath) {
  149. return await invokeMethod(filePath, '搜索');
  150. }
  151. export async function play(filePath) {
  152. return await invokeMethod(filePath, 'lazy');
  153. }
  154. 3.utils/req.js
  155. export async function req(param) {
  156. // 模拟异步请求
  157. return new Promise((resolve) => {
  158. setTimeout(() => {
  159. resolve(`Response for ${param}`);
  160. }, 1000);
  161. });
  162. }
  163. 4.utils/utils.js
  164. // utils.js: 存放工具类方法
  165. import pkg from 'lodash';
  166. const {cloneDeep} = pkg;
  167. export function getTitleLength(title) {
  168. return title.length; // 返回标题长度
  169. }
  170. export function getNowTime() {
  171. return (new Date()).getTime()
  172. }
  173. export async function sleep(ms) {
  174. // 模拟异步请求
  175. return new Promise((resolve) => {
  176. setTimeout(() => {
  177. resolve();
  178. }, ms);
  179. });
  180. }
  181. export function sleepSync(ms) {
  182. const end = Date.now() + ms; // 获取当前时间并计算结束时间
  183. while (Date.now() < end) {
  184. // 阻塞式等待,直到时间到达
  185. }
  186. }
  187. export const deepCopy = cloneDeep
  188. 5. js/_360.js
  189. // js/_360.js
  190. var rule = {
  191. title: '标题1',
  192. description: '这是描述',
  193. category: '视频',
  194. class_parse: async () => {
  195. console.log('执行了分类获取')
  196. return [
  197. {type_id: '1', type_name: '电影'},
  198. {type_id: '2', type_name: '电视剧'},
  199. {type_id: '3', type_name: '综艺'},
  200. {type_id: '4', type_name: '动漫'},
  201. ]
  202. },
  203. 预处理: async () => {
  204. console.log('执行了预处理')
  205. rule.title = '360影视'
  206. },
  207. 推荐: async () => {
  208. sleepSync(2000);
  209. console.log('进入了推荐')
  210. // return '这是推荐:' + rule.title
  211. return [
  212. {vod_name: '测试电影1', vod_pic: '1.png', vod_remarks: '测试描述1', vod_id: 'http://www.1.com'},
  213. {vod_name: '测试电影2', vod_pic: '2.png', vod_remarks: '测试描述2', vod_id: 'http://www.2.com'},
  214. ]
  215. },
  216. 一级: async () => {
  217. // await sleep(200);
  218. sleepSync(200);
  219. let html = await req('123');
  220. console.log('title:', rule.title);
  221. console.log('html:' + html);
  222. return html + '\n' + '这是一级:' + rule.title
  223. },
  224. 二级: async () => {
  225. return '这是二级:' + rule.title
  226. },
  227. 搜索: async () => {
  228. return '这是搜索:' + rule.title
  229. },
  230. lazy: async () => {
  231. return '这是播放:' + rule.title
  232. },
  233. };