kkys_open.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import { Crypto, dayjs, jinja2, _ } from './lib/cat.js';
  2. let key = 'kkys';
  3. let url = 'https://api1.baibaipei.com:8899';
  4. let device = {};
  5. let siteKey = '';
  6. let siteType = 0;
  7. async function request(reqUrl, postData, agentSp, get) {
  8. let ts = dayjs().valueOf().toString();
  9. let rand = randStr(32);
  10. let sign = Crypto.MD5('abcdexxxdd2daklmn25129_' + ts + '_' + rand)
  11. .toString()
  12. .toLowerCase();
  13. let headers = {
  14. 'user-agent': agentSp || device.ua,
  15. };
  16. if (reqUrl.includes('baibaipei')) {
  17. headers['device-id'] = device.id;
  18. headers['push-token'] = '';
  19. headers['sign'] = sign;
  20. headers['time'] = ts;
  21. headers['md5'] = rand;
  22. headers['version'] = '2.1.0';
  23. headers['system-model'] = device.model;
  24. headers['system-brand'] = device.brand;
  25. headers['system-version'] = device.release;
  26. }
  27. let res = await req(reqUrl, {
  28. method: get ? 'get' : 'post',
  29. headers: headers,
  30. data: postData || {},
  31. postType: get ? '' : 'form',
  32. });
  33. let content = res.content;
  34. // console.log(content);
  35. return content;
  36. }
  37. async function init(cfg) {
  38. siteKey = cfg.skey;
  39. siteType = cfg.stype;
  40. var deviceKey = 'device';
  41. var deviceInfo = await local.get(key, deviceKey);
  42. if (deviceInfo.length > 0) {
  43. try {
  44. device = JSON.parse(deviceInfo);
  45. } catch (error) {}
  46. }
  47. if (_.isEmpty(device)) {
  48. device = randDevice();
  49. device.id = randStr(33).toLowerCase();
  50. device.ua = 'okhttp/3.12.0';
  51. await local.set(key, deviceKey, JSON.stringify(device));
  52. }
  53. }
  54. async function home(filter) {
  55. // await req('https://www.facebook.com', {});
  56. let data = JSON.parse(await request(url + '/api.php/Index/getTopVideoCategory')).data;
  57. let classes = [];
  58. let filterObj = {};
  59. for (const type of data) {
  60. let typeName = type.nav_name;
  61. if (typeName == '推荐') continue;
  62. let typeId = type.nav_type_id.toString();
  63. classes.push({
  64. type_id: typeId,
  65. type_name: typeName,
  66. });
  67. if (!filter) continue;
  68. try {
  69. let filterAll = [];
  70. let filterData = JSON.parse(await request(url + '/api.php/Video/getFilterType', { type: typeId })).data;
  71. for (let key of Object.keys(filterData)) {
  72. let itemValues = filterData[key];
  73. if (key === 'plot') key = 'class';
  74. let typeExtendName = '';
  75. switch (key) {
  76. case 'class':
  77. typeExtendName = '类型';
  78. break;
  79. case 'area':
  80. typeExtendName = '地区';
  81. break;
  82. case 'lang':
  83. typeExtendName = '语言';
  84. break;
  85. case 'year':
  86. typeExtendName = '年代';
  87. break;
  88. case 'sort':
  89. typeExtendName = '排序';
  90. break;
  91. }
  92. if (typeExtendName.length === 0) continue;
  93. let newTypeExtend = {
  94. key: key,
  95. name: typeExtendName,
  96. };
  97. let newTypeExtendKV = [];
  98. for (let j = 0; j < itemValues.length; j++) {
  99. const name = itemValues[j];
  100. let value = key === 'sort' ? j + '' : name === '全部' ? '0' : name;
  101. newTypeExtendKV.push({ n: name, v: value });
  102. }
  103. newTypeExtend['init'] = key === 'sort' ? '1' : newTypeExtendKV[0]['v'];
  104. newTypeExtend.value = newTypeExtendKV;
  105. filterAll.push(newTypeExtend);
  106. }
  107. if (!_.isEmpty(filterAll)) {
  108. filterObj[typeId] = filterAll;
  109. }
  110. } catch (e) {
  111. console.log(e);
  112. }
  113. }
  114. // console.log(await homeVod());
  115. // console.log(classes);
  116. // console.log(filterObj);
  117. return JSON.stringify({
  118. class: classes,
  119. filters: filterObj,
  120. });
  121. }
  122. async function homeVod() {
  123. let jsonArray = JSON.parse(await request(url + '/api.php/Index/getHomePage', { type: 1, p: 1 })).data.video;
  124. let videos = [];
  125. for (const item of jsonArray) {
  126. if (item.title.styleType !== 0) continue;
  127. for (const vObj of item.list) {
  128. videos.push({
  129. vod_id: vObj.vod_id,
  130. vod_name: vObj.vod_name,
  131. vod_pic: vObj.vod_pic,
  132. vod_remarks: vObj.vod_remarks || vObj.vod_score || '',
  133. });
  134. }
  135. }
  136. return JSON.stringify({
  137. list: videos,
  138. });
  139. }
  140. async function category(tid, pg, filter, extend) {
  141. if (pg == 0) pg = 1;
  142. let reqUrl = url + '/api.php/Video/getFilterVideoList';
  143. var formData = JSON.parse(
  144. jinja2(
  145. `{
  146. "type": "{{tid}}",
  147. "p": "{{pg}}",
  148. "area": "{{ext.area|default(0)}}",
  149. "year": "{{ext.year|default(0)}}",
  150. "sort": "{{ext.sort|default(0)}}",
  151. "class": "{{ext.class|default(0)}}"
  152. }`,
  153. { ext: extend, tid: tid, pg: pg }
  154. )
  155. );
  156. console.log(formData);
  157. let data = JSON.parse(await request(reqUrl, formData)).data;
  158. let videos = [];
  159. for (const vod of data.data) {
  160. videos.push({
  161. vod_id: vod.vod_id,
  162. vod_name: vod.vod_name,
  163. vod_pic: vod.vod_pic,
  164. vod_remarks: vod.vod_remarks || vod.vod_score || '',
  165. });
  166. }
  167. return JSON.stringify({
  168. page: parseInt(data.current_page),
  169. pagecount: parseInt(data.last_page),
  170. limit: parseInt(data.per_page),
  171. total: parseInt(data.total),
  172. list: videos,
  173. });
  174. }
  175. async function detail(id) {
  176. let data = JSON.parse(await request(url + '/api.php/Video/getVideoInfo', { video_id: id })).data.video;
  177. let vod = {
  178. vod_id: data.vod_id,
  179. vod_name: data.vod_name,
  180. vod_pic: data.vod_pic,
  181. type_name: data.vod_class,
  182. vod_year: data.vod_year,
  183. vod_area: data.vod_area,
  184. vod_remarks: data.vod_remarks || '',
  185. vod_actor: data.vod_actor,
  186. vod_director: data.vod_director,
  187. vod_content: data.vod_content.trim(),
  188. };
  189. let playlist = {};
  190. for (const item of data.vod_play) {
  191. let from = item.playerForm;
  192. if (from === 'jp') continue;
  193. if (from === 'xg') continue;
  194. let urls = [];
  195. for (const u of item.url) {
  196. urls.push(formatPlayUrl(vod.vod_name, u.title) + '$' + u.play_url);
  197. }
  198. if (!playlist.hasOwnProperty(from) && urls.length > 0) {
  199. playlist[from] = urls;
  200. }
  201. }
  202. parse = data.parse || [];
  203. vod.vod_play_from = _.keys(playlist).join('$$$');
  204. let urls = _.values(playlist);
  205. let vod_play_url = [];
  206. for (const urlist of urls) {
  207. vod_play_url.push(urlist.join('#'));
  208. }
  209. vod.vod_play_url = vod_play_url.join('$$$');
  210. return JSON.stringify({
  211. list: [vod],
  212. });
  213. }
  214. var parse = [];
  215. async function play(flag, id, flags) {
  216. try {
  217. if (id.indexOf('youku') >= 0 || id.indexOf('iqiyi') >= 0 || id.indexOf('v.qq.com') >= 0 || id.indexOf('pptv') >= 0 || id.indexOf('le.com') >= 0 || id.indexOf('1905.com') >= 0 || id.indexOf('mgtv') >= 0) {
  218. if (parse.length > 0) {
  219. for (let index = 0; index < parse.length; index++) {
  220. try {
  221. const p = parse[index];
  222. let res = await req(p + id, {
  223. headers: { 'user-agent': 'okhttp/4.1.0' },
  224. });
  225. var result = jsonParse(id, JSON.parse(res.content));
  226. if (result.url) {
  227. result.parse = 0;
  228. return JSON.stringify(result);
  229. }
  230. } catch (error) {}
  231. }
  232. }
  233. }
  234. if (id.indexOf('jqq-') >= 0) {
  235. var jqqHeader = await request(url + '/jqqheader.json', null, null, true);
  236. var jqqHeaders = JSON.parse(jqqHeader);
  237. var ids = id.split('-');
  238. var jxJqq = await req('https://api.juquanquanapp.com/app/drama/detail?dramaId=' + ids[1] + '&episodeSid=' + ids[2] + '&quality=LD', { headers: jqqHeaders });
  239. var jqqInfo = JSON.parse(jxJqq.content);
  240. if (jqqInfo.data.playInfo.url) {
  241. return JSON.stringify({
  242. parse: 0,
  243. playUrl: '',
  244. url: jqqInfo.data.playInfo.url,
  245. });
  246. }
  247. }
  248. let res = await request(url + '/video.php', { url: id });
  249. var result = jsonParse(id, JSON.parse(res).data);
  250. if (result.url) {
  251. result.parse = 0;
  252. // demo of block hls ads
  253. if (/vip\.lz|hd\.lz/.test(result.url)) {
  254. result.url = await js2Proxy(true, siteType, siteKey, 'lzm3u8/' + base64Encode(result.url), {});
  255. }
  256. return JSON.stringify(result);
  257. }
  258. return JSON.stringify({
  259. parse: 0,
  260. playUrl: '',
  261. url: id,
  262. });
  263. } catch (e) {
  264. console.log(e);
  265. return JSON.stringify({
  266. parse: 0,
  267. url: id,
  268. });
  269. }
  270. }
  271. async function proxy(segments, headers) {
  272. let what = segments[0];
  273. let url = base64Decode(segments[1]);
  274. if (what == 'lzm3u8') {
  275. const resp = await req(url, {});
  276. let hls = resp.content;
  277. const jsBase = await js2Proxy(false, siteType, siteKey, 'lzm3u8/', {});
  278. const baseUrl = url.substr(0, url.lastIndexOf('/') + 1);
  279. console.log(hls.length);
  280. hls = hls.replace(/#EXT-X-DISCONTINUITY\r*\n*#EXTINF:6.433333,[\s\S]*?#EXT-X-DISCONTINUITY/, '');
  281. console.log(hls.length);
  282. hls = hls.replace(/(#EXT-X-KEY\S+URI=")(\S+)("\S+)/g, function (match, p1, p2, p3) {
  283. let up = (!p2.startsWith('http') ? baseUrl : '') + p2;
  284. return p1 + up + p3;
  285. });
  286. hls = hls.replace(/(#EXT-X-STREAM-INF:.*\n)(.*)/g, function (match, p1, p2) {
  287. let up = (!p2.startsWith('http') ? baseUrl : '') + p2;
  288. return p1 + jsBase + base64Encode(up);
  289. });
  290. hls = hls.replace(/(#EXTINF:.*\n)(.*)/g, function (match, p1, p2) {
  291. let up = (!p2.startsWith('http') ? baseUrl : '') + p2;
  292. return p1 + up;
  293. });
  294. return JSON.stringify({
  295. code: resp.code,
  296. content: hls,
  297. headers: resp.headers,
  298. });
  299. }
  300. return JSON.stringify({
  301. code: 500,
  302. content: '',
  303. });
  304. }
  305. async function search(wd, quick) {
  306. let data = JSON.parse(await request(url + '/api.php/Search/getSearch', { key: wd, type_id: 0, p: 1 })).data;
  307. let videos = [];
  308. for (const vod of data.data) {
  309. videos.push({
  310. vod_id: vod.vod_id,
  311. vod_name: vod.vod_name,
  312. vod_pic: vod.vod_pic,
  313. vod_remarks: vod.vod_remarks || vod.vod_score || '',
  314. });
  315. }
  316. return JSON.stringify({
  317. list: videos,
  318. });
  319. }
  320. function base64Encode(text) {
  321. return Crypto.enc.Base64.stringify(Crypto.enc.Utf8.parse(text));
  322. }
  323. function base64Decode(text) {
  324. return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
  325. }
  326. const charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
  327. function randStr(len, withNum) {
  328. var _str = '';
  329. let containsNum = withNum === undefined ? true : withNum;
  330. for (var i = 0; i < len; i++) {
  331. let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
  332. _str += charStr[idx];
  333. }
  334. return _str;
  335. }
  336. function randDevice() {
  337. return {
  338. brand: 'Huawei',
  339. model: 'HUAWEI Mate 20',
  340. release: '10',
  341. buildId: randStr(3, false).toUpperCase() + _.random(11, 99) + randStr(1, false).toUpperCase(),
  342. };
  343. }
  344. function formatPlayUrl(src, name) {
  345. return name
  346. .trim()
  347. .replaceAll(src, '')
  348. .replace(/<|>|《|》/g, '')
  349. .replace(/\$|#/g, ' ')
  350. .trim();
  351. }
  352. function jsonParse(input, json) {
  353. try {
  354. let url = json.url ?? '';
  355. if (url.startsWith('//')) {
  356. url = 'https:' + url;
  357. }
  358. if (!url.startsWith('http')) {
  359. return {};
  360. }
  361. let headers = json['headers'] || {};
  362. let ua = (json['user-agent'] || '').trim();
  363. if (ua.length > 0) {
  364. headers['User-Agent'] = ua;
  365. }
  366. let referer = (json['referer'] || '').trim();
  367. if (referer.length > 0) {
  368. headers['Referer'] = referer;
  369. }
  370. _.keys(headers).forEach((hk) => {
  371. if (!headers[hk]) delete headers[hk];
  372. });
  373. return {
  374. header: headers,
  375. url: url,
  376. };
  377. } catch (error) {
  378. console.log(error);
  379. }
  380. return {};
  381. }
  382. export function __jsEvalReturn() {
  383. return {
  384. init: init,
  385. home: home,
  386. homeVod: homeVod,
  387. category: category,
  388. detail: detail,
  389. play: play,
  390. proxy: proxy,
  391. search: search,
  392. };
  393. }