123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- import { Crypto, load, _ } from 'assets://js/lib/cat.js';
- /**
- * 发布页:https://kan80.app/
- */
- const MOBILE_UA = 'Mozilla/5.0 (Linux; Android 11; M2007J3SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045714 Mobile Safari/537.36';
- const PC_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36';
- const UA = 'Mozilla/5.0';
- const UC_UA = 'Mozilla/5.0 (Linux; U; Android 9; zh-CN; MI 9 Build/PKQ1.181121.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.5.5.1035 Mobile Safari/537.36';
- const IOS_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';
- const RULE_CK = 'cookie'; // 源cookie的key值
- let html = '';
- var charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789';
- let HOST = '';
- let validUrl = HOST + '/index.php/verify/index.html?';
- let validCheckUrl = 'https://www.hdmyy.com/index.php/ajax/verify_check?type=search&verify='
- let siteKey = '';
- let siteType = 0;
- let COOKIE = 'PHPSESSID=' + randStr(26, true);
- let maxRetryTime = 5;
- let currentRetryTime = 0;
- let parseUrl = [];
- var rule = {};
- let ext = {};
- let classes = [];
- let videos = [];
- let videoDetail = {};
- let filterObj = {};
- let pagecount = 999;
- let page = 1;
- let classId = '';
- let flagParse = {};
- let playFlag;
- let playUrl = '';
- let searchUrl = '';
- let input = '';
- let timeout = 10000;
- let headers = {
- 'User-Agent': PC_UA,
- 'Referer': HOST,
- 'Cookie': COOKIE
- };
- async function request(reqUrl, data, header, method) {
- let res = await req(reqUrl, {
- method: method || 'get',
- data: data || '',
- headers: header || headers,
- postType: method === 'post' ? 'form-data' : '',
- timeout: timeout,
- });
- return res.content;
- }
- // cfg = {skey: siteKey, ext: extend}
- async function init(cfg) {
- siteKey = cfg.skey;
- siteType = cfg.stype;
- if (cfg.ext) {
- await parseRule(cfg.ext);//解析规则
- }
- if (rule.initHost) {
- html = await request(HOST);
- if (html.indexOf('document.cookie = ') > 0) {
- COOKIE = html.match(/document.cookie = "(.*?)"/)[1];
- //console.log('cookie', COOKIE);
- html = await request(HOST);
- }
- }
- //await parseHost();//解析HOST主页地址
- }
- async function parseRule(ext) {
- let ruleText = '';
- if(typeof(ext) == 'string' && ext.startsWith('http')) {
- ruleText = await request(ext);
- eval(ruleText);
- } else {
- rule = ext;
- }
- //console.log('rule', rule);
- await parseHost();
-
-
- }
- async function parseHost() {
- //console.log('rule', rule);
- //rule.hostJs = 'const host = "http://baidu.com";request(host)||console.log("html", html)'
- //console.log('host', rule.host);
- if(rule.host) {
- HOST = rule.host;
- }
- if(rule.headers) {
- Object.assign(headers, rule.headers);
- }
- if(rule.timeout) timeout = rule.timeout;
- const initParse = rule.initJs || rule.hostJs;
- if(initParse) {
- const split = initParse.split('||');
- for(let i = 0; i < split.length; i++) {
- if(split[i].indexOf('request(') >= 0) {
- html = await eval(split[i]);
- } else {
- eval(split[i]);
- }
- }
- }
- //console.log('HOST', HOST);
- }
- async function home(filter) {
- classes = [];
- if (rule.class_name) {
- let class_name = rule.class_name.split('&');
- for (let i = 0; i < class_name.length; i++) {
- let type_id = rule.class_url.split('&')[i];
- classes.push({'type_id':type_id,'type_name':class_name[i]});
- }
- } else if (rule.class_parse) {
- let homeUrl = rule.homeUrl;
- if (homeUrl) {
- if (homeUrl.startsWith('/')) {
- homeUrl = HOST + homeUrl;
- }
- html = await request(homeUrl);
- }
- const $ = load(html);
- const split = rule.class_parse.split(';');
- _.forEach($(split[0]), item => {
- let typeId = getCssVal($, item, split[2]);
- let typeName = getCssVal($, item, split[1]);
- classes.push({'type_id':typeId,'type_name':typeName});
- });
- }
- if (rule.filter) {
- filterObj = rule.filter;
- }
- if (rule.homeJS) {
- await evalCustomerJs(rule.homeJS);
- }
- //let classes = [{'type_id':1,'type_name':'电影'},{'type_id':2,'type_name':'电视剧'},{'type_id':3,'type_name':'综艺'},{'type_id':4,'type_name':'动漫'},{'type_id':63,'type_name':'纪录片'}];
- //let filterObj =
- return JSON.stringify({
- class: classes,
- filters: filterObj,
- });
- }
- /**
- * css选择器获取属性值方法
- * $: js选择器驱动
- * item: 父节点表达式
- * parse:子节点表达式&&值属性&&正则表达式
- */
- function getCssVal($, item, parse) {
- if (!parse) return '';
- let xpa = parse.split('&&');
- if (!xpa || xpa.length < 2) return '';
- let el;
- if(item) {
- if (xpa[0]) {
- el = $(item).find(xpa[0]);
- } else {
- el = $(item);
- }
- } else {
- el = $(xpa[0]);
- }
-
- let v = '';
- //console.log('xpa[1]', xpa[1]);
- if (xpa[1].indexOf('||') > 0) {
- const attrs = xpa[1].split('||');
- v = $(el).attr(attrs[0]) || $(el).attr(attrs[1]);
- } else if(xpa[1] == 'Text') {
- v = $(el).text().trim();
- } else {
- v = $(el).attr(xpa[1]);
- }
-
- if(xpa[2]) {
- const match = v.match(new RegExp(xpa[2]));
- if (match) v = match[1];
- }
- return v;
- }
- function getCssValArray($, item, parse) {
- if (!parse) return '';
- let xpa = parse.split('&&');
- if (!xpa || xpa.length < 2) return '';
- let val = [];
- let el;
- if(item) {
- if (xpa[0]) {
- el = $(item).find(xpa[0]);
- } else {
- el = $(item);
- }
- } else {
- el = $(xpa[0]);
- }
- _.forEach(el, item => {
- let v = '';
- if (xpa[1].indexOf('||') > 0) {
- const attrs = xpa[1].split('||');
- v = $(item).attr(attrs[0]) || $(item).attr(attrs[0]);
- } else if(xpa[1] == 'Text') {
- v = $(item).text().trim();
- } else {
- v = $(item).attr(xpa[1]);
- }
-
- if(xpa[2]) {
- const match = v.match(new RegExp(xpa[2]));
- if (match) v = match[1];
- }
- if (v) {
- val.push(v);
- }
-
- });
- return val;
- }
- async function homeVod() {
- videos = [];
- const vodParse = rule.homeVod || rule.推荐;
- const vodParseJS = rule.homeVodJS || rule.推荐JS;
- if (vodParse) {
- let url = HOST;
- if(rule.homeUrl && rule.homeUrl.startsWith('/')) {
- url = HOST + rule.homeUrl;
- } else if (rule.homeUrl && rule.homeUrl.startsWith('http')) {
- url = rule.homeUrl;
- }
- const $ = load(await request(url));
- videos = getVideoByCssParse($, vodParse);
- return JSON.stringify({
- list: videos,
- });
- } else if(vodParseJS) {
- await evalCustomerJs(vodParseJS);
- return JSON.stringify({
- list: videos,
- });
- }
- }
- function getVideoByCssParse($, cssParse) {
- let videos = [];
- const split = cssParse.split(';');
- _.forEach($(split[0]), item => {
- let vod_id = getCssVal($, item, split[2]);
- if(vod_id) {
- let pic = getCssVal($, item, split[3]);
- if(pic.startsWith('/')) pic = HOST + pic;
- videos.push({
- vod_id: vod_id,
- vod_name: getCssVal($, item, split[1]),
- vod_pic: pic,
- vod_remarks: getCssVal($, item, split[4]),
- })
- }
- });
- return videos;
- }
- async function category(tid, pg, filter, extend) {
- videos = [];
- if (pg <= 0) pg = 1;
- classId = tid;
- ext = extend;
- page = pg;
- if(rule.url) {
- let url = rule.url.replaceAll('fypage', page).replaceAll('fyclass', tid);
- if (!url.startsWith('http')) {
- url = HOST + url;
- }
- const regex = /\{\{(.*?)\}\}/g;
- const matches = url.match(regex);
- if(matches) {
- _.forEach(matches, match => {
- let param = match.replace(/\{\{(.*?)\}\}/, '$1').trim();
- url = url.replace(match, extend[param] || '');
- });
- }
- //console.log('cate url', url);
- html = await request(url);
- //console.log('cate res', res);
- const vodParse = rule.一级 || rule.categoryVod;
- if (vodParse) {
- const $ = load(html);
- videos = getVideoByCssParse($, vodParse);
- return JSON.stringify({
- list: videos,
- filters: filterObj,
- page: page,
- pagecount: pagecount,
- });
- }
- }
- const vodParseJS = rule.一级JS || rule.categoryVodJS;
- if(vodParseJS) {
- await evalCustomerJs(vodParseJS);
- return JSON.stringify({
- list: videos,
- filters: filterObj,
- page: page,
- pagecount: pagecount,
- });
- }
- return '{}';
- }
- async function detail(id) {
- videos = [];
- input = id;
- let url = id;
- if (rule.detailUrl) url = rule.detailUrl;
- if(url.startsWith('/')) url = HOST + url;
- url = url.replace('fyid', id);
-
- const vod = {
- }
- const parse = rule.二级 || rule.detailVod;
- const jsCode = rule.二级JS || rule.detailVodJS;
- if (parse) {
- html = await request(url);
- const $ = load(html);
- if ('object' === typeof(parse)) {
- if (parse['director']) {
- vod.vod_director = getCssValArray($,'',parse['director']).join(' ');
- }
- if(parse['actor']) {
- vod.vod_actor = getCssValArray($,'',parse['actor']).join(' ');
- }
- if(parse['area']) {
- vod.vod_area = getCssVal($, '', parse['area']);
- }
- if(parse['year']) {
- vod.vod_year = getCssVal($, '', parse['year']);
- }
- if(parse['remarks']) {
- vod.vod_remarks = getCssVal($, '', parse['remarks']);
- }
- if(parse['content']) {
- vod.vod_content = getCssVal($, '', parse['content']);
- }
- if (parse['type_name']) {
- vod.type_name = getCssValArray($, '', parse['type_name']).join('/');
- }
- if (parse['playFrom'] && parse['playUrl']) {
- const playMap = {};
- const tabNames = getCssValArray($, '', parse['playFrom']);
- //console.log('playFrom', tabNames);
- const split = parse['playUrl'].split(';');
- const tabs = $(split[0]);
- _.each(tabs, (tab,i) => {
- //console.log('tab_exclude', parse['tab_exclude'].indexOf(tabNames[i]));
- if(rule['tab_exclude'] && rule['tab_exclude'].indexOf(tabNames[i]) > -1) {
- return;
- }
- _.each($(tab).find(split[1] || 'a'), it => {
- const title = getCssVal($, it, split[2]);
- const playUrl = getCssVal($, it, split[3]);
- if(!playMap.hasOwnProperty(tabNames[i])) {
- playMap[tabNames[i]] = [];
- }
- playMap[tabNames[i]].push(title + '$' + playUrl);
- });
- });
- vod.vod_play_from = _.keys(playMap).join('$$$');
- const urls = _.values(playMap);
- const vod_play_url = _.map(urls, (urlist) => {
- return urlist.join('#');
- });
- vod.vod_play_url = vod_play_url.join('$$$');
- }
- }
- return JSON.stringify({
- list: [vod],
- });
- } else if(jsCode) {
- videoDetail = {};
- await evalCustomerJs(jsCode);
- }
- return JSON.stringify({
- list: videos,
- });
- }
- async function play(flag, id, flags) {
- let url = id;
- playFlag = flag;
- input = id;
- if (url.startsWith('magnet:')) {
- return JSON.stringify({
- parse: 0,
- url: url,
- });
- }
- if (url.startsWith('/')) {
- url = HOST + url;
- }
- playUrl = url;
- if (rule.lazy) {
- try {
- await evalCustomerJs(rule.lazy);
- return JSON.stringify({
- parse: 0,
- url: playUrl,
- header: headers
- });
- } catch(error) {
- console.log(error);
- }
- }
- if(/\.(m3u8|mp4|mkv|flv|mp3|m4a|aac)$/.test(playUrl.split('?'))) {
- return JSON.stringify({
- parse: 0,
- url: playUrl,
- header: headers
- });
- }
- try {
- html = await request(url);
- const json = getPlay4aJson(html);
- if (json) {
- let js = JSON.parse(json);
- playUrl = js.url;
- if (js.encrypt == 1) {
- playUrl = unescape(playUrl);
- } else if (js.encrypt == 2) {
- playUrl = unescape(base64Decode(playUrl));
- }
- }
- if(/\.(m3u8|mp4|mkv|flv|mp3|m4a|aac)$/.test(playUrl.split('?'))) {
- return JSON.stringify({
- parse: 0,
- url: playUrl,
- header: headers
- });
- }
- } catch(error) {
- console.log(error);
- }
- return JSON.stringify({
- parse: 1,
- url: playUrl,
- });
- }
- function getPlay4aJson(html) {
- let $ = load(html);
- return $('script:contains(player_aaaa)').text().replace('var player_aaaa=','');
- }
- function base64Decode(text) {
- return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(text));
- }
- //aes加密
- function aesEncode(str, keyStr, ivStr, type) {
- const key = Crypto.enc.Utf8.parse(keyStr);
- let encData = Crypto.AES.encrypt(str, key, {
- iv: Crypto.enc.Utf8.parse(ivStr),
- mode: Crypto.mode.CBC,
- padding: Crypto.pad.Pkcs7
- });
- if (type === 'hex') return encData.ciphertext.toString(Crypto.enc.Hex);
- return encData.toString(Crypto.enc.Utf8);
- }
- //aes解密
- function aesDecode(str, keyStr, ivStr, type) {
- const key = Crypto.enc.Utf8.parse(keyStr);
- if (type === 'hex') {
- str = Crypto.enc.Hex.parse(str);
- return Crypto.AES.decrypt({
- ciphertext: str
- }, key, {
- iv: Crypto.enc.Utf8.parse(ivStr),
- mode: Crypto.mode.CBC,
- padding: Crypto.pad.Pkcs7
- }).toString(Crypto.enc.Utf8);
- } else {
- return Crypto.AES.decrypt(str, key, {
- iv: Crypto.enc.Utf8.parse(ivStr),
- mode: Crypto.mode.CBC,
- padding: Crypto.pad.Pkcs7
- }).toString(Crypto.enc.Utf8);
- }
- }
- function md5(text) {
- return Crypto.MD5(text).toString();
- }
- function sha1(text) {
- return Crypto.SHA1(text).toString();
- }
- async function search(wd, quick, pg) {
- try{
- videos = [];
- input = wd;
- if (!pg) pg = '';
- let url = '/search.php?searchword=' + wd;
- if(rule.searchUrl) url = rule.searchUrl;
- url = url.replace('**', wd).replace('fypage', page);
- if(!url.startsWith('http')) url = HOST + url;
- searchUrl = url;
- if(rule.searchVodJS) {
- //执行自定义js
- await evalCustomerJs(rule.searchVodJS);
- } else if (rule.searchVod) {
- let html = await request(url);
- //按css选择器组装数据
- const $ = load(html);
- videos = getVideoByCssParse($, rule.searchVod)
- }
- return JSON.stringify({
- list: videos,
- });
- // const $ = load(html);
- // const title = $('title').text();
- // if(currentRetryTime >= maxRetryTime) {
- // currentRetryTime = 0;
- // return '{}';
- // }
- // if(title === '系统安全验证') {
- // currentRetryTime = currentRetryTime + 1;
- // if(currentRetryTime >= 1) {
- // await sleep(5000);
- // }
- // await validCode(validUrl);
- // return await search(wd, quick, pg);
- // } else {
- // const cards = $('div.module-item-pic');
- // let videos = _.map(cards, (n) => {
- // let id = $($(n).find('a')[0]).attr('href');
- // let name = $($(n).find('a')[0]).attr('title').replaceAll('立刻播放', '');
- // let pic = $($(n).find('img')[0]).attr('data-src');
- // return {
- // vod_id: id,
- // vod_name: name,
- // vod_pic: pic,
- // vod_remarks: '',
- // };
- // });
- // return JSON.stringify({
- // list: videos,
- // });
- // }
- currentRetryTime = 0;
- } catch(error) {
- console.log(error);
- currentRetryTime = 0;
- return '{}';
- }
-
- }
- async function validCode(url) {
- try {
- //获取验证码的base64
- const res = await req(url, {
- buffer: 2,
- headers: {
- 'User-Agent': UA,
- 'Referer': HOST,
- 'Cookie': COOKIE
- }
- });
- const response = await req('https://api.nn.ci/ocr/b64/text', {
- method: 'post',
- data: res.content,
- headers: {
- 'Content-Type': 'text/plain',
- },
- });
- if(response['code'] === 200) {
- let checkRes = await request(validCheckUrl + response.content);
- }
- } catch (error) {
- console.error(error);
- }
- }
- function randStr(len, withNum) {
- var _str = '';
- let containsNum = withNum === undefined ? true : withNum;
- for (var i = 0; i < len; i++) {
- let idx = _.random(0, containsNum ? charStr.length - 1 : charStr.length - 11);
- _str += charStr[idx];
- }
- return _str;
- }
- function sleep(ms) {
- //return new Promise(resolve => setTimeout(resolve, ms));
- let now = new Date();
- const exitTime = now.getTime() + ms;
- while(true) {
- now = new Date();
- if(now.getTime() > exitTime) return;
- }
- }
- async function evalCustomerJs(jsCode) {
- const split = jsCode.split('|||');
- for(let i = 0; i < split.length; i++) {
- if(split[i].indexOf('request(') >= 0) {
- html = await eval(split[i]);
- } else {
- eval(split[i]);
- }
- }
- }
- export function __jsEvalReturn() {
- return {
- init: init,
- home: home,
- homeVod: homeVod,
- category: category,
- detail: detail,
- play: play,
- search: search,
- validCode: validCode,
- };
- }
|