From 043af5b2d8e29fb11508b2946c551be3c127c392 Mon Sep 17 00:00:00 2001 From: XC-Pro <19840+xc-pro@noreply.example.org> Date: Wed, 12 Aug 2026 18:28:55 +0200 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=E3=80=8Cjs=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/夸克影视.js | 32 ++ js/夸克影院.js | 151 ++++++++++ js/米盘搜索.js | 105 +++++++ js/耐看.js | 772 +++++++++++++++++++++++++++++++++++++++++++++++++ js/酷我听书.js | 1 + 5 files changed, 1061 insertions(+) create mode 100644 js/夸克影视.js create mode 100644 js/夸克影院.js create mode 100644 js/米盘搜索.js create mode 100644 js/耐看.js create mode 100644 js/酷我听书.js diff --git a/js/夸克影视.js b/js/夸克影视.js new file mode 100644 index 0000000..2df8460 --- /dev/null +++ b/js/夸克影视.js @@ -0,0 +1,32 @@ +var rule = { + title: '夸克影视[优]', + host: 'https://www.quarktv.com/', + url: 'https://www.quarktv.com/category/fyclass/page/fypage', + searchUrl: '/?s=**', + class_parse: `.site-nav li:gt(0):lt(10);a&&Text;a&&href;.*/category/(.*/?)`, + searchable: 2, + quickSearch: 0, + filterable: 0, + headers: { + 'User-Agent': 'MOBILE_UA', + }, + play_parse: true, + lazy: $js.toString(() => { + let html = request(input); + let url = input.startsWith('push://') ? input : 'push://' + input; + input = {parse: 0, url: url}; + }), + limit: 6, + double: true, + 推荐: '.content;.excerpt;*;*;*;*', + 一级: '.content .excerpt;img&&alt;img&&data-src;.meta&&Text;a&&href', + 二级: { + title: 'h1&&Text', + img: '.cover img&&src', + desc: '.article-meta&&Text;;;;', + content: '.intro&&Text', + tabs: "js:TABS=['下载']", + lists: '.ul-pans li:last-child', + }, + 搜索: '*', +}; diff --git a/js/夸克影院.js b/js/夸克影院.js new file mode 100644 index 0000000..78b0f65 --- /dev/null +++ b/js/夸克影院.js @@ -0,0 +1,151 @@ +let host = 'https://www.qkmov.cc'; +let headers = { + "User-Agent": "Mozilla/5.0 (Linux; Android 13; M2102J2SC Build/TKQ1.221114.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/143.0.7499.3 Mobile Safari/537.36" +}; +async function init(cfg) {} + +function getList(html) { + let videos = []; + let items = pdfa(html, ".stui-vodlist__box,.clearfix li"); + items.forEach(it => { + let idMatch = it.match(/href="([\s\S]*?)"/); + let nameMatch = it.match(/title="([\s\S]*?)"/); + let picMatch = it.match(/data-original="([\s\S]*?)"/); + let remarksMatch = it.match(/text-right">([\s\S]*?)); + if (idMatch && nameMatch) { + let pic = picMatch ? (picMatch[1] || picMatch[2]) : ""; + videos.push({ + vod_id: idMatch[1], + vod_name: nameMatch[1], + vod_pic: pic.startsWith('/') ? host + pic : pic, + vod_remarks: (remarksMatch || ["", ""])[1].replace(/<.*?>/g, "") + }); + } + }); + return videos; +} +async function home(filter) { + return JSON.stringify({ + "class": [{ + "type_id": "20", + "type_name": "电影" + }, { + "type_id": "21", + "type_name": "剧集" + }, { + "type_id": "23", + "type_name": "综艺" + }, { + "type_id": "22", + "type_name": "动漫" + }] + }); +} +async function homeVod() { + let resp = await req(host, { + headers + }); + return JSON.stringify({ + list: getList(resp.content) + }); +} +async function category(tid, pg, filter, extend) { + let p = pg || 1; + let targetId = (extend && extend.class) ? extend.class : tid; + let url = `${host}/type/${tid}-${p}.html`; + let resp = await req(url, { + headers + }); + return JSON.stringify({ + list: getList(resp.content), + page: parseInt(p) + }); +} +async function detail(id) { + const dUrl = host + id; + const dResp = await req(dUrl, { + headers + }); + const dhtml = dResp.content; + const playPageUrl = pdfh(dhtml, '.picture.v-thumb&&href'); + if (!playPageUrl) { + return JSON.stringify({ + list: [] + }); + } + const pResp = await req(host + playPageUrl, { + headers + }); + const phtml = pResp.content; + const blockList = []; + const tabs = pdfa(phtml, '.play-source-tabs'); + const lists = pdfa(phtml, '.play-source-content'); + const playPairs = tabs + .map((tab, idx) => { + const name = (tab.match(/"kua">([\s\S]*?)<\/div>/) || ['', '线路'])[1].trim(); + const urlArr = pdfa(lists[idx] || '', 'a').map(a => { + const n = (a.match(/">([\s\S]*?)<\/a>/) || ['', '播放'])[1]; + const v = a.match(/data-url="([\s\S]*?)"/); + return n + '$' + (v ? v[1] : ''); + }).join('#'); + return { + name, + url: urlArr + }; + }) + .filter(item => !blockList.includes(item.name)); + const playFrom = playPairs.map(p => p.name).join('$$$'); + const playUrl = playPairs.map(p => p.url).join('$$$'); + return JSON.stringify({ + list: [{ + vod_id: id, + vod_name: (dhtml.match(/
([\s\S]*?)<\/p>/) || ['', ''])[1].replace(/<.*?>/g, ''), + vod_play_from: playFrom, + vod_play_url: playUrl + }] + }); +} + +async function search(wd, quick, pg) { + let p = pg || 1; + let url = `${host}/search/${wd}----------${p}---.html`; + let resp = await req(url, { + headers + }); + return JSON.stringify({ + list: getList(resp.content) + }); +} + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} +async function play(flag, id, flags) { + const playUrl = /^http/.test(id) ? id : `${host}${id}`; + await sleep(5000); + return JSON.stringify({ + jx: 0, + parse: 0, + url: 'push://' + playUrl, + header: headers + }); +} +export default { + init, + home, + homeVod, + category, + detail, + search, + play +}; \ No newline at end of file diff --git a/js/米盘搜索.js b/js/米盘搜索.js new file mode 100644 index 0000000..2fee580 --- /dev/null +++ b/js/米盘搜索.js @@ -0,0 +1,105 @@ +var rule = { + +safeParseJSON: function(jStr){ + try {return JSON.parse(jStr);} catch(e) {return null;} +}, + +getkvods: function (url, words = '米', emode = false) { + let kwd = words; + let rbody = { + "page": 1, + "q": kwd, + "user": "", + "exact": emode, + "format": [".mp4", ".mkv", ".flv", ".rmvb", ".wmv", ".3gp", ".mov", ".m4v", ".swf", ".f4v", ".webm", ".ogg", ".ogv", ".m3u8", ".mpd", ".avi", ".mpg", ".mpeg", ".mpe", ".mpv", ".m2v", ".mxf", ".3g2", ".f4p", ".f4a", ".f4b"], + "share_time": "", + "size": 15, "type": "", + "exclude_user": [], + "adv_params": {"wechat_pwd": "", "platform": ""} + }; + let khtml = fetch(url, { + headers: { + ...rule.headers, + "Content-Type": "application/json; charset=UTF-8" + }, + method: 'POST', + body: rbody + }); + let klists = rule.safeParseJSON(khtml)?.data?.list ?? []; + let kvods = []; + klists.forEach(it => { + let kname = it.disk_name.replace(/<[^>]*?>/g, '') || '名称'; + let kpic = rule.panPics[it.disk_type] || '图片'; + let kremarks = `${it.disk_type}|${it.shared_time || '无分享时间'}`; + kvods.push({ + vod_name: kname, + vod_pic: kpic, + vod_remarks: kremarks, + vod_id: `${it.link}@${kname}@${kpic}@${kremarks}` + }); + }); + return kvods; +}, + +author: '小可乐/v5.12.1', +title: '米盘搜', +类型: '影视', +host: 'http://misopan.fun', +headers: {'User-Agent': MOBILE_UA}, +编码: 'utf-8', +timeout: 5000, + +homeUrl: '/v1/search/disk', +url: '/v1/search/disk', +searchUrl: '/v1/search/disk', + +limit: 9, +double: false, +class_name: '电影&国产剧&短剧', +class_url: '电影&国产剧&短剧', +pagecount: {"电影": 1, "国产剧": 1, "短剧": 1}, + +exaxt: false,//精准搜索改为true +panPics: { + "QUARK": "https://so.slowread.net/static/img/quark.jpg", + "BDY": "https://so.slowread.net/static/img/baidu.jpg", + "UC": "https://so.slowread.net/static/img/uc.jpg" +}, + +推荐: $js.toString(() => { + let kwd = '美剧'; + VODS = rule.getkvods(input, kwd, rule.exaxt); +}), +一级: $js.toString(() => { + VODS = rule.getkvods(input, MY_CATE, rule.exaxt); +}), +搜索: $js.toString(() => { + VODS = rule.getkvods(input, KEY, rule.exaxt); +}), +二级: $js.toString(() => { + let [kid, kname, kpic, kremarks] = input.split('@'); + let [type, remark='状态'] = kremarks.split('|'); + let kurl = `合集$${kid}`; + VOD = { + vod_id: kid, + vod_name: kname, + vod_pic: kpic, + type_name: type, + vod_remarks: remark, + vod_year: '1000', + vod_area: '地区', + vod_lang: '语言', + vod_director: '导演', + vod_actor: '演员', + vod_content: `${kname}_${kid}`, + vod_play_from: type, + vod_play_url: kurl + }; +}), + +play_parse: true, +lazy: $js.toString(() => { + let kurl = `push://${input}`; + input = { jx: 0, parse: 0, url: kurl }; +}), +} \ No newline at end of file diff --git a/js/耐看.js b/js/耐看.js new file mode 100644 index 0000000..4ef69fd --- /dev/null +++ b/js/耐看.js @@ -0,0 +1,772 @@ +/** + title: "耐看影视", + author: "", + logo: "https://nkvod.org/upload/site/20241223-1/a9ca623af581c93ed3c2f3e98e3a5d4b.png", + more: { + sourceTag: "在线播放" + } +*/ +import { Crypto, load, _ } from 'assets://js/lib/cat.js'; + +let HOST = 'https://nkvod.org'; +let siteKey = "", siteType = "", sourceKey = "", ext = ""; +let searchCookie = ''; + +const UA = 'Mozilla/5.0 (Linux; Android 12; ALN-AL00 Build/HUAWEIALN-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Mobile Safari/537.36'; + +async function getCaptchaBinaryData(url) { + try { + const res = await req(url, { + headers: { + 'User-Agent': UA, + 'Referer': HOST + }, + buffer: 1 + }); + + let binaryData; + if (Array.isArray(res.content)) { + binaryData = new Uint8Array(res.content); + } else { + binaryData = res.content; + } + + return { + headers: res.headers, + binaryData: binaryData + }; + } catch (error) { + throw error; + } +} + +async function request(reqUrl, options = {}) { + const defaultOptions = { + method: 'GET', + headers: { + 'User-Agent': UA, + 'Referer': HOST + } + }; + + if (searchCookie) { + defaultOptions.headers['Cookie'] = searchCookie; + } + + const mergedOptions = {...defaultOptions, ...options}; + + let res = await req(reqUrl, mergedOptions); + return res.content; +} + +async function requestWithCaptcha(reqUrl, options = {}) { + let verifyType = 'search'; + if (typeof options === 'string') { + verifyType = options; + options = {}; + } else if (options.verifyType) { + verifyType = options.verifyType; + } + + let html = await request(reqUrl, options); + + const needCaptcha = html && ( + html.includes('系统安全验证') || + html.includes('请输入验证码') || + html.includes('verify/index.html') || + html.includes('verify_check') + ); + + if (needCaptcha) { + searchCookie = ''; + await fetchCk(verifyType); + + if (searchCookie) { + html = await request(reqUrl, { + ...options, + headers: { + ...options.headers, + 'Cookie': searchCookie + } + }); + } + + const stillNeedCaptcha = html && ( + html.includes('系统安全验证') || + html.includes('请输入验证码') + ); + + if (stillNeedCaptcha) { + return null; + } + } + + return html; +} + +async function fetchCk(verifyType = 'search') { + try { + const yzm = HOST + "/index.php/verify/index.html?" + Date.now(); + + const yzmResponse = await getCaptchaBinaryData(yzm); + + let cookie = ""; + const headers = yzmResponse.headers; + + for (const key in headers) { + if (key.toLowerCase() === "set-cookie") { + const cookieValue = headers[key]; + if (Array.isArray(cookieValue)) { + cookie = cookieValue[0].split(";")[0]; + } else if (typeof cookieValue === 'string') { + cookie = cookieValue.split(";")[0]; + } + break; + } + } + + if (!cookie) { + return; + } + + let base64Image; + if (yzmResponse.binaryData instanceof Uint8Array) { + const wordArray = Crypto.lib.WordArray.create(yzmResponse.binaryData); + base64Image = Crypto.enc.Base64.stringify(wordArray); + } else { + return; + } + + if (!base64Image) { + return; + } + + try { + const ocrResponse = await req("https://api.nn.ci/ocr/b64/text", { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + 'User-Agent': UA, + 'Accept': 'application/json' + }, + body: base64Image, + timeout: 10000 + }); + + if (!ocrResponse || !ocrResponse.content) { + return; + } + + let verifyCode = ocrResponse.content.trim(); + if (!verifyCode) { + return; + } + + verifyCode = verifyCode.replace(/[^a-zA-Z0-9]/g, ''); + + if (verifyCode.length < 4) { + return; + } + + const submit_url = `${HOST}/index.php/ajax/verify_check?type=${verifyType}&verify=${verifyCode}`; + + const submitResponse = await req(submit_url, { + method: 'POST', + headers: { + 'User-Agent': UA, + 'X-Requested-With': 'XMLHttpRequest', + 'Origin': HOST, + 'Referer': HOST + '/', + 'Cookie': cookie, + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: '' + }); + + if (submitResponse && submitResponse.content) { + try { + const submitJson = JSON.parse(submitResponse.content); + if (submitJson && submitJson.code === 1) { + searchCookie = cookie; + } + } catch (parseError) { + if (submitResponse.content.includes('"code":1') || submitResponse.content.includes('验证成功')) { + searchCookie = cookie; + } + } + } + + } catch (ocrError) { + } + } catch (error) { + } +} + +function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; + sourceKey = cfg.sourceKey; + ext = cfg.ext; + if (ext && ext.indexOf('http') == 0) { + HOST = ext; + } +} + +// 辅助函数:获取元素文本内容(兼容 flutter_js 的 cheerio) +// flutter_js 的 cheerio 实现中 .text() 方法可能返回空,需要使用 .html() 作为备用 +function getText($elem) { + if (!$elem || !$elem.length) return ''; + // 优先使用 text(),如果返回空则尝试从 html() 提取 + let text = ''; + try { + text = $elem.text(); + } catch (e) {} + if (!text || text.trim() === '') { + try { + // 从 html 中去除标签获取纯文本 + const html = $elem.html(); + if (html) { + text = html.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' '); + } + } catch (e) {} + } + return (text || '').trim(); +} + +async function home(filter) { + const classes = [ + { type_id: "1", type_name: "电影" }, + { type_id: "2", type_name: "剧集" }, + { type_id: "4", type_name: "动漫" }, + { type_id: "3", type_name: "综艺" } + ]; + + const filterObj = { +"1":[{"key":"class","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":"奇幻"},{"n":"武侠","v":"武侠"},{"n":"冒险","v":"冒险"},{"n":"枪战","v":"枪战"},{"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":"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":"印度"},{"n":"意大利","v":"意大利"},{"n":"西班牙","v":"西班牙"},{"n":"加拿大","v":"加拿大"},{"n":"其它","v":"其它"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2026","v":"2026"},{"n":"2025","v":"2025"},{"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":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"}]},{"key":"lang","name":"语言","value":[{"n":"全部","v":""},{"n":"国语","v":"国语"},{"n":"英语","v":"英语"},{"n":"粤语","v":"粤语"},{"n":"闽南语","v":"闽南语"},{"n":"韩语","v":"韩语"},{"n":"日语","v":"日语"},{"n":"法语","v":"法语"},{"n":"德语","v":"德语"},{"n":"其它","v":"其它"}]},{"key":"letter","name":"字母","value":[{"n":"字母","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}], +"2":[{"key":"class","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":"情景"},{"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":"其他"}]},{"key":"lang","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":"2026","v":"2026"},{"n":"2025","v":"2025"},{"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":"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":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"}]},{"key":"letter","name":"字母","value":[{"n":"字母","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}], +"3":[{"key":"class","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":"游戏互动"},{"n":"财经","v":"财经"},{"n":"求职","v":"求职"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"内地","v":"内地"},{"n":"港台","v":"港台"},{"n":"日韩","v":"日韩"},{"n":"欧美","v":"欧美"}]},{"key":"lang","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":"2026","v":"2026"},{"n":"2025","v":"2025"},{"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":"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":"letter","name":"字母","value":[{"n":"字母","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}], + +"4":[{"key":"class","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":"运动"},{"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":"其他"}]},{"key":"lang","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":"2026","v":"2026"},{"n":"2025","v":"2025"},{"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":"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":"letter","name":"字母","value":[{"n":"字母","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}]} + + return JSON.stringify({ + class: classes, + filters: filterObj + }); +} + +async function homeVod() { + const link = `${HOST}/`; + try { + const html = await request(link); + if (!html) return null; + const $ = load(html); + + const hotSection = $('.title-a:contains("热播推荐")').closest('.box-width'); + if (hotSection.length === 0) return null; + + const items = hotSection.find('.public-list-box'); + if (items.length === 0) return null; + + const videos = _.map(items, (item) => { + const $item = $(item); + const $link = $item.find('.public-list-exp'); + const $img = $item.find('.gen-movie-img'); + const $title = $item.find('.time-title'); + const $subtitle = $item.find('.public-list-subtitle'); + + const href = $link.attr('href'); + const title = $title.attr('title') || getText($title); + const imgSrc = $img.attr('data-src'); + const remarks = getText($subtitle); + + const vod_id = href && href.startsWith('http') ? href : HOST + (href || ''); + const vod_name = title; + const vod_pic = imgSrc ? (imgSrc.startsWith('http') ? imgSrc : HOST + imgSrc) : ''; + const vod_remarks = remarks; + + return { + vod_id, + vod_name, + vod_pic, + vod_remarks + }; + }); + + return JSON.stringify({ + list: videos + }); + } catch (error) { + return JSON.stringify({ + list: [] + }); + } +} + +async function category(tid, pg, filter, extend) { + if (pg <= 0) pg = 1; + const homeFilter = {}; + const homeResult = JSON.parse(await home(homeFilter)); + const filterObj = homeResult.filters; + if (!filterObj) return null; + const filterGroup = filterObj[tid]; + if (!filterGroup) return null; + const area = getFilterValue(filterGroup, 'area', extend); + const by = getFilterValue(filterGroup, 'by', extend); + const classValue = getFilterValue(filterGroup, 'class', extend); + const lang = getFilterValue(filterGroup, 'lang', extend); + const letter = getFilterValue(filterGroup, 'letter', extend); + const year = getFilterValue(filterGroup, 'year', extend); + const cateId = getFilterValue(filterGroup, 'cateId', extend); + const baseUrl = `${HOST}/show/${tid}`; + const link = `${baseUrl}-${area}-${by}-${classValue}-${lang}-${letter}---${pg}---${year}.html`; + try { + const html = await requestWithCaptcha(link, 'show'); + if (!html) return null; + const $ = load(html); + + const isParsedSuccessfully = $('.public-list-box').length > 0; + if (!isParsedSuccessfully) return null; + + const items = $('.public-list-box'); + const videos = _.map(items, (item) => { + const $item = $(item); + + const $link = $item.find('.public-list-exp'); + const $title = $item.find('.time-title'); + const $img = $item.find('.gen-movie-img'); + const $remarks = $item.find('.public-list-subtitle'); + + const href = $link.attr('href'); + const title = $title.attr('title') || getText($title); + const imgSrc = $img.attr('data-src'); + const remarks = getText($remarks); + + const vod_id = href && href.startsWith('http') ? href : HOST + (href || ''); + const vod_name = title; + const vod_pic = imgSrc ? (imgSrc.startsWith('http') ? imgSrc : HOST + imgSrc) : ''; + const vod_remarks = remarks; + + return { + 'vod_id': vod_id, + 'vod_name': vod_name, + 'vod_pic': vod_pic, + 'vod_remarks': vod_remarks + }; + }); + + return JSON.stringify({ + list: videos + }); + } catch (error) { + return JSON.stringify({ + list: [] + }); + } +} + +function getFilterValue(filterGroup, key, extend) { + const filterItem = filterGroup.find(item => item.key === key); + if (!filterItem) return ''; + const userValue = extend[key]; + if (userValue) { + const option = filterItem.value.find(opt => opt.v === userValue); + return option ? option.v : ''; + } + return filterItem.value[0].v; +} + +async function search(wd) { + const searchUrl = `${HOST}/nk/-------------.html?wd=${encodeURIComponent(wd)}`; + const lowerWd = wd.toLowerCase(); + try { + const html = await requestWithCaptcha(searchUrl, 'search'); + if (!html) return JSON.stringify({ list: [], error: '需要验证码但无法自动识别' }); + const $ = load(html); + + const hasSearchResults = $('.public-list-box.search-box').length > 0; + const hasSearchInput = $('input[name="wd"]').length > 0; + const hasSearchHeader = $('.m-search').length > 0; + + if ((hasSearchInput || hasSearchHeader) && !hasSearchResults) { + return JSON.stringify({ list: [], error: '搜索无结果或需要验证码' }); + } + + if (!hasSearchInput && !hasSearchHeader && !hasSearchResults) { + return JSON.stringify({ list: [], error: '需要验证码但无法自动识别' }); + } + + const items = $('.public-list-box.search-box'); + const videos = []; + + items.each((index, item) => { + const $item = $(item); + + const $link = $item.find('.public-list-exp'); + const href = $link.attr('href'); + if (!href) return; + + const $title = $item.find('.thumb-txt a'); + const vod_name = getText($title); + if (!vod_name) return; + + const $img = $item.find('.gen-movie-img'); + const vod_pic = $img.attr('data-src'); + + const $remarks = $item.find('.public-list-prb'); + const vod_remarks = getText($remarks); + + const $info = $item.find('.thumb-else'); + const yearText = getText($info.find('a[href*="202"]').first()); + const areaText = getText($info.find('a[href*="美国"], a[href*="英国"], a[href*="泰国"]').first()); + + const lowerTitle = vod_name.toLowerCase(); + if (lowerTitle.includes(lowerWd)) { + videos.push({ + 'vod_id': HOST + href, + 'vod_name': vod_name, + 'vod_pic': vod_pic, + 'vod_remarks': vod_remarks, + 'vod_year': yearText, + 'vod_area': areaText + }); + } + }); + + return JSON.stringify({ list: videos }); + } catch (error) { + return JSON.stringify({ list: [] }); + } +} + +async function detail(id) { + try { + const html = await request(id); + if (!html) return JSON.stringify({ list: [] }); + const $ = load(html); + + const vod = { + vod_id: id, + vod_name: getText($('.slide-info-title')), + vod_pic: $('.detail-pic img').attr('data-src') || $('.detail-pic img').attr('src'), + vod_year: '', + vod_area: '', + vod_remarks: '', + vod_actor: '', + vod_director: '', + vod_content: getText($('#height_limit')), + vod_play_from: '', + vod_play_url: '' + }; + + $('.slide-info').each((i, elem) => { + const $elem = $(elem); + const text = getText($elem); + + if (text.includes('备注 :') || text.includes('备注 :')) { + vod.vod_remarks = text.replace(/备注\s*[::]/g, '').trim(); + } else if (text.includes('导演 :') || text.includes('导演 :')) { + vod.vod_director = text.replace(/导演\s*[::]/g, '').replace(/[\/\s]+$/, '').trim(); + } else if (text.includes('演员 :') || text.includes('演员 :')) { + vod.vod_actor = text.replace(/演员\s*[::]/g, '').replace(/[\/\s]+$/, '').trim(); + } else if (text.includes('更新 :') || text.includes('更新 :')) { + const updateText = text.replace(/更新\s*[::]/g, '').trim(); + const yearMatch = updateText.match(/\d{4}/); + if (yearMatch) { + vod.vod_year = yearMatch[0]; + } + } + }); + + // 从链接中提取年份和地区 + const yearLink = $('.slide-info a[href*="202"]').first(); + if (yearLink.length) { + const yearText = getText(yearLink); + if (/^\d{4}$/.test(yearText)) vod.vod_year = yearText; + } + + // 尝试从 slide-info-remarks 获取年份和地区 + $('.slide-info-remarks a').each((i, elem) => { + const $a = $(elem); + const href = $a.attr('href') || ''; + const aText = getText($a); + if (/\d{4}/.test(aText) && !vod.vod_year) { + vod.vod_year = aText.match(/\d{4}/)[0]; + } + if ((href.includes('内地') || href.includes('香港') || href.includes('台湾') || + href.includes('美国') || href.includes('韩国') || href.includes('日本') || + href.includes('泰国') || href.includes('英国')) && !vod.vod_area) { + vod.vod_area = aText; + } + }); + + const playFrom = []; + const playUrl = []; + $('.anthology-tab .swiper-slide').each((i, tab) => { + const $tab = $(tab); + let from = $tab.attr('data-from') || ''; + if (!from) from = `nk${i + 1}`; + // 获取线路名称,优先从文本中提取 + let show = getText($tab); + // 清理文本:去除图标字符、badge数字等 + show = show.replace(/[\ue000-\uf8ff]/g, '') // 去除图标字体 + .replace(/&\w+;/g, '') + .replace(/\s*\d+\s*$/, '') // 去除末尾的badge数字 + .trim(); + if (!show) show = from; + playFrom.push(show); + }); + + $('.anthology-list-box').each((i, box) => { + const episodes = []; + const $tab = $('.anthology-tab .swiper-slide').eq(i); + let from = $tab.attr('data-from') || ''; + if (!from) from = `nk${i + 1}`; + $(box).find('.anthology-list-play a').each((j, link) => { + const $link = $(link); + let episodeName = getText($link); + if (!episodeName) { + // 如果还是获取不到,从 href 中提取 + const href = $link.attr('href') || ''; + const match = href.match(/-(\d+)\.html$/); + episodeName = match ? `第${match[1]}集` : `第${j + 1}集`; + } + const episodeUrl = HOST + $link.attr('href'); + episodes.push(`${episodeName}$${episodeUrl}@${from}`); + }); + playUrl.push(episodes.join('#')); + }); + + vod.vod_play_from = playFrom.join('$$$'); + vod.vod_play_url = playUrl.join('$$$'); + + return JSON.stringify({ list: [vod] }); + } catch (error) { + return JSON.stringify({ list: [] }); + } +} + +async function play(flag, id, flags) { + try { + const parts = id.split('@'); + if (parts.length < 2) { + throw new Error('播放链接格式错误,缺少英文标识'); + } + + const playUrl = parts[0]; + const from = parts[1]; + const html = await request(playUrl); + const playerStart = html.indexOf('var player_aaaa='); + if (playerStart === -1) throw new Error('未找到player_aaaa'); + const playerEnd = html.indexOf('', playerStart); + if (playerEnd === -1) throw new Error('未找到脚本结束标签'); + + let playerScript = html.substring(playerStart + 'var player_aaaa='.length, playerEnd); + playerScript = playerScript.split(';')[0].trim() + .replace(/,\s*$/, '') + .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/\/\/.*/g, ''); + + let playerData; + try { + playerData = JSON.parse(playerScript); + } catch (parseErr) { + eval(`playerData = ${playerScript}`); + } + if (!playerData || !playerData.url) { + throw new Error('播放数据格式异常: url 缺失'); + } + + let playurl = playerData.url; + if (/m3u8|mp4/i.test(playurl)) { + return JSON.stringify({ parse: 0, url: playurl }); + } + + const configUrl = `${HOST}/static/js/playerconfig.js?t=20251225`; + const configJs = await request(configUrl); + if (!configJs) throw new Error('获取 playerconfig.js 失败'); + + let MacPlayerConfig = {}; + try { + const evalCode = `(function(){ + var MacPlayerConfig = {}; + ${configJs.replace(/^var MacPlayerConfig=.*?;/, '')} + return MacPlayerConfig; + })()`; + MacPlayerConfig = eval(evalCode); + } catch (e) { + MacPlayerConfig = { + player_list: { + nk1: { parse: 'https://gg.xn--it-if7c19g5s4bps5c.com/nkvod3.php' }, + nk2: { parse: 'https://gg.xn--it-if7c19g5s4bps5c.com/nkvod3.php' }, + nk4k: { parse: 'https://gg.xn--it-if7c19g5s4bps5c.com/nkvod3.php' } + } + }; + } + const playerList = MacPlayerConfig.player_list || {}; + let parseDomain = playerList[from]?.parse || playerList.nk4k.parse; + + let jx = ''; + if (parseDomain.includes('?')) { + jx = `${parseDomain}&url=${encodeURIComponent(playurl)}&next=${encodeURIComponent(playerData.link_next || '')}&title=${encodeURIComponent(playerData.vod_data?.vod_name || '')}`; + } else { + jx = `${parseDomain}?url=${encodeURIComponent(playurl)}&next=${encodeURIComponent(playerData.link_next || '')}&title=${encodeURIComponent(playerData.vod_data?.vod_name || '')}`; + } + + const jxhtml = await request(jx); + if (!jxhtml) throw new Error('解析接口响应为空'); + + let raw_key = [], iv = [], encrypted = ''; + + const rawKeyMatch = jxhtml.match(/var\s+raw_key\s*=\s*\[([^\]]+)\]/); + if (rawKeyMatch) { + raw_key = rawKeyMatch[1].split(',').map(item => parseInt(item.trim())).filter(num => !isNaN(num)); + } + + const ivMatch = jxhtml.match(/var\s+iv\s*=\s*\[([^\]]+)\]/); + if (ivMatch) { + iv = ivMatch[1].split(',').map(item => parseInt(item.trim())).filter(num => !isNaN(num)); + } + + const encryptedMatch = jxhtml.match(/var\s+encrypted\s*=\s*["']([a-fA-F0-9]+)["']/); + if (encryptedMatch) { + encrypted = encryptedMatch[1]; + } + + const validKeyLengths = [16, 32]; + const validIVLength = 16; + if (!encrypted || !validKeyLengths.includes(raw_key.length) || iv.length !== validIVLength) { + throw new Error(`加密参数提取失败或长度异常 → key:${raw_key.length}, iv:${iv.length}, encrypted:${encrypted.length}`); + } + + const decryptedText = decryptData(encrypted, raw_key, iv); + + if (!decryptedText) { + throw new Error('解密失败'); + } + + let finalPlayUrl = ''; + const randomMatch = decryptedText.match(/getrandom\(['"]([^'"]+)['"]\)/); + if (randomMatch) { + finalPlayUrl = getrandom(randomMatch[1]); + } else { + const urlPattern = /https?:\/\/[^\s"'<>]+/gi; + const urlMatches = decryptedText.match(urlPattern); + if (urlMatches && urlMatches.length > 0) { + finalPlayUrl = urlMatches[0]; + } else { + throw new Error('未找到 getrandom 参数或URL'); + } + } + + return JSON.stringify({ parse: 0, url: finalPlayUrl }); + } catch (error) { + return JSON.stringify({ parse: 1, url: id, error: error.message }); + } +} +function validateHexData(hexStr) { + if (hexStr.length % 2 !== 0) { + return false; + } + if (!/^[0-9a-fA-F]+$/.test(hexStr)) { + return false; + } + return true; +} + +function decryptData(encryptedHex, rawKeyArray, ivArray) { + if (!validateHexData(encryptedHex)) { + return null; + } + + const rawKey = Crypto.lib.WordArray.create(new Uint8Array(rawKeyArray)); + const iv = Crypto.lib.WordArray.create(new Uint8Array(ivArray)); + const encrypted = Crypto.enc.Hex.parse(encryptedHex); + + const modes = [ + { name: 'CBC', mode: Crypto.mode.CBC }, + { name: 'OFB', mode: Crypto.mode.OFB }, + { name: 'CTR', mode: Crypto.mode.CTR }, + { name: 'ECB', mode: Crypto.mode.ECB }, + { name: 'CFB', mode: Crypto.mode.CFB } + ]; + + for (let modeInfo of modes) { + try { + const decryptionOptions = { + mode: modeInfo.mode, + padding: Crypto.pad.Pkcs7 + }; + if (modeInfo.name !== 'ECB') decryptionOptions.iv = iv; + + const decrypted = Crypto.AES.decrypt({ ciphertext: encrypted }, rawKey, decryptionOptions); + const result = decrypted.toString(Crypto.enc.Utf8); + if (result && result.length > 0) { + return result; + } + } catch (e) { + } + } + return null; +} + +function getrandom(b) { + try { + const string = b.substring(10); + let substr; + try { + const base64Data = Crypto.enc.Base64.parse(string); + substr = base64Data.toString(Crypto.enc.Latin1); + } catch (e) { + throw new Error('Base64解码失败'); + } + + if (!substr) { + throw new Error('Base64解码结果为空'); + } + + const substrTrim = substr.substring(10); + let data2 = substrTrim.replace('_nanke', ''); + let data3 = data2.slice(0, 20) + data2.slice(21); + const hexStr = data3.replace(/[^0-9a-fA-F]/g, ''); + const finalUrl = hexDecodeAndFilter(hexStr); + return finalUrl; + } catch (error) { + throw error; + } +} + +function hexDecodeAndFilter(hexStr) { + try { + let pureHex = hexStr.replace(/[^0-9a-fA-F]/g, ''); + if (pureHex.length % 2 !== 0) { + pureHex += '0'; + } + let decoded = ''; + for (let i = 0; i < pureHex.length; i += 2) { + const hexByte = pureHex.substr(i, 2); + const charCode = parseInt(hexByte, 16); + const char = String.fromCharCode(charCode); + const isUrlValid = /[a-zA-Z0-9:\/\.\-\?\&=\%]/.test(char); + if (isUrlValid) { + decoded += char; + } + } + const urlMatch = decoded.match(/https?:\/\/[^\s]+/); + decoded = urlMatch ? urlMatch[0] : decoded.trim(); + return decoded; + } catch (e) { + throw e; + } +} + +export function __jsEvalReturn() { + return { + init: init, + detail: detail, + home: home, + play: play, + search: search, + homeVod: homeVod, + category: category + }; +} diff --git a/js/酷我听书.js b/js/酷我听书.js new file mode 100644 index 0000000..ae6c6c3 --- /dev/null +++ b/js/酷我听书.js @@ -0,0 +1 @@ +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 \ No newline at end of file