JOJO影视.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. import req from '../../util/req.js';
  2. import pkg from 'lodash';
  3. const { _ } = pkg;
  4. import CryptoJS from 'crypto-js';
  5. import { load } from 'cheerio';
  6. import axios from 'axios';
  7. import Crypto from 'crypto-js';
  8. import dayjs from 'dayjs';
  9. let key = 'jiohub';
  10. let url = 'https://jiohub.top';
  11. let siteKey = '';
  12. let siteType = 0;
  13. const UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1';
  14. const cookie = {};
  15. async function request(reqUrl, referer, mth, data, hd) {
  16. const headers = {
  17. 'User-Agent': UA,
  18. Cookie: _.map(cookie, (value, key) => {
  19. return `${key}=${value}`;
  20. }).join(';'),
  21. 'Authorization' : null,
  22. 'Sec-Fetch-Dest' : 'empty',
  23. 'Sec-Fetch-Mode' : 'cors',
  24. 'Sec-Fetch-Site' : 'cross-site',
  25. 'Content-Type' : 'application/json'
  26. };
  27. if (referer) headers.referer = encodeURIComponent(referer);
  28. let res = await req(reqUrl, {
  29. method: mth || 'get',
  30. headers: headers,
  31. data: data,
  32. postType: mth === 'post' ? 'form' : '',
  33. });
  34. return res.data;
  35. }
  36. // cfg = {skey: siteKey, ext: extend}
  37. async function init(inReq, _outResp) {
  38. // siteKey = cfg.skey;
  39. // siteType = cfg.stype;
  40. return {};
  41. }
  42. async function home(inReq, _outResp) {
  43. return JSON.stringify({
  44. 'class': [{'type_id':'最新','type_name':'最新'},{'type_id':'电影','type_name':'电影'},{'type_id':'美剧','type_name':'美剧'},{'type_id':'韩剧','type_name':'韩剧'},{'type_id':'日剧','type_name':'日剧'},{'type_id':'动漫','type_name':'动漫'},{'type_id':'国产','type_name':'国产'}],
  45. 'filters': {
  46. "最新3":[{"key":"tag","name":"标签","value":[{"n":"全部","v":"标签"},{"n":"国产剧","v":"国产剧"},{"n":"港台剧","v":"港台剧"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":"地区"},{"n":"内地","v":"内地"},{"n":"香港地区","v":"香港地区"},{"n":"台湾地区","v":"台湾地区"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":"年份"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"10年代","v":"10年代"},{"n":"00年代","v":"00年代"},{"n":"90年代","v":"90年代"},{"n":"80年代","v":"80年代"}]},{"key":"by","name":"排序","value":[{"n":"热播榜","v":"热播榜"},{"n":"好评榜","v":"好评榜"},{"n":"新上线","v":"新上线"}]}],
  47. "1":[{"key":"class","name":"类型","value":[{"n":"全部","v":"类型"},{"n":"动作片","v":"动作片"},{"n":"喜剧片","v":"喜剧片"},{"n":"爱情片","v":"爱情片"},{"n":"科幻片","v":"科幻片"},{"n":"恐怖片","v":"恐怖片"},{"n":"剧情片","v":"剧情片"},{"n":"战争片","v":"战争片"},{"n":"惊悚片","v":"惊悚片"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":"地区"},{"n":"华语","v":"华语"},{"n":"香港地区","v":"香港地区"},{"n":"美国","v":"美国"},{"n":"欧洲","v":"欧洲"},{"n":"韩国","v":"韩国"},{"n":"日本","v":"日本"},{"n":"台湾地区","v":"台湾地区"},{"n":"泰国","v":"泰国"},{"n":"台湾地区","v":"台湾地区"},{"n":"印度","v":"印度"},{"n":"其它","v":"其它"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":"年份"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"10年代","v":"10年代"},{"n":"00年代","v":"00年代"},{"n":"90年代","v":"90年代"},{"n":"80年代","v":"80年代"}]},{"key":"by","name":"排序","value":[{"n":"热播榜","v":"热播榜"},{"n":"好评榜","v":"好评榜"},{"n":"新上线","v":"新上线"}]}],
  48. "4":[{"key":"class","name":"类型","value":[{"n":"全部","v":"类型"},{"n":"国产漫","v":"国产漫"},{"n":"欧美漫","v":"欧美漫"},{"n":"日韩漫","v":"日韩漫"},{"n":"港台漫","v":"港台漫"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":"地区"},{"n":"中国大陆","v":"中国大陆"},{"n":"日本","v":"日本"},{"n":"韩国","v":"韩国"},{"n":"欧美","v":"欧美"},{"n":"其它","v":"其它"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":"年份"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"10年代","v":"10年代"},{"n":"00年代","v":"00年代"},{"n":"90年代","v":"90年代"},{"n":"80年代","v":"80年代"}]},{"key":"by","name":"排序","value":[{"n":"热播榜","v":"热播榜"},{"n":"新上线","v":"新上线"}]},{"key":"total","name":"状态","value":[{"n":"全部","v":"状态"},{"n":"连载","v":"连载"},{"n":"完结","v":"完结"}]}],
  49. "3":[{"key":"class","name":"类型","value":[{"n":"全部","v":"类型"},{"n":"大陆","v":"大陆"},{"n":"港台","v":"港台"},{"n":"日韩","v":"日韩"},{"n":"欧美","v":"欧美"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":"地区"},{"n":"内地","v":"内地"},{"n":"港台","v":"港台"},{"n":"日韩","v":"日韩"},{"n":"欧美","v":"欧美"},{"n":"其它","v":"其它"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":"年份"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"10年代","v":"10年代"},{"n":"00年代","v":"00年代"},{"n":"90年代","v":"90年代"},{"n":"80年代","v":"80年代"}]},{"key":"by","name":"排序","value":[{"n":"热播榜","v":"热播榜"},{"n":"新上线","v":"新上线"}]}],
  50. "8":[{"key":"class","name":"类型","value":[{"n":"全部","v":"类型"},{"n":"日韩剧","v":"日韩剧"},{"n":"欧美剧","v":"欧美剧"},{"n":"海外剧","v":"海外剧"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":"地区"},{"n":"韩国","v":"韩国"},{"n":"美剧","v":"美剧"},{"n":"日本","v":"日本"},{"n":"泰国","v":"泰国"},{"n":"英国","v":"英国"},{"n":"新加坡","v":"新加坡"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":"年份"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"10年代","v":"10年代"},{"n":"00年代","v":"00年代"},{"n":"90年代","v":"90年代"},{"n":"80年代","v":"80年代"}]},{"key":"by","name":"排序","value":[{"n":"热播榜","v":"热播榜"},{"n":"好评榜","v":"好评榜"},{"n":"新上线","v":"新上线"}]}]
  51. },
  52. });
  53. }
  54. async function homeVod() {
  55. return '{}';
  56. }
  57. // tid, pg, filter, extend
  58. async function category(inReq, _outResp) {
  59. const tid = inReq.body.id;
  60. let pg = inReq.body.page;
  61. const extend = inReq.body.filters;
  62. if (pg <= 0) pg = 1;
  63. let tag = extend['tag']?extend['tag']:'全部';
  64. let year = extend['year']?extend['year']:'全部';
  65. // const link = url + '/list/' + tid + "?page=" + pg + '&size=24';
  66. const link = 'https://pan.syrme.top/v1/api/video/jojo/type/tag/year?type=' + tid + '&tag=' + tag + '&year=' + year + '&page=' + pg + '&size=24';
  67. const res = await request(link, null, 'post', null);
  68. // 换普通处理方法
  69. let videos = [];
  70. for (const vod of res.data) {
  71. let a = {
  72. vod_id: vod.ID,
  73. vod_name: vod.title,
  74. vod_pic: vod.image,
  75. vod_remarks: vod.score,
  76. }
  77. videos.push(a);
  78. }
  79. return JSON.stringify({
  80. page: pg,
  81. pagecount: _.ceil(res.num / 24),
  82. list: videos,
  83. });
  84. /*
  85. const $ = load(html);
  86. const items = $('div.content-body > a');
  87. let videos = _.map(items, (item) => {
  88. const img = $(item).find('img:first')[0].attribs['src'];
  89. const a = item.attribs['href'].match(/\/watch\/(.*)/)[1];
  90. const n = ($(item).find('p.card-title')[0]).children[0].data;
  91. let speed = ($(item).find('p.item-speed')[0]).children[0].data || '';
  92. const score = ($(item).find('p.score')[0]).children[0].data || '';
  93. if (speed == tid) speed = '';
  94. return {
  95. vod_id: a,
  96. vod_name: n,
  97. vod_pic: img,
  98. vod_remarks: speed || score || '',
  99. };
  100. });
  101. let total = 24;
  102. const pag = $('ui-pagination');
  103. if (pag.length > 0) {
  104. try {
  105. total = parseInt(pag[0].attribs['total']);
  106. } catch (error) {
  107. }
  108. }
  109. return JSON.stringify({
  110. page: pg,
  111. pagecount: _.ceil(total / 24),
  112. list: videos,
  113. });*/
  114. }
  115. function stripHtmlTag(src) {
  116. return src
  117. .replace(/<\/?[^>]+(>|$)/g, '')
  118. .replace(/&.{1,5};/g, '')
  119. .replace(/\s{2,}/g, ' ');
  120. }
  121. async function detail(inReq, _outResp) {
  122. const ids = !Array.isArray(inReq.body.id) ? [inReq.body.id] : inReq.body.id;
  123. const videos = [];
  124. for (const id of ids) {
  125. // https://pan.syrme.top/v1/api/video/jojo/id?id=63901
  126. const data = (await request('https://pan.syrme.top/v1/api/video/jojo/id?id=' + id, null, 'post', null)).data;
  127. let vod = {
  128. vod_name: data.title,
  129. vod_pic: data.image,
  130. type_name: data.video_type,
  131. vod_year: data.year,
  132. vod_remarks: data.score,
  133. vod_content: data.content,
  134. };
  135. let playFroms = [];
  136. let playUrls = [];
  137. playFroms.push('JOJO线路');
  138. let nameUrls = [];
  139. for (const play of data.url_content.split('\n')) {
  140. nameUrls.push(play)
  141. }
  142. playUrls.push(nameUrls.join('#'));
  143. /*
  144. let nameUrls = [];
  145. for (const play of ) {
  146. nameUrls.push(play.name + '$' + play['url'][0]);
  147. }*/
  148. vod.vod_play_from = playFroms.join('$$$');
  149. vod.vod_play_url = playUrls.join('$$$');
  150. videos.push(vod);
  151. }
  152. return {
  153. list: videos,
  154. };
  155. }
  156. function playPid() {
  157. var key = Crypto.enc.Utf8.parse('VSmJTRRE'+dayjs().format('YYYYMMDD'));
  158. var iv = Crypto.enc.Hex.parse("00000000000000000000000000000000");
  159. var pid = Crypto.AES.encrypt(dayjs().format('YYYY-MM-DD HH:mm'), key, { iv: iv, padding: Crypto.pad.Pkcs7 });
  160. pid = pid.toString().replace(/\+/g, '-');
  161. return pid;
  162. }
  163. async function play(inReq, _outResp) {
  164. const id = inReq.body.id;
  165. return JSON.stringify({
  166. parse: 0,
  167. url: id, // + '?pid=' + playPid(),
  168. header: {
  169. 'User-Agent': UA,
  170. },
  171. });
  172. }
  173. async function search(inReq, _outResp) {
  174. const pg = inReq.body.page;
  175. const wd = inReq.body.wd;
  176. let page = pg || 1;
  177. if (page == 0) page = 1;
  178. const link = url + '/video/search?q=' + wd + "&page=" + page + '&size=18&pid=' + playPid();
  179. const html = await request(link);
  180. const $ = load(html);
  181. const items = $('div.content-body > a');
  182. let videos = _.map(items, (item) => {
  183. const img = $(item).find('img:first')[0].attribs['src'];
  184. const a = item.attribs['href'].match(/\/watch\/(.*)/)[1];
  185. const n = ($(item).find('p.card-title')[0]).children[0].data;
  186. let speed = ($(item).find('p.item-speed')[0]).children[0].data || '';
  187. const score = ($(item).find('p.score')[0]).children[0].data || '';
  188. if (speed == '电影') speed = '';
  189. return {
  190. vod_id: a,
  191. vod_name: n,
  192. vod_pic: img,
  193. vod_remarks: speed || score || '',
  194. };
  195. });
  196. let total = 18;
  197. const pag = $('ui-pagination');
  198. if (pag.length > 0) {
  199. try {
  200. total = parseInt(pag[0].attribs['total']);
  201. } catch (error) {
  202. }
  203. }
  204. return JSON.stringify({
  205. page: page,
  206. pagecount: _.ceil(total / 18),
  207. list: videos,
  208. });
  209. }
  210. async function test(inReq, outResp) {
  211. try {
  212. const printErr = function (json) {
  213. if (json.statusCode && json.statusCode == 500) {
  214. console.error(json);
  215. }
  216. };
  217. const prefix = inReq.server.prefix;
  218. const dataResult = {};
  219. let resp = await inReq.server.inject().post(`${prefix}/init`);
  220. dataResult.init = resp.json();
  221. printErr(resp.json());
  222. resp = await inReq.server.inject().post(`${prefix}/home`);
  223. dataResult.home = resp.json();
  224. printErr("" + resp.json());
  225. if (dataResult.home.class.length > 0) {
  226. resp = await inReq.server.inject().post(`${prefix}/category`).payload({
  227. id: dataResult.home.class[0].type_id,
  228. page: 1,
  229. filter: true,
  230. filters: {},
  231. });
  232. dataResult.category = resp.json();
  233. printErr(resp.json());
  234. if (dataResult.category.list.length > 0) {
  235. resp = await inReq.server.inject().post(`${prefix}/detail`).payload({
  236. id: dataResult.category.list[0].vod_id, // dataResult.category.list.map((v) => v.vod_id),
  237. });
  238. dataResult.detail = resp.json();
  239. printErr(resp.json());
  240. if (dataResult.detail.list && dataResult.detail.list.length > 0) {
  241. dataResult.play = [];
  242. for (const vod of dataResult.detail.list) {
  243. const flags = vod.vod_play_from.split('$$$');
  244. const ids = vod.vod_play_url.split('$$$');
  245. for (let j = 0; j < flags.length; j++) {
  246. const flag = flags[j];
  247. const urls = ids[j].split('#');
  248. for (let i = 0; i < urls.length && i < 2; i++) {
  249. resp = await inReq.server
  250. .inject()
  251. .post(`${prefix}/play`)
  252. .payload({
  253. flag: flag,
  254. id: urls[i].split('$')[1],
  255. });
  256. dataResult.play.push(resp.json());
  257. }
  258. }
  259. }
  260. }
  261. }
  262. }
  263. resp = await inReq.server.inject().post(`${prefix}/search`).payload({
  264. wd: '暴走',
  265. page: 1,
  266. });
  267. dataResult.search = resp.json();
  268. printErr(resp.json());
  269. return dataResult;
  270. } catch (err) {
  271. console.error(err);
  272. outResp.code(500);
  273. return { err: err.message, tip: 'check debug console output' };
  274. }
  275. }
  276. export default {
  277. meta: {
  278. key: 'jojo',
  279. name: 'JOJO影视',
  280. type: 3,
  281. },
  282. api: async (fastify) => {
  283. fastify.post('/init', init);
  284. fastify.post('/home', home);
  285. fastify.post('/category', category);
  286. fastify.post('/detail', detail);
  287. fastify.post('/play', play);
  288. fastify.post('/search', search);
  289. fastify.get('/test', test);
  290. },
  291. };