diff --git a/cat/js/4kysxz_open.js b/cat/js/4kysxz_open.js new file mode 100644 index 00000000..8c0bf57f --- /dev/null +++ b/cat/js/4kysxz_open.js @@ -0,0 +1,183 @@ +import { Crypto, load, _ } from './lib/cat.js'; + +let siteUrl = 'https://4kysxz.top'; +let siteKey = ''; +let siteType = 0; +let headers = {}; + +async function request(reqUrl, postData, agentSp, get) { + + let res = await req(reqUrl, { + method: get ? 'get' : 'post', + headers: headers, + data: postData || {}, + postType: get ? '' : 'form', + }); + + let content = res.content; + return content; +} + +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; +} + +async function home(filter) { + let classes = [{ + type_id: '16', + type_name: '高清电影', + },{ + type_id: '17', + type_name: '高清剧集', + }]; + + //let filterObj = genFilterObj(); + return JSON.stringify({ + class: classes, + //filters: filterObj + }); +} + +async function homeVod() { + let videos = await getVideos(siteUrl); + return JSON.stringify({ + list: videos, + }); +} + +async function category(tid, pg, filter, extend) { + if (!pg) pg = 1; + if (pg <= 0) pg = 1; + let url = siteUrl + '/category-' + tid + '_' + pg + '.html'; + let videos = await getVideos(url); + return JSON.stringify({ + list: videos, + page: pg, + }); +} + +async function detail(id) { + try { + const html = await request(id); + const $ = load(html); + + + let actors = _.map($('div.entry-content.u-text-format.u-clearfix > div:nth-child(10) > div > span > span'), (n) => { + return $(n).text().split(' ')[0]; + }); + let actor = actors.join(' '); + + let directors = _.map($('div.entry-content.u-text-format.u-clearfix > div:nth-child(8) > div > span'), (n) => { + return $(n).text().split(' ')[0]; + }); + let director = directors.join(' '); + + let title = $('div.site-content > section > div > header > h1').text().trim(); + + let content = '该影视由【Leospring】采集分享'; + let playUrlStr = ''; + let playFromStr = ''; + //高清直播 + const cards = $('div.entry-content.u-text-format.u-clearfix > custag > ul > li > a'); + if (cards.length > 0) { + let playUrls = _.map(cards, (n) => { + let playUrl = n.attribs['href']; + if (playUrl.indexOf('url=') > 0) { + playUrl = playUrl.split('url=')[1].split('&name')[0]; + } + return $(n).text() + '$' + playUrl; + }); + playUrlStr = playUrls.join('#'); + playFromStr = '高清直播'; + } + + //磁力链接 + const tbs = $('loginshow > table'); + let playFrom = ''; + let nameUrls = []; + for(let i = 0;i< tbs.length;i++) { + if (i%2 == 0) { + playFrom = $(tbs[i]).find('tbody > tr >td').text().replaceAll('WEB', '磁力'); + } else if (i%2 == 1) { + const tds = $(tbs[i]).find('tbody > tr >td'); + let nameUrl = ''; + for (let j = 0;j < tds.length;j++) { + if (j%2 == 0) { + nameUrl = $(tds[j]).text().split('.')[0].split(' ')[0]; + } else if (j%2==1){ + nameUrl = nameUrl + '$' + $(tds[j]).text().split('【')[0]; + nameUrls.push(nameUrl); + } + } + if (playFromStr.length > 0) { + playFromStr += '$$$'; + playUrlStr += '$$$'; + } + playFromStr += playFrom; + playUrlStr += nameUrls.join('#'); + } + } + + + const video = { + vod_actor: actor, + vod_play_from: playFromStr, + vod_play_url: playUrlStr, + vod_director: director, + vod_content: content, + }; + const list = [video]; + const result = { list }; + return JSON.stringify(result); + } catch (e) { + //console.log('err', e); + } + return null; +} + +async function search(wd, quick, pg) { + let url = siteUrl + '/search.php?q=' + wd + //console.log('search url:', url); + let videos = await getVideos(url); + return JSON.stringify({ + list: videos, + }); +} + +async function play(flag, id, flags) { + return JSON.stringify({ + parse: 0, + url: id, + }); +} + +async function getVideos(url) { + const html = await request(url); + const $ = load(html); + const cards = $('div.row.posts-wrapper >div > article > div.entry-media > div > a') + let videos = _.map(cards, (n) => { + let id = n.attribs['href']; + let name = $($(n).find('img')[0]).attr('alt').replaceAll('','').replaceAll('', '').split(' ')[0]; + let pic = $($(n).find('img')[0]).attr('data-src'); + return { + vod_id: id, + vod_name: name, + vod_pic: pic, + vod_remarks: '', + }; + }); + return videos; +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + homeVod: homeVod, + category: category, + detail: detail, + play: play, + search: search, + }; +} \ No newline at end of file diff --git a/cat/js/config_open.json b/cat/js/config_open.json index 2e4b3d8d..6b26712e 100644 --- a/cat/js/config_open.json +++ b/cat/js/config_open.json @@ -5,6 +5,13 @@ {"key":"xinshijue_open","name":"影视 | 新视觉","type":3,"api":"assets://js/xinshijue_open.js"}, {"key":"sc1080_open","name":"影视 | 圣城","type":3,"api":"assets://js/sc1080_open.js"}, +{"key":"ff_open","name":"影视 | 非凡","type":3,"api":"assets://js/ff_open.js"}, +{"key":"push_agent","name":"影视 | 推送","type":4,"api":"assets://js/push_open.js","ext":{"token":"ali_token","cookie":"quark_cookie"}}, +{"key":"ggys_open","name":"影视 | 高光","type":3,"api":"assets://js/ggys_open.js"}, +{"key":"ddys_open","name":"影视 | 低端","type":3,"api":"assets://js/ddys_open.js"}, +{"key":"4kysxz_open","name":"影视 | 4KXZ","type":3,"api":"assets://js/4kysxz_open.js"}, +{"key":"nkvod_open","name":"影视 | 耐看","type":3,"api":"assets://js/nkvod_open.js"}, + {"key":"52ju_open","name":"影视 | 我爱剧","type":3,"api":"assets://js/52ju_open.js"}, {"key":"dyxs_open","name":"影视 | 电影先生","type":3,"api":"assets://js/dyxs_openn.js"}, {"key":"lz_open","name":"影视 | 量子","type":3,"api":"assets://js/lz_open.js"}, diff --git a/cat/js/ddys_open.js b/cat/js/ddys_open.js new file mode 100644 index 00000000..5c570f0f --- /dev/null +++ b/cat/js/ddys_open.js @@ -0,0 +1,239 @@ +import { Crypto, load, _ } from 'assets://js/lib/cat.js'; + +const key = 'ddys'; +let DOMAIN = 'ddys.pro'; +let HOST = 'https://' + DOMAIN; +let PLAY_HOST = 'https://v.' + DOMAIN; +const FROM_DIRECT = '直连'; +const FROM_PARSE = '解析'; +let siteKey = ''; +let siteType = 0; + +const 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'; + +async function request(reqUrl) { + const res = await req(reqUrl, { + method: 'get', + headers: { + 'Host': HOST.match(/.*\:\/\/(.*)/)[1], + 'User-Agent': UA, + 'Referer': HOST, + 'Accept-Encoding': 'gzip', + }, + }); + return res.content; +} + +// cfg = {skey: siteKey, ext: extend} +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; + if (cfg.hasOwnProperty('ext')) { + if (cfg.ext.hasOwnProperty('domain')) { + DOMAIN = cfg.ext.domain; + HOST = 'https://' + DOMAIN; + PLAY_HOST = 'https://v.' + DOMAIN; + } + } +} + +async function home(filter) { + const classes = [{'type_id':'class','type_name':'类型'},{'type_id':'movie','type_name':'电影'},{'type_id':'airing','type_name':'热映中'},{'type_id':'drama','type_name':'剧集'},{'type_id':'anime','type_name':'动画'},{'type_id':'documentary','type_name':'纪录片'},{'type_id':'variety','type_name':'综艺'}]; + const filterObj = { + 'class':[{'key':'tag','name':'标签','init':'recommend','value':[{'n':'站长推荐','v':'recommend'},{'n':'动作','v':'action'},{'n':'喜剧','v':'comedy'},{'n':'爱情','v':'romance'},{'n':'科幻','v':'sci-fi'},{'n':'犯罪','v':'crime'},{'n':'悬疑','v':'mystery'},{'n':'恐怖','v':'horror'}]}], + 'movie':[{'key':'type','name':'分类','init':'','value':[{'n':'全部','v':''},{'n':'欧美电影','v':'western-movie'},{'n':'日韩电影','v':'asian-movie'},{'n':'华语电影','v':'chinese-movie'}]}], + 'drama':[{'key':'type','name':'分类','init':'','value':[{'n':'全部','v':''},{'n':'欧美剧','v':'western-drama'},{'n':'日剧','v':'jp-drama'},{'n':'韩剧','v':'kr-drama'},{'n':'华语剧','v':'cn-drama'},{'n':'其他地区','v':'other'}]}], + 'anime':[{'key':'type','name':'分类','init':'','value':[{'n':'全部','v':''},{'n':'本季新番','v':'new-bangumi'}]}] + }; + return JSON.stringify({ + class: classes, + filters: filterObj, + }); +} + +async function homeVod() {} + +async function category(tid, pg, filter, extend) { + if (pg <= 0) pg = 1; + let path = ''; + if (extend.tag) { + path = '/tag/' + extend.tag; + } else { + path = '/category/' + tid; + if (!_.isEmpty(extend.type)) { + path += '/' + extend.type; + } + } + let page = ''; + if (pg > 1) { + page = 'page/' + pg + '/'; + } + const link = HOST + path + '/' + page; + const html = await request(link); + const $ = load(html); + const items = $('.post-box-list article'); + const videos = _.map(items, (item) => { + const $item = $(item); + const title = $item.find('.post-box-title a'); + const name = title.text(); + const url = title.attr('href'); + const image = $item.find('.post-box-image').attr('style').replace(/.*url\((.*)\);/g, '$1'); + const remarks = $item.find('.post-box-meta').text(); + return { + vod_id: url.replace(/.*\/\/.*\/(.*)\//g, '$1'), + vod_name: name, + vod_pic: image, + vod_remarks: remarks || '', + }; + }); + const limit = 28; + const hasMore = $('nav.navigation a.next').length > 0; + const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); + return JSON.stringify({ + page: parseInt(pg), + pagecount: pgCount, + limit: limit, + total: limit * pgCount, + list: videos, + }); +} + +async function detail(id) { + const html = await request(HOST + '/' + id + '/'); + const $ = load(html); + const abstract = $('div.abstract')[0].children; + const vod = { + vod_id: id, + vod_name: $('h1.post-title').text(), + vod_type: findAbstractText(abstract, '类型:'), + vod_year: findAbstractText(abstract, '年份:'), + vod_area: findAbstractText(abstract, '制片国家/地区:'), + vod_director: findAbstractText(abstract, '导演:'), + vod_actor: findAbstractText(abstract, '演员:'), + vod_pic: $('div.post img:first').attr('data-cfsrc'), + vod_remarks : $('span.cat-links').text().trim(), + vod_content: findAbstractText(abstract, '简介:'), + }; + const playMap = {}; + parseAndUpdateUrls($, playMap); + const links = $('div.page-links a'); + if (!_.isEmpty(links)) { + const promiseList = _.map(links, (link) => { + const url = $(link).attr('href'); + return request(url); + }); + const respList = await Promise.all(promiseList); + _.each(respList, (resp) => { + try { + const $ = load(resp); + parseAndUpdateUrls($, playMap); + } catch(e) { + } + }); + } + 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], + }); +} + +function findAbstractText(children, keyword) { + for (const item of children) { + if (item.type == 'text' && item.data && item.data.startsWith(keyword)) { + return item.data.substring(keyword.length).trim(); + } + } + return ''; +} + +function parseAndUpdateUrls($, playMap) { + const trackText = $('script.wp-playlist-script').text(); + const tracks = JSON.parse(trackText).tracks; + _.each(tracks, (track) => { + const title = track.caption; + const directUrl = track.src0; + if (!playMap.hasOwnProperty(FROM_DIRECT)) { + playMap[FROM_DIRECT] = []; + } + playMap[FROM_DIRECT].push(title + '$' + directUrl); + if (!_.isEmpty(track.src1)) { + if (!playMap.hasOwnProperty(FROM_PARSE)) { + playMap[FROM_PARSE] = []; + } + playMap[FROM_PARSE].push(title + '$' + track.src1); + } + }); +} + +async function play(flag, id, flags) { + let playUrl; + if (flag == FROM_PARSE) { + const resp = await request(HOST + '/getvddr2/video?id=' + id + '&type=json'); + playUrl = JSON.parse(resp).url; + } else { + playUrl = PLAY_HOST + id; + } + const headers = { + 'User-Agent': UA, + 'Referer': HOST, + 'Icy-MetaData': '1', + 'Sec-Fetch-Site': 'same-site', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'video', + }; + return JSON.stringify({ + parse: 0, + url: playUrl, + header: headers, + }); +} + +async function search(wd, quick, pg) { + let page = ''; + if (pg > 1) { + page = '/page/' + pg; + } + const html = await request(HOST + page + '/?s=' + wd + '&post_type=post'); + const $ = load(html); + const list = $('div.post-content'); + const videos = _.map(list, (item) => { + const $item = $(item); + const title = $item.find('.post-title a'); + const name = title.text(); + const url = title.attr('href'); + const remarks = $item.find('.cat-links').text(); + return { + vod_id: url.replace(/.*\/\/.*\/(.*)\//g, '$1'), + vod_name: name, + vod_pic: HOST + '/android-chrome-512x512.png', + vod_remarks: remarks, + }; + }); + const limit = 100; + const hasMore = $('nav.navigation a.next').length > 0; + const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); + return JSON.stringify({ + page: parseInt(pg), + pagecount: pgCount, + limit: limit, + total: limit * pgCount, + list: videos, + }); +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + homeVod: homeVod, + category: category, + detail: detail, + play: play, + search: search, + }; +} \ No newline at end of file diff --git a/cat/js/ff_open.js b/cat/js/ff_open.js new file mode 100644 index 00000000..3d5873e1 --- /dev/null +++ b/cat/js/ff_open.js @@ -0,0 +1,126 @@ +import { Crypto, load, _, jinja2 } from './lib/cat.js'; + +let key = 'ff'; +let HOST = 'https://cj.ffzyapi.com'; +let siteKey = ''; +let siteType = 0; + +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'; + +async function request(reqUrl, agentSp) { + let res = await req(reqUrl, { + method: 'get', + headers: { + 'User-Agent': agentSp || UA, + 'Referer': HOST + }, + }); + return res.content; +} + +// cfg = {skey: siteKey, ext: extend} +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; +} + +async function home(filter) { + let classes = [{"type_id":1,"type_name":"电影"},{"type_id":2,"type_name":"追剧"},{"type_id":3,"type_name":"综艺"},{"type_id":4,"type_name":"动漫"}]; + let filterObj = { + "2":[{"key":"cateId","name":"类型","value":[{"n":"全部","v":"2"},{"n":"短剧","v":"36"},{"n":"陆剧","v":"13"},{"n":"韩剧","v":"15"},{"n":"欧美剧","v":"16"},{"n":"港剧","v":"14"},{"n":"台剧","v":"21"},{"n":"日剧","v":"22"},{"n":"海外剧","v":"23"},{"n":"泰剧","v":"24"},{"n":"纪录片","v":"20"}]}], + "1":[{"key":"cateId","name":"类型","value":[{"n":"全部","v":"1"},{"n":"动作片","v":"6"},{"n":"喜剧片","v":"7"},{"n":"爱情片","v":"8"},{"n":"科幻片","v":"9"},{"n":"恐怖片","v":"10"},{"n":"剧情片","v":"11"},{"n":"战争片","v":"12"}]}], + "3":[{"key":"cateId","name":"类型","value":[{"n":"全部","v":"3"},{"n":"国综","v":"25"},{"n":"港综","v":"26"},{"n":"韩日综","v":"27"},{"n":"欧美综","v":"28"}]}], + "4":[{"key":"cateId","name":"类型","value":[{"n":"全部","v":"4"},{"n":"国漫","v":"29"},{"n":"日韩动漫","v":"30"},{"n":"欧美动漫","v":"31"},{"n":"港漫","v":"32"},{"n":"海外动漫","v":"33"}]}] + }; + + return JSON.stringify({ + class: classes, + filters: filterObj, + }); +} + +async function homeVod() {} + +async function category(tid, pg, filter, extend) { + if (pg <= 0) pg = 1; + let data = JSON.parse(await request(HOST + '/index.php/ajax/data?mid=1&tid=' + (extend.cateId || tid) + '&page=' + pg + '&limit=20')); + + let videos = []; + for (const vod of data.list) { + videos.push({ + vod_id: vod.vod_id, + vod_name: vod.vod_name, + vod_pic: vod.vod_pic, + vod_remarks: '', + }); + } + return JSON.stringify({ + page: parseInt(data.page), + pagecount: data.pagecount, + limit: 20, + total: data.total, + list: videos, + }); +} + +async function detail(id) { + var html = await request( HOST + '/index.php/vod/detail/id/' + id + '.html'); + var $ = load(html); + var vod = { + vod_id: id, + vod_name: $('h1:first').text().trim(), + vod_type: $('.stui-content__detail p:first a').text(), + vod_actor: $('.stui-content__detail p:nth-child(3)').text().replace('主演:',''), + vod_pic: $('.stui-content__thumb img:first').attr('data-original'), + vod_remarks : $('.stui-content__detail p:nth-child(5)').text() || '', + vod_content: $('span.detail-content').text().trim(), + }; + const playlist = _.map($('div.ffm3u8 > li > a[target*=_blank]'), (it) => { + return it.attribs.title + '$' + it.attribs.href; + }); + vod.vod_play_from = "非凡直达"; + vod.vod_play_url = playlist.join('#'); + return JSON.stringify({ + list: [vod], + }); +} +async function play(flag, id, flags) { + return JSON.stringify({ + parse: 0, + url: id, + }); +} + +async function search(wd, quick, pg) { + if (pg <= 0) pg = 1; + let data = JSON.parse(await request(HOST + '/api.php/provide/vod/?wd=' + wd + '&pg=' +pg + '&ac=detail'));///api.php/provide/vod/?wd=搜索词&pg=翻页&ac=detail + + let videos = []; + for (const vod of data.list) { + videos.push({ + vod_id: vod.vod_id, + vod_name: vod.vod_name, + vod_pic: vod.vod_pic, + vod_remarks: '', + }); + } + return JSON.stringify({ + page: parseInt(data.page), + pagecount: data.pagecount, + limit: 20, + total: data.total, + list: videos, + }); +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + homeVod: homeVod, + category: category, + detail: detail, + play: play, + search: search, + }; +} \ No newline at end of file diff --git a/cat/js/ggys_open.js b/cat/js/ggys_open.js new file mode 100644 index 00000000..ccaf5015 --- /dev/null +++ b/cat/js/ggys_open.js @@ -0,0 +1,222 @@ +import { Crypto, load, _ } from 'assets://js/lib/cat.js'; + +const key = 'ggys'; +const HOST = 'https://ggys.me'; +const TYPE_MOVIE = 'movie'; +const TYPE_TVSHOW = 'tv-show'; +let siteKey = ''; +let siteType = 0; + +const 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'; + +async function request(reqUrl, method, data) { + const res = await req(reqUrl, { + method: method || 'get', + headers: { + 'User-Agent': UA, + 'Referer': HOST, + }, + data: data, + postType: method === 'post' ? 'form' : '', + }); + return res.content; +} + +// cfg = {skey: siteKey, ext: extend} +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; + if (cfg.hasOwnProperty('ext')) { + if (cfg.ext.hasOwnProperty('host')) { + HOST = cfg.ext.host; + } + } +} + +async function home(filter) { + const classes = [{'type_id':'movies','type_name':'电影'},{'type_id':'tv-shows','type_name':'剧集'}]; + const filterObj = { + 'movies':[{'key':'class','name':'类型','init':'','value':[{'n':'全部','v':''},{'n':'欧美电影','v':'tag/欧美电影'},{'n':'华语电影','v':'tag/华语电影'},{'n':'日韩电影','v':'tag/日韩电影'},{'n':'其他地区','v':'tag/其他地区'},{'n':'冒险','v':'genre/冒险'},{'n':'剧情','v':'genre/剧情'},{'n':'动作','v':'genre/动作'},{'n':'动画','v':'genre/动画'},{'n':'历史','v':'genre/历史'},{'n':'喜剧','v':'genre/喜剧'},{'n':'奇幻','v':'genre/奇幻'},{'n':'家庭','v':'genre/家庭'},{'n':'恐怖','v':'genre/恐怖'},{'n':'悬疑','v':'genre/悬疑'},{'n':'惊悚','v':'genre/惊悚'},{'n':'战争','v':'genre/战争'},{'n':'爱情','v':'genre/爱情'},{'n':'犯罪','v':'genre/犯罪'},{'n':'科幻','v':'genre/科幻'},{'n':'纪录','v':'genre/纪录'},{'n':'音乐','v':'genre/音乐'}]}], + 'tv-shows':[{'key':'class','name':'类型','init':'','value':[{'n':'全部','v':''},{'n':'欧美剧','v':'tag/欧美剧'},{'n':'日韩剧','v':'tag/日韩剧'},{'n':'国产剧','v':'tag/国产剧'},{'n':'其他地区','v':'tag/其他地区'},{'n':'剧情','v':'genre/剧情'},{'n':'动作','v':'genre/动作'},{'n':'动画','v':'genre/动画'},{'n':'喜剧','v':'genre/喜剧'},{'n':'家庭','v':'genre/家庭'},{'n':'悬疑','v':'genre/悬疑'},{'n':'犯罪','v':'genre/犯罪'},{'n':'科幻','v':'genre/科幻'},{'n':'西部','v':'genre/西部'}]}], + }; + return JSON.stringify({ + class: classes, + filters: filterObj, + }); +} + +async function homeVod() {} + +async function category(tid, pg, filter, extend) { + if (pg <= 0) pg = 1; + let path = ''; + const prefixMap = { + 'movies': TYPE_MOVIE, + 'tv-shows': TYPE_TVSHOW, + } + const prefix = prefixMap[tid]; + if (extend.class) { + path = '/' + prefix + '-' + extend.class; + } else { + path = '/' + tid; + } + let page = ''; + if (pg > 1) { + page = 'page/' + pg + '/'; + } + const link = HOST + path + '/' + page; + const html = await request(link); + const $ = load(html); + const videos = []; + parseVideoList($, prefix, false, videos); + const limit = 20; + const hasMore = $('.page-numbers a.next').length > 0; + const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); + return JSON.stringify({ + page: parseInt(pg), + pagecount: pgCount, + limit: limit, + total: limit * pgCount, + list: videos, + }); +} + +function parseVideoList($, prefix, imgSrc, videos) { + const items = $('.' + prefix); + _.each(items, (item) => { + const $item = $(item); + const title = $item.find('.' + prefix + '__title:first').text(); + const url = $item.find('.' + prefix + '__actions a:first').attr('href'); + const imgAttr = imgSrc ? 'src' : 'data-lazy-src'; + const image = $item.find('.' + prefix + '__poster img:first').attr(imgAttr); + const remarks = $item.find('.' + prefix + '__meta span:last').text(); + if (!url) return; + const videoItem = { + vod_id: decodeURIComponent(url.replace(/.*\/\/.*\/(.*\/.*)\//g, '$1')), + vod_name: title, + vod_pic: image, + vod_remarks: remarks, + }; + videos.push(videoItem); + }); +} + +async function detail(id) { + const isMovieType = id.startsWith(TYPE_MOVIE); + const html = await request(HOST + '/' + id + '/'); + const $ = load(html); + const prefix = isMovieType ? TYPE_MOVIE : TYPE_TVSHOW; + const vod = { + vod_id: id, + vod_name: $('.' + prefix + '_title').text(), + vod_actor: $('.' + prefix + '-casts').text().trim().substring(3).replace(/\s+\/\s+/g, '/'), + vod_pic: $('.' + prefix + '__poster img:first').attr('data-lazy-src'), + vod_remarks: $('.' + prefix + '__meta span:last').text(), + }; + if (isMovieType) { + vod.vod_type = $('.' + prefix + '__meta span:last').text(); + vod.vod_year = $('.' + prefix + '__meta span:first').text(); + vod.vod_content = $('.movie__description').text(); + } else { + vod.vod_type = $('.' + prefix + '__meta span:first').text(); + vod.vod_content = $('.tv-show__info--body').text(); + } + const from = 'ggys'; + const playMap = {}; + if (isMovieType) { + const playId = $('.ggys-video-player').attr('data-source-id'); + const playCfg = playId + '@' + TYPE_MOVIE; + playMap[from] = [ '全$' + playCfg ]; + } else { + const tabs = $('.tv_show__season-tabs-wrap .nav-item'); + const episodes = $('.episodes'); + _.each(tabs, (tab, i) => { + const titlePrefix = $(tab).text().trim(); + const episodeList = $(episodes[i]).find('.episode__body'); + _.each(episodeList, (episode) => { + const $episode = $(episode); + const title = titlePrefix + ' ' + $episode.text().trim(); + const url = $episode.find('a').attr('href'); + const playCfg = url + '@' + TYPE_TVSHOW; + if (!playMap.hasOwnProperty(from)) { + playMap[from] = []; + } + playMap[from].push(title + '$' + playCfg); + }); + }); + } + 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], + }); +} + +async function play(flag, id, flags) { + const playCfg = id.split('@'); + const playType = playCfg[1]; + let playId = playCfg[0]; + let playUrl; + if (playType == TYPE_TVSHOW) { + const html = await request(playId); + const $ = load(html); + playId = $('.ggys-video-player').attr('data-source-id'); + } + const param = { + video_id: playId, + }; + const resp = await request(HOST + '/wp-json/get_addr/v1/get_video_url', 'post', param); + playUrl = JSON.parse(resp).video_url; + const headers = { + 'User-Agent': UA, + 'Referer': HOST, + }; + return JSON.stringify({ + parse: 0, + url: playUrl, + header: headers, + }); +} + +async function search(wd, quick, pg) { + let page = ''; + if (pg > 1) { + page = '/page/' + pg; + } + const url = HOST + '/search/' + wd + page + '/?post_type='; + const videos = []; + let html = await request(url + 'movie'); + let $ = load(html); + parseVideoList($, TYPE_MOVIE, true, videos); + const hasMoreMovie = $('.page-numbers a.next').length > 0; + html = await request(url + 'tv_show'); + $ = load(html); + parseVideoList($, TYPE_TVSHOW, true, videos); + const hasMoreTVShow = $('.page-numbers a.next').length > 0; + const limit = 40; + const hasMore = hasMoreMovie || hasMoreTVShow; + const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); + return JSON.stringify({ + page: parseInt(pg), + pagecount: pgCount, + limit: limit, + total: limit * pgCount, + list: videos, + }); +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + homeVod: homeVod, + category: category, + detail: detail, + play: play, + search: search, + }; +} \ No newline at end of file diff --git a/cat/js/nkvod_open.js b/cat/js/nkvod_open.js new file mode 100644 index 00000000..928c9887 --- /dev/null +++ b/cat/js/nkvod_open.js @@ -0,0 +1,207 @@ +import { Crypto, load, _ } from 'assets://js/lib/cat.js'; + +let key = 'nkvod'; +let HOST = 'https://nkvod.pro'; +let parseMap = {}; +let siteKey = ''; +let siteType = 0; + +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'; + +async function request(reqUrl) { + let res = await req(reqUrl, { + method: 'get', + headers: { + 'User-Agent': UA, + 'Referer': HOST + }, + }); + return res.content; +} + +// cfg = {skey: siteKey, ext: extend} +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; + await initParseMap(); +} + +async function initParseMap() { + const date = new Date(); + const t = '' + date.getFullYear() + (date.getMonth() + 1) + date.getDate(); + const js = await request(HOST + '/static/js/playerconfig.js?t=' + t); + try { + const jsEval = js + '\nMacPlayerConfig'; + const playerList = eval(jsEval).player_list; + const players = _.values(playerList); + _.each(players, (item) => { + if (!item.ps || item.ps == '0') return; + if (_.isEmpty(item.parse)) return; + parseMap[item.show] = item.parse; + }); + } catch(e) { + } +} + +async function home(filter) { + const classes = [{'type_id':'1','type_name':'电影'},{'type_id':'2','type_name':'电视剧'},{'type_id':'3','type_name':'综艺'},{'type_id':'4','type_name':'动漫'}]; + const filterObj = { + '1':[{'key':'cateId','name':'类型','init':'1','value':[{'n':'全部','v':'1'},{'n':'动作片','v':'6'},{'n':'喜剧片','v':'7'},{'n':'爱情片','v':'8'},{'n':'科幻片','v':'9'},{'n':'恐怖片','v':'10'},{'n':'剧情片','v':'11'},{'n':'战争片','v':'12'}]},{'key':'year','name':'年代','init':'','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':'2014','v':'2014'},{'n':'2013','v':'2013'},{'n':'2012','v':'2012'},{'n':'2011','v':'2011'},{'n':'2010','v':'2010'}]},{'key':'by','name':'排序','value':[{'n':'时间','v':'time'},{'n':'人气','v':'hits'},{'n':'评分','v':'score'}]}], + '2':[{'key':'cateId','name':'类型','init':'2','value':[{'n':'全部','v':'2'},{'n':'国产剧','v':'13'},{'n':'港台剧','v':'14'},{'n':'日韩剧','v':'15'},{'n':'欧美剧','v':'16'},{'n':'其他剧','v':'20'}]},{'key':'year','name':'年代','init':'','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':'2014','v':'2014'},{'n':'2013','v':'2013'},{'n':'2012','v':'2012'},{'n':'2011','v':'2011'},{'n':'2010','v':'2010'},{'n':'2009','v':'2009'},{'n':'2008','v':'2008'},{'n':'2007','v':'2007'},{'n':'2006','v':'2006'},{'n':'2005','v':'2005'},{'n':'2004','v':'2004'}]},{'key':'by','name':'排序','value':[{'n':'时间','v':'time'},{'n':'人气','v':'hits'},{'n':'评分','v':'score'}]}], + '3':[{'key':'year','name':'年代','init':'','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':'2014','v':'2014'},{'n':'2013','v':'2013'},{'n':'2012','v':'2012'},{'n':'2011','v':'2011'},{'n':'2010','v':'2010'},{'n':'2009','v':'2009'},{'n':'2008','v':'2008'},{'n':'2007','v':'2007'},{'n':'2006','v':'2006'},{'n':'2005','v':'2005'},{'n':'2004','v':'2004'}]},{'key':'by','name':'排序','value':[{'n':'时间','v':'time'},{'n':'人气','v':'hits'},{'n':'评分','v':'score'}]}], + '4':[{'key':'year','name':'年代','init':'','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':'2014','v':'2014'},{'n':'2013','v':'2013'},{'n':'2012','v':'2012'},{'n':'2011','v':'2011'},{'n':'2010','v':'2010'},{'n':'2009','v':'2009'},{'n':'2008','v':'2008'},{'n':'2007','v':'2007'},{'n':'2006','v':'2006'},{'n':'2005','v':'2005'},{'n':'2004','v':'2004'}]},{'key':'by','name':'排序','value':[{'n':'时间','v':'time'},{'n':'人气','v':'hits'},{'n':'评分','v':'score'}]}] + }; + return JSON.stringify({ + class: classes, + filters: filterObj, + }); +} + +async function homeVod() {} + +async function category(tid, pg, filter, extend) { + if (pg <= 0) pg = 1; + const link = HOST + '/show/' + (extend.cateId || tid) + '--' + (extend.by || '') + '-' + (extend.class || '') + '--' + (extend.letter || '') + '---' + pg + '---' + (extend.year || '') + '.html'; + const html = await request(link); + const $ = load(html); + const items = $('a.module-item'); + const videos = _.map(items, (item) => { + const $item = $(item); + const a = $item; + const img = $item.find('img:first'); + const remarks = $item.find('div.module-item-note').text().trim(); + return { + vod_id: a.attr('href').replace(/.*?\/detail\/(.*).html/g, '$1'), + vod_name: a.attr('title'), + vod_pic: img.attr('data-original'), + vod_remarks: remarks, + }; + }); + const limit = 72; + const hasMore = $('div#page > a:contains(下一页)').length > 0; + const pgCount = hasMore ? parseInt(pg) + 1 : parseInt(pg); + return JSON.stringify({ + page: parseInt(pg), + pagecount: pgCount, + limit: limit, + total: limit * pgCount, + list: videos, + }); +} + +async function detail(id) { + const html = await request(HOST + '/detail/' + id + '.html'); + const $ = load(html); + const vod = { + vod_id: id, + vod_name: $('h1:first').text().trim(), + vod_type: $('.module-info-tag a:eq(2)').text().trim(), + vod_year: $('.module-info-tag a:eq(0)').text().trim(), + vod_area: $('.module-info-tag a:eq(1)').text().trim(), + vod_actor: $('.module-info-item:contains(主演:)').text().trim().substring(3).replace(/\/$/, ''), + vod_director: $('.module-info-item:contains(导演:)').text().trim().substring(3).replace(/\/$/, ''), + vod_pic: $('.module-info-poster img:first').attr('data-original'), + vod_remarks : $('.module-info-item:contains(备注:)').text(), + vod_content: $('.module-info-introduction-content').text().trim(), + }; + const playMap = {}; + const tabs = $('.module-tab .module-tab-item span'); + const playlists = $('.module-play-list'); + _.each(tabs, (tab, i) => { + const $tab = $(tab); + const from = $tab.text().trim(); + let list = playlists[i]; + list = $(list).find('a'); + _.each(list, (it) => { + const $it = $(it); + let title = $it.find('span').text(); + const playUrl = $it.attr('href'); + if (_.isEmpty(title)) title = $it.text(); + if (!playMap.hasOwnProperty(from)) { + playMap[from] = []; + } + playMap[from].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], + }); +} + +async function play(flag, id, flags) { + const link = HOST + id; + const html = await request(link); + const $ = load(html); + const js = JSON.parse($('script:contains(player_)').html().replace('var player_aaaa=','')); + let playUrl = js.url; + if (js.encrypt == 1) { + playUrl = unescape(playUrl); + } else if (js.encrypt == 2) { + playUrl = unescape(base64Decode(playUrl)); + } + const parseUrl = parseMap[flag]; + if (parseUrl) { + const reqUrl = parseUrl + playUrl; + const parseHtml = await request(reqUrl); + const matches = parseHtml.match(/let ConFig = {([\w\W]*)},box/); + if (!_.isEmpty(matches)) { + const configJson = '{' + matches[1].trim() + '}'; + const config = JSON.parse(configJson); + playUrl = decryptUrl(config); + } + } + return JSON.stringify({ + parse: 0, + url: playUrl, + header: { + 'User-Agent': UA, + } + }); +} + +function decryptUrl(jsConfig) { + const key = Crypto.enc.Utf8.parse('2890' + jsConfig.config.uid + 'tB959C'); + const iv = Crypto.enc.Utf8.parse('GZ4JgN2BdSqVWJ1z'); + const mode = Crypto.mode.CBC; + const padding = Crypto.pad.Pkcs7; + const decrypted = Crypto.AES.decrypt(jsConfig.url, key, { + iv: iv, + mode: mode, + padding: padding + }); + const decryptedUrl = Crypto.enc.Utf8.stringify(decrypted); + return decryptedUrl; +} + +async function search(wd, quick) { + const data = JSON.parse(await request(HOST + '/index.php/ajax/suggest?mid=1&limit=50&wd=' + wd)).list; + const videos = _.map(data, (vod) => { + return { + vod_id: vod.id, + vod_name: vod.name, + vod_pic: vod.pic, + vod_remarks: '', + }; + }); + return JSON.stringify({ + list: videos, + }); +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + homeVod: homeVod, + category: category, + detail: detail, + play: play, + search: search, + }; +} \ No newline at end of file diff --git a/cat/js/push_open.js b/cat/js/push_open.js new file mode 100644 index 00000000..231f1142 --- /dev/null +++ b/cat/js/push_open.js @@ -0,0 +1 @@ +(function(_0x5502de,_0x28ce57){const _0x3d8968=_0x1d20,_0x3846a8=_0x5502de();while(!![]){try{const _0x6da132=-parseInt(_0x3d8968(0xff))/0x1+-parseInt(_0x3d8968(0xec))/0x2+-parseInt(_0x3d8968(0xf2))/0x3+parseInt(_0x3d8968(0xea))/0x4*(-parseInt(_0x3d8968(0xf9))/0x5)+-parseInt(_0x3d8968(0xf6))/0x6+parseInt(_0x3d8968(0xf5))/0x7+parseInt(_0x3d8968(0xe4))/0x8;if(_0x6da132===_0x28ce57)break;else _0x3846a8['push'](_0x3846a8['shift']());}catch(_0x3bf5ae){_0x3846a8['push'](_0x3846a8['shift']());}}}(_0x23d9,0x242d0));const _0x989826=(function(){let _0x48deae=!![];return function(_0x299763,_0x2277f6){const _0x5f5716=_0x48deae?function(){if(_0x2277f6){const _0x217adc=_0x2277f6['apply'](_0x299763,arguments);return _0x2277f6=null,_0x217adc;}}:function(){};return _0x48deae=![],_0x5f5716;};}()),_0x17f8da=_0x989826(this,function(){const _0x34e035=_0x1d20;let _0x313e96;try{const _0x1ace3f=Function(_0x34e035(0xf4)+_0x34e035(0xeb)+(_0x34e035(0x100)+'ctor(\x22retu'+_0x34e035(0xef)+'\x20)')+');');_0x313e96=_0x1ace3f();}catch(_0x45e725){_0x313e96=window;}const _0x3fb422=_0x313e96[_0x34e035(0xf8)]=_0x313e96[_0x34e035(0xf8)]||{},_0xece77b=['log',_0x34e035(0xe6),_0x34e035(0xf1),_0x34e035(0xfc),_0x34e035(0x108),'table',_0x34e035(0xf3)];for(let _0x33f9b0=0x0;_0x33f9b0<_0xece77b['length'];_0x33f9b0++){const _0x55a52a=_0x989826[_0x34e035(0x103)+'r'][_0x34e035(0xed)][_0x34e035(0xe5)](_0x989826),_0x49eb74=_0xece77b[_0x33f9b0],_0x1e3c4b=_0x3fb422[_0x49eb74]||_0x55a52a;_0x55a52a[_0x34e035(0xf7)]=_0x989826[_0x34e035(0xe5)](_0x989826),_0x55a52a[_0x34e035(0xf0)]=_0x1e3c4b[_0x34e035(0xf0)][_0x34e035(0xe5)](_0x1e3c4b),_0x3fb422[_0x49eb74]=_0x55a52a;}});_0x17f8da();import{_}from'assets://js/lib/cat.js';import*as _0x210159 from'./lib/ali.js';import*as _0x432f53 from'./lib/quark.js';let siteKey='push_agent',siteType=0x0;async function init(_0x19d74a){const _0x523839=_0x1d20;try{siteKey=_0x19d74a[_0x523839(0xe3)],siteType=_0x19d74a['stype'];let _0x1aff0a=_0x19d74a['ext'];typeof _0x1aff0a==_0x523839(0xfa)&&_0x1aff0a[_0x523839(0xee)]('{')&&(_0x1aff0a=JSON['parse'](_0x1aff0a));let _0x13aacd=_0x1aff0a[_0x523839(0x102)],_0x4e1794=_0x1aff0a[_0x523839(0xfd)];await _0x210159['initAli'](_0x13aacd),await _0x432f53[_0x523839(0xe9)](_0x4e1794);}catch(_0x333994){console['debug'](_0x333994);}}async function support(_0x348c76){const _0x300331=_0x1d20;if(!_['isEmpty'](_0x348c76[_0x300331(0x101)](_0x210159[_0x300331(0x107)]))||!_[_0x300331(0xe8)](_0x348c76[_0x300331(0x101)](_0x432f53[_0x300331(0xe7)+'rn'])))return!![];return![];}async function detail(_0x3af4de){const _0x2bf575=_0x1d20;if(!_['isEmpty'](_0x3af4de[_0x2bf575(0x101)](_0x210159[_0x2bf575(0x107)])))return await _0x210159[_0x2bf575(0xe1)+_0x2bf575(0xe2)](_0x3af4de);if(!_[_0x2bf575(0xe8)](_0x3af4de[_0x2bf575(0x101)](_0x432f53[_0x2bf575(0xe7)+'rn'])))return await _0x432f53['detailCont'+_0x2bf575(0xe2)](_0x3af4de);return'{}';}function _0x23d9(){const _0x32888f=['265VXRnLB','string','detail','error','cookie','init','196130ZNashF','{}.constru','match','token','constructo','search','play','support','aliPattern','exception','detailCont','ent','skey','5549256yMZltv','bind','warn','quarkPatte','isEmpty','initQuark','20164Diufks','nction()\x20','122892uhCkuX','prototype','startsWith','rn\x20this\x22)(','toString','info','212574VZCmlY','trace','return\x20(fu','1147909UjKeSz','683166hmvbbu','__proto__','console'];_0x23d9=function(){return _0x32888f;};return _0x23d9();}function _0x1d20(_0x4c5477,_0x30049e){const _0x392059=_0x23d9();return _0x1d20=function(_0x17f8da,_0x989826){_0x17f8da=_0x17f8da-0xe1;let _0x14831b=_0x392059[_0x17f8da];return _0x14831b;},_0x1d20(_0x4c5477,_0x30049e);}async function play(_0x30754e,_0x35a4ec,_0x31bae4){if(_0x30754e['indexOf']('夸克')>-0x1)return await _0x432f53['playConten'+'t'](_0x30754e,_0x35a4ec,_0x31bae4);return await _0x210159['playConten'+'t'](_0x30754e,_0x35a4ec,_0x31bae4);}async function search(_0x3bf45f,_0x17ece4){return'{}';}export function __jsEvalReturn(){const _0x5514bd=_0x1d20,_0x8f8cb={};return _0x8f8cb[_0x5514bd(0xfe)]=init,_0x8f8cb[_0x5514bd(0x106)]=support,_0x8f8cb[_0x5514bd(0xfb)]=detail,_0x8f8cb[_0x5514bd(0x105)]=play,_0x8f8cb[_0x5514bd(0x104)]=search,_0x8f8cb;} \ No newline at end of file