mirror of
https://github.com/ls125781003/tvboxtg.git
synced 2026-11-02 17:53:22 +00:00
0610
This commit is contained in:
1 parent
2d385a1497
commit
4f89a5c886
89 files changed
+5312
-36791
No files matched your search
-202
@@ -1,202 +0,0 @@
|
||||
import { load, _ } from 'assets://js/lib/cat.js';
|
||||
|
||||
let HOST = 'https://www.budaichuchen.net';
|
||||
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
|
||||
|
||||
const DefaultHeader = {
|
||||
'User-Agent': UA,
|
||||
'Referer': HOST + '/',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
||||
};
|
||||
|
||||
async function request(url, options = {}) {
|
||||
try {
|
||||
const optObj = {
|
||||
headers: options.headers || DefaultHeader,
|
||||
timeout: 10000,
|
||||
method: options.method || 'GET',
|
||||
data: options.data || ''
|
||||
};
|
||||
const res = await req(url, optObj);
|
||||
return res?.content ?? '';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function parseHtml(html) {
|
||||
return load(html);
|
||||
}
|
||||
|
||||
async function init(cfg) {
|
||||
if (cfg.ext && typeof cfg.ext === 'string') {
|
||||
HOST = cfg.ext;
|
||||
}
|
||||
}
|
||||
|
||||
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: '动漫' },
|
||||
{ type_id: '5', type_name: '短剧' }
|
||||
];
|
||||
return JSON.stringify({ class: classes });
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
const html = await request(HOST);
|
||||
if (!html) return JSON.stringify({ list: [] });
|
||||
const $ = parseHtml(html);
|
||||
let videos = [];
|
||||
$('.public-list-box').each((_, el) => {
|
||||
const a = $(el).find('.public-list-exp');
|
||||
const href = a.attr('href') || '';
|
||||
if (href.includes('/detail/')) {
|
||||
videos.push({
|
||||
vod_id: href.match(/detail\/(.*?)\.html/)[1],
|
||||
vod_name: a.attr('title'),
|
||||
vod_pic: a.find('img').attr('data-src') || a.find('img').attr('src'),
|
||||
vod_remarks: $(el).find('.public-list-prb').text().trim()
|
||||
});
|
||||
}
|
||||
});
|
||||
return JSON.stringify({ list: videos });
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
const area = extend.area || '';
|
||||
const by = extend.by || 'time';
|
||||
const clazz = extend.class || '';
|
||||
const year = extend.year || '';
|
||||
const lang = extend.lang || '';
|
||||
const letter = extend.letter || '';
|
||||
const url = `${HOST}/cupfox-list/${tid}-${area}-${by}-${clazz}-${lang}-${letter}---${pg}---${year}.html`;
|
||||
const html = await request(url);
|
||||
if (!html) return JSON.stringify({ list: [] });
|
||||
const $ = parseHtml(html);
|
||||
let videos = [];
|
||||
$('.public-list-box').each((_, el) => {
|
||||
const a = $(el).find('.public-list-exp');
|
||||
const href = a.attr('href') || '';
|
||||
if (href.includes('/detail/')) {
|
||||
videos.push({
|
||||
vod_id: href.match(/detail\/(.*?)\.html/)[1],
|
||||
vod_name: a.attr('title'),
|
||||
vod_pic: $(el).find('img').attr('data-src') || $(el).find('img').attr('src'),
|
||||
vod_remarks: $(el).find('.public-list-prb').text().trim()
|
||||
});
|
||||
}
|
||||
});
|
||||
return JSON.stringify({ page: parseInt(pg), list: videos });
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const url = `${HOST}/detail/${id}.html`;
|
||||
const html = await request(url);
|
||||
if (!html) return "{}";
|
||||
const $ = parseHtml(html);
|
||||
const vod = {
|
||||
vod_id: id,
|
||||
vod_name: $('.slide-info-title').text().trim(),
|
||||
vod_pic: $('.detail-pic img').attr('data-src') || $('.detail-pic img').attr('src'),
|
||||
vod_content: $('#height_limit').text().trim(),
|
||||
vod_play_from: [],
|
||||
vod_play_url: []
|
||||
};
|
||||
$('.anthology-tab a').each((_, el) => {
|
||||
const name = $(el).text().trim().replace(/\s/g, '').replace(/\(\d+\)/, '');
|
||||
if (name) vod.vod_play_from.push(name);
|
||||
});
|
||||
$('.anthology-list-box').each((_, el) => {
|
||||
let items = [];
|
||||
$(el).find('ul li a').each((_, a) => {
|
||||
const name = $(a).text().trim();
|
||||
const href = $(a).attr('href');
|
||||
if (href) {
|
||||
const playMatch = href.match(/play\/(.*?)\.html/);
|
||||
if (playMatch) items.push(`${name}$${playMatch[1]}`);
|
||||
}
|
||||
});
|
||||
items.reverse();
|
||||
vod.vod_play_url.push(items.join('#'));
|
||||
});
|
||||
vod.vod_play_from = vod.vod_play_from.join('$$$');
|
||||
vod.vod_play_url = vod.vod_play_url.join('$$$');
|
||||
return JSON.stringify({ list: [vod] });
|
||||
}
|
||||
|
||||
async function search(wd, quick) {
|
||||
const url = `${HOST}/cupfox-search/${encodeURIComponent(wd)}----------1---.html`;
|
||||
const html = await request(url);
|
||||
if (!html) return JSON.stringify({ list: [] });
|
||||
const $ = parseHtml(html);
|
||||
let videos = [];
|
||||
$('.search-box').each((_, el) => {
|
||||
const a = $(el).find('.public-list-exp');
|
||||
const href = a.attr('href') || '';
|
||||
if (href.includes('/detail/')) {
|
||||
videos.push({
|
||||
vod_id: href.match(/detail\/(.*?)\.html/)[1],
|
||||
vod_name: $(el).find('.thumb-txt a').text().trim(),
|
||||
vod_pic: a.find('img').attr('data-src') || a.find('img').attr('src'),
|
||||
vod_remarks: a.find('.public-list-prb').text().trim()
|
||||
});
|
||||
}
|
||||
});
|
||||
return JSON.stringify({ list: videos });
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
try {
|
||||
const url = `${HOST}/play/${id}.html`;
|
||||
const html = await request(url);
|
||||
if (!html) return JSON.stringify({ parse: 0, url: '' });
|
||||
|
||||
const match = html.match(/var\s+player_aaaa\s*=\s*(\{.*?\});/);
|
||||
if (!match) return JSON.stringify({ parse: 1, url: url });
|
||||
|
||||
const config = JSON.parse(match[1]);
|
||||
const rawUrl = config.url || '';
|
||||
const from = config.from || '';
|
||||
|
||||
if (rawUrl.startsWith('http')) {
|
||||
const isDirect = rawUrl.includes('.m3u8') || rawUrl.includes('.mp4');
|
||||
return JSON.stringify({
|
||||
parse: isDirect ? 0 : 1,
|
||||
url: rawUrl,
|
||||
header: DefaultHeader
|
||||
});
|
||||
}
|
||||
|
||||
if (from === 'JD4K' || from === 'JD' || rawUrl.startsWith('JD-')) {
|
||||
const jxUrl = 'https://fgsrg.hzqingshan.com/player/?url=' + rawUrl;
|
||||
return JSON.stringify({
|
||||
parse: 1,
|
||||
url: jxUrl,
|
||||
header: DefaultHeader
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
parse: 1,
|
||||
url: rawUrl || url,
|
||||
header: DefaultHeader
|
||||
});
|
||||
} catch (e) {
|
||||
return JSON.stringify({ parse: 1, url: url });
|
||||
}
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
// 本资源来源于互联网公开渠道,仅可用于个人学习爬虫技术。
|
||||
// 严禁将其用于任何商业用途,下载后请于 24 小时内删除,搜索结果均来自源站,本人不承担任何责任。
|
||||
import{Crypto as t,_ as e}from"assets://js/lib/cat.js";let n="https://api.dbokutv.com";const o={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)",Connection:"Keep-Alive",Referer:"https://www.duboku.tv/"};async function r(t){}async function a(t){const e=[{type_id:2,type_name:"连续剧"},{type_id:3,type_name:"综艺"},{type_id:1,type_name:"电影"},{type_id:4,type_name:"动漫"}],r={},a=e.map(async t=>{const e=t.type_id,a=f(`${n}/vodshow/${e}-----------`);try{const t=await req(a,{headers:o}),n=JSON.parse(t.content);if(n&&n.FilterList){const t=[];for(const e of n.FilterList){let n="";switch(e.Class){case"剧情":n="class";break;case"地区":n="area";break;case"年份":n="year";break;case"语言":n="lang";break;case"字母":n="letter";break;case"排序":n="sort";break;case"类型":n="scat"}if(n&&e.OptionList&&e.OptionList.length>0){const o=[];let r="";"sort"===n?(e.OptionList.forEach(t=>{o.push({n:t.Option,v:t.Option})}),r="时间"):(o.push({n:"全部",v:""}),e.OptionList.forEach(t=>{"全部"!==t.Option&&o.push({n:t.Option,v:t.Option})}),r=""),t.push({key:n,name:e.Class,value:o,init:r})}}t.length>0&&(r[e]=t)}}catch(t){}});return await Promise.all(a),JSON.stringify({class:e,filters:r})}async function s(){const t=f(`${n}/home`),e=await req(t,{headers:o}),r=JSON.parse(e.content);let a=[];if(r&&Array.isArray(r))for(const t of r){const e=t.VodList||[];for(const t of e)a.push({vod_id:l(t.DId||t.DuId),vod_name:t.Name,vod_pic:l(t.TnId),vod_remarks:t.Tag})}return JSON.stringify({list:a})}async function i(t,e,r,a){const s=new Array(12).fill("");s[0]=t,s[1]=a.area||"",s[2]=a.sort||"时间",s[3]=a.class||"",s[4]=a.lang||"",s[5]=a.letter||"",s[6]=a.scat||"",s[8]="1"===e.toString()?"":e,s[11]=a.year||"";const i=f(`${n}/vodshow/${s.join("-")}`),c=await req(i,{headers:o}),p=JSON.parse(c.content);let d=[];if(p.VodList)for(const t of p.VodList)d.push({vod_id:l(t.DId||t.DuId),vod_name:t.Name,vod_pic:l(t.TnId),vod_remarks:t.Tag});let u=0;try{if(p.PaginationList){for(const t of p.PaginationList)if("StartEnd"===t.Type){const e=l(t.PId||t.PuId).split("-");if(e.length>8){const t=parseInt(e[8]);t&&(u=t)}}if(0===u)for(const t of p.PaginationList)if("ShortPage"===t.Type){const e=t.Name.split("/");if(e.length>1){const t=parseInt(e[1]);t&&(u=t)}}}}catch(t){u=1}return 0===u&&(u=1),JSON.stringify({list:d,page:parseInt(e),pagecount:u})}async function c(t,e,r=1){let a=f(`${n}/vodsearch`);a+=`&wd=${encodeURIComponent(t)}`;const s=await req(a,{headers:o}),i=JSON.parse(s.content);let c=[];if(i&&Array.isArray(i))for(const t of i)c.push({vod_id:l(t.DId||t.DuId),vod_name:t.Name,vod_pic:l(t.TnId),vod_remarks:t.Tag,vod_actor:t.Actor,vod_score:t.Rating});return JSON.stringify({list:c,page:parseInt(r)})}async function p(t){const e=f(`${n}${t}`),r=await req(e,{headers:o}),a=JSON.parse(r.content);let s=[];a.Playlist&&(s=a.Playlist.map(t=>`${t.EpisodeName}$${l(t.VId)}`));const i={vod_id:t,vod_name:a.Name,vod_pic:l(a.TnId),vod_remarks:`评分:${a.Rating}`,vod_year:a.ReleaseYear,vod_area:a.Region,vod_actor:Array.isArray(a.Actor)?a.Actor.join(","):a.Actor,vod_director:a.Director,vod_content:a.Description,vod_play_from:"独播库",vod_play_url:s.join("#"),type_name:`${a.Genre},${a.Scenario},${a.Language}`};return JSON.stringify({list:[i]})}async function d(t,e,r){const a=f(`${n}${e}`),s=await req(a,{headers:o}),i=l(JSON.parse(s.content).HId);return JSON.stringify({jx:0,parse:0,url:i,header:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36","Accept-Encoding":"gzip, deflate",origin:"https://w.duboku.io",referer:"https://w.duboku.io/",priority:"u=1, i"}})}function l(e){if(!e||"string"!=typeof e)return"";let n=e.replace(/['"]/g,"");if(!n)return"";let o="";for(let t=0;t<n.length;t+=10){o+=n.substring(t,t+10).split("").reverse().join("")}o=o.replace(/\./g,"=");try{const e=t.enc.Base64.parse(o);return t.enc.Utf8.stringify(e)}catch(t){return""}}function f(e){const n=Math.floor(800000001*Math.random()),o=function(t,e){let n=[];const o=Math.min(t.length,e.length);for(let r=0;r<o;r++)n.push(t[r]),n.push(e[r]);return n.push(t.substring(o)),n.push(e.substring(o)),n.join("")}(`${n+1e8}${9e8-n}`,Math.floor(Date.now()/1e3).toString()),r=t.enc.Utf8.parse(o),a=t.enc.Base64.stringify(r).replace(/=/g,".");return`${e}?sign=${u(60)}&token=${u(38)}&ssid=${a}`}function u(t){const e="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";let n="";for(let o=0;o<t;o++)n+=e.charAt(Math.floor(62*Math.random()));return n}export function __jsEvalReturn(){return{init:r,home:a,homeVod:s,category:i,search:c,detail:p,play:d}}
|
||||
Vendored
-3108
File diff suppressed because it is too large.
Load diff
-833
@@ -1,833 +0,0 @@
|
||||
import { Crypto, _ } from 'assets://js/lib/cat.js';
|
||||
|
||||
let siteUrl = '';
|
||||
let key = '';
|
||||
let iv = '';
|
||||
let siteKey = '';
|
||||
let siteType = 3;
|
||||
let apiPrefix = 'getappapi.index';
|
||||
|
||||
const prefixMap = {
|
||||
'1': 'getappapi.index',
|
||||
'2': 'qijiappapi.index',
|
||||
'3': 'appapi'
|
||||
};
|
||||
|
||||
let enableVerifyTimeSign = false;
|
||||
let headers = {
|
||||
'User-Agent': 'okhttp/3.10.0',
|
||||
'app-user-device-id': '291b226282010337c9443590d6457be15',
|
||||
'app-version-code': '112'
|
||||
};
|
||||
|
||||
let parseMap = {};
|
||||
let homeVods = [];
|
||||
let Searchstatus = false;
|
||||
let searchApiSuffix = '';
|
||||
let souParamName = '';
|
||||
let souSalt = '';
|
||||
let extraSearchHeaders = {};
|
||||
let initSuffix = 'init';
|
||||
let hasCustomInit = false;
|
||||
let thirdDanmuBaseUrl = '';
|
||||
let customPlayUa = ''; // 新增:自定义播放链接UA
|
||||
|
||||
let request = async (reqUrl, data, header, method) => {
|
||||
let finalHeaders = { ...headers };
|
||||
if (enableVerifyTimeSign) {
|
||||
const timestamp = Math.floor(Date.now() / 1000).toString();
|
||||
const sign = aesEncode(timestamp, key, iv);
|
||||
finalHeaders['app-api-verify-time'] = timestamp;
|
||||
finalHeaders['app-api-verify-sign'] = sign;
|
||||
}
|
||||
if (header) {
|
||||
finalHeaders = { ...finalHeaders, ...header };
|
||||
}
|
||||
let res = await req(reqUrl, {
|
||||
method: method || 'get',
|
||||
data: data || '',
|
||||
headers: finalHeaders,
|
||||
postType: method === 'post' ? 'form' : '',
|
||||
timeout: 10000,
|
||||
});
|
||||
return res.content;
|
||||
};
|
||||
|
||||
let request_text = async (reqUrl, data, header, method, tobase64) => {
|
||||
let finalHeaders = { ...headers };
|
||||
if (enableVerifyTimeSign) {
|
||||
const timestamp = Math.floor(Date.now() / 1000).toString();
|
||||
const sign = aesEncode(timestamp, key, iv);
|
||||
finalHeaders['app-api-verify-time'] = timestamp;
|
||||
finalHeaders['app-api-verify-sign'] = sign;
|
||||
}
|
||||
if (header) {
|
||||
finalHeaders = { ...finalHeaders, ...header };
|
||||
}
|
||||
let optObj = {
|
||||
headers: finalHeaders,
|
||||
method: method || 'get',
|
||||
data: method === 'post' ? data : undefined,
|
||||
postType: method === 'post' ? (data ? 'raw' : 'form') : undefined,
|
||||
timeout: 10000,
|
||||
};
|
||||
if (tobase64) {
|
||||
optObj.buffer = 2;
|
||||
}
|
||||
let res = await req(reqUrl, optObj);
|
||||
return res.content;
|
||||
};
|
||||
|
||||
async function init(cfg) {
|
||||
siteKey = cfg.skey;
|
||||
siteType = cfg.stype;
|
||||
if (!cfg.ext) return;
|
||||
let extObj;
|
||||
if (typeof cfg.ext === 'string') {
|
||||
extObj = JSON.parse(cfg.ext);
|
||||
} else if (typeof cfg.ext === 'object' && cfg.ext !== null) {
|
||||
extObj = cfg.ext;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (extObj.init && typeof extObj.init === 'string' && extObj.init.startsWith('V')) {
|
||||
initSuffix = 'init' + extObj.init;
|
||||
hasCustomInit = true;
|
||||
}
|
||||
if (extObj.time !== undefined) {
|
||||
const timeVal = String(extObj.time);
|
||||
enableVerifyTimeSign = (timeVal === '1' || timeVal === 'true' || timeVal === '1');
|
||||
}
|
||||
if (extObj.code !== undefined) {
|
||||
forceVerifyCode = String(extObj.code).trim();
|
||||
}
|
||||
// 新增:读取自定义播放UA
|
||||
if (extObj.ua2 !== undefined) {
|
||||
customPlayUa = String(extObj.ua2).trim();
|
||||
}
|
||||
if (extObj.head && typeof extObj.head === 'string') {
|
||||
const headStr = extObj.head.trim();
|
||||
if (headStr) {
|
||||
const items = headStr.split(',');
|
||||
for (let item of items) {
|
||||
const trimmed = item.trim();
|
||||
if (!trimmed) continue;
|
||||
const colonIndex = trimmed.indexOf(':');
|
||||
if (colonIndex > 0) {
|
||||
const hKey = trimmed.substring(0, colonIndex).trim();
|
||||
const hValue = trimmed.substring(colonIndex + 1).trim();
|
||||
if (hKey && hValue) {
|
||||
headers[hKey] = hValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let host = extObj.host || '';
|
||||
if (host) {
|
||||
if (host.startsWith('http') && (host.endsWith('.txt') || host.endsWith('.json'))) {
|
||||
let response = await request(host, null, headers, 'get');
|
||||
let urls = response.split('\n').map(line => line.trim()).filter(line => line && line.startsWith('http'));
|
||||
if (urls.length > 0) {
|
||||
host = urls[0];
|
||||
}
|
||||
}
|
||||
siteUrl = host.replace(/\/+$/, '');
|
||||
if (!siteUrl.includes('php')) {
|
||||
siteUrl += '/api.php';
|
||||
}
|
||||
}
|
||||
key = extObj.key || '';
|
||||
iv = extObj.iv || key;
|
||||
if (extObj.api && prefixMap[extObj.api]) {
|
||||
apiPrefix = prefixMap[extObj.api];
|
||||
}
|
||||
if (extObj.version) {
|
||||
headers['app-version-code'] = String(extObj.version);
|
||||
}
|
||||
if (extObj.id) {
|
||||
headers['app-user-device-id'] = extObj.id;
|
||||
}
|
||||
if (extObj.token) {
|
||||
headers['app-user-token'] = extObj.token;
|
||||
}
|
||||
if (extObj.ua) {
|
||||
headers['User-Agent'] = extObj.ua;
|
||||
}
|
||||
}
|
||||
|
||||
function processSignatureValue(sig) {
|
||||
if (sig.length < 8) {
|
||||
return sig.split('').reverse().join('');
|
||||
} else {
|
||||
let rear = sig.slice(-8).split('').reverse().join('');
|
||||
let front = sig.slice(0, -8).split('').reverse().join('');
|
||||
return front + rear;
|
||||
}
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
let initUrl = `${siteUrl}/${apiPrefix}/${initSuffix}`;
|
||||
let rets = JSON.parse(await request(initUrl)).data;
|
||||
let data = JSON.parse(aesDecode(rets, key, iv));
|
||||
|
||||
let rawDanmuUrl = data.config?.third_danmu_url || '';
|
||||
|
||||
if (Array.isArray(rawDanmuUrl)) {
|
||||
rawDanmuUrl = rawDanmuUrl.find(u => u && typeof u === 'string' && u.trim()) || '';
|
||||
} else if (typeof rawDanmuUrl !== 'string') {
|
||||
rawDanmuUrl = '';
|
||||
}
|
||||
|
||||
if (rawDanmuUrl) {
|
||||
thirdDanmuBaseUrl = rawDanmuUrl.trim();
|
||||
let lower = thirdDanmuBaseUrl.toLowerCase();
|
||||
if (!lower.match(/[?&]url=$/)) {
|
||||
thirdDanmuBaseUrl += thirdDanmuBaseUrl.includes('?') ? '&url=' : '?url=';
|
||||
}
|
||||
} else {
|
||||
thirdDanmuBaseUrl = 'https://dmku.hls.one/?ac=dm&url=';
|
||||
}
|
||||
|
||||
if (data.box_config) {
|
||||
let originalKey = key;
|
||||
let swappedKey = originalKey.split('').reverse().join('');
|
||||
let md5Key = md5(swappedKey);
|
||||
let dynamicIv = md5Key.substring(0, 16);
|
||||
let decrypted = aesDecode(data.box_config, swappedKey, dynamicIv);
|
||||
let boxJson = JSON.parse(decrypted);
|
||||
if (boxJson.search_name) {
|
||||
searchApiSuffix = boxJson.search_name;
|
||||
}
|
||||
if (boxJson.signature_name && boxJson.signature_value) {
|
||||
souParamName = boxJson.signature_name;
|
||||
souSalt = processSignatureValue(boxJson.signature_value);
|
||||
}
|
||||
if (boxJson.api_header && boxJson.api_header.key && boxJson.api_header.value) {
|
||||
extraSearchHeaders[boxJson.api_header.key] = boxJson.api_header.value;
|
||||
}
|
||||
} else {
|
||||
searchApiSuffix = 'searchList';
|
||||
souParamName = '';
|
||||
souSalt = '';
|
||||
}
|
||||
|
||||
Searchstatus = data.config?.system_search_verify_status || false;
|
||||
|
||||
let filters = {};
|
||||
let classes = [];
|
||||
homeVods = [];
|
||||
|
||||
_.forEach(data.type_list, item => {
|
||||
if (item.type_id > 0) {
|
||||
if (item.recommend_list && Array.isArray(item.recommend_list)) {
|
||||
homeVods = homeVods.concat(item.recommend_list);
|
||||
}
|
||||
}
|
||||
|
||||
classes.push({
|
||||
type_id: item.type_id,
|
||||
type_name: item.type_name,
|
||||
});
|
||||
|
||||
let filterList = [];
|
||||
_.forEach(item.filter_type_list, f => {
|
||||
let filter = {};
|
||||
if (f.name === 'class') {
|
||||
filter['name'] = '分类';
|
||||
filter['key'] = f.name;
|
||||
filter['value'] = _.map(f.list, i => ({ v: i, n: i }));
|
||||
}
|
||||
if (f.name === 'area') {
|
||||
filter['name'] = '区域';
|
||||
filter['key'] = f.name;
|
||||
filter['value'] = _.map(f.list, i => ({ v: i, n: i }));
|
||||
}
|
||||
if (f.name === 'lang') {
|
||||
filter['name'] = '语言';
|
||||
filter['key'] = f.name;
|
||||
filter['value'] = _.map(f.list, i => ({ v: i, n: i }));
|
||||
}
|
||||
if (f.name === 'year') {
|
||||
filter['name'] = '年份';
|
||||
filter['key'] = f.name;
|
||||
filter['value'] = _.map(f.list, i => ({ v: i, n: i }));
|
||||
}
|
||||
if (f.name === 'sort') {
|
||||
filter['name'] = '排序';
|
||||
filter['key'] = f.name;
|
||||
filter['value'] = _.map(f.list, i => ({ v: i, n: i }));
|
||||
}
|
||||
if (Object.keys(filter).length > 0) {
|
||||
filterList.push(filter);
|
||||
}
|
||||
});
|
||||
if (filterList.length > 0) {
|
||||
filters[item.type_id] = filterList;
|
||||
}
|
||||
});
|
||||
|
||||
return JSON.stringify({
|
||||
'class': classes,
|
||||
'filters': filters,
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
return JSON.stringify({
|
||||
list: homeVods,
|
||||
});
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
if (pg <= 0) pg = 1;
|
||||
let url = `${siteUrl}/${apiPrefix}/typeFilterVodList`;
|
||||
let params = {
|
||||
"area": extend['area'] || "全部",
|
||||
"sort": extend['sort'] || "最新",
|
||||
"class": extend['class'] || "全部",
|
||||
"type_id": tid,
|
||||
"year": extend['year'] || "全部",
|
||||
"lang": extend['lang'] || '全部',
|
||||
"page": pg,
|
||||
};
|
||||
let encData = JSON.parse(await request(url, params, '', 'post')).data;
|
||||
let videos = JSON.parse(aesDecode(encData, key, iv)).recommend_list;
|
||||
return JSON.stringify({
|
||||
page: pg,
|
||||
pagecount: 9999,
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
let url = `${siteUrl}/${apiPrefix}/vodDetail`;
|
||||
let resp = await request(url, { vod_id: id }, '', 'post');
|
||||
let jsonResp = JSON.parse(resp);
|
||||
let encData = jsonResp.data;
|
||||
let decoded = aesDecode(encData, key, iv);
|
||||
let info = JSON.parse(decoded);
|
||||
let videos = {
|
||||
vod_id: info.vod.vod_id,
|
||||
vod_name: info.vod.vod_name,
|
||||
vod_area: info.vod.vod_area,
|
||||
vod_director: info.vod.vod_director,
|
||||
vod_actor: info.vod.vod_actor,
|
||||
vod_pic: info.vod.vod_pic,
|
||||
vod_content: info.vod.vod_content,
|
||||
type_name: info.vod.vod_class,
|
||||
vod_year: info.vod.vod_year
|
||||
};
|
||||
let froms = [];
|
||||
let urls = [];
|
||||
let playSources = _.map(info.vod_play_list, item => {
|
||||
const playerInfo = item.player_info || {};
|
||||
const parse = playerInfo.parse || '';
|
||||
const ua = playerInfo.user_agent || customPlayUa || ''; // 修改:优先使用自定义UA,如果没有则使用原有的
|
||||
const nameUrls = _.map(item.urls || [], item2 => {
|
||||
const { name = '', url = '', token = '', parse_api_url = '', nid = 1 } = item2;
|
||||
return `${name}$${url}@@${parse}@@${token}@@${parse_api_url}@@${ua}@@${info.vod.vod_id}@@${nid}`;
|
||||
}).join('#');
|
||||
return {
|
||||
show: playerInfo.show || 'Unknown',
|
||||
urls: nameUrls
|
||||
};
|
||||
});
|
||||
let showCount = {};
|
||||
playSources = _.map(playSources, source => {
|
||||
let showName = source.show;
|
||||
if (showCount[showName]) {
|
||||
showCount[showName]++;
|
||||
showName = `${showName}${showCount[showName]}`;
|
||||
} else {
|
||||
showCount[showName] = 1;
|
||||
}
|
||||
return {
|
||||
show: showName,
|
||||
urls: source.urls
|
||||
};
|
||||
});
|
||||
playSources.sort((a, b) => {
|
||||
const aShow = a.show.toLowerCase();
|
||||
const bShow = b.show.toLowerCase();
|
||||
const getPriority = (show) => {
|
||||
if (show.includes('4k')) return 1;
|
||||
if (show.includes('K')) return 2;
|
||||
if (show.includes('独家')) return 3;
|
||||
if (show.includes('秒播')) return 4;
|
||||
if (show.includes('自建')) return 5;
|
||||
if (show.includes('蓝光')) return 6;
|
||||
if (show.includes('专线')) return 7;
|
||||
return 8;
|
||||
};
|
||||
return getPriority(aShow) - getPriority(bShow);
|
||||
});
|
||||
froms = _.map(playSources, source => source.show);
|
||||
urls = _.map(playSources, source => source.urls);
|
||||
videos.vod_play_from = froms.join('$$$');
|
||||
videos.vod_play_url = urls.join('$$$');
|
||||
return JSON.stringify({
|
||||
list: [videos],
|
||||
});
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
let parts = id.split('@@');
|
||||
let playUrl = parts[0];
|
||||
let parse = parts[1] || '';
|
||||
let token = parts[2] || '';
|
||||
let parse_api_url = parts[3] || '';
|
||||
let ua = parts[4] || ''; // 新增:获取UA
|
||||
let vodId = parts[5] || '';
|
||||
let nidStr = parts[6] || '1';
|
||||
|
||||
let danmakuUrl = '';
|
||||
if (thirdDanmuBaseUrl && vodId) {
|
||||
let nid = parseInt(nidStr, 10);
|
||||
if (isNaN(nid) || nid < 1) nid = 1;
|
||||
let urlPosition = nid - 1;
|
||||
let danmuParams = {
|
||||
url_position: urlPosition.toString(),
|
||||
vod_id: vodId
|
||||
};
|
||||
let danmuRet = await request(`${siteUrl}/${apiPrefix}/danmuList`, danmuParams, '', 'post');
|
||||
let danmuResponse = JSON.parse(danmuRet);
|
||||
if (danmuResponse.data) {
|
||||
let decryptedDanmu = JSON.parse(aesDecode(danmuResponse.data, key, iv));
|
||||
if (decryptedDanmu && decryptedDanmu.official_url) {
|
||||
let realDanmuUrl = thirdDanmuBaseUrl + decryptedDanmu.official_url;
|
||||
let EncodedUrl = encodeURIComponent(realDanmuUrl);
|
||||
let headerJson = JSON.stringify(headers);
|
||||
danmakuUrl = js2Proxy(
|
||||
false,
|
||||
siteType,
|
||||
siteKey || '',
|
||||
EncodedUrl,
|
||||
headers
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修改:如果存在自定义UA,添加到返回参数中
|
||||
if (
|
||||
(playUrl.includes('http://') || playUrl.includes('https://')) &&
|
||||
(playUrl.includes('m3u8') || playUrl.includes('mp4') || playUrl.includes('mkv')) &&
|
||||
!parse_api_url
|
||||
) {
|
||||
let result = {
|
||||
parse: 0,
|
||||
url: playUrl,
|
||||
danmaku: danmakuUrl
|
||||
};
|
||||
// 如果存在自定义UA,添加到返回结果中
|
||||
if (ua) {
|
||||
result.header = { 'User-Agent': ua };
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
if (parse.startsWith("http")) {
|
||||
let parseUrl = parse + playUrl;
|
||||
if (token) {
|
||||
parseUrl += '&token=' + token;
|
||||
}
|
||||
// 如果存在自定义UA,在请求解析接口时使用
|
||||
let requestHeaders = {};
|
||||
if (ua) {
|
||||
requestHeaders['User-Agent'] = ua;
|
||||
}
|
||||
let rets = await request(parseUrl, null, requestHeaders, 'get');
|
||||
if (rets.indexOf('DOCTYPE html') > -1) {
|
||||
let result = {
|
||||
parse: 1,
|
||||
url: parseUrl,
|
||||
danmaku: danmakuUrl
|
||||
};
|
||||
if (ua) {
|
||||
result.header = { 'User-Agent': ua };
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
let parseJson = JSON.parse(rets);
|
||||
let result = {
|
||||
parse: 0,
|
||||
url: parseJson['url'] || parseJson['data']['url'] || '',
|
||||
danmaku: danmakuUrl
|
||||
};
|
||||
// 如果存在自定义UA,添加到返回结果中
|
||||
if (ua) {
|
||||
result.header = { 'User-Agent': ua };
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
let params = {
|
||||
'parse_api': parse,
|
||||
'url': aesEncode(playUrl, key, iv),
|
||||
'token': token,
|
||||
};
|
||||
// 如果存在自定义UA,在请求时使用
|
||||
let requestHeaders = {};
|
||||
if (ua) {
|
||||
requestHeaders['User-Agent'] = ua;
|
||||
}
|
||||
let rets = await request(`${siteUrl}/${apiPrefix}/vodParse`, params, requestHeaders, 'post');
|
||||
let urlDecoded = aesDecode(JSON.parse(rets).data, key, iv);
|
||||
let finalPlayUrl = '';
|
||||
let parsed = JSON.parse(urlDecoded);
|
||||
finalPlayUrl = JSON.parse(parsed.json).url || '';
|
||||
let result = {
|
||||
parse: 0,
|
||||
url: finalPlayUrl,
|
||||
danmaku: danmakuUrl
|
||||
};
|
||||
// 如果存在自定义UA,添加到返回结果中
|
||||
if (ua) {
|
||||
result.header = { 'User-Agent': ua };
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
async function search(wd, quick, pg) {
|
||||
if (hasCustomInit) {
|
||||
await home({});
|
||||
}
|
||||
let searchPath = searchApiSuffix || 'searchList';
|
||||
let url = `${siteUrl}/${apiPrefix}/${searchPath}`;
|
||||
let retryCount = 0;
|
||||
const maxRetries = 1;
|
||||
let videos = [];
|
||||
let attemptedCaptcha = false;
|
||||
let attemptedSlider = false;
|
||||
let sliderVerified = false;
|
||||
let sliderId = '';
|
||||
|
||||
let params = {
|
||||
'page': '1',
|
||||
'type_id': '0',
|
||||
'keywords': wd,
|
||||
};
|
||||
|
||||
if (souParamName && souSalt) {
|
||||
const currentTimestamp = Math.floor(Date.now() / 1000).toString();
|
||||
const souString = `/${souParamName}-${currentTimestamp}-sb-0-${souSalt}`;
|
||||
const md5Value = md5(souString);
|
||||
const finalValue = `${currentTimestamp}-sb-0-${md5Value}`;
|
||||
params[souParamName] = finalValue;
|
||||
}
|
||||
|
||||
let searchHeaders = { ...headers, ...extraSearchHeaders };
|
||||
|
||||
if (forceVerifyCode) {
|
||||
params['code'] = forceVerifyCode;
|
||||
const random_uuid = generateUUID();
|
||||
params['key'] = random_uuid;
|
||||
}
|
||||
|
||||
const maxWaitRetries = 2;
|
||||
let waitRetryCount = 0;
|
||||
|
||||
while (true) {
|
||||
let encData = await request(url, params, searchHeaders, 'post');
|
||||
let response = JSON.parse(encData);
|
||||
|
||||
if (response.code === 1001 && response.need_slider === true && !attemptedSlider) {
|
||||
attemptedSlider = true;
|
||||
|
||||
let getSliderUrl = `${siteUrl}/${apiPrefix}/getSlider`;
|
||||
let sliderResponse = await request(getSliderUrl, {}, searchHeaders, 'post');
|
||||
let sliderJson = JSON.parse(sliderResponse);
|
||||
|
||||
if (sliderJson.code === 1 && sliderJson.data) {
|
||||
let sliderDecrypted = aesDecode(sliderJson.data, key, iv);
|
||||
let sliderData = JSON.parse(sliderDecrypted);
|
||||
|
||||
sliderId = sliderData.slider_id || '';
|
||||
let targetX = parseInt(sliderData.target_x) || 0;
|
||||
let targetY = parseInt(sliderData.target_y) || 0;
|
||||
|
||||
if (sliderId && targetX > 0) {
|
||||
let posX = targetX;
|
||||
if (targetX > 0) {
|
||||
let randomOffset = Math.floor(Math.random() * 3) - 1;
|
||||
posX = targetX + randomOffset;
|
||||
if (posX < 1) posX = 1;
|
||||
if (posX > (sliderData.bg_width || 280)) posX = sliderData.bg_width || 280;
|
||||
}
|
||||
|
||||
let timestamp = Date.now();
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
let verifyParams = {
|
||||
pos_x: posX.toString(),
|
||||
slider_id: sliderId,
|
||||
timestamp: timestamp.toString()
|
||||
};
|
||||
|
||||
let verifySliderUrl = `${siteUrl}/${apiPrefix}/verifySlider`;
|
||||
let verifyResponse = await request(verifySliderUrl, verifyParams, searchHeaders, 'post');
|
||||
let verifyJson = JSON.parse(verifyResponse);
|
||||
|
||||
if (verifyJson.code === 1 && verifyJson.data) {
|
||||
let verifyDecrypted = aesDecode(verifyJson.data, key, iv);
|
||||
let verifyResult = JSON.parse(verifyDecrypted);
|
||||
|
||||
if (verifyResult.verified === true) {
|
||||
sliderVerified = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!sliderVerified) {
|
||||
if (!forceVerifyCode && (Searchstatus || (response.code === 0 && response.msg && response.msg.includes('验证码')))) {
|
||||
if (attemptedCaptcha) break;
|
||||
attemptedCaptcha = true;
|
||||
const random_uuid = generateUUID();
|
||||
let modifiedApiPrefix = apiPrefix.replace('.index', '');
|
||||
let verifyUrl = `${siteUrl}/${modifiedApiPrefix}.verify/create?key=${random_uuid}`;
|
||||
let base64Img = await request_text(verifyUrl, null, headers, 'get', true);
|
||||
base64Img = base64Img.replace(/\n/g, '');
|
||||
let ocrResult = await request_text('https://api.nn.ci/ocr/b64/text', base64Img, { 'User-Agent': 'okhttp/3.10.0' }, 'post');
|
||||
params['code'] = ocrResult.trim();
|
||||
params['key'] = random_uuid;
|
||||
retryCount++;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (response.code === 0 &&
|
||||
(!response.data || response.data.length === 0) &&
|
||||
response.msg &&
|
||||
/等.*秒|等待.*秒|等|搜|请等待|稍等|稍候/i.test(response.msg)) {
|
||||
if (waitRetryCount >= maxWaitRetries) break;
|
||||
let waitSeconds = extractWaitTime(response.msg);
|
||||
if (waitSeconds < 1) waitSeconds = 2;
|
||||
if (waitSeconds > 30) waitSeconds = 30;
|
||||
const actualWait = waitSeconds + 1;
|
||||
await new Promise(resolve => setTimeout(resolve, actualWait * 1000));
|
||||
waitRetryCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (response.data && response.data.length > 0) {
|
||||
let decodedData = JSON.parse(aesDecode(response.data, key, iv));
|
||||
videos = decodedData.search_list || [];
|
||||
break;
|
||||
} else if (!forceVerifyCode && (Searchstatus || (response.code === 0 && response.msg && response.msg.includes('验证码')))) {
|
||||
if (attemptedCaptcha) break;
|
||||
attemptedCaptcha = true;
|
||||
const random_uuid = generateUUID();
|
||||
let modifiedApiPrefix = apiPrefix.replace('.index', '');
|
||||
let verifyUrl = `${siteUrl}/${modifiedApiPrefix}.verify/create?key=${random_uuid}`;
|
||||
let base64Img = await request_text(verifyUrl, null, headers, 'get', true);
|
||||
base64Img = base64Img.replace(/\n/g, '');
|
||||
let ocrResult = await request_text('https://api.nn.ci/ocr/b64/text', base64Img, { 'User-Agent': 'okhttp/3.10.0' }, 'post');
|
||||
params['code'] = ocrResult.trim();
|
||||
params['key'] = random_uuid;
|
||||
retryCount++;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
});
|
||||
}
|
||||
|
||||
function generateUUID() {
|
||||
const chars = '0123456789abcdef';
|
||||
const uuidTemplate = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
|
||||
return uuidTemplate.replace(/[xy]/g, (c) => {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return chars[v];
|
||||
});
|
||||
}
|
||||
|
||||
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 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();
|
||||
}
|
||||
|
||||
function md5(text) {
|
||||
return Crypto.MD5(text).toString();
|
||||
}
|
||||
|
||||
function chineseToNumber(chineseStr) {
|
||||
const chineseNumMap = {
|
||||
'零': 0, '〇': 0, '一': 1, '壹': 1, '二': 2, '贰': 2, '两': 2,
|
||||
'三': 3, '叁': 3, '四': 4, '肆': 4, '五': 5, '伍': 5,
|
||||
'六': 6, '陆': 6, '七': 7, '柒': 7, '八': 8, '捌': 8,
|
||||
'九': 9, '玖': 9, '十': 10, '拾': 10
|
||||
};
|
||||
|
||||
if (chineseStr.length === 1) {
|
||||
return chineseNumMap[chineseStr] || 2;
|
||||
}
|
||||
|
||||
if (chineseStr.startsWith('十') && chineseStr.length === 2) {
|
||||
const units = chineseNumMap[chineseStr[1]];
|
||||
return units ? 10 + units : 10;
|
||||
}
|
||||
|
||||
if (chineseStr.endsWith('十') && chineseStr.length === 2) {
|
||||
const tens = chineseNumMap[chineseStr[0]];
|
||||
return tens ? tens * 10 : 10;
|
||||
}
|
||||
|
||||
if (chineseStr.length === 3 && chineseStr.includes('十')) {
|
||||
const tens = chineseNumMap[chineseStr[0]];
|
||||
const units = chineseNumMap[chineseStr[2]];
|
||||
return tens && units ? tens * 10 + units : (tens ? tens * 10 : 10);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
function extractWaitTime(message) {
|
||||
const digitMatch = message.match(/(\d+)\s*秒/);
|
||||
if (digitMatch && digitMatch[1]) {
|
||||
return parseInt(digitMatch[1], 10);
|
||||
}
|
||||
|
||||
const chineseMatch = message.match(/([零一二三四五六七八九十两壹贰叁肆伍陆柒捌玖拾〇]+)\s*秒/);
|
||||
if (chineseMatch && chineseMatch[1]) {
|
||||
return chineseToNumber(chineseMatch[1]);
|
||||
}
|
||||
|
||||
if (/几秒|数秒|若干秒/i.test(message)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
function hexToDec(hex) {
|
||||
hex = (hex || '#FFFFFF').replace(/^#/, '').toUpperCase();
|
||||
if (hex.length !== 6) {
|
||||
while (hex.length < 6) hex += '0';
|
||||
hex = hex.slice(0, 6);
|
||||
}
|
||||
return parseInt(hex, 16);
|
||||
}
|
||||
|
||||
function escapeXml(str) {
|
||||
if (typeof str !== 'string') return '';
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function jsonDanmakuToXml(json) {
|
||||
if (!json || !json.danmuku || !Array.isArray(json.danmuku)) {
|
||||
return '<?xml version="1.0" encoding="utf-8"?><i><code>0</code><id>error_no_danmaku</id></i>';
|
||||
}
|
||||
let lines = [];
|
||||
lines.push('<?xml version="1.0" encoding="utf-8"?>');
|
||||
lines.push('<i>');
|
||||
lines.push(` <code>${json.code || 0}</code>`);
|
||||
lines.push(` <id>${escapeXml(json.name || '12345')}</id>`);
|
||||
const positionMap = {
|
||||
'top': 5,
|
||||
'right': 1,
|
||||
'bottom': 4,
|
||||
'left': 6,
|
||||
'scroll': 1
|
||||
};
|
||||
json.danmuku.forEach(danmu => {
|
||||
if (!Array.isArray(danmu) || danmu.length < 5) return;
|
||||
let [
|
||||
time = 0,
|
||||
mode = 'scroll',
|
||||
colorHex = '#FFFFFF',
|
||||
,
|
||||
text = '',
|
||||
, ,
|
||||
fontSize = "24px"
|
||||
] = danmu;
|
||||
colorHex = '#' + Array(6).fill(0).map(() => '0123456789ABCDEF'[Math.floor(Math.random() * 16)]).join('');
|
||||
|
||||
let pos = positionMap[mode] || 1;
|
||||
let colorDec = hexToDec(colorHex);
|
||||
let fs = parseInt(String(fontSize).replace(/px/gi, '')) || 24;
|
||||
let p = `${Number(time).toFixed(3)},${pos},${fs},${colorDec},,,,,`;
|
||||
let safeText = escapeXml(text);
|
||||
lines.push(` <d p="${p}">${safeText}</d>`);
|
||||
});
|
||||
lines.push('</i>');
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
async function proxy(params) {
|
||||
let jsonUrl = decodeURIComponent(
|
||||
params.url || params[0] || params.danmaku || '' || ''
|
||||
);
|
||||
if (!jsonUrl || !jsonUrl.startsWith('http')) {
|
||||
return JSON.stringify({
|
||||
code: 400,
|
||||
content: "缺少有效的弹幕 URL",
|
||||
headers: { "Content-Type": "text/plain" }
|
||||
});
|
||||
}
|
||||
let jsonContent = await request_text(jsonUrl, null, headers, 'get');
|
||||
let jsonObj = JSON.parse(jsonContent);
|
||||
let xmlContent = jsonDanmakuToXml(jsonObj);
|
||||
return JSON.stringify({
|
||||
code: 200,
|
||||
content: xmlContent,
|
||||
headers: {
|
||||
"Content-Type": "text/xml; charset=utf-8",
|
||||
"Cache-Control": "no-cache"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let forceVerifyCode = null;
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
detail: detail,
|
||||
play: play,
|
||||
search: search,
|
||||
proxy: proxy
|
||||
};
|
||||
}
|
||||
-607
@@ -1,607 +0,0 @@
|
||||
/*!
|
||||
* Jinja Templating for JavaScript v0.1.8
|
||||
* https://github.com/sstur/jinja-js
|
||||
*
|
||||
* This is a slimmed-down Jinja2 implementation [http://jinja.pocoo.org/]
|
||||
*
|
||||
* In the interest of simplicity, it deviates from Jinja2 as follows:
|
||||
* - Line statements, cycle, super, macro tags and block nesting are not implemented
|
||||
* - auto escapes html by default (the filter is "html" not "e")
|
||||
* - Only "html" and "safe" filters are built in
|
||||
* - Filters are not valid in expressions; `foo|length > 1` is not valid
|
||||
* - Expression Tests (`if num is odd`) not implemented (`is` translates to `==` and `isnot` to `!=`)
|
||||
*
|
||||
* Notes:
|
||||
* - if property is not found, but method '_get' exists, it will be called with the property name (and cached)
|
||||
* - `{% for n in obj %}` iterates the object's keys; get the value with `{% for n in obj %}{{ obj[n] }}{% endfor %}`
|
||||
* - subscript notation `a[0]` takes literals or simple variables but not `a[item.key]`
|
||||
* - `.2` is not a valid number literal; use `0.2`
|
||||
*
|
||||
*/
|
||||
/*global require, exports, module, define */
|
||||
|
||||
(function(global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jinja = {}));
|
||||
})(this, (function(jinja) {
|
||||
"use strict";
|
||||
var STRINGS = /'(\\.|[^'])*'|"(\\.|[^"'"])*"/g;
|
||||
var IDENTS_AND_NUMS = /([$_a-z][$\w]*)|([+-]?\d+(\.\d+)?)/g;
|
||||
var NUMBER = /^[+-]?\d+(\.\d+)?$/;
|
||||
//non-primitive literals (array and object literals)
|
||||
var NON_PRIMITIVES = /\[[@#~](,[@#~])*\]|\[\]|\{([@i]:[@#~])(,[@i]:[@#~])*\}|\{\}/g;
|
||||
//bare identifiers such as variables and in object literals: {foo: 'value'}
|
||||
var IDENTIFIERS = /[$_a-z][$\w]*/ig;
|
||||
var VARIABLES = /i(\.i|\[[@#i]\])*/g;
|
||||
var ACCESSOR = /(\.i|\[[@#i]\])/g;
|
||||
var OPERATORS = /(===?|!==?|>=?|<=?|&&|\|\||[+\-\*\/%])/g;
|
||||
//extended (english) operators
|
||||
var EOPS = /(^|[^$\w])(and|or|not|is|isnot)([^$\w]|$)/g;
|
||||
var LEADING_SPACE = /^\s+/;
|
||||
var TRAILING_SPACE = /\s+$/;
|
||||
|
||||
var START_TOKEN = /\{\{\{|\{\{|\{%|\{#/;
|
||||
var TAGS = {
|
||||
'{{{': /^('(\\.|[^'])*'|"(\\.|[^"'"])*"|.)+?\}\}\}/,
|
||||
'{{': /^('(\\.|[^'])*'|"(\\.|[^"'"])*"|.)+?\}\}/,
|
||||
'{%': /^('(\\.|[^'])*'|"(\\.|[^"'"])*"|.)+?%\}/,
|
||||
'{#': /^('(\\.|[^'])*'|"(\\.|[^"'"])*"|.)+?#\}/
|
||||
};
|
||||
|
||||
var delimeters = {
|
||||
'{%': 'directive',
|
||||
'{{': 'output',
|
||||
'{#': 'comment'
|
||||
};
|
||||
|
||||
var operators = {
|
||||
and: '&&',
|
||||
or: '||',
|
||||
not: '!',
|
||||
is: '==',
|
||||
isnot: '!='
|
||||
};
|
||||
|
||||
var constants = {
|
||||
'true': true,
|
||||
'false': false,
|
||||
'null': null
|
||||
};
|
||||
|
||||
function Parser() {
|
||||
this.nest = [];
|
||||
this.compiled = [];
|
||||
this.childBlocks = 0;
|
||||
this.parentBlocks = 0;
|
||||
this.isSilent = false;
|
||||
}
|
||||
|
||||
Parser.prototype.push = function(line) {
|
||||
if (!this.isSilent) {
|
||||
this.compiled.push(line);
|
||||
}
|
||||
};
|
||||
|
||||
Parser.prototype.parse = function(src) {
|
||||
this.tokenize(src);
|
||||
return this.compiled;
|
||||
};
|
||||
|
||||
Parser.prototype.tokenize = function(src) {
|
||||
var lastEnd = 0,
|
||||
parser = this,
|
||||
trimLeading = false;
|
||||
matchAll(src, START_TOKEN, function(open, index, src) {
|
||||
//here we match the rest of the src against a regex for this tag
|
||||
var match = src.slice(index + open.length).match(TAGS[open]);
|
||||
match = (match ? match[0] : '');
|
||||
//here we sub out strings so we don't get false matches
|
||||
var simplified = match.replace(STRINGS, '@');
|
||||
//if we don't have a close tag or there is a nested open tag
|
||||
if (!match || ~simplified.indexOf(open)) {
|
||||
return index + 1;
|
||||
}
|
||||
var inner = match.slice(0, 0 - open.length);
|
||||
//check for white-space collapse syntax
|
||||
if (inner.charAt(0) === '-') var wsCollapseLeft = true;
|
||||
if (inner.slice(-1) === '-') var wsCollapseRight = true;
|
||||
inner = inner.replace(/^-|-$/g, '').trim();
|
||||
//if we're in raw mode and we are not looking at an "endraw" tag, move along
|
||||
if (parser.rawMode && (open + inner) !== '{%endraw') {
|
||||
return index + 1;
|
||||
}
|
||||
var text = src.slice(lastEnd, index);
|
||||
lastEnd = index + open.length + match.length;
|
||||
if (trimLeading) text = trimLeft(text);
|
||||
if (wsCollapseLeft) text = trimRight(text);
|
||||
if (wsCollapseRight) trimLeading = true;
|
||||
if (open === '{{{') {
|
||||
//liquid-style: make {{{x}}} => {{x|safe}}
|
||||
open = '{{';
|
||||
inner += '|safe';
|
||||
}
|
||||
parser.textHandler(text);
|
||||
parser.tokenHandler(open, inner);
|
||||
});
|
||||
var text = src.slice(lastEnd);
|
||||
if (trimLeading) text = trimLeft(text);
|
||||
this.textHandler(text);
|
||||
};
|
||||
|
||||
Parser.prototype.textHandler = function(text) {
|
||||
this.push('write(' + JSON.stringify(text) + ');');
|
||||
};
|
||||
|
||||
Parser.prototype.tokenHandler = function(open, inner) {
|
||||
var type = delimeters[open];
|
||||
if (type === 'directive') {
|
||||
this.compileTag(inner);
|
||||
} else if (type === 'output') {
|
||||
var extracted = this.extractEnt(inner, STRINGS, '@');
|
||||
//replace || operators with ~
|
||||
extracted.src = extracted.src.replace(/\|\|/g, '~').split('|');
|
||||
//put back || operators
|
||||
extracted.src = extracted.src.map(function(part) {
|
||||
return part.split('~').join('||');
|
||||
});
|
||||
var parts = this.injectEnt(extracted, '@');
|
||||
if (parts.length > 1) {
|
||||
var filters = parts.slice(1).map(this.parseFilter.bind(this));
|
||||
this.push('filter(' + this.parseExpr(parts[0]) + ',' + filters.join(',') + ');');
|
||||
} else {
|
||||
this.push('filter(' + this.parseExpr(parts[0]) + ');');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Parser.prototype.compileTag = function(str) {
|
||||
var directive = str.split(' ')[0];
|
||||
var handler = tagHandlers[directive];
|
||||
if (!handler) {
|
||||
throw new Error('Invalid tag: ' + str);
|
||||
}
|
||||
handler.call(this, str.slice(directive.length).trim());
|
||||
};
|
||||
|
||||
Parser.prototype.parseFilter = function(src) {
|
||||
src = src.trim();
|
||||
var match = src.match(/[:(]/);
|
||||
var i = match ? match.index : -1;
|
||||
if (i < 0) return JSON.stringify([src]);
|
||||
var name = src.slice(0, i);
|
||||
var args = src.charAt(i) === ':' ? src.slice(i + 1) : src.slice(i + 1, -1);
|
||||
args = this.parseExpr(args, {
|
||||
terms: true
|
||||
});
|
||||
return '[' + JSON.stringify(name) + ',' + args + ']';
|
||||
};
|
||||
|
||||
Parser.prototype.extractEnt = function(src, regex, placeholder) {
|
||||
var subs = [],
|
||||
isFunc = typeof placeholder == 'function';
|
||||
src = src.replace(regex, function(str) {
|
||||
var replacement = isFunc ? placeholder(str) : placeholder;
|
||||
if (replacement) {
|
||||
subs.push(str);
|
||||
return replacement;
|
||||
}
|
||||
return str;
|
||||
});
|
||||
return {
|
||||
src: src,
|
||||
subs: subs
|
||||
};
|
||||
};
|
||||
|
||||
Parser.prototype.injectEnt = function(extracted, placeholder) {
|
||||
var src = extracted.src,
|
||||
subs = extracted.subs,
|
||||
isArr = Array.isArray(src);
|
||||
var arr = (isArr) ? src : [src];
|
||||
var re = new RegExp('[' + placeholder + ']', 'g'),
|
||||
i = 0;
|
||||
arr.forEach(function(src, index) {
|
||||
arr[index] = src.replace(re, function() {
|
||||
return subs[i++];
|
||||
});
|
||||
});
|
||||
return isArr ? arr : arr[0];
|
||||
};
|
||||
|
||||
//replace complex literals without mistaking subscript notation with array literals
|
||||
Parser.prototype.replaceComplex = function(s) {
|
||||
var parsed = this.extractEnt(s, /i(\.i|\[[@#i]\])+/g, 'v');
|
||||
parsed.src = parsed.src.replace(NON_PRIMITIVES, '~');
|
||||
return this.injectEnt(parsed, 'v');
|
||||
};
|
||||
|
||||
//parse expression containing literals (including objects/arrays) and variables (including dot and subscript notation)
|
||||
//valid expressions: `a + 1 > b.c or c == null`, `a and b[1] != c`, `(a < b) or (c < d and e)`, 'a || [1]`
|
||||
Parser.prototype.parseExpr = function(src, opts) {
|
||||
opts = opts || {};
|
||||
//extract string literals -> @
|
||||
var parsed1 = this.extractEnt(src, STRINGS, '@');
|
||||
//note: this will catch {not: 1} and a.is; could we replace temporarily and then check adjacent chars?
|
||||
parsed1.src = parsed1.src.replace(EOPS, function(s, before, op, after) {
|
||||
return (op in operators) ? before + operators[op] + after : s;
|
||||
});
|
||||
//sub out non-string literals (numbers/true/false/null) -> #
|
||||
// the distinction is necessary because @ can be object identifiers, # cannot
|
||||
var parsed2 = this.extractEnt(parsed1.src, IDENTS_AND_NUMS, function(s) {
|
||||
return (s in constants || NUMBER.test(s)) ? '#' : null;
|
||||
});
|
||||
//sub out object/variable identifiers -> i
|
||||
var parsed3 = this.extractEnt(parsed2.src, IDENTIFIERS, 'i');
|
||||
//remove white-space
|
||||
parsed3.src = parsed3.src.replace(/\s+/g, '');
|
||||
|
||||
//the rest of this is simply to boil the expression down and check validity
|
||||
var simplified = parsed3.src;
|
||||
//sub out complex literals (objects/arrays) -> ~
|
||||
// the distinction is necessary because @ and # can be subscripts but ~ cannot
|
||||
while (simplified !== (simplified = this.replaceComplex(simplified)));
|
||||
//now @ represents strings, # represents other primitives and ~ represents non-primitives
|
||||
//replace complex variables (those with dot/subscript accessors) -> v
|
||||
while (simplified !== (simplified = simplified.replace(/i(\.i|\[[@#i]\])+/, 'v')));
|
||||
//empty subscript or complex variables in subscript, are not permitted
|
||||
simplified = simplified.replace(/[iv]\[v?\]/g, 'x');
|
||||
//sub in "i" for @ and # and ~ and v (now "i" represents all literals, variables and identifiers)
|
||||
simplified = simplified.replace(/[@#~v]/g, 'i');
|
||||
//sub out operators
|
||||
simplified = simplified.replace(OPERATORS, '%');
|
||||
//allow 'not' unary operator
|
||||
simplified = simplified.replace(/!+[i]/g, 'i');
|
||||
var terms = opts.terms ? simplified.split(',') : [simplified];
|
||||
terms.forEach(function(term) {
|
||||
//simplify logical grouping
|
||||
while (term !== (term = term.replace(/\(i(%i)*\)/g, 'i')));
|
||||
if (!term.match(/^i(%i)*/)) {
|
||||
throw new Error('Invalid expression: ' + src + " " + term);
|
||||
}
|
||||
});
|
||||
parsed3.src = parsed3.src.replace(VARIABLES, this.parseVar.bind(this));
|
||||
parsed2.src = this.injectEnt(parsed3, 'i');
|
||||
parsed1.src = this.injectEnt(parsed2, '#');
|
||||
return this.injectEnt(parsed1, '@');
|
||||
};
|
||||
|
||||
Parser.prototype.parseVar = function(src) {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var str = args.pop(),
|
||||
index = args.pop();
|
||||
//quote bare object identifiers (might be a reserved word like {while: 1})
|
||||
if (src === 'i' && str.charAt(index + 1) === ':') {
|
||||
return '"i"';
|
||||
}
|
||||
var parts = ['"i"'];
|
||||
src.replace(ACCESSOR, function(part) {
|
||||
if (part === '.i') {
|
||||
parts.push('"i"');
|
||||
} else if (part === '[i]') {
|
||||
parts.push('get("i")');
|
||||
} else {
|
||||
parts.push(part.slice(1, -1));
|
||||
}
|
||||
});
|
||||
return 'get(' + parts.join(',') + ')';
|
||||
};
|
||||
|
||||
//escapes a name to be used as a javascript identifier
|
||||
Parser.prototype.escName = function(str) {
|
||||
return str.replace(/\W/g, function(s) {
|
||||
return '$' + s.charCodeAt(0).toString(16);
|
||||
});
|
||||
};
|
||||
|
||||
Parser.prototype.parseQuoted = function(str) {
|
||||
if (str.charAt(0) === "'") {
|
||||
str = str.slice(1, -1).replace(/\\.|"/, function(s) {
|
||||
if (s === "\\'") return "'";
|
||||
return s.charAt(0) === '\\' ? s : ('\\' + s);
|
||||
});
|
||||
str = '"' + str + '"';
|
||||
}
|
||||
//todo: try/catch or deal with invalid characters (linebreaks, control characters)
|
||||
return JSON.parse(str);
|
||||
};
|
||||
|
||||
|
||||
//the context 'this' inside tagHandlers is the parser instance
|
||||
var tagHandlers = {
|
||||
'if': function(expr) {
|
||||
this.push('if (' + this.parseExpr(expr) + ') {');
|
||||
this.nest.unshift('if');
|
||||
},
|
||||
'else': function() {
|
||||
if (this.nest[0] === 'for') {
|
||||
this.push('}, function() {');
|
||||
} else {
|
||||
this.push('} else {');
|
||||
}
|
||||
},
|
||||
'elseif': function(expr) {
|
||||
this.push('} else if (' + this.parseExpr(expr) + ') {');
|
||||
},
|
||||
'endif': function() {
|
||||
this.nest.shift();
|
||||
this.push('}');
|
||||
},
|
||||
'for': function(str) {
|
||||
var i = str.indexOf(' in ');
|
||||
var name = str.slice(0, i).trim();
|
||||
var expr = str.slice(i + 4).trim();
|
||||
this.push('each(' + this.parseExpr(expr) + ',' + JSON.stringify(name) + ',function() {');
|
||||
this.nest.unshift('for');
|
||||
},
|
||||
'endfor': function() {
|
||||
this.nest.shift();
|
||||
this.push('});');
|
||||
},
|
||||
'raw': function() {
|
||||
this.rawMode = true;
|
||||
},
|
||||
'endraw': function() {
|
||||
this.rawMode = false;
|
||||
},
|
||||
'set': function(stmt) {
|
||||
var i = stmt.indexOf('=');
|
||||
var name = stmt.slice(0, i).trim();
|
||||
var expr = stmt.slice(i + 1).trim();
|
||||
this.push('set(' + JSON.stringify(name) + ',' + this.parseExpr(expr) + ');');
|
||||
},
|
||||
'block': function(name) {
|
||||
if (this.isParent) {
|
||||
++this.parentBlocks;
|
||||
var blockName = 'block_' + (this.escName(name) || this.parentBlocks);
|
||||
this.push('block(typeof ' + blockName + ' == "function" ? ' + blockName + ' : function() {');
|
||||
} else if (this.hasParent) {
|
||||
this.isSilent = false;
|
||||
++this.childBlocks;
|
||||
blockName = 'block_' + (this.escName(name) || this.childBlocks);
|
||||
this.push('function ' + blockName + '() {');
|
||||
}
|
||||
this.nest.unshift('block');
|
||||
},
|
||||
'endblock': function() {
|
||||
this.nest.shift();
|
||||
if (this.isParent) {
|
||||
this.push('});');
|
||||
} else if (this.hasParent) {
|
||||
this.push('}');
|
||||
this.isSilent = true;
|
||||
}
|
||||
},
|
||||
'extends': function(name) {
|
||||
name = this.parseQuoted(name);
|
||||
var parentSrc = this.readTemplateFile(name);
|
||||
this.isParent = true;
|
||||
this.tokenize(parentSrc);
|
||||
this.isParent = false;
|
||||
this.hasParent = true;
|
||||
//silence output until we enter a child block
|
||||
this.isSilent = true;
|
||||
},
|
||||
'include': function(name) {
|
||||
name = this.parseQuoted(name);
|
||||
var incSrc = this.readTemplateFile(name);
|
||||
this.isInclude = true;
|
||||
this.tokenize(incSrc);
|
||||
this.isInclude = false;
|
||||
}
|
||||
};
|
||||
|
||||
//liquid style
|
||||
tagHandlers.assign = tagHandlers.set;
|
||||
//python/django style
|
||||
tagHandlers.elif = tagHandlers.elseif;
|
||||
|
||||
var getRuntime = function runtime(data, opts) {
|
||||
var defaults = {
|
||||
autoEscape: 'toJson'
|
||||
};
|
||||
var _toString = Object.prototype.toString;
|
||||
var _hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var getKeys = Object.keys || function(obj) {
|
||||
var keys = [];
|
||||
for (var n in obj)
|
||||
if (_hasOwnProperty.call(obj, n)) keys.push(n);
|
||||
return keys;
|
||||
};
|
||||
var isArray = Array.isArray || function(obj) {
|
||||
return _toString.call(obj) === '[object Array]';
|
||||
};
|
||||
var create = Object.create || function(obj) {
|
||||
function F() {}
|
||||
|
||||
F.prototype = obj;
|
||||
return new F();
|
||||
};
|
||||
var toString = function(val) {
|
||||
if (val == null) return '';
|
||||
return (typeof val.toString == 'function') ? val.toString() : _toString.call(val);
|
||||
};
|
||||
var extend = function(dest, src) {
|
||||
var keys = getKeys(src);
|
||||
for (var i = 0, len = keys.length; i < len; i++) {
|
||||
var key = keys[i];
|
||||
dest[key] = src[key];
|
||||
}
|
||||
return dest;
|
||||
};
|
||||
//get a value, lexically, starting in current context; a.b -> get("a","b")
|
||||
var get = function() {
|
||||
var val, n = arguments[0],
|
||||
c = stack.length;
|
||||
while (c--) {
|
||||
val = stack[c][n];
|
||||
if (typeof val != 'undefined') break;
|
||||
}
|
||||
for (var i = 1, len = arguments.length; i < len; i++) {
|
||||
if (val == null) continue;
|
||||
n = arguments[i];
|
||||
val = (_hasOwnProperty.call(val, n)) ? val[n] : (typeof val._get == 'function' ? (val[n] = val._get(n)) : null);
|
||||
}
|
||||
return (val == null) ? '' : val;
|
||||
};
|
||||
var set = function(n, val) {
|
||||
stack[stack.length - 1][n] = val;
|
||||
};
|
||||
var push = function(ctx) {
|
||||
stack.push(ctx || {});
|
||||
};
|
||||
var pop = function() {
|
||||
stack.pop();
|
||||
};
|
||||
var write = function(str) {
|
||||
output.push(str);
|
||||
};
|
||||
var filter = function(val) {
|
||||
for (var i = 1, len = arguments.length; i < len; i++) {
|
||||
var arr = arguments[i],
|
||||
name = arr[0],
|
||||
filter = filters[name];
|
||||
if (filter) {
|
||||
arr[0] = val;
|
||||
//now arr looks like [val, arg1, arg2]
|
||||
val = filter.apply(data, arr);
|
||||
} else {
|
||||
throw new Error('Invalid filter: ' + name);
|
||||
}
|
||||
}
|
||||
if (opts.autoEscape && name !== opts.autoEscape && name !== 'safe') {
|
||||
//auto escape if not explicitly safe or already escaped
|
||||
val = filters[opts.autoEscape].call(data, val);
|
||||
}
|
||||
output.push(val);
|
||||
};
|
||||
var each = function(obj, loopvar, fn1, fn2) {
|
||||
if (obj == null) return;
|
||||
var arr = isArray(obj) ? obj : getKeys(obj),
|
||||
len = arr.length;
|
||||
var ctx = {
|
||||
loop: {
|
||||
length: len,
|
||||
first: arr[0],
|
||||
last: arr[len - 1]
|
||||
}
|
||||
};
|
||||
push(ctx);
|
||||
for (var i = 0; i < len; i++) {
|
||||
extend(ctx.loop, {
|
||||
index: i + 1,
|
||||
index0: i
|
||||
});
|
||||
fn1(ctx[loopvar] = arr[i]);
|
||||
}
|
||||
if (len === 0 && fn2) fn2();
|
||||
pop();
|
||||
};
|
||||
var block = function(fn) {
|
||||
push();
|
||||
fn();
|
||||
pop();
|
||||
};
|
||||
var render = function() {
|
||||
return output.join('');
|
||||
};
|
||||
data = data || {};
|
||||
opts = extend(defaults, opts || {});
|
||||
var filters = extend({
|
||||
html: function(val) {
|
||||
return toString(val)
|
||||
.split('&').join('&')
|
||||
.split('<').join('<')
|
||||
.split('>').join('>')
|
||||
.split('"').join('"');
|
||||
},
|
||||
safe: function(val) {
|
||||
return val;
|
||||
},
|
||||
toJson: function(val) {
|
||||
if (typeof val === 'object') {
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
return toString(val);
|
||||
}
|
||||
}, opts.filters || {});
|
||||
var stack = [create(data || {})],
|
||||
output = [];
|
||||
return {
|
||||
get: get,
|
||||
set: set,
|
||||
push: push,
|
||||
pop: pop,
|
||||
write: write,
|
||||
filter: filter,
|
||||
each: each,
|
||||
block: block,
|
||||
render: render
|
||||
};
|
||||
};
|
||||
|
||||
var runtime;
|
||||
|
||||
jinja.compile = function(markup, opts) {
|
||||
opts = opts || {};
|
||||
var parser = new Parser();
|
||||
parser.readTemplateFile = this.readTemplateFile;
|
||||
var code = [];
|
||||
code.push('function render($) {');
|
||||
code.push('var get = $.get, set = $.set, push = $.push, pop = $.pop, write = $.write, filter = $.filter, each = $.each, block = $.block;');
|
||||
code.push.apply(code, parser.parse(markup));
|
||||
code.push('return $.render();');
|
||||
code.push('}');
|
||||
code = code.join('\n');
|
||||
if (opts.runtime === false) {
|
||||
var fn = new Function('data', 'options', 'return (' + code + ')(runtime(data, options))');
|
||||
} else {
|
||||
runtime = runtime || (runtime = getRuntime.toString());
|
||||
fn = new Function('data', 'options', 'return (' + code + ')((' + runtime + ')(data, options))');
|
||||
}
|
||||
return {
|
||||
render: fn
|
||||
};
|
||||
};
|
||||
|
||||
jinja.render = function(markup, data, opts) {
|
||||
var tmpl = jinja.compile(markup);
|
||||
return tmpl.render(data, opts);
|
||||
};
|
||||
|
||||
jinja.templateFiles = [];
|
||||
|
||||
jinja.readTemplateFile = function(name) {
|
||||
var templateFiles = this.templateFiles || [];
|
||||
var templateFile = templateFiles[name];
|
||||
if (templateFile == null) {
|
||||
throw new Error('Template file not found: ' + name);
|
||||
}
|
||||
return templateFile;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function trimLeft(str) {
|
||||
return str.replace(LEADING_SPACE, '');
|
||||
}
|
||||
|
||||
function trimRight(str) {
|
||||
return str.replace(TRAILING_SPACE, '');
|
||||
}
|
||||
|
||||
function matchAll(str, reg, fn) {
|
||||
//copy as global
|
||||
reg = new RegExp(reg.source, 'g' + (reg.ignoreCase ? 'i' : '') + (reg.multiline ? 'm' : ''));
|
||||
var match;
|
||||
while ((match = reg.exec(str))) {
|
||||
var result = fn(match[0], match.index, str);
|
||||
if (typeof result == 'number') {
|
||||
reg.lastIndex = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -1,360 +0,0 @@
|
||||
/*
|
||||
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if (typeof exports === 'object' && typeof module === 'object') {
|
||||
// CommonJS
|
||||
module.exports = exports = factory();
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
define([], factory);
|
||||
} else {
|
||||
// Global (browser)
|
||||
globalThis.JSEncrypt = factory();
|
||||
}
|
||||
})(this, () => {
|
||||
return /******/ (() => { // webpackBootstrap
|
||||
/******/
|
||||
var __webpack_modules__ = ({
|
||||
|
||||
/***/
|
||||
"./lib/JSEncrypt.js":
|
||||
/*!**************************!*\
|
||||
!*** ./lib/JSEncrypt.js ***!
|
||||
\**************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"JSEncrypt\": () => (/* binding */ JSEncrypt)\n/* harmony export */ });\n/* harmony import */ var _lib_jsbn_base64__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/jsbn/base64 */ \"./lib/lib/jsbn/base64.js\");\n/* harmony import */ var _JSEncryptRSAKey__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./JSEncryptRSAKey */ \"./lib/JSEncryptRSAKey.js\");\n/* provided dependency */ var process = __webpack_require__(/*! process/browser */ \"./node_modules/process/browser.js\");\nvar _a;\n\n\nvar version = typeof process !== 'undefined'\n ? (_a = process.env) === null || _a === void 0 ? void 0 : \"3.3.2\"\n : undefined;\n/**\n *\n * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour\n * possible parameters are:\n * - default_key_size {number} default: 1024 the key size in bit\n * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent\n * - log {boolean} default: false whether log warn/error or not\n * @constructor\n */\nvar JSEncrypt = /** @class */ (function () {\n function JSEncrypt(options) {\n if (options === void 0) { options = {}; }\n options = options || {};\n this.default_key_size = options.default_key_size\n ? parseInt(options.default_key_size, 10)\n : 1024;\n this.default_public_exponent = options.default_public_exponent || \"010001\"; // 65537 default openssl public exponent for rsa key type\n this.log = options.log || false;\n // The private and public key.\n this.key = null;\n }\n /**\n * Method to set the rsa key parameter (one method is enough to set both the public\n * and the private key, since the private key contains the public key paramenters)\n * Log a warning if logs are enabled\n * @param {Object|string} key the pem encoded string or an object (with or without header/footer)\n * @public\n */\n JSEncrypt.prototype.setKey = function (key) {\n if (this.log && this.key) {\n console.warn(\"A key was already set, overriding existing.\");\n }\n this.key = new _JSEncryptRSAKey__WEBPACK_IMPORTED_MODULE_1__.JSEncryptRSAKey(key);\n };\n /**\n * Proxy method for setKey, for api compatibility\n * @see setKey\n * @public\n */\n JSEncrypt.prototype.setPrivateKey = function (privkey) {\n // Create the key.\n this.setKey(privkey);\n };\n /**\n * Proxy method for setKey, for api compatibility\n * @see setKey\n * @public\n */\n JSEncrypt.prototype.setPublicKey = function (pubkey) {\n // Sets the public key.\n this.setKey(pubkey);\n };\n /**\n * Proxy method for RSAKey object's decrypt, decrypt the string using the private\n * components of the rsa key object. Note that if the object was not set will be created\n * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor\n * @param {string} str base64 encoded crypted string to decrypt\n * @return {string} the decrypted string\n * @public\n */\n JSEncrypt.prototype.decrypt = function (str) {\n // Return the decrypted string.\n try {\n return this.getKey().decrypt((0,_lib_jsbn_base64__WEBPACK_IMPORTED_MODULE_0__.b64tohex)(str));\n }\n catch (ex) {\n return false;\n }\n };\n /**\n * Proxy method for RSAKey object's encrypt, encrypt the string using the public\n * components of the rsa key object. Note that if the object was not set will be created\n * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor\n * @param {string} str the string to encrypt\n * @return {string} the encrypted string encoded in base64\n * @public\n */\n JSEncrypt.prototype.encrypt = function (str) {\n // Return the encrypted string.\n try {\n return (0,_lib_jsbn_base64__WEBPACK_IMPORTED_MODULE_0__.hex2b64)(this.getKey().encrypt(str));\n }\n catch (ex) {\n return false;\n }\n };\n /**\n * Proxy method for RSAKey object's sign.\n * @param {string} str the string to sign\n * @param {function} digestMethod hash method\n * @param {string} digestName the name of the hash algorithm\n * @return {string} the signature encoded in base64\n * @public\n */\n JSEncrypt.prototype.sign = function (str, digestMethod, digestName) {\n // return the RSA signature of 'str' in 'hex' format.\n try {\n return (0,_lib_jsbn_base64__WEBPACK_IMPORTED_MODULE_0__.hex2b64)(this.getKey().sign(str, digestMethod, digestName));\n }\n catch (ex) {\n return false;\n }\n };\n
Line truncated
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/JSEncryptRSAKey.js":
|
||||
/*!********************************!*\
|
||||
!*** ./lib/JSEncryptRSAKey.js ***!
|
||||
\********************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"JSEncryptRSAKey\": () => (/* binding */ JSEncryptRSAKey)\n/* harmony export */ });\n/* harmony import */ var _lib_jsbn_base64__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/jsbn/base64 */ \"./lib/lib/jsbn/base64.js\");\n/* harmony import */ var _lib_asn1js_hex__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/asn1js/hex */ \"./lib/lib/asn1js/hex.js\");\n/* harmony import */ var _lib_asn1js_base64__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/asn1js/base64 */ \"./lib/lib/asn1js/base64.js\");\n/* harmony import */ var _lib_asn1js_asn1__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./lib/asn1js/asn1 */ \"./lib/lib/asn1js/asn1.js\");\n/* harmony import */ var _lib_jsbn_rsa__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/jsbn/rsa */ \"./lib/lib/jsbn/rsa.js\");\n/* harmony import */ var _lib_jsbn_jsbn__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/jsbn/jsbn */ \"./lib/lib/jsbn/jsbn.js\");\n/* harmony import */ var _lib_jsrsasign_asn1_1_0__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/jsrsasign/asn1-1.0 */ \"./lib/lib/jsrsasign/asn1-1.0.js\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\n\n\n\n\n\n/**\n * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.\n * This object is just a decorator for parsing the key parameter\n * @param {string|Object} key - The key in string format, or an object containing\n * the parameters needed to build a RSAKey object.\n * @constructor\n */\nvar JSEncryptRSAKey = /** @class */ (function (_super) {\n __extends(JSEncryptRSAKey, _super);\n function JSEncryptRSAKey(key) {\n var _this = _super.call(this) || this;\n // Call the super constructor.\n // RSAKey.call(this);\n // If a key key was provided.\n if (key) {\n // If this is a string...\n if (typeof key === \"string\") {\n _this.parseKey(key);\n }\n else if (JSEncryptRSAKey.hasPrivateKeyProperty(key) ||\n JSEncryptRSAKey.hasPublicKeyProperty(key)) {\n // Set the values for the key.\n _this.parsePropertiesFrom(key);\n }\n }\n return _this;\n }\n /**\n * Method to parse a pem encoded string containing both a public or private key.\n * The method will translate the pem encoded string in a der encoded string and\n * will parse private key and public key parameters. This method accepts public key\n * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).\n *\n * @todo Check how many rsa formats use the same format of pkcs #1.\n *\n * The format is defined as:\n * PublicKeyInfo ::= SEQUENCE {\n * algorithm AlgorithmIdentifier,\n * PublicKey BIT STRING\n * }\n * Where AlgorithmIdentifier is:\n * AlgorithmIdentifier ::= SEQUENCE {\n * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm\n * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)\n * }\n * and PublicKey is a SEQUENCE encapsulated in a BIT STRING\n * RSAPublicKey ::= SEQUENCE {\n * modulus INTEGER, -- n\n * publicExponent INTEGER -- e\n * }\n * it's possible to examine the structure of the keys obtained from openssl using\n * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/\n * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer\n * @private\n */\n JSEncryptRSAKey.prototype.parseKey = function (pem) {\n try {\n var modulus = 0;\n var public_exponent = 0;\n var reHex = /^\\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\\s*)+$/;\n var der = reHex.test(pem) ? _lib_asn1js_hex__WEBPACK_IMPORTED_MODULE_1__.Hex.decode(pem) : _lib_asn1js_base64__WEBPACK_IMPORTED_MODULE_2__.Base64.unarmor(pem);\n var asn1 = _lib_asn1js_asn1__WEBPACK_IMPORTED_MODULE_3__.ASN1.decode(der);\n // Fixes a bug with OpenSSL
Line truncated
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/index.js":
|
||||
/*!**********************!*\
|
||||
!*** ./lib/index.js ***!
|
||||
\**********************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"JSEncrypt\": () => (/* reexport safe */ _JSEncrypt__WEBPACK_IMPORTED_MODULE_0__.JSEncrypt),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _JSEncrypt__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./JSEncrypt */ \"./lib/JSEncrypt.js\");\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_JSEncrypt__WEBPACK_IMPORTED_MODULE_0__.JSEncrypt);\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/index.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/asn1js/asn1.js":
|
||||
/*!********************************!*\
|
||||
!*** ./lib/lib/asn1js/asn1.js ***!
|
||||
\********************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ASN1\": () => (/* binding */ ASN1),\n/* harmony export */ \"ASN1Tag\": () => (/* binding */ ASN1Tag),\n/* harmony export */ \"Stream\": () => (/* binding */ Stream)\n/* harmony export */ });\n/* harmony import */ var _int10__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./int10 */ \"./lib/lib/asn1js/int10.js\");\n// ASN.1 JavaScript decoder\n// Copyright (c) 2008-2014 Lapo Luchini <lapo@lapo.it>\n// Permission to use, copy, modify, and/or distribute this software for any\n// purpose with or without fee is hereby granted, provided that the above\n// copyright notice and this permission notice appear in all copies.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */\n/*global oids */\n\nvar ellipsis = \"\\u2026\";\nvar reTimeS = /^(\\d\\d)(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])([01]\\d|2[0-3])(?:([0-5]\\d)(?:([0-5]\\d)(?:[.,](\\d{1,3}))?)?)?(Z|[-+](?:[0]\\d|1[0-2])([0-5]\\d)?)?$/;\nvar reTimeL = /^(\\d\\d\\d\\d)(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])([01]\\d|2[0-3])(?:([0-5]\\d)(?:([0-5]\\d)(?:[.,](\\d{1,3}))?)?)?(Z|[-+](?:[0]\\d|1[0-2])([0-5]\\d)?)?$/;\nfunction stringCut(str, len) {\n if (str.length > len) {\n str = str.substring(0, len) + ellipsis;\n }\n return str;\n}\nvar Stream = /** @class */ (function () {\n function Stream(enc, pos) {\n this.hexDigits = \"0123456789ABCDEF\";\n if (enc instanceof Stream) {\n this.enc = enc.enc;\n this.pos = enc.pos;\n }\n else {\n // enc should be an array or a binary string\n this.enc = enc;\n this.pos = pos;\n }\n }\n Stream.prototype.get = function (pos) {\n if (pos === undefined) {\n pos = this.pos++;\n }\n if (pos >= this.enc.length) {\n throw new Error(\"Requesting byte offset \".concat(pos, \" on a stream of length \").concat(this.enc.length));\n }\n return (\"string\" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos];\n };\n Stream.prototype.hexByte = function (b) {\n return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF);\n };\n Stream.prototype.hexDump = function (start, end, raw) {\n var s = \"\";\n for (var i = start; i < end; ++i) {\n s += this.hexByte(this.get(i));\n if (raw !== true) {\n switch (i & 0xF) {\n case 0x7:\n s += \" \";\n break;\n case 0xF:\n s += \"\\n\";\n break;\n default:\n s += \" \";\n }\n }\n }\n return s;\n };\n Stream.prototype.isASCII = function (start, end) {\n for (var i = start; i < end; ++i) {\n var c = this.get(i);\n if (c < 32 || c > 176) {\n return false;\n }\n }\n return true;\n };\n Stream.prototype.parseStringISO = function (start, end) {\n var s = \"\";\n for (var i = start; i < end; ++i) {\n s += String.fromCharCode(this.get(i));\n }\n return s;\n };\n Stream.prototype.parseStringUTF = function (start, end) {\n var s = \"\";\n for (var i = start; i < end;) {\n var c = this.get(i++);\n if (c < 128) {\n s += String.fromCharCode(c);\n }\n else if ((c > 191) && (c < 224)) {\n s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F));\n }\n else {\n s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F));\n }\n }\n return s;\n };\n Stream.prototype.parseStringBMP = function (start, end) {\n var str = \"\";\n var hi;\n var lo;\n for (var i = start; i < end;) {\n hi = this.get(i++);\n lo = this.get(i++);\n str += String.fromCharCode((hi << 8) | lo);\n }\n return str;\n };\n Stream.prototype.parseTime = function (start, end, shortYear) {\n var s = this.parseStringISO(start, end);\n var m = (shoLine truncated
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/asn1js/base64.js":
|
||||
/*!**********************************!*\
|
||||
!*** ./lib/lib/asn1js/base64.js ***!
|
||||
\**********************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Base64\": () => (/* binding */ Base64)\n/* harmony export */ });\n// Base64 JavaScript decoder\n// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>\n// Permission to use, copy, modify, and/or distribute this software for any\n// purpose with or without fee is hereby granted, provided that the above\n// copyright notice and this permission notice appear in all copies.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */\nvar decoder;\nvar Base64 = {\n decode: function (a) {\n var i;\n if (decoder === undefined) {\n var b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n var ignore = \"= \\f\\n\\r\\t\\u00A0\\u2028\\u2029\";\n decoder = Object.create(null);\n for (i = 0; i < 64; ++i) {\n decoder[b64.charAt(i)] = i;\n }\n decoder['-'] = 62; //+\n decoder['_'] = 63; //-\n for (i = 0; i < ignore.length; ++i) {\n decoder[ignore.charAt(i)] = -1;\n }\n }\n var out = [];\n var bits = 0;\n var char_count = 0;\n for (i = 0; i < a.length; ++i) {\n var c = a.charAt(i);\n if (c == \"=\") {\n break;\n }\n c = decoder[c];\n if (c == -1) {\n continue;\n }\n if (c === undefined) {\n throw new Error(\"Illegal character at offset \" + i);\n }\n bits |= c;\n if (++char_count >= 4) {\n out[out.length] = (bits >> 16);\n out[out.length] = (bits >> 8) & 0xFF;\n out[out.length] = bits & 0xFF;\n bits = 0;\n char_count = 0;\n }\n else {\n bits <<= 6;\n }\n }\n switch (char_count) {\n case 1:\n throw new Error(\"Base64 encoding incomplete: at least 2 bits missing\");\n case 2:\n out[out.length] = (bits >> 10);\n break;\n case 3:\n out[out.length] = (bits >> 16);\n out[out.length] = (bits >> 8) & 0xFF;\n break;\n }\n return out;\n },\n re: /-----BEGIN [^-]+-----([A-Za-z0-9+\\/=\\s]+)-----END [^-]+-----|begin-base64[^\\n]+\\n([A-Za-z0-9+\\/=\\s]+)====/,\n unarmor: function (a) {\n var m = Base64.re.exec(a);\n if (m) {\n if (m[1]) {\n a = m[1];\n }\n else if (m[2]) {\n a = m[2];\n }\n else {\n throw new Error(\"RegExp out of sync\");\n }\n }\n return Base64.decode(a);\n }\n};\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/asn1js/base64.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/asn1js/hex.js":
|
||||
/*!*******************************!*\
|
||||
!*** ./lib/lib/asn1js/hex.js ***!
|
||||
\*******************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Hex\": () => (/* binding */ Hex)\n/* harmony export */ });\n// Hex JavaScript decoder\n// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>\n// Permission to use, copy, modify, and/or distribute this software for any\n// purpose with or without fee is hereby granted, provided that the above\n// copyright notice and this permission notice appear in all copies.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */\nvar decoder;\nvar Hex = {\n decode: function (a) {\n var i;\n if (decoder === undefined) {\n var hex = \"0123456789ABCDEF\";\n var ignore = \" \\f\\n\\r\\t\\u00A0\\u2028\\u2029\";\n decoder = {};\n for (i = 0; i < 16; ++i) {\n decoder[hex.charAt(i)] = i;\n }\n hex = hex.toLowerCase();\n for (i = 10; i < 16; ++i) {\n decoder[hex.charAt(i)] = i;\n }\n for (i = 0; i < ignore.length; ++i) {\n decoder[ignore.charAt(i)] = -1;\n }\n }\n var out = [];\n var bits = 0;\n var char_count = 0;\n for (i = 0; i < a.length; ++i) {\n var c = a.charAt(i);\n if (c == \"=\") {\n break;\n }\n c = decoder[c];\n if (c == -1) {\n continue;\n }\n if (c === undefined) {\n throw new Error(\"Illegal character at offset \" + i);\n }\n bits |= c;\n if (++char_count >= 2) {\n out[out.length] = bits;\n bits = 0;\n char_count = 0;\n }\n else {\n bits <<= 4;\n }\n }\n if (char_count) {\n throw new Error(\"Hex encoding incomplete: 4 bits missing\");\n }\n return out;\n }\n};\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/asn1js/hex.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/asn1js/int10.js":
|
||||
/*!*********************************!*\
|
||||
!*** ./lib/lib/asn1js/int10.js ***!
|
||||
\*********************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Int10\": () => (/* binding */ Int10)\n/* harmony export */ });\n// Big integer base-10 printing library\n// Copyright (c) 2014 Lapo Luchini <lapo@lapo.it>\n// Permission to use, copy, modify, and/or distribute this software for any\n// purpose with or without fee is hereby granted, provided that the above\n// copyright notice and this permission notice appear in all copies.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */\nvar max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256\nvar Int10 = /** @class */ (function () {\n function Int10(value) {\n this.buf = [+value || 0];\n }\n Int10.prototype.mulAdd = function (m, c) {\n // assert(m <= 256)\n var b = this.buf;\n var l = b.length;\n var i;\n var t;\n for (i = 0; i < l; ++i) {\n t = b[i] * m + c;\n if (t < max) {\n c = 0;\n }\n else {\n c = 0 | (t / max);\n t -= c * max;\n }\n b[i] = t;\n }\n if (c > 0) {\n b[i] = c;\n }\n };\n Int10.prototype.sub = function (c) {\n // assert(m <= 256)\n var b = this.buf;\n var l = b.length;\n var i;\n var t;\n for (i = 0; i < l; ++i) {\n t = b[i] - c;\n if (t < 0) {\n t += max;\n c = 1;\n }\n else {\n c = 0;\n }\n b[i] = t;\n }\n while (b[b.length - 1] === 0) {\n b.pop();\n }\n };\n Int10.prototype.toString = function (base) {\n if ((base || 10) != 10) {\n throw new Error(\"only base 10 is supported\");\n }\n var b = this.buf;\n var s = b[b.length - 1].toString();\n for (var i = b.length - 2; i >= 0; --i) {\n s += (max + b[i]).toString().substring(1);\n }\n return s;\n };\n Int10.prototype.valueOf = function () {\n var b = this.buf;\n var v = 0;\n for (var i = b.length - 1; i >= 0; --i) {\n v = v * max + b[i];\n }\n return v;\n };\n Int10.prototype.simplify = function () {\n var b = this.buf;\n return (b.length == 1) ? b[0] : this;\n };\n return Int10;\n}());\n\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/asn1js/int10.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsbn/base64.js":
|
||||
/*!********************************!*\
|
||||
!*** ./lib/lib/jsbn/base64.js ***!
|
||||
\********************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"b64toBA\": () => (/* binding */ b64toBA),\n/* harmony export */ \"b64tohex\": () => (/* binding */ b64tohex),\n/* harmony export */ \"hex2b64\": () => (/* binding */ hex2b64)\n/* harmony export */ });\n/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util */ \"./lib/lib/jsbn/util.js\");\n\nvar b64map = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nvar b64pad = \"=\";\nfunction hex2b64(h) {\n var i;\n var c;\n var ret = \"\";\n for (i = 0; i + 3 <= h.length; i += 3) {\n c = parseInt(h.substring(i, i + 3), 16);\n ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);\n }\n if (i + 1 == h.length) {\n c = parseInt(h.substring(i, i + 1), 16);\n ret += b64map.charAt(c << 2);\n }\n else if (i + 2 == h.length) {\n c = parseInt(h.substring(i, i + 2), 16);\n ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);\n }\n while ((ret.length & 3) > 0) {\n ret += b64pad;\n }\n return ret;\n}\n// convert a base64 string to hex\nfunction b64tohex(s) {\n var ret = \"\";\n var i;\n var k = 0; // b64 state, 0-3\n var slop = 0;\n for (i = 0; i < s.length; ++i) {\n if (s.charAt(i) == b64pad) {\n break;\n }\n var v = b64map.indexOf(s.charAt(i));\n if (v < 0) {\n continue;\n }\n if (k == 0) {\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(v >> 2);\n slop = v & 3;\n k = 1;\n }\n else if (k == 1) {\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)((slop << 2) | (v >> 4));\n slop = v & 0xf;\n k = 2;\n }\n else if (k == 2) {\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(slop);\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(v >> 2);\n slop = v & 3;\n k = 3;\n }\n else {\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)((slop << 2) | (v >> 4));\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(v & 0xf);\n k = 0;\n }\n }\n if (k == 1) {\n ret += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(slop << 2);\n }\n return ret;\n}\n// convert a base64 string to a byte/number array\nfunction b64toBA(s) {\n // piggyback on b64tohex for now, optimize later\n var h = b64tohex(s);\n var i;\n var a = [];\n for (i = 0; 2 * i < h.length; ++i) {\n a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16);\n }\n return a;\n}\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/jsbn/base64.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsbn/jsbn.js":
|
||||
/*!******************************!*\
|
||||
!*** ./lib/lib/jsbn/jsbn.js ***!
|
||||
\******************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BigInteger\": () => (/* binding */ BigInteger),\n/* harmony export */ \"intAt\": () => (/* binding */ intAt),\n/* harmony export */ \"nbi\": () => (/* binding */ nbi),\n/* harmony export */ \"nbits\": () => (/* binding */ nbits),\n/* harmony export */ \"nbv\": () => (/* binding */ nbv),\n/* harmony export */ \"parseBigInt\": () => (/* binding */ parseBigInt)\n/* harmony export */ });\n/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util */ \"./lib/lib/jsbn/util.js\");\n// Copyright (c) 2005 Tom Wu\n// All Rights Reserved.\n// See \"LICENSE\" for details.\n// Basic JavaScript BN library - subset useful for RSA encryption.\n\n// Bits per digit\nvar dbits;\n// JavaScript engine analysis\nvar canary = 0xdeadbeefcafe;\nvar j_lm = ((canary & 0xffffff) == 0xefcafe);\n//#region\nvar lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];\nvar lplim = (1 << 26) / lowprimes[lowprimes.length - 1];\n//#endregion\n// (public) Constructor\nvar BigInteger = /** @class */ (function () {\n function BigInteger(a, b, c) {\n if (a != null) {\n if (\"number\" == typeof a) {\n this.fromNumber(a, b, c);\n }\n else if (b == null && \"string\" != typeof a) {\n this.fromString(a, 256);\n }\n else {\n this.fromString(a, b);\n }\n }\n }\n //#region PUBLIC\n // BigInteger.prototype.toString = bnToString;\n // (public) return string representation in given radix\n BigInteger.prototype.toString = function (b) {\n if (this.s < 0) {\n return \"-\" + this.negate().toString(b);\n }\n var k;\n if (b == 16) {\n k = 4;\n }\n else if (b == 8) {\n k = 3;\n }\n else if (b == 2) {\n k = 1;\n }\n else if (b == 32) {\n k = 5;\n }\n else if (b == 4) {\n k = 2;\n }\n else {\n return this.toRadix(b);\n }\n var km = (1 << k) - 1;\n var d;\n var m = false;\n var r = \"\";\n var i = this.t;\n var p = this.DB - (i * this.DB) % k;\n if (i-- > 0) {\n if (p < this.DB && (d = this[i] >> p) > 0) {\n m = true;\n r = (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(d);\n }\n while (i >= 0) {\n if (p < k) {\n d = (this[i] & ((1 << p) - 1)) << (k - p);\n d |= this[--i] >> (p += this.DB - k);\n }\n else {\n d = (this[i] >> (p -= k)) & km;\n if (p <= 0) {\n p += this.DB;\n --i;\n }\n }\n if (d > 0) {\n m = true;\n }\n if (m) {\n r += (0,_util__WEBPACK_IMPORTED_MODULE_0__.int2char)(d);\n }\n }\n }\n return m ? r : \"0\";\n };\n // BigInteger.prototype.negate = bnNegate;\n // (public) -this\n BigInteger.prototype.negate = function () {\n var r = nbi();\n BigInteger.ZERO.subTo(this, r);\n return r;\n };\n // BigInteger.prototype.abs = bnAbs;\n // (public) |this|\n BigInteger.prototype.abs = function () {\n return (this.s < 0) ? this.negate() : this;\n };\n // BigInteger.prototype.compareTo = bnCompareTo;\n // (public) return + if this > a, - if this < a, 0 if equal\n BigInteger.prototype.compareTo = function (a) {\n var r = this.s - a.s;\n if (r != 0) {\n return r;\n }\n var i = this.t;\n r = i - a.t;\n if (r != 0) {\n return (this.s < 0) ? -r : r;\n }\n while (--i >= 0) {\n if ((r = this[i] - a[i]) != 0) {\n return r;\n }\n }\n return 0;\n };\n // BigInteger.protot
Line truncated
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsbn/prng4.js":
|
||||
/*!*******************************!*\
|
||||
!*** ./lib/lib/jsbn/prng4.js ***!
|
||||
\*******************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Arcfour\": () => (/* binding */ Arcfour),\n/* harmony export */ \"prng_newstate\": () => (/* binding */ prng_newstate),\n/* harmony export */ \"rng_psize\": () => (/* binding */ rng_psize)\n/* harmony export */ });\n// prng4.js - uses Arcfour as a PRNG\nvar Arcfour = /** @class */ (function () {\n function Arcfour() {\n this.i = 0;\n this.j = 0;\n this.S = [];\n }\n // Arcfour.prototype.init = ARC4init;\n // Initialize arcfour context from key, an array of ints, each from [0..255]\n Arcfour.prototype.init = function (key) {\n var i;\n var j;\n var t;\n for (i = 0; i < 256; ++i) {\n this.S[i] = i;\n }\n j = 0;\n for (i = 0; i < 256; ++i) {\n j = (j + this.S[i] + key[i % key.length]) & 255;\n t = this.S[i];\n this.S[i] = this.S[j];\n this.S[j] = t;\n }\n this.i = 0;\n this.j = 0;\n };\n // Arcfour.prototype.next = ARC4next;\n Arcfour.prototype.next = function () {\n var t;\n this.i = (this.i + 1) & 255;\n this.j = (this.j + this.S[this.i]) & 255;\n t = this.S[this.i];\n this.S[this.i] = this.S[this.j];\n this.S[this.j] = t;\n return this.S[(t + this.S[this.i]) & 255];\n };\n return Arcfour;\n}());\n\n// Plug in your RNG constructor here\nfunction prng_newstate() {\n return new Arcfour();\n}\n// Pool size must be a multiple of 4 and greater than 32.\n// An array of bytes the size of the pool will be passed to init()\nvar rng_psize = 256;\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/jsbn/prng4.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsbn/rng.js":
|
||||
/*!*****************************!*\
|
||||
!*** ./lib/lib/jsbn/rng.js ***!
|
||||
\*****************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"SecureRandom\": () => (/* binding */ SecureRandom)\n/* harmony export */ });\n/* harmony import */ var _prng4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./prng4 */ \"./lib/lib/jsbn/prng4.js\");\n// Random number generator - requires a PRNG backend, e.g. prng4.js\n\nvar rng_state;\nvar rng_pool = null;\nvar rng_pptr;\n// Initialize the pool with junk if needed.\nif (rng_pool == null) {\n rng_pool = [];\n rng_pptr = 0;\n var t = void 0;\n if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {\n // Extract entropy (2048 bits) from RNG if available\n var z = new Uint32Array(256);\n window.crypto.getRandomValues(z);\n for (t = 0; t < z.length; ++t) {\n rng_pool[rng_pptr++] = z[t] & 255;\n }\n }\n // Use mouse events for entropy, if we do not have enough entropy by the time\n // we need it, entropy will be generated by Math.random.\n var count = 0;\n var onMouseMoveListener_1 = function (ev) {\n count = count || 0;\n if (count >= 256 || rng_pptr >= _prng4__WEBPACK_IMPORTED_MODULE_0__.rng_psize) {\n if (window.removeEventListener) {\n window.removeEventListener(\"mousemove\", onMouseMoveListener_1, false);\n }\n else if (window.detachEvent) {\n window.detachEvent(\"onmousemove\", onMouseMoveListener_1);\n }\n return;\n }\n try {\n var mouseCoordinates = ev.x + ev.y;\n rng_pool[rng_pptr++] = mouseCoordinates & 255;\n count += 1;\n }\n catch (e) {\n // Sometimes Firefox will deny permission to access event properties for some reason. Ignore.\n }\n };\n if (typeof window !== 'undefined') {\n if (window.addEventListener) {\n window.addEventListener(\"mousemove\", onMouseMoveListener_1, false);\n }\n else if (window.attachEvent) {\n window.attachEvent(\"onmousemove\", onMouseMoveListener_1);\n }\n }\n}\nfunction rng_get_byte() {\n if (rng_state == null) {\n rng_state = (0,_prng4__WEBPACK_IMPORTED_MODULE_0__.prng_newstate)();\n // At this point, we may not have collected enough entropy. If not, fall back to Math.random\n while (rng_pptr < _prng4__WEBPACK_IMPORTED_MODULE_0__.rng_psize) {\n var random = Math.floor(65536 * Math.random());\n rng_pool[rng_pptr++] = random & 255;\n }\n rng_state.init(rng_pool);\n for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) {\n rng_pool[rng_pptr] = 0;\n }\n rng_pptr = 0;\n }\n // TODO: allow reseeding after first request\n return rng_state.next();\n}\nvar SecureRandom = /** @class */ (function () {\n function SecureRandom() {\n }\n SecureRandom.prototype.nextBytes = function (ba) {\n for (var i = 0; i < ba.length; ++i) {\n ba[i] = rng_get_byte();\n }\n };\n return SecureRandom;\n}());\n\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/jsbn/rng.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsbn/rsa.js":
|
||||
/*!*****************************!*\
|
||||
!*** ./lib/lib/jsbn/rsa.js ***!
|
||||
\*****************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"RSAKey\": () => (/* binding */ RSAKey)\n/* harmony export */ });\n/* harmony import */ var _jsbn__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./jsbn */ \"./lib/lib/jsbn/jsbn.js\");\n/* harmony import */ var _rng__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./rng */ \"./lib/lib/jsbn/rng.js\");\n// Depends on jsbn.js and rng.js\n// Version 1.1: support utf-8 encoding in pkcs1pad2\n// convert a (hex) string to a bignum object\n\n\n// function linebrk(s,n) {\n// var ret = \"\";\n// var i = 0;\n// while(i + n < s.length) {\n// ret += s.substring(i,i+n) + \"\\n\";\n// i += n;\n// }\n// return ret + s.substring(i,s.length);\n// }\n// function byte2Hex(b) {\n// if(b < 0x10)\n// return \"0\" + b.toString(16);\n// else\n// return b.toString(16);\n// }\nfunction pkcs1pad1(s, n) {\n if (n < s.length + 22) {\n console.error(\"Message too long for RSA\");\n return null;\n }\n var len = n - s.length - 6;\n var filler = \"\";\n for (var f = 0; f < len; f += 2) {\n filler += \"ff\";\n }\n var m = \"0001\" + filler + \"00\" + s;\n return (0,_jsbn__WEBPACK_IMPORTED_MODULE_0__.parseBigInt)(m, 16);\n}\n// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint\nfunction pkcs1pad2(s, n) {\n if (n < s.length + 11) { // TODO: fix for utf-8\n console.error(\"Message too long for RSA\");\n return null;\n }\n var ba = [];\n var i = s.length - 1;\n while (i >= 0 && n > 0) {\n var c = s.charCodeAt(i--);\n if (c < 128) { // encode using utf-8\n ba[--n] = c;\n }\n else if ((c > 127) && (c < 2048)) {\n ba[--n] = (c & 63) | 128;\n ba[--n] = (c >> 6) | 192;\n }\n else {\n ba[--n] = (c & 63) | 128;\n ba[--n] = ((c >> 6) & 63) | 128;\n ba[--n] = (c >> 12) | 224;\n }\n }\n ba[--n] = 0;\n var rng = new _rng__WEBPACK_IMPORTED_MODULE_1__.SecureRandom();\n var x = [];\n while (n > 2) { // random non-zero pad\n x[0] = 0;\n while (x[0] == 0) {\n rng.nextBytes(x);\n }\n ba[--n] = x[0];\n }\n ba[--n] = 2;\n ba[--n] = 0;\n return new _jsbn__WEBPACK_IMPORTED_MODULE_0__.BigInteger(ba);\n}\n// \"empty\" RSA key constructor\nvar RSAKey = /** @class */ (function () {\n function RSAKey() {\n this.n = null;\n this.e = 0;\n this.d = null;\n this.p = null;\n this.q = null;\n this.dmp1 = null;\n this.dmq1 = null;\n this.coeff = null;\n }\n //#region PROTECTED\n // protected\n // RSAKey.prototype.doPublic = RSADoPublic;\n // Perform raw public operation on \"x\": return x^e (mod n)\n RSAKey.prototype.doPublic = function (x) {\n return x.modPowInt(this.e, this.n);\n };\n // RSAKey.prototype.doPrivate = RSADoPrivate;\n // Perform raw private operation on \"x\": return x^d (mod n)\n RSAKey.prototype.doPrivate = function (x) {\n if (this.p == null || this.q == null) {\n return x.modPow(this.d, this.n);\n }\n // TODO: re-calculate any missing CRT params\n var xp = x.mod(this.p).modPow(this.dmp1, this.p);\n var xq = x.mod(this.q).modPow(this.dmq1, this.q);\n while (xp.compareTo(xq) < 0) {\n xp = xp.add(this.p);\n }\n return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);\n };\n //#endregion PROTECTED\n //#region PUBLIC\n // RSAKey.prototype.setPublic = RSASetPublic;\n // Set the public key fields N and e from hex strings\n RSAKey.prototype.setPublic = function (N, E) {\n if (N != null && E != null && N.length > 0 && E.length > 0) {\n this.n = (0,_jsbn__WEBPACK_IMPORTED_MODULE_0__.parseBigInt)(N, 16);\n this.e = parseInt(E, 16);\n }\n else {\n console.error(\"Invalid RSA public key\");\n }\n };\n // RSAKey.prototype.encrypt = RSAEncrypt;\n // Return the PKCS#1 RSA encryption of \"text\" as an even-length hex string\n RSAKey.prototype.encrypt = function (text) {\n var maxLength = (this.n.bitLength() + 7) >> 3;\n var m = pkcs1pad2(text, maxLength);\n if (m == null) {\n return null;\n }\n var c = this.doPublic(m);\n if (c == null) {\n return null;\n }\n var h = c.toString(16);\n var length = h.length;\n // fix zero before result\n for (var i = 0; i < maxLength * 2 - length; i++) {\n h = \"0\" + h;\n }\n return h;\n };\n // RSAKey.prototype.setPrivate = RSASetPrivate;\n // Set the private key fields N, e, and d from hex strings\n RSAKey.prototype.setPrivate = function (N, E,
Line truncated
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsbn/util.js":
|
||||
/*!******************************!*\
|
||||
!*** ./lib/lib/jsbn/util.js ***!
|
||||
\******************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"cbit\": () => (/* binding */ cbit),\n/* harmony export */ \"int2char\": () => (/* binding */ int2char),\n/* harmony export */ \"lbit\": () => (/* binding */ lbit),\n/* harmony export */ \"op_and\": () => (/* binding */ op_and),\n/* harmony export */ \"op_andnot\": () => (/* binding */ op_andnot),\n/* harmony export */ \"op_or\": () => (/* binding */ op_or),\n/* harmony export */ \"op_xor\": () => (/* binding */ op_xor)\n/* harmony export */ });\nvar BI_RM = \"0123456789abcdefghijklmnopqrstuvwxyz\";\nfunction int2char(n) {\n return BI_RM.charAt(n);\n}\n//#region BIT_OPERATIONS\n// (public) this & a\nfunction op_and(x, y) {\n return x & y;\n}\n// (public) this | a\nfunction op_or(x, y) {\n return x | y;\n}\n// (public) this ^ a\nfunction op_xor(x, y) {\n return x ^ y;\n}\n// (public) this & ~a\nfunction op_andnot(x, y) {\n return x & ~y;\n}\n// return index of lowest 1-bit in x, x < 2^31\nfunction lbit(x) {\n if (x == 0) {\n return -1;\n }\n var r = 0;\n if ((x & 0xffff) == 0) {\n x >>= 16;\n r += 16;\n }\n if ((x & 0xff) == 0) {\n x >>= 8;\n r += 8;\n }\n if ((x & 0xf) == 0) {\n x >>= 4;\n r += 4;\n }\n if ((x & 3) == 0) {\n x >>= 2;\n r += 2;\n }\n if ((x & 1) == 0) {\n ++r;\n }\n return r;\n}\n// return number of 1 bits in x\nfunction cbit(x) {\n var r = 0;\n while (x != 0) {\n x &= x - 1;\n ++r;\n }\n return r;\n}\n//#endregion BIT_OPERATIONS\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/jsbn/util.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsrsasign/asn1-1.0.js":
|
||||
/*!***************************************!*\
|
||||
!*** ./lib/lib/jsrsasign/asn1-1.0.js ***!
|
||||
\***************************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"KJUR\": () => (/* binding */ KJUR)\n/* harmony export */ });\n/* harmony import */ var _jsbn_jsbn__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../jsbn/jsbn */ \"./lib/lib/jsbn/jsbn.js\");\n/* harmony import */ var _yahoo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./yahoo */ \"./lib/lib/jsrsasign/yahoo.js\");\n/* asn1-1.0.13.js (c) 2013-2017 Kenji Urushima | kjur.github.com/jsrsasign/license\n */\n/*\n * asn1.js - ASN.1 DER encoder classes\n *\n * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com)\n *\n * This software is licensed under the terms of the MIT License.\n * https://kjur.github.io/jsrsasign/license\n *\n * The above copyright and license notice shall be\n * included in all copies or substantial portions of the Software.\n */\n\n\n/**\n * @fileOverview\n * @name asn1-1.0.js\n * @author Kenji Urushima kenji.urushima@gmail.com\n * @version asn1 1.0.13 (2017-Jun-02)\n * @since jsrsasign 2.1\n * @license <a href=\"https://kjur.github.io/jsrsasign/license/\">MIT License</a>\n */\n/**\n * kjur's class library name space\n * <p>\n * This name space provides following name spaces:\n * <ul>\n * <li>{@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder</li>\n * <li>{@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL</li>\n * <li>{@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature\n * class and utilities</li>\n * </ul>\n * </p>\n * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.\n * @name KJUR\n * @namespace kjur's class library name space\n */\nvar KJUR = {};\n/**\n * kjur's ASN.1 class library name space\n * <p>\n * This is ITU-T X.690 ASN.1 DER encoder class library and\n * class structure and methods is very similar to\n * org.bouncycastle.asn1 package of\n * well known BouncyCaslte Cryptography Library.\n * <h4>PROVIDING ASN.1 PRIMITIVES</h4>\n * Here are ASN.1 DER primitive classes.\n * <ul>\n * <li>0x01 {@link KJUR.asn1.DERBoolean}</li>\n * <li>0x02 {@link KJUR.asn1.DERInteger}</li>\n * <li>0x03 {@link KJUR.asn1.DERBitString}</li>\n * <li>0x04 {@link KJUR.asn1.DEROctetString}</li>\n * <li>0x05 {@link KJUR.asn1.DERNull}</li>\n * <li>0x06 {@link KJUR.asn1.DERObjectIdentifier}</li>\n * <li>0x0a {@link KJUR.asn1.DEREnumerated}</li>\n * <li>0x0c {@link KJUR.asn1.DERUTF8String}</li>\n * <li>0x12 {@link KJUR.asn1.DERNumericString}</li>\n * <li>0x13 {@link KJUR.asn1.DERPrintableString}</li>\n * <li>0x14 {@link KJUR.asn1.DERTeletexString}</li>\n * <li>0x16 {@link KJUR.asn1.DERIA5String}</li>\n * <li>0x17 {@link KJUR.asn1.DERUTCTime}</li>\n * <li>0x18 {@link KJUR.asn1.DERGeneralizedTime}</li>\n * <li>0x30 {@link KJUR.asn1.DERSequence}</li>\n * <li>0x31 {@link KJUR.asn1.DERSet}</li>\n * </ul>\n * <h4>OTHER ASN.1 CLASSES</h4>\n * <ul>\n * <li>{@link KJUR.asn1.ASN1Object}</li>\n * <li>{@link KJUR.asn1.DERAbstractString}</li>\n * <li>{@link KJUR.asn1.DERAbstractTime}</li>\n * <li>{@link KJUR.asn1.DERAbstractStructured}</li>\n * <li>{@link KJUR.asn1.DERTaggedObject}</li>\n * </ul>\n * <h4>SUB NAME SPACES</h4>\n * <ul>\n * <li>{@link KJUR.asn1.cades} - CAdES long term signature format</li>\n * <li>{@link KJUR.asn1.cms} - Cryptographic Message Syntax</li>\n * <li>{@link KJUR.asn1.csr} - Certificate Signing Request (CSR/PKCS#10)</li>\n * <li>{@link KJUR.asn1.tsp} - RFC 3161 Timestamping Protocol Format</li>\n * <li>{@link KJUR.asn1.x509} - RFC 5280 X.509 certificate and CRL</li>\n * </ul>\n * </p>\n * NOTE: Please ignore method summary and document of this namespace.\n * This caused by a bug of jsdoc2.\n * @name KJUR.asn1\n * @namespace\n */\nif (typeof KJUR.asn1 == \"undefined\" || !KJUR.asn1)\n KJUR.asn1 = {};\n/**\n * ASN1 utilities class\n * @name KJUR.asn1.ASN1Util\n * @class ASN1 utilities class\n * @since asn1 1.0.2\n */\nKJUR.asn1.ASN1Util = new function () {\n this.integerToByteHex = function (i) {\n var h = i.toString(16);\n if ((h.length % 2) == 1)\n h = '0' + h;\n return h;\n };\n this.bigIntToMinTwosComplementsHex = function (bigIntegerValue) {\n var h = bigIntegerValue.toString(16);\n if (h.substr(0, 1) != '-') {\n if (h.length % 2 == 1) {\n h = '0' + h;\n }\n else {\n if (!h.match(/^[0-7]/)) {\n h = '00' + h;\n }\n }\n }\n else {\n var hPos = h.substr(1);\n var xorLen = hPos.length;\n if (xorLen % 2 == 1) {\n xorLen += 1;\n }\n else {\n if (!h.match(/^[0-7]/)) {\n xorLen += 2;\n }\n }\n var hMask = '';\n for (var i = 0; i < xorLen; i++) {\n hMask += 'f';\n
Line truncated
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./lib/lib/jsrsasign/yahoo.js":
|
||||
/*!************************************!*\
|
||||
!*** ./lib/lib/jsrsasign/yahoo.js ***!
|
||||
\************************************/
|
||||
/***/
|
||||
((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"YAHOO\": () => (/* binding */ YAHOO)\n/* harmony export */ });\n/*!\nCopyright (c) 2011, Yahoo! Inc. All rights reserved.\nCode licensed under the BSD License:\nhttp://developer.yahoo.com/yui/license.html\nversion: 2.9.0\n*/\nvar YAHOO = {};\nYAHOO.lang = {\n /**\n * Utility to set up the prototype, constructor and superclass properties to\n * support an inheritance strategy that can chain constructors and methods.\n * Static members will not be inherited.\n *\n * @method extend\n * @static\n * @param {Function} subc the object to modify\n * @param {Function} superc the object to inherit\n * @param {Object} overrides additional properties/methods to add to the\n * subclass prototype. These will override the\n * matching items obtained from the superclass\n * if present.\n */\n extend: function (subc, superc, overrides) {\n if (!superc || !subc) {\n throw new Error(\"YAHOO.lang.extend failed, please check that \" +\n \"all dependencies are included.\");\n }\n var F = function () { };\n F.prototype = superc.prototype;\n subc.prototype = new F();\n subc.prototype.constructor = subc;\n subc.superclass = superc.prototype;\n if (superc.prototype.constructor == Object.prototype.constructor) {\n superc.prototype.constructor = superc;\n }\n if (overrides) {\n var i;\n for (i in overrides) {\n subc.prototype[i] = overrides[i];\n }\n /*\n * IE will not enumerate native functions in a derived object even if the\n * function was overridden. This is a workaround for specific functions\n * we care about on the Object prototype.\n * @property _IEEnumFix\n * @param {Function} r the object to receive the augmentation\n * @param {Function} s the object that supplies the properties to augment\n * @static\n * @private\n */\n var _IEEnumFix = function () { }, ADD = [\"toString\", \"valueOf\"];\n try {\n if (/MSIE/.test(navigator.userAgent)) {\n _IEEnumFix = function (r, s) {\n for (i = 0; i < ADD.length; i = i + 1) {\n var fname = ADD[i], f = s[fname];\n if (typeof f === 'function' && f != Object.prototype[fname]) {\n r[fname] = f;\n }\n }\n };\n }\n }\n catch (ex) { }\n ;\n _IEEnumFix(subc.prototype, overrides);\n }\n }\n};\n\n\n//# sourceURL=webpack://JSEncrypt/./lib/lib/jsrsasign/yahoo.js?");
|
||||
|
||||
/***/
|
||||
}),
|
||||
|
||||
/***/
|
||||
"./node_modules/process/browser.js":
|
||||
/*!*****************************************!*\
|
||||
!*** ./node_modules/process/browser.js ***!
|
||||
\*****************************************/
|
||||
/***/
|
||||
((module) => {
|
||||
|
||||
eval("// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess
Line truncated
|
||||
|
||||
/***/
|
||||
})
|
||||
|
||||
/******/
|
||||
});
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/
|
||||
var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/
|
||||
function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/
|
||||
var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/
|
||||
if (cachedModule !== undefined) {
|
||||
/******/
|
||||
return cachedModule.exports;
|
||||
/******/
|
||||
}
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/
|
||||
var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/
|
||||
exports: {}
|
||||
/******/
|
||||
};
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/
|
||||
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/
|
||||
return module.exports;
|
||||
/******/
|
||||
}
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/* webpack/runtime/define property getters */
|
||||
/******/
|
||||
(() => {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/
|
||||
__webpack_require__.d = (exports, definition) => {
|
||||
/******/
|
||||
for (var key in definition) {
|
||||
/******/
|
||||
if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: definition[key]
|
||||
});
|
||||
/******/
|
||||
}
|
||||
/******/
|
||||
}
|
||||
/******/
|
||||
};
|
||||
/******/
|
||||
})();
|
||||
/******/
|
||||
/******/
|
||||
/* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/
|
||||
(() => {
|
||||
/******/
|
||||
__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
||||
/******/
|
||||
})();
|
||||
/******/
|
||||
/******/
|
||||
/* webpack/runtime/make namespace object */
|
||||
/******/
|
||||
(() => {
|
||||
/******/ // define __esModule on exports
|
||||
/******/
|
||||
__webpack_require__.r = (exports) => {
|
||||
/******/
|
||||
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/
|
||||
Object.defineProperty(exports, Symbol.toStringTag, {
|
||||
value: 'Module'
|
||||
});
|
||||
/******/
|
||||
}
|
||||
/******/
|
||||
Object.defineProperty(exports, '__esModule', {
|
||||
value: true
|
||||
});
|
||||
/******/
|
||||
};
|
||||
/******/
|
||||
})();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module can't be inlined because the eval devtool is used.
|
||||
/******/
|
||||
var __webpack_exports__ = __webpack_require__("./lib/index.js");
|
||||
/******/
|
||||
__webpack_exports__ = __webpack_exports__["default"];
|
||||
/******/
|
||||
/******/
|
||||
return __webpack_exports__;
|
||||
/******/
|
||||
})();
|
||||
});
|
||||
-1809
File diff suppressed because it is too large.
Load diff
-5858
File diff suppressed because it is too large.
Load diff
Vendored
-1439
File diff suppressed because it is too large.
Load diff
-475
@@ -1,475 +0,0 @@
|
||||
import 'assets://lib/crypto-js.js';
|
||||
const UA = 'Mozilla/5.0 (Linux; Android 9; V2196A Build/PQ3A.190705.08211809; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36;webank/h5face;webank/1.0;netType:NETWORK_WIFI;appVersion:416;packageName:com.jp3.xg3';
|
||||
const aggConfig = {
|
||||
keys: 'd3dGiJc651gSQ8w1',
|
||||
charMap: {
|
||||
'+': 'P', '/': 'X', '0': 'M', '1': 'U', '2': 'l', '3': 'E', '4': 'r', '5': 'Y', '6': 'W', '7': 'b', '8': 'd', '9': 'J',
|
||||
'A': '9', 'B': 's', 'C': 'a', 'D': 'I', 'E': '0', 'F': 'o', 'G': 'y', 'H': '_', 'I': 'H', 'J': 'G', 'K': 'i', 'L': 't',
|
||||
'M': 'g', 'N': 'N', 'O': 'A', 'P': '8', 'Q': 'F', 'R': 'k', 'S': '3', 'T': 'h', 'U': 'f', 'V': 'R', 'W': 'q', 'X': 'C',
|
||||
'Y': '4', 'Z': 'p', 'a': 'm', 'b': 'B', 'c': 'O', 'd': 'u', 'e': 'c', 'f': '6', 'g': 'K', 'h': 'x', 'i': '5', 'j': 'T',
|
||||
'k': '-', 'l': '2', 'm': 'z', 'n': 'S', 'o': 'Z', 'p': '1', 'q': 'V', 'r': 'v', 's': 'j', 't': 'Q', 'u': '7', 'v': 'D',
|
||||
'w': 'w', 'x': 'n', 'y': 'L', 'z': 'e'
|
||||
},
|
||||
headers: {
|
||||
default: { 'User-Agent': 'okhttp/3.12.11', 'content-type': 'application/json; charset=utf-8' }
|
||||
},
|
||||
platform: {
|
||||
百度: { host: 'https://api.jkyai.top', url1: '/API/bddjss.php?name=fyclass&page=fypage', url2: '/API/bddjss.php?id=fyid', search: '/API/bddjss.php?name=**&page=fypage' },
|
||||
锦鲤: { host: 'https://api.jinlidj.com', search: '/api/search', url2: '/api/detail' },
|
||||
番茄: { host: 'https://reading.snssdk.com', url1: '/reading/bookapi/bookmall/cell/change/v', url2: 'https://fqgo.52dns.cc/catalog', search: 'https://fqgo.52dns.cc/search' },
|
||||
星芽: { host: 'https://app.whjzjx.cn', url1: '/cloud/v2/theater/home_page?theater_class_id', url2: '/v2/theater_parent/detail', search: '/v3/search', loginUrl: 'https://u.shytkjgs.com/user/v1/account/login' },
|
||||
西饭: { host: 'https://xifan-api-cn.youlishipin.com', url1: '/xifan/drama/portalPage', url2: '/xifan/drama/getDuanjuInfo', search: '/xifan/search/getSearchList' },
|
||||
软鸭: { host: 'https://api.xingzhige.com', url1: '/API/playlet', search: '/API/playlet' },
|
||||
七猫: { host: 'https://api-store.qmplaylet.com', url1: '/api/v1/playlet/index', url2: 'https://api-read.qmplaylet.com/player/api/v1/playlet/info', search: '/api/v1/playlet/search' },
|
||||
围观: { host: 'https://api.drama.9ddm.com', url1: '/drama/home/shortVideoTags', url2: '/drama/home/shortVideoDetail', search: '/drama/home/search' },
|
||||
甜圈: { host: 'https://mov.cenguigui.cn', url1: '/duanju/api.php?classname', url2: '/duanju/api.php?book_id', search: '/duanju/api.php?name' }
|
||||
},
|
||||
platformList: [
|
||||
{ name: '甜圈短剧', id: '甜圈' }, { name: '七猫短剧', id: '七猫' }, { name: '锦鲤短剧', id: '锦鲤' },
|
||||
{ name: '番茄短剧', id: '番茄' }, { name: '星芽短剧', id: '星芽' }, { name: '西饭短剧', id: '西饭' },
|
||||
{ name: '软鸭短剧', id: '软鸭' }, { name: '百度短剧', id: '百度' }, { name: '围观短剧', id: '围观' }
|
||||
],
|
||||
search: { limit: 30, timeout: 6000 }
|
||||
};
|
||||
|
||||
const ruleFilterDef = {
|
||||
百度: { area: '逆袭' },
|
||||
锦鲤: { area: '' },
|
||||
番茄: { area: 'videoseries_hot' },
|
||||
星芽: { area: '1' },
|
||||
西饭: { area: '' },
|
||||
软鸭: { area: '战神' },
|
||||
七猫: { area: '0' },
|
||||
围观: { area: '' },
|
||||
甜圈: { area: '推荐榜' }
|
||||
};
|
||||
|
||||
const filterOptionsB64 = "eyLnlJzlnIgiOlt7ImtleSI6ImFyZWEiLCJuYW1lIjoi5Ymn5oOFIiwidmFsdWUiOlt7Im4iOiLlhajpg6giLCJ2IjoiIn0seyJuIjoi5o6o6I2Q5qacIiwidiI6IuaOqOiNkOamnCJ9LHsibiI6IueDreaSreamnCIsInYiOiLng63mkq3mppwifSx7Im4iOiLmlrDkuabmppwiLCJ2Ijoi5paw5Lmm5qacIn0seyJuIjoi5a6M57uT5qacIiwidiI6IuWujOe7k+amnCJ9LHsibiI6Iui/nui9veamnCIsInYiOiLov57ovb3mppwifSx7Im4iOiLlhY3otLnmppwiLCJ2Ijoi5YWN6LS55qacIn0seyJuIjoi5paw5YmnIiwidiI6IuaWsOWJpyJ9LHsibiI6IumAhuiirSIsInYiOiLpgIbooq0ifSx7Im4iOiLpnLjmgLsiLCJ2Ijoi6Zy45oC7In0seyJuIjoi546w5Luj6KiA5oOFIiwidiI6IueOsOS7o+iogOaDhSJ9LHsibiI6IuaJk+iEuOiZkOa4oyIsInYiOiLmiZPohLjomZDmuKMifSx7Im4iOiLosarpl6jmganmgKgiLCJ2Ijoi6LGq6Zeo5oGp5oCoIn0seyJuIjoi56We6LGqIiwidiI6IuelnuixqiJ9LHsibiI6IumprOeUsiIsInYiOiLpqaznlLIifSx7Im4iOiLpg73luILml6XluLgiLCJ2Ijoi6YO95biC5pel5bi4In0seyJuIjoi5oiY56We5b2S5p2lIiwidiI6IuaImOelnuW9kuadpSJ9LHsibiI6IuWwj+S6uueJqSIsInYiOiLlsI/kurrniakifSx7Im4iOiLlpbPmgKfmiJDplb8iLCJ2Ijoi5aWz5oCn5oiQ6ZW/In0seyJuIjoi5aSn5aWz5Li7IiwidiI6IuWkp+Wls+S4uyJ9LHsibiI6Iuepv+i2iiIsInYiOiLnqb/otooifSx7Im4iOiLpg73luILkv67ku5kiLCJ2Ijoi6YO95biC5L+u5LuZIn0seyJuIjoi5by66ICF5Zue5b2SIiwidiI6IuW8uuiAheWbnuW9kiJ9LHsibiI6IuS6suaDhSIsInYiOiLkurLmg4UifSx7Im4iOiLlj6Too4UiLCJ2Ijoi5Y+k6KOFIn0seyJuIjoi6YeN55SfIiwidiI6IumHjeeUnyJ9LHsibiI6IumXquWpmiIsInYiOiLpl6rlqZoifSx7Im4iOiLotZjlqb/pgIbooq0iLCJ2Ijoi6LWY5am/6YCG6KKtIn0seyJuIjoi6JmQ5oGLIiwidiI6IuiZkOaBiyJ9LHsibiI6Iui/veWmuyIsInYiOiLov73lprsifSx7Im4iOiLlpKnkuIvml6DmlYwiLCJ2Ijoi5aSp5LiL5peg5pWMIn0seyJuIjoi5a625bqt5Lym55CGIiwidiI6IuWutuW6reS8pueQhiJ9LHsibiI6IuiQjOWunSIsInYiOiLokIzlrp0ifSx7Im4iOiLlj6Tpo47mnYPosIsiLCJ2Ijoi5Y+k6aOO5p2D6LCLIn0seyJuIjoi6IGM5Zy6IiwidiI6IuiBjOWcuiJ9LHsibiI6IuWlh+W5u+iEkea0niIsInYiOiLlpYflubvohJHmtJ4ifSx7Im4iOiLlvILog70iLCJ2Ijoi5byC6IO9In0seyJuIjoi5peg5pWM56We5Yy7IiwidiI6IuaXoOaVjOelnuWMuyJ9LHsibiI6IuWPpOmjjuiogOaDhSIsInYiOiLlj6Tpo47oqIDmg4UifSx7Im4iOiLkvKDmib/op4nphpIiLCJ2Ijoi5Lyg5om/6KeJ6YaSIn0seyJuIjoi546w6KiA55Sc5a6gIiwidiI6IueOsOiogOeUnOWuoCJ9LHsibiI6IuWlh+W5u+eIseaDhSIsInYiOiLlpYflubvniLHmg4UifSx7Im4iOiLkuaHmnZEiLCJ2Ijoi5Lmh5p2RIn0seyJuIjoi5Y6G5Y+y5Y+k5LujIiwidiI6IuWOhuWPsuWPpOS7oyJ9LHsibiI6IueOi+WmgyIsInYiOiLnjovlpoMifSx7Im4iOiLpq5jmiYvkuIvlsbEiLCJ2Ijoi6auY5omL5LiL5bGxIn0seyJuIjoi5aix5LmQ5ZyIIiwidiI6IuWoseS5kOWciCJ9XX1dLCLplKbpsqQiOlt7ImtleSI6ImFyZWEiLCJuYW1lIjoi5YiG57G7IiwidmFsdWUiOlt7Im4iOiLlhajpg6giLCJ2IjoiIn0seyJuIjoi5oOF5oSf5YWz57O7IiwidiI6IjEifSx7Im4iOiLmiJDplb/pgIbooq0iLCJ2IjoiMiJ9LHsibiI6IuWlh+W5u+W8guiDvSIsInYiOiIzIn0seyJuIjoi5oiY5paX54Ot6KGAIiwidiI6IjQifSx7Im4iOiLkvKbnkIbnjrDlrp4iLCJ2IjoiNSJ9LHsibiI6IuaXtuepuuepv+i2iiIsInYiOiI2In0seyJuIjoi5p2D6LCL6Lqr5Lu9IiwidiI6IjcifV19XSwi55Wq6IyEIjpbeyJrZXkiOiJhcmVhIiwibmFtZSI6IuWIhuexuyIsInZhbHVlIjpbeyJuIjoi54Ot5YmnIiwidiI6InZpZGVvc2VyaWVzX2hvdCJ9LHsibiI6IuaWsOWJpyIsInYiOiJmaXJzdG9ubGluZXRpbWVfbmV3In0seyJuIjoi6YCG6KKtIiwidiI6ImNhdGVfNzM5In0seyJuIjoi5oC76KOBIiwidiI6ImNhdGVfMjkifSx7Im4iOiLnjrDoqIAiLCJ2IjoiY2F0ZV8zIn0seyJuIjoi5omT6IS4IiwidiI6ImNhdGVfMTA1MSJ9LHsibiI6IumprOeUsiIsInYiOiJjYXRlXzI2NiJ9LHsibiI6IuixqumXqCIsInYiOiJjYXRlXzEwNTMifSx7Im4iOiLpg73luIIiLCJ2IjoiY2F0ZV8yNjEifSx7Im4iOiLnpZ7osaoiLCJ2IjoiY2F0ZV8yMCJ9XX1dLCLmmJ/oir0iOlt7ImtleSI6ImFyZWEiLCJuYW1lIjoi5YiG57G7IiwidmFsdWUiOlt7Im4iOiLliaflnLoiLCJ2IjoiMSJ9LHsibiI6IueDreaSreWJpyIsInYiOiIyIn0seyJuIjoi5Lya5ZGY5LiT5LqrIiwidiI6IjgifSx7Im4iOiLmmJ/pgInlpb3liaciLCJ2IjoiNyJ9LHsibiI6IuaWsOWJpyIsInYiOiIzIn0seyJuIjoi6Ziz5YWJ5Ymn5Zy6IiwidiI6IjUifV19XSwi6KW/6aWtIjpbeyJrZXkiOiJhcmVhIiwibmFtZSI6IuWIhuexuyIsInZhbHVlIjpbeyJuIjoi5YWo6YOoIiwidiI6IiJ9LHsibiI6IumDveW4giIsInYiOiI2OEDpg73luIIifSx7Im4iOiLpnZLmmKUiLCJ2IjoiNjhA6Z2S5pilIn0seyJuIjoi546w5Luj6KiA5oOFIiwidiI6IjgxQOeOsOS7o+iogOaDhSJ9LHsibiI6IuixqumXqCIsInYiOiI4MUDosarpl6gifSx7Im4iOiLlpKflpbPkuLsiLCJ2IjoiODBA5aSn5aWz5Li7In0seyJuIjoi6YCG6KKtIiwidiI6Ijc5QOmAhuiirSJ9LHsibiI6IuaJk+iEuOiZkOa4oyIsInYiOiI3OUDmiZPohLjomZDmuKMifSx7Im4iOiLnqb/otooiLCJ2IjoiODFA56m/6LaKIn1dfV0sIui9r+m4rSI6W3sia2V5IjoiYXJlYSIsIm5hbWUiOiLliIbnsbsiLCJ2YWx1ZSI6W3sibiI6IuWFqOmDqCIsInYiOiIifSx7Im4iOiLmiJjnpZ4iLCJ2Ijoi5oiY56WeIn0seyJuIjoi6YCG6KKtIiwidiI6IumAhuiirSJ9LHsibiI6IumcuOaAuyIsInYiOiLpnLjmgLsifSx7Im4iOiLnpZ7osaoiLCJ2Ijoi56We6LGqIn0seyJuIjoi6YO95biCIiwidiI6IumDveW4giJ9LHsibiI6IueOhOW5uyIsInYiOiLnjoTlubsifSx7Im4iOiLoqIDmg4UiLCJ2Ijoi6KiA5oOFIn1dfV0sIuS4g+eMqyI6W3sia2V5IjoiYXJlYSIsIm5hbWUiOiLliIbnsbsiLCJ2YWx1ZSI6W3sibiI6IuWFqOmDqCIsInYiOiIifSx7Im4iOiLmjqjojZAiLCJ2IjoiMCJ9LHsibiI6IuaWsOWJpyIsInYiOiItMSJ9LHsibiI6IumDveW4guaDheaEnyIsInYiOiIxMjczIn0seyJuIjoi5Y+k6KOFIiwidiI6IjEyNzIifSx7Im4iOiLpg73luIIiLCJ2IjoiNTcxIn0seyJuIjoi546E5bm75LuZ5L6gIiwidiI6IjEyODYifSx7Im4iOiLlpYflubsiLCJ2IjoiNTcwIn0seyJuIjoi5Lmh5p2RIiwidiI6IjU5MCJ9LHsibiI6IuawkeWbvSIsInYiOiI1NzMifSx7Im4iOiLlubTku6MiLCJ2IjoiNTcyIn0seyJuIjoi6Z2S5pil5qCh5ZutIiwidiI6IjEyODgifSx7Im4iOiLmrabkvqAiLCJ2IjoiMzcxIn0seyJuIjoi56eR5bm7IiwidiI6IjU5NCJ9LHsibiI6Iuacq+S4liIsInYiOiI1NTYifSx7Im4iOiLkuozmrKHlhYMiLCJ2IjoiMTI4OSJ9LHsibiI6IumAhuiirSIsInYiOiI0MDAifSx7Im4iOiLnqb/otooiLCJ2IjoiMzczIn0seyJuIjoi5aSN5LuHIiwidiI6Ijc5NSJ9LHsibiI6Iuezu+e7nyIsInYiOiI3ODcifSx7Im4iOiLmnYPosIsiLCJ2IjoiNzkwIn0seLine truncated
|
||||
|
||||
let xingya_headers = {};
|
||||
function base64Encode(text) {
|
||||
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(text));
|
||||
}
|
||||
function base64Decode(text) {
|
||||
return CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(text));
|
||||
}
|
||||
async function request(url, options = {}) {
|
||||
const { method = 'GET', headers = {}, body, timeout = 5000 } = options;
|
||||
const isPost = method.toUpperCase() === 'POST';
|
||||
let requestBody = body && typeof body === 'object' ? JSON.stringify(body) : body;
|
||||
if (typeof req !== 'undefined') {
|
||||
return (await req(url, {
|
||||
method,
|
||||
headers: { ...aggConfig.headers.default, ...headers },
|
||||
body: isPost ? requestBody : null,
|
||||
timeout
|
||||
})).content;
|
||||
}
|
||||
}
|
||||
async function md5(str) {
|
||||
return CryptoJS.MD5(str).toString(CryptoJS.enc.Hex).toLowerCase();
|
||||
}
|
||||
function guid() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
const r = Math.random() * 16 | 0;
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||
});
|
||||
}
|
||||
function getFilterOptions() {
|
||||
try {
|
||||
return JSON.parse(base64Decode(filterOptionsB64));
|
||||
} catch (e) {
|
||||
console.error('filterOptions 解码失败', e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
async function getQmParamsAndSign() {
|
||||
const sessionId = Date.now().toString();
|
||||
const data = {
|
||||
"static_score": "0.8",
|
||||
"uuid": "00000000-7fc7-08dc-0000-000000000000",
|
||||
"device-id": "20250220125449b9b8cac84c2dd3d035c9052a2572f7dd0122edde3cc42a70",
|
||||
"sourceuid": "aa7de295aad621a6",
|
||||
"refresh-type": "0",
|
||||
"model": "22021211RC",
|
||||
"client-id": "aa7de295aad621a6",
|
||||
"brand": "Redmi",
|
||||
"sys-ver": "12",
|
||||
"phone-level": "H",
|
||||
"wlb-uid": "aa7de295aad621a6",
|
||||
"session-id": sessionId
|
||||
};
|
||||
const jsonStr = JSON.stringify(data);
|
||||
const base64Str = base64Encode(unescape(encodeURIComponent(jsonStr)));
|
||||
let qmParams = '';
|
||||
for (const c of base64Str) {
|
||||
qmParams += aggConfig.charMap[c] || c;
|
||||
}
|
||||
const paramsStr = `AUTHORIZATION=app-version=10001application-id=com.duoduo.readchannel=unknownis-white=net-env=5platform=androidqm-params=${qmParams}reg=${aggConfig.keys}`;
|
||||
const sign = await md5(paramsStr);
|
||||
return { qmParams, sign };
|
||||
}
|
||||
async function getHeaderX() {
|
||||
const { qmParams, sign } = await getQmParamsAndSign();
|
||||
return {
|
||||
'net-env': '5',
|
||||
'reg': '',
|
||||
'channel': 'unknown',
|
||||
'is-white': '',
|
||||
'platform': 'android',
|
||||
'application-id': 'com.duoduo.read',
|
||||
'authorization': '',
|
||||
'app-version': '10001',
|
||||
'user-agent': 'webviewversion/0',
|
||||
'qm-params': qmParams,
|
||||
'sign': sign
|
||||
};
|
||||
}
|
||||
async function init(cfg) {
|
||||
try {
|
||||
const res = JSON.parse(await request(aggConfig.platform.星芽.loginUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'User-Agent': 'okhttp/4.10.0', platform: '1', 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ device: '24250683a3bdb3f118dff25ba4b1cba1a' })
|
||||
}));
|
||||
const token = res?.data?.token || res?.token;
|
||||
xingya_headers = token ? { ...aggConfig.headers.default, authorization: token } : aggConfig.headers.default;
|
||||
} catch (e) {
|
||||
xingya_headers = aggConfig.headers.default;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async function getXingyaHeaders() {
|
||||
return xingya_headers.authorization ? xingya_headers : aggConfig.headers.default;
|
||||
}
|
||||
async function home(filter) {
|
||||
const classes = aggConfig.platformList.map(p => ({ type_name: p.name, type_id: p.id }));
|
||||
const filters = {};
|
||||
const filterOptions = getFilterOptions();
|
||||
aggConfig.platformList.forEach(item => {
|
||||
const platformId = item.id;
|
||||
if (filterOptions[platformId]) {
|
||||
filters[platformId] = filterOptions[platformId];
|
||||
}
|
||||
});
|
||||
return JSON.stringify({ class: classes, filters });
|
||||
}
|
||||
async function homeVod() { return await recommend(); }
|
||||
async function recommend() {
|
||||
const randomPlat = aggConfig.platformList[Math.floor(Math.random() * aggConfig.platformList.length)];
|
||||
const platId = randomPlat.id;
|
||||
const area = ruleFilterDef[platId]?.area || '';
|
||||
const videos = await category(platId, 1, false, { area });
|
||||
const list = JSON.parse(videos).list.slice(0, 10).map(v => ({ ...v, vod_content: `${randomPlat.name} | ${v.vod_remarks}` }));
|
||||
return JSON.stringify({ list });
|
||||
}
|
||||
async function category(tid, pg, filter, extend) {
|
||||
const plat = aggConfig.platform[tid];
|
||||
const area = (extend?.area !== undefined ? extend.area : ruleFilterDef[tid]?.area) || '';
|
||||
const page = parseInt(pg) || 1;
|
||||
const videos = [];
|
||||
if (!plat) return JSON.stringify({ list: videos, page, pagecount: 1, limit: 0, total: 0 });
|
||||
try {
|
||||
if (tid === '七猫') {
|
||||
const sign = await md5(`operation=1playlet_privacy=1tag_id=${area}${aggConfig.keys}`);
|
||||
const url = `${plat.host}${plat.url1}?tag_id=${area}&playlet_privacy=1&operation=1&sign=${sign}`;
|
||||
const res = JSON.parse(await request(url, { headers: { ...await getHeaderX(), ...aggConfig.headers.default } }));
|
||||
(res?.data?.list || []).forEach(i => videos.push({
|
||||
vod_id: `七猫@${encodeURIComponent(i.playlet_id)}`,
|
||||
vod_name: i.title,
|
||||
vod_pic: i.image_link,
|
||||
vod_remarks: `${i.total_episode_num}集`
|
||||
}));
|
||||
} else if (tid === '百度') {
|
||||
const url = `${plat.host}${plat.url1.replace('fyclass', area).replace('fypage', page)}`;
|
||||
const res = JSON.parse(await request(url));
|
||||
if (res?.data) videos.push(...res.data.map(i => ({
|
||||
vod_id: `百度@${i.id}`, vod_name: i.title, vod_pic: i.cover, vod_remarks: `更新至${i.totalChapterNum}集`
|
||||
})));
|
||||
} else if (tid === '锦鲤') {
|
||||
const res = JSON.parse(await request(plat.host + plat.search, { method: 'POST', body: JSON.stringify({ page, limit: 24, type_id: area, keyword: '' }) }));
|
||||
if (res?.data?.list) videos.push(...res.data.list.map(i => ({
|
||||
vod_id: `锦鲤@${i.vod_id}`, vod_name: i.vod_name, vod_pic: i.vod_pic, vod_remarks: `${i.vod_total}集`
|
||||
})));
|
||||
} else if (tid === '番茄') {
|
||||
const sessionId = new Date().toISOString().slice(0, 16).replace(/-|T:/g, '');
|
||||
let url = `${plat.host}${plat.url1}?change_type=0&selected_items=${area}&tab_type=8&cell_id=6952850996422770718&version_tag=video_feed_refactor&device_id=1423244030195267&aid=1967&app_name=novelapp&ssmix=a&session_id=${sessionId}`;
|
||||
if (page > 1) url += `&offset=${(page - 1) * 12}`;
|
||||
const res = JSON.parse(await request(url));
|
||||
const items = res?.data?.cell_view?.cell_data || (Array.isArray(res?.data) ? res.data : []);
|
||||
items.forEach(i => {
|
||||
const v = i.video_data?.[0] || i;
|
||||
videos.push({ vod_id: `番茄@${v.series_id || v.book_id || ''}`, vod_name: v.title, vod_pic: v.cover || v.horiz_cover, vod_remarks: v.sub_title || '' });
|
||||
});
|
||||
} else if (tid === '星芽') {
|
||||
const headers = await getXingyaHeaders();
|
||||
const url = `${plat.host}${plat.url1}=${area}&type=1&class2_ids=0&page_num=${page}&page_size=24`;
|
||||
const res = JSON.parse(await request(url, { headers }));
|
||||
if (res?.data?.list) videos.push(...res.data.list.map(i => ({
|
||||
vod_id: `星芽@${plat.host}${plat.url2}?theater_parent_id=${i.theater.id}`,
|
||||
vod_name: i.theater.title, vod_pic: i.theater.cover_url, vod_remarks: `${i.theater.total}集`
|
||||
})));
|
||||
} else if (tid === '西饭') {
|
||||
const [typeId, typeName] = area.split('@');
|
||||
const ts = Math.floor(Date.now() / 1000);
|
||||
const url = `${plat.host}${plat.url1}?reqType=aggregationPage&offset=${(page - 1) * 30}&categoryId=${typeId}&quickEngineVersion=-1&scene=&categoryNames=${encodeURIComponent(typeName || '')}&categoryVersion=1&density=1.5&pageID=page_theater&version=2001001&androidVersionCode=28&requestId=${ts}aa498144140ef297&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY1ODI5NCIsInVuIjoiT1BHXzFlZGQ5OTZhNjQ3ZTQ1MjU4Nzc1MTE2YzFkNzViN2QwIiwiZnQiOiIxNzQwNjU4Mjk0In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjMzOTY4MTI2MTQ4NjQxNTM2LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjU4Mjk0LCJ1bm0iOiJPUEdfMWVkZDk5NmE2NDdlNDUyNTg3NzUxMTZjMWQ3NWI3ZDAiLCJpZCI6IjNiMzViZmYzYWE0OTgxNDQxNDBlZjI5N2JkMDY5NGNhIiwiZXhwIjoxNzQxMjYzMDk0LCJkYyI6Imd6cXkifQ.JS3QY6ER0P2cQSxAE_OGKSMIWNAMsYUZ3mJTnEpf-Rc`;
|
||||
const res = JSON.parse(await request(url, { headers: aggConfig.headers.default }));
|
||||
const elements = res?.result?.elements || [];
|
||||
elements.forEach(s => (s.contents || []).forEach(v => {
|
||||
const d = v.duanjuVo;
|
||||
if (d) {
|
||||
videos.push({ vod_id: `西饭@${d.duanjuId}#${d.source}`, vod_name: d.title, vod_pic: d.coverImageUrl, vod_remarks: `${d.total}集` });
|
||||
}
|
||||
}));
|
||||
} else if (tid === '软鸭') {
|
||||
const url = `${plat.host}${plat.url1}/?keyword=${encodeURIComponent(area)}&page=${page}`;
|
||||
const res = JSON.parse(await request(url));
|
||||
if (res?.data) videos.push(...res.data.map(i => {
|
||||
const purl = `${i.title}@${i.cover}@${i.author}@${i.type}@${i.desc}@${i.book_id}`;
|
||||
return { vod_id: `软鸭@${encodeURIComponent(purl)}`, vod_name: i.title, vod_pic: i.cover, vod_remarks: i.type };
|
||||
}));
|
||||
} else if (tid === '围观') {
|
||||
const res = JSON.parse(await request(`${plat.host}${plat.search}`, {
|
||||
method: 'POST', body: JSON.stringify({ audience: "全部受众", page, pageSize: 30, searchWord: "", subject: "全部主题" })
|
||||
}));
|
||||
if (res?.data) videos.push(...res.data.map(i => ({
|
||||
vod_id: `围观@${i.oneId}`, vod_name: i.title, vod_pic: i.vertPoster, vod_remarks: `集数:${i.episodeCount} 播放:${i.viewCount}`
|
||||
})));
|
||||
} else if (tid === '甜圈') {
|
||||
const url = `${plat.host}${plat.url1}=${encodeURIComponent(area)}&offset=${page}`;
|
||||
const res = JSON.parse(await request(url));
|
||||
if (res?.data) {
|
||||
videos.push(...res.data.map(i => ({
|
||||
vod_id: `甜圈@${i.book_id}`,
|
||||
vod_name: i.title,
|
||||
vod_pic: i.cover,
|
||||
vod_remarks: `${i.sub_title || ''}`
|
||||
})));
|
||||
}
|
||||
}
|
||||
} catch (e) { }
|
||||
return JSON.stringify({ list: videos, page, pagecount: page + 1, limit: videos.length, total: videos.length * (page + 1) });
|
||||
}
|
||||
async function detail(id) {
|
||||
const [platId, ...rest] = id.split('@');
|
||||
const did = rest.join('@');
|
||||
const plat = aggConfig.platform[platId];
|
||||
if (!plat) return JSON.stringify({ list: [{ vod_id: id, vod_name: '平台不支持', vod_play_url: '' }] });
|
||||
let vod = { vod_id: id, vod_name: '未知', vod_pic: '', vod_remarks: '', vod_content: '', vod_play_from: '', vod_play_url: '' };
|
||||
try {
|
||||
if (platId === '七猫') {
|
||||
const didDecoded = decodeURIComponent(did);
|
||||
const sign = await md5(`playlet_id=${didDecoded}${aggConfig.keys}`);
|
||||
const url = `${plat.url2}?playlet_id=${didDecoded}&sign=${sign}`;
|
||||
const res = JSON.parse(await request(url, { headers: { ...await getHeaderX(), ...aggConfig.headers.default } }));
|
||||
if (res?.data) {
|
||||
const d = res.data;
|
||||
vod = {
|
||||
...vod,
|
||||
vod_name: d.title,
|
||||
vod_pic: d.image_link,
|
||||
vod_remarks: `${d.total_episode_num}集`,
|
||||
vod_content: d.intro,
|
||||
vod_play_from: '七猫短剧',
|
||||
vod_play_url: (d.play_list || []).map(i => `${i.sort}$${i.video_url}`).join('#')
|
||||
};
|
||||
}
|
||||
} else if (platId === '百度') {
|
||||
const res = JSON.parse(await request(`${plat.host}${plat.url2.replace('fyid', did)}`));
|
||||
if (res) vod = { ...vod, vod_name: res.title, vod_pic: res.data?.[0]?.cover, vod_remarks: `更新至:${res.total || 0}集`, vod_play_from: '百度短剧', vod_play_url: (res.data || []).map(i => `${i.title}$${i.video_id}`).join('#') };
|
||||
} else if (platId === '锦鲤') {
|
||||
const res = JSON.parse(await request(`${plat.host}${plat.url2}/${did}`));
|
||||
if (res?.data) {
|
||||
const list = res.data;
|
||||
const urls = list.player ? Object.keys(list.player).map(k => `${k}$${list.player[k]}`) : [];
|
||||
vod = { ...vod, vod_name: list.vod_name, vod_pic: list.vod_pic, vod_remarks: list.vod_remarks, vod_play_from: '锦鲤短剧', vod_play_url: urls.join('#') };
|
||||
}
|
||||
} else if (platId === '番茄') {
|
||||
const res = JSON.parse(await request(`${plat.url2}?book_id=${did}`));
|
||||
if (res?.data) {
|
||||
const b = res.data.book_info;
|
||||
const u = (res.data.item_data_list || []).map(i => `${i.title}$${i.item_id}`).join('#');
|
||||
vod = { ...vod, vod_name: b.book_name, vod_pic: b.thumb_url, vod_remarks: `更新至${res.data.item_data_list?.length}集`, vod_play_from: '番茄短剧', vod_play_url: u };
|
||||
}
|
||||
} else if (platId === '星芽') {
|
||||
const headers = await getXingyaHeaders();
|
||||
const res = JSON.parse(await request(did, { headers }));
|
||||
if (res?.data) {
|
||||
const d = res.data;
|
||||
const u = (d.theaters || []).map(i => `${i.num}$${i.son_video_url}`).join('#');
|
||||
vod = { ...vod, vod_name: d.title, vod_pic: d.cover_url, vod_remarks: d.desc_tags + '', vod_play_from: '星芽短剧', vod_play_url: u };
|
||||
}
|
||||
} else if (platId === '西饭') {
|
||||
const [duanjuId, source] = did.split('#');
|
||||
const url = `${plat.host}${plat.url2}?duanjuId=${duanjuId}&source=${source}`;
|
||||
const res = JSON.parse(await request(url));
|
||||
if (res?.result) {
|
||||
const d = res.result;
|
||||
const u = (d.episodeList || []).map(e => `${e.index}$${e.playUrl}`).join('#');
|
||||
vod = { ...vod, vod_name: d.title, vod_pic: d.coverImageUrl, vod_remarks: d.updateStatus === 'over' ? `${d.total}集 已完结` : `更新${d.total}集`, vod_play_from: '西饭短剧', vod_play_url: u };
|
||||
}
|
||||
} else if (platId === '甜圈') {
|
||||
const url = `${plat.host}${plat.url2}=${did}`;
|
||||
const res = JSON.parse(await request(url));
|
||||
if (res) {
|
||||
const u = (res.data || []).map(item => `${item.title}$${item.video_id}`).join('#');
|
||||
vod = { ...vod, vod_name: res.book_name, vod_pic: res.book_pic, vod_remarks: `${res.duration || ''}`, vod_content: res.desc || '', vod_play_from: '甜圈短剧', vod_play_url: u };
|
||||
}
|
||||
} else if (platId === '软鸭') {
|
||||
const didDecoded = decodeURIComponent(did);
|
||||
const [title, img, author, type, desc, book_id] = didDecoded.split('@');
|
||||
const detailUrl = `${plat.host}${plat.url1}/?book_id=${book_id || did.split('@')[5]}`;
|
||||
const res = JSON.parse(await request(detailUrl, { headers: aggConfig.headers.default }));
|
||||
const u = (res.data?.video_list || []).map(e => `${e.title}$${e.video_id}`).join('#');
|
||||
vod = { ...vod, vod_name: title, vod_pic: img, vod_remarks: type, vod_content: desc, vod_play_from: '软鸭短剧', vod_play_url: u };
|
||||
} else if (platId === '围观') {
|
||||
const res = JSON.parse(await request(`${plat.host}${plat.url2}?oneId=${did}&page=1&pageSize=1000`));
|
||||
if (res?.data?.length) {
|
||||
const d = res.data;
|
||||
vod = { ...vod, vod_name: d[0].title, vod_pic: d[0].vertPoster, vod_remarks: `共${d.length}集`, vod_play_from: '围观短剧', vod_play_url: d.map(e => `${e.title}第${e.playOrder}集$${e.playSetting}`).join('#') };
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) { vod.vod_name = '加载失败'; }
|
||||
return JSON.stringify({ list: [vod] });
|
||||
}
|
||||
async function play(flag, id) {
|
||||
if (/七猫/.test(flag)) {
|
||||
return JSON.stringify({ parse: 0, url: id });
|
||||
}
|
||||
if (/百度/.test(flag)) {
|
||||
const res = JSON.parse(await request(`https://api.jkyai.top/API/bddjss.php?video_id=${id}`));
|
||||
if (res?.data?.qualities) {
|
||||
const order = ["1080p", "sc", "sd"];
|
||||
const qMap = { "1080p": "蓝光", "sc": "超清", "sd": "标清" };
|
||||
const urls = [];
|
||||
order.forEach(k => {
|
||||
const q = res.data.qualities.find(x => x.quality === k);
|
||||
if (q) urls.push(qMap[k], q.download_url);
|
||||
});
|
||||
return JSON.stringify({ parse: 0, url: urls });
|
||||
}
|
||||
}
|
||||
if (/甜圈/.test(flag)) {
|
||||
return JSON.stringify({ parse: 0, url: `https://mov.cenguigui.cn/duanju/api.php?video_id=${id}&type=mp4` });
|
||||
}
|
||||
if (/锦鲤/.test(flag)) {
|
||||
try {
|
||||
const html = await request(`${id}&auto=1`, { headers: { referer: 'https://www.jinlidj.com/' } });
|
||||
const match = html.match(/let data\s*=\s*({[^;]*});/);
|
||||
if (match) {
|
||||
const data = JSON.parse(match[1]);
|
||||
if (data.url) return JSON.stringify({ parse: 0, url: data.url });
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
if (/番茄/.test(flag)) {
|
||||
try {
|
||||
const res = JSON.parse(await request(`https://fqgo.52dns.cc/video?item_ids=${id}`));
|
||||
if (res?.data?.[id]?.video_model) {
|
||||
const model = JSON.parse(res.data[id].video_model);
|
||||
const mainUrl = model?.video_list?.video_1?.main_url;
|
||||
if (mainUrl) return JSON.stringify({ parse: 0, url: base64Decode(mainUrl) });
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
if (/软鸭/.test(flag)) {
|
||||
const response = await request(`${aggConfig.platform.软鸭.host}/API/playlet/?video_id=${id}&quality=1080p`, { headers: aggConfig.headers.default });
|
||||
const res = JSON.parse(response);
|
||||
return JSON.stringify({ parse: 0, url: res.data?.video?.url || '' });
|
||||
}
|
||||
if (/围观/.test(flag)) {
|
||||
try {
|
||||
const ps = typeof id === 'string' ? JSON.parse(id) : id;
|
||||
const urls = [];
|
||||
if (ps?.super) urls.push("超清", ps.super);
|
||||
if (ps?.high) urls.push("高清", ps.high);
|
||||
if (ps?.normal) urls.push("流畅", ps.normal);
|
||||
return JSON.stringify({ parse: 0, url: urls });
|
||||
} catch { return JSON.stringify({ parse: 0, url: id }); }
|
||||
}
|
||||
return JSON.stringify({ parse: 0, url: id });
|
||||
}
|
||||
async function search(wd, quick, pg) {
|
||||
const page = parseInt(pg) || 1;
|
||||
const videos = [];
|
||||
try {
|
||||
const sign = await md5(`operation=2playlet_privacy=1search_word=${wd}${aggConfig.keys}`);
|
||||
const url = `${aggConfig.platform.七猫.host}${aggConfig.platform.七猫.search}?search_word=${encodeURIComponent(wd)}&playlet_privacy=1&operation=2&sign=${sign}`;
|
||||
const res = JSON.parse(await request(url, {
|
||||
headers: { ...await getHeaderX(), ...aggConfig.headers.default },
|
||||
timeout: aggConfig.search.timeout
|
||||
}));
|
||||
(res?.data?.list || []).forEach(i => {
|
||||
if (i.title.toLowerCase().includes(wd.toLowerCase())) {
|
||||
videos.push({
|
||||
vod_id: `七猫@${encodeURIComponent(i.playlet_id)}`,
|
||||
vod_name: i.title,
|
||||
vod_pic: i.image_link,
|
||||
vod_remarks: `七猫短剧|${i.total_episode_num}集`
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch {}
|
||||
const platforms = ['百度', '锦鲤', '番茄', '星芽', '西饭', '软鸭', '围观', '甜圈'];
|
||||
for (const tid of platforms) {
|
||||
const plat = aggConfig.platform[tid];
|
||||
try {
|
||||
let res, data;
|
||||
if (tid === '百度') {
|
||||
res = await request(`${plat.host}${plat.search.replace('**', encodeURIComponent(wd)).replace('fypage', page)}`);
|
||||
data = (JSON.parse(res)?.data || []).map(i => ({ vod_id: `百度@${i.id}`, vod_name: i.title, vod_pic: i.cover, vod_remarks: `百度短剧|更新至${i.totalChapterNum}集` }));
|
||||
} else if (tid === '锦鲤') {
|
||||
res = await request(plat.host + plat.search, { method: 'POST', body: JSON.stringify({ page, limit: 30, keyword: wd }) });
|
||||
data = (JSON.parse(res)?.data?.list || []).map(i => ({ vod_id: `锦鲤@${i.vod_id}`, vod_name: i.vod_name, vod_pic: i.vod_pic, vod_remarks: `锦鲤短剧|${i.vod_total}集` }));
|
||||
} else if (tid === '番茄') {
|
||||
res = await request(`${plat.search}?keyword=${encodeURIComponent(wd)}&page=${page}`);
|
||||
data = (JSON.parse(res)?.data || []).map(i => ({ vod_id: `番茄@${i.series_id}`, vod_name: i.title, vod_pic: i.cover, vod_remarks: `番茄短剧|${i.sub_title}` }));
|
||||
} else if (tid === '星芽') {
|
||||
const headers = await getXingyaHeaders();
|
||||
res = await request(plat.host + plat.search, { method: 'POST', headers, body: JSON.stringify({ text: wd }) });
|
||||
data = (JSON.parse(res)?.data?.theater?.search_data || []).map(i => ({ vod_id: `星芽@${plat.host}${plat.url2}?theater_parent_id=${i.id}`, vod_name: i.title, vod_pic: i.cover_url, vod_remarks: `星芽短剧|${i.total}集 播放:${i.play_amount_str}` }));
|
||||
} else if (tid === '西饭') {
|
||||
const ts = Math.floor(Date.now() / 1000);
|
||||
const url = `${plat.host}${plat.search}?reqType=search&offset=${(page - 1) * 30}&keyword=${encodeURIComponent(wd)}&quickEngineVersion=-1&scene=`;
|
||||
res = await request(url);
|
||||
data = (JSON.parse(res)?.result?.elements || []).map(vod => {
|
||||
const dj = vod.duanjuVo || {};
|
||||
return { vod_id: `西饭@${dj.duanjuId}#${dj.source}`, vod_name: dj.title, vod_pic: dj.coverImageUrl, vod_remarks: `西饭短剧|${dj.total}集` };
|
||||
});
|
||||
} else if (tid === '软鸭') {
|
||||
res = await request(`${plat.host}${plat.search}/?keyword=${encodeURIComponent(wd)}&page=${page}`);
|
||||
data = (JSON.parse(res)?.data || []).map(i => {
|
||||
const purl = `${i.title}@${i.cover}@${i.author}@${i.type}@${i.desc}@${i.book_id}`;
|
||||
return { vod_id: `软鸭@${encodeURIComponent(purl)}`, vod_name: i.title, vod_pic: i.cover, vod_remarks: `软鸭短剧|${i.type}` };
|
||||
});
|
||||
} else if (tid === '围观') {
|
||||
res = await request(`${plat.host}${plat.search}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ audience: "", page, pageSize: 30, searchWord: wd, subject: "" })
|
||||
});
|
||||
data = (JSON.parse(res)?.data || []).map(i => ({ vod_id: `围观@${i.oneId}`, vod_name: i.title, vod_pic: i.vertPoster, vod_remarks: `围观短剧|集数:${i.episodeCount} 播放:${i.viewCount}` }));
|
||||
} else if (tid === '甜圈') {
|
||||
const url = `${plat.host}${plat.search}=${encodeURIComponent(wd)}&offset=${page}`;
|
||||
res = await request(url);
|
||||
data = (JSON.parse(res)?.data || []).map(i => ({
|
||||
vod_id: `甜圈@${i.book_id}`,
|
||||
vod_name: i.title,
|
||||
vod_pic: i.cover,
|
||||
vod_remarks: `甜圈短剧|${i.sub_title || '无简介'}`
|
||||
}));
|
||||
}
|
||||
if (data) videos.push(...data.filter(v => v.vod_name?.toLowerCase().includes(wd.toLowerCase())));
|
||||
} catch {}
|
||||
}
|
||||
return JSON.stringify({
|
||||
list: videos,
|
||||
page,
|
||||
pagecount: page + 1,
|
||||
limit: videos.length,
|
||||
total: videos.length * (page + 1)
|
||||
});
|
||||
}
|
||||
export function __jsEvalReturn() {
|
||||
return { init, home, homeVod, category, detail, play, proxy: null, search };
|
||||
}
|
||||
-552
@@ -1,552 +0,0 @@
|
||||
# coding=utf-8
|
||||
# !/usr/bin/python
|
||||
|
||||
"""
|
||||
|
||||
作者 精彩一瞬间 内容均从互联网收集而来 仅供交流学习使用 严禁用于商业用途 请于24小时内删除
|
||||
====================Diudiumiao====================
|
||||
|
||||
"""
|
||||
|
||||
from Crypto.Util.Padding import unpad
|
||||
from Crypto.Util.Padding import pad
|
||||
from urllib.parse import urlparse
|
||||
from urllib.parse import unquote
|
||||
from Crypto.Cipher import ARC4
|
||||
from urllib.parse import quote
|
||||
from base.spider import Spider
|
||||
from Crypto.Cipher import AES
|
||||
from datetime import datetime
|
||||
from bs4 import BeautifulSoup
|
||||
from base64 import b64decode
|
||||
import concurrent.futures
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import datetime
|
||||
import binascii
|
||||
import requests
|
||||
import hashlib
|
||||
import base64
|
||||
import json
|
||||
import time
|
||||
import hmac
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
sys.path.append('..')
|
||||
|
||||
xurl = "https://www.wasu.cn"
|
||||
|
||||
headerx = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36'
|
||||
}
|
||||
|
||||
headerz = {
|
||||
'accept': '*/*',
|
||||
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'cache-control': 'no-cache',
|
||||
'origin': xurl,
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': xurl,
|
||||
'sec-ch-ua': '"Microsoft Edge";v="143", "Chromium";v="143", "Not A(Brand";v="24"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'cross-site',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0',
|
||||
}
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def getName(self):
|
||||
return "精彩"
|
||||
|
||||
def init(self, extend):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def homeVideoContent(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {}
|
||||
result = {"class": [{"type_id": "961", "type_name": "电影"},
|
||||
{"type_id": "962", "type_name": "剧集"},
|
||||
{"type_id": "963", "type_name": "少儿"},
|
||||
{"type_id": "965", "type_name": "栏目"},
|
||||
{"type_id": "966", "type_name": "新闻"}],
|
||||
"list": [],
|
||||
"filters": {"961": [{"key": "地区",
|
||||
"name": "地区",
|
||||
"value": [{"n": "全部", "v": ""},
|
||||
{"n": "内地", "v": "内地"},
|
||||
{"n": "港台", "v": "港台"},
|
||||
{"n": "欧美", "v": "欧美"},
|
||||
{"n": "日韩", "v": "日韩"},
|
||||
{"n": "泰国", "v": "泰国"},
|
||||
{"n": "其他", "v": "其他"}]},
|
||||
{"key": "类型",
|
||||
"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": "年代",
|
||||
"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"}]}],
|
||||
"962": [{"key": "地区",
|
||||
"name": "地区",
|
||||
"value": [{"n": "全部", "v": ""},
|
||||
{"n": "内地", "v": "内地"},
|
||||
{"n": "港台", "v": "港台"},
|
||||
{"n": "日韩", "v": "日韩"},
|
||||
{"n": "欧美", "v": "欧美"},
|
||||
{"n": "泰国", "v": "泰国"},
|
||||
{"n": "其他", "v": "其他"}]},
|
||||
{"key": "类型",
|
||||
"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": "年代",
|
||||
"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"}]}],
|
||||
"963": [{"key": "地区",
|
||||
"name": "地区",
|
||||
"value": [{"n": "全部", "v": ""},
|
||||
{"n": "内地", "v": "内地"},
|
||||
{"n": "日韩", "v": "日韩"},
|
||||
{"n": "欧美", "v": "欧美"},
|
||||
{"n": "港台", "v": "港台"},
|
||||
{"n": "其他", "v": "其他"}]},
|
||||
{"key": "类型",
|
||||
"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": "年代",
|
||||
"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"}]}],
|
||||
"965": [{"key": "地区",
|
||||
"name": "地区",
|
||||
"value": [{"n": "全部", "v": ""},
|
||||
{"n": "内地", "v": "内地"},
|
||||
{"n": "欧美", "v": "欧美"}]},
|
||||
{"key": "类型",
|
||||
"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": "年代",
|
||||
"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"}]}],
|
||||
"966": [{"key": "类型",
|
||||
"name": "类型",
|
||||
"value": [{"n": "全部", "v": ""},
|
||||
{"n": "国内视野", "v": "国内视野"},
|
||||
{"n": "国际纵览", "v": "国际纵览"},
|
||||
{"n": "军事话题", "v": "军事话题"},
|
||||
{"n": "社会百态", "v": "社会百态"},
|
||||
{"n": "央视频", "v": "央视频"}]}]}}
|
||||
return result
|
||||
|
||||
def generate_x_sign(self, secret_b64):
|
||||
secret_key = self.decode_secret_key(secret_b64)
|
||||
data = self.get_data_string()
|
||||
signature = self.compute_signature(secret_key, data)
|
||||
x_sign = self.encode_signature(signature)
|
||||
return x_sign
|
||||
|
||||
def decode_secret_key(self, secret_b64):
|
||||
return base64.b64decode(secret_b64)
|
||||
|
||||
def get_data_string(self):
|
||||
return "{}"
|
||||
|
||||
def compute_signature(self, secret_key, data):
|
||||
return hmac.new(secret_key, data.encode('utf-8'), hashlib.sha256).digest()
|
||||
|
||||
def encode_signature(self, signature):
|
||||
return base64.b64encode(signature).decode('utf-8')
|
||||
|
||||
def get_current_app_key(self, xurl, headerx):
|
||||
resp = self.fetch_index_page(xurl, headerx)
|
||||
js_path = self.extract_js_path(resp.text)
|
||||
js_url = f"{xurl}{js_path}"
|
||||
js_content = self.fetch_js_content(js_url, headerx)
|
||||
target_key_b64 = self.extract_target_key(js_content)
|
||||
return target_key_b64
|
||||
|
||||
def fetch_index_page(self, xurl, headerx):
|
||||
resp = requests.get(xurl, headers=headerx)
|
||||
resp.raise_for_status()
|
||||
return resp
|
||||
|
||||
def extract_js_path(self, html_content):
|
||||
js_path_pattern = r'src="(/[\d\.]+/assets/js/index-[\w\.-]+\.js)"'
|
||||
match = re.search(js_path_pattern, html_content)
|
||||
return match.group(1)
|
||||
|
||||
def fetch_js_content(self, js_url, headerx):
|
||||
js_resp = requests.get(js_url, headers=headerx)
|
||||
js_resp.raise_for_status()
|
||||
return js_resp.text
|
||||
|
||||
def extract_target_key(self, js_content):
|
||||
key_pattern = r'const \w+="([^"]+)",\w+="([^"]+)",\w+="([^"]+)";'
|
||||
key_match = re.search(key_pattern, js_content)
|
||||
return key_match.group(2)
|
||||
|
||||
def get_headers(self, sign1, xurl):
|
||||
return {
|
||||
'accept': 'application/json, text/plain, */*',
|
||||
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'cache-control': 'no-cache',
|
||||
'launchchannel': 'web_channel',
|
||||
'origin': xurl,
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': xurl,
|
||||
'sec-ch-ua': '"Microsoft Edge";v="143", "Chromium";v="143", "Not A(Brand";v="24"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'cross-site',
|
||||
'siteid': '1000101',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0',
|
||||
'x-sign': sign1,
|
||||
}
|
||||
|
||||
def categoryContent(self, cid, pg, filter, ext):
|
||||
secret_b64 = self.get_current_app_key(xurl, headerx)
|
||||
sign1 = self.generate_x_sign(secret_b64)
|
||||
page = self.get_page_number(pg)
|
||||
NdType, DqType, LxType = self.extract_filter_types(ext)
|
||||
headers = self.get_headers(sign1, xurl)
|
||||
params = self.build_category_params(cid, page, NdType, DqType, LxType)
|
||||
data = self.fetch_category_data(params, headers)
|
||||
videos = self.parse_category_videos(data)
|
||||
return self.build_category_result(videos, pg)
|
||||
|
||||
def get_page_number(self, pg):
|
||||
return int(pg) if pg else 1
|
||||
|
||||
def extract_filter_types(self, ext):
|
||||
NdType = ext.get('年代', '全部')
|
||||
DqType = ext.get('地区', '全部')
|
||||
LxType = ext.get('类型', '全部')
|
||||
return NdType, DqType, LxType
|
||||
|
||||
def build_category_params(self, cid, page, NdType, DqType, LxType):
|
||||
return {'functionName': 'getNewsSearchedByCondition','nodeId': cid,'nodeTag': LxType,'yearTag': NdType,'countryTag': DqType,'orderType': '0','pageSize': '40','page': page,'keyword': '','siteId': '1000101',}
|
||||
|
||||
def fetch_category_data(self, params, headers):
|
||||
detail = requests.get('https://ups.5g.wasu.tv/rmp-user-suggest/1000101/hzhs/searchServlet', params=params,headers=headers)
|
||||
detail.encoding = "utf-8"
|
||||
return detail.json()
|
||||
|
||||
def parse_category_videos(self, data):
|
||||
videos = []
|
||||
for vod in data['data']:
|
||||
videos.append(self.parse_category_video(vod))
|
||||
return videos
|
||||
|
||||
def parse_category_video(self, vod):
|
||||
return {"vod_id": f"{vod['nodeId']}@{vod['newsId']}","vod_name": vod['title'],"vod_pic": vod['hPic'],"vod_year": vod.get('pubTime', '暂无日期'),"vod_remarks": vod.get('episodeDesc', '暂无备注')}
|
||||
|
||||
def build_category_result(self, videos, pg):
|
||||
result = {'list': videos}
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
did = ids[0]
|
||||
secret_b64 = self.get_current_app_key(xurl, headerx)
|
||||
sign1 = self.generate_x_sign(secret_b64)
|
||||
fenge = did.split("@")
|
||||
headers = self.get_headers(sign1, xurl)
|
||||
params = self.build_detail_params(fenge)
|
||||
data = self.fetch_detail_data(params, headers)
|
||||
content = self.build_content(data)
|
||||
director = self.extract_detail_field(data, 'director')
|
||||
actor = self.extract_detail_field(data, 'actor')
|
||||
remarks = self.extract_detail_field(data, 'episodeDesc')
|
||||
year = self.extract_detail_field(data, 'pubTime')
|
||||
area = self.extract_detail_field(data, 'countryTag')
|
||||
bofang = self.build_play_url(data)
|
||||
videos = [self.build_video_data(did, director, actor, remarks, year, area, content, bofang)]
|
||||
return self.build_result(videos)
|
||||
|
||||
def build_detail_params(self, fenge):
|
||||
return {'siteId': '1000101', 'functionName': 'getCurrentNews', 'nodeId': fenge[0], 'newsId': fenge[1],'platform': 'web',}
|
||||
|
||||
def fetch_detail_data(self, params, headers):
|
||||
detail = requests.get('https://mcspapp.5g.wasu.tv/bvradio_app/hzhs/newsServlet', params=params, headers=headers)
|
||||
detail.encoding = "utf-8"
|
||||
return detail.json()
|
||||
|
||||
def build_content(self, data):
|
||||
return '介绍剧情👉' + data.get('data', {}).get('newsAbstract', '')
|
||||
|
||||
def extract_detail_field(self, data, field_name):
|
||||
return data.get('data', {}).get(field_name, '')
|
||||
|
||||
def build_play_url(self, data):
|
||||
bofang = ''
|
||||
for vod in data['data']['vodList']:
|
||||
name = vod['title']
|
||||
if len(vod['fileList']) > 1:
|
||||
id = vod['fileList'][1]['playUrl']
|
||||
else:
|
||||
id = vod['fileList'][0]['playUrl']
|
||||
bofang += name + '$' + id + '#'
|
||||
return bofang[:-1]
|
||||
|
||||
def build_video_data(self, did, director, actor, remarks, year, area, content, bofang):
|
||||
return {"vod_id": did, "vod_director": director, "vod_actor": actor, "vod_remarks": remarks, "vod_year": year, "vod_area": area, "vod_content": content, "vod_play_from": "华数", "vod_play_url": bofang}
|
||||
|
||||
def build_result(self, videos):
|
||||
result = {}
|
||||
result['list'] = videos
|
||||
return result
|
||||
|
||||
def get_x_sign_for_post(self, secret_b64, playUrl):
|
||||
secret_key = self.decode_secret_key(secret_b64)
|
||||
payload_dict = self.build_payload_dict(playUrl)
|
||||
data_string = self.serialize_payload(payload_dict)
|
||||
signature = self.compute_hmac_signature(secret_key, data_string)
|
||||
x_sign = self.encode_signature(signature)
|
||||
return x_sign
|
||||
|
||||
def decode_secret_key(self, secret_b64):
|
||||
return base64.b64decode(secret_b64)
|
||||
|
||||
def build_payload_dict(self, playUrl):
|
||||
return {"playUrl": playUrl, "platform": "web"}
|
||||
|
||||
def serialize_payload(self, payload_dict):
|
||||
return json.dumps(payload_dict, separators=(',', ':'), ensure_ascii=False)
|
||||
|
||||
def compute_hmac_signature(self, secret_key, data_string):
|
||||
return hmac.new(secret_key, data_string.encode('utf-8'), hashlib.sha256).digest()
|
||||
|
||||
def encode_signature(self, signature):
|
||||
return base64.b64encode(signature).decode('utf-8')
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
secret_b64 = self.get_current_app_key(xurl, headerx)
|
||||
id = self.normalize_play_url(id)
|
||||
sign2 = self.get_x_sign_for_post(secret_b64, id)
|
||||
headers = self.get_headers(sign2, xurl)
|
||||
json_data = self.build_request_json(id)
|
||||
result = self.post_play_url_request(headers, json_data)
|
||||
play_url = result['data']['playUrl']
|
||||
return self.build_player_result(play_url)
|
||||
|
||||
def normalize_play_url(self, id):
|
||||
return id.replace('.mp4', '/playlist.m3u8')
|
||||
|
||||
def build_request_json(self, playUrl):
|
||||
return {'playUrl': playUrl, 'platform': 'web', }
|
||||
|
||||
def post_play_url_request(self, headers, json_data):
|
||||
response = requests.post('https://mcspapp.5g.wasu.tv/thirdApiFile/file/getPlayUrl', headers=headers, json=json_data)
|
||||
return response.json()
|
||||
|
||||
def build_player_result(self, play_url):
|
||||
result = {}
|
||||
result["parse"] = 0
|
||||
result["playUrl"] = ''
|
||||
result["url"] = play_url
|
||||
result["header"] = headerz
|
||||
return result
|
||||
|
||||
def searchContentPage(self, key, quick, pg):
|
||||
page = self.get_page_number(pg)
|
||||
secret_b64 = self.get_current_app_key(xurl, headerx)
|
||||
sign1 = self.generate_x_sign(secret_b64)
|
||||
headers = self.get_headers(sign1, xurl)
|
||||
params = self.build_search_params(key, page)
|
||||
data = self.fetch_search_data(params, headers)
|
||||
videos = self.parse_search_videos(data)
|
||||
return self.build_search_result(videos, pg)
|
||||
|
||||
def get_page_number(self, pg):
|
||||
return int(pg) if pg else 1
|
||||
|
||||
def build_search_params(self, key, page):
|
||||
return {'functionName': 'getNewsSearched', 'searchNewsType': '3,4,5', 'keyword': key, 'pageSize': 10, 'page': page, 'siteId': 1000101}
|
||||
|
||||
def fetch_search_data(self, params, headers):
|
||||
detail = requests.get("https://ups.5g.wasu.tv/rmp-user-suggest/1000101/hzhs/searchServlet", params=params, headers=headers)
|
||||
detail.encoding = "utf-8"
|
||||
return detail.json()
|
||||
|
||||
def parse_search_videos(self, data):
|
||||
videos = []
|
||||
for vod in data['data']:
|
||||
videos.append(self.parse_search_video(vod))
|
||||
return videos
|
||||
|
||||
def parse_search_video(self, vod):
|
||||
return {"vod_id": f"{vod['nodeId']}@{vod['newsId']}", "vod_name": vod['title'], "vod_pic": vod['hPic'], "vod_year": vod.get('pubTime', '暂无日期'), "vod_remarks": vod.get('episodeDesc', '暂无备注')}
|
||||
|
||||
def build_search_result(self, videos, pg):
|
||||
result = {'list': videos}
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
return self.searchContentPage(key, quick, '1')
|
||||
|
||||
def localProxy(self, params):
|
||||
if params['type'] == "m3u8":
|
||||
return self.proxyM3u8(params)
|
||||
elif params['type'] == "media":
|
||||
return self.proxyMedia(params)
|
||||
elif params['type'] == "ts":
|
||||
return self.proxyTs(params)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-225
@@ -1,225 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import json
|
||||
import sys
|
||||
import threading
|
||||
import uuid
|
||||
import requests
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
import time
|
||||
from Crypto.Hash import MD5, SHA1
|
||||
|
||||
class Spider(Spider):
|
||||
'''
|
||||
配置示例:
|
||||
{
|
||||
"key": "xxxx",
|
||||
"name": "xxxx",
|
||||
"type": 3,
|
||||
"api": ".所在路径/金牌.py",
|
||||
"searchable": 1,
|
||||
"quickSearch": 1,
|
||||
"filterable": 1,
|
||||
"changeable": 1,
|
||||
"ext": {
|
||||
"site": "https://www.jiabaide.cn,域名2,域名3"
|
||||
}
|
||||
},
|
||||
'''
|
||||
def init(self, extend=""):
|
||||
if extend:
|
||||
hosts=json.loads(extend)['site']
|
||||
self.host = self.host_late(hosts)
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
cdata = self.fetch(f"{self.host}/api/mw-movie/anonymous/get/filer/type", headers=self.getheaders()).json()
|
||||
fdata = self.fetch(f"{self.host}/api/mw-movie/anonymous/v1/get/filer/list", headers=self.getheaders()).json()
|
||||
result = {}
|
||||
classes = []
|
||||
filters={}
|
||||
for k in cdata['data']:
|
||||
classes.append({
|
||||
'type_name': k['typeName'],
|
||||
'type_id': str(k['typeId']),
|
||||
})
|
||||
sort_values = [{"n": "最近更新", "v": "2"},{"n": "人气高低", "v": "3"}, {"n": "评分高低", "v": "4"}]
|
||||
for tid, d in fdata['data'].items():
|
||||
current_sort_values = sort_values.copy()
|
||||
if tid == '1':
|
||||
del current_sort_values[0]
|
||||
filters[tid] = [
|
||||
{"key": "type", "name": "类型",
|
||||
"value": [{"n": i["itemText"], "v": i["itemValue"]} for i in d["typeList"]]},
|
||||
|
||||
*([] if not d["plotList"] else [{"key": "v_class", "name": "剧情",
|
||||
"value": [{"n": i["itemText"], "v": i["itemText"]}
|
||||
for i in d["plotList"]]}]),
|
||||
|
||||
{"key": "area", "name": "地区",
|
||||
"value": [{"n": i["itemText"], "v": i["itemText"]} for i in d["districtList"]]},
|
||||
|
||||
{"key": "year", "name": "年份",
|
||||
"value": [{"n": i["itemText"], "v": i["itemText"]} for i in d["yearList"]]},
|
||||
|
||||
{"key": "lang", "name": "语言",
|
||||
"value": [{"n": i["itemText"], "v": i["itemText"]} for i in d["languageList"]]},
|
||||
|
||||
{"key": "sort", "name": "排序", "value": current_sort_values}
|
||||
]
|
||||
result['class'] = classes
|
||||
result['filters'] = filters
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
data1 = self.fetch(f"{self.host}/api/mw-movie/anonymous/v1/home/all/list", headers=self.getheaders()).json()
|
||||
data2=self.fetch(f"{self.host}/api/mw-movie/anonymous/home/hotSearch",headers=self.getheaders()).json()
|
||||
data=[]
|
||||
for i in data1['data'].values():
|
||||
data.extend(i['list'])
|
||||
data.extend(data2['data'])
|
||||
vods=self.getvod(data)
|
||||
return {'list':vods}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
|
||||
params = {
|
||||
"area": extend.get('area', ''),
|
||||
"filterStatus": "1",
|
||||
"lang": extend.get('lang', ''),
|
||||
"pageNum": pg,
|
||||
"pageSize": "30",
|
||||
"sort": extend.get('sort', '1'),
|
||||
"sortBy": "1",
|
||||
"type": extend.get('type', ''),
|
||||
"type1": tid,
|
||||
"v_class": extend.get('v_class', ''),
|
||||
"year": extend.get('year', '')
|
||||
}
|
||||
data = self.fetch(f"{self.host}/api/mw-movie/anonymous/video/list?{self.js(params)}", headers=self.getheaders(params)).json()
|
||||
result = {}
|
||||
result['list'] = self.getvod(data['data']['list'])
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
data=self.fetch(f"{self.host}/api/mw-movie/anonymous/video/detail?id={ids[0]}",headers=self.getheaders({'id':ids[0]})).json()
|
||||
vod=self.getvod([data['data']])[0]
|
||||
vod['vod_play_from']='拾光有文才'
|
||||
vod['vod_play_url'] = '#'.join(
|
||||
f"{i['name'] if len(vod['episodelist']) > 1 else vod['vod_name']}${ids[0]}@@{i['nid']}" for i in
|
||||
vod['episodelist'])
|
||||
vod.pop('episodelist', None)
|
||||
return {'list':[vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
params = {
|
||||
"keyword": key,
|
||||
"pageNum": pg,
|
||||
"pageSize": "8",
|
||||
"sourceCode": "1"
|
||||
}
|
||||
data=self.fetch(f"{self.host}/api/mw-movie/anonymous/video/searchByWord?{self.js(params)}",headers=self.getheaders(params)).json()
|
||||
vods=self.getvod(data['data']['result']['list'])
|
||||
return {'list':vods,'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
self.header = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.61 Chrome/126.0.6478.61 Not/A)Brand/8 Safari/537.36',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'DNT': '1',
|
||||
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'Origin': self.host,
|
||||
'Referer': f'{self.host}/'
|
||||
}
|
||||
ids=id.split('@@')
|
||||
pdata = self.fetch(f"{self.host}/api/mw-movie/anonymous/v2/video/episode/url?clientType=1&id={ids[0]}&nid={ids[1]}",headers=self.getheaders({'clientType':'1','id': ids[0], 'nid': ids[1]})).json()
|
||||
vlist=[]
|
||||
for i in pdata['data']['list']:vlist.extend([i['resolutionName'],i['url']])
|
||||
return {'parse':0,'url':vlist,'header':self.header}
|
||||
|
||||
def localProxy(self, param):
|
||||
pass
|
||||
|
||||
def host_late(self, url_list):
|
||||
if isinstance(url_list, str):
|
||||
urls = [u.strip() for u in url_list.split(',')]
|
||||
else:
|
||||
urls = url_list
|
||||
if len(urls) <= 1:
|
||||
return urls[0] if urls else ''
|
||||
|
||||
results = {}
|
||||
threads = []
|
||||
|
||||
def test_host(url):
|
||||
try:
|
||||
start_time = time.time()
|
||||
response = requests.head(url, timeout=1.0, allow_redirects=False)
|
||||
delay = (time.time() - start_time) * 1000
|
||||
results[url] = delay
|
||||
except Exception as e:
|
||||
results[url] = float('inf')
|
||||
for url in urls:
|
||||
t = threading.Thread(target=test_host, args=(url,))
|
||||
threads.append(t)
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
return min(results.items(), key=lambda x: x[1])[0]
|
||||
|
||||
def md5(self, sign_key):
|
||||
md5_hash = MD5.new()
|
||||
md5_hash.update(sign_key.encode('utf-8'))
|
||||
md5_result = md5_hash.hexdigest()
|
||||
return md5_result
|
||||
|
||||
def js(self, param):
|
||||
return '&'.join(f"{k}={v}" for k, v in param.items())
|
||||
|
||||
def getheaders(self, param=None):
|
||||
if param is None:param = {}
|
||||
t=str(int(time.time()*1000))
|
||||
param['key']='cb808529bae6b6be45ecfab29a4889bc'
|
||||
param['t']=t
|
||||
sha1_hash = SHA1.new()
|
||||
sha1_hash.update(self.md5(self.js(param)).encode('utf-8'))
|
||||
sign = sha1_hash.hexdigest()
|
||||
deviceid = str(uuid.uuid4())
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.61 Chrome/126.0.6478.61 Not/A)Brand/8 Safari/537.36',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'sign': sign,
|
||||
't': t,
|
||||
'deviceid':deviceid
|
||||
}
|
||||
return headers
|
||||
|
||||
def convert_field_name(self, field):
|
||||
field = field.lower()
|
||||
if field.startswith('vod') and len(field) > 3:
|
||||
field = field.replace('vod', 'vod_')
|
||||
if field.startswith('type') and len(field) > 4:
|
||||
field = field.replace('type', 'type_')
|
||||
return field
|
||||
|
||||
def getvod(self, array):
|
||||
return [{self.convert_field_name(k): v for k, v in item.items()} for item in array]
|
||||
|
||||
-318
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
title: '星辰影院', author: '小可乐/v6.1.1'
|
||||
说明:可以不写ext,也可以写ext,ext支持的参数和格式参数如下
|
||||
"ext": {
|
||||
"host": "xxxx", //站点网址
|
||||
"timeout": 6000, //请求超时,单位毫秒
|
||||
"catesSet": "电视剧&电影&综艺", //指定分类和顺序
|
||||
"tabsSet": "土星&下载线1" //指定线路和顺序
|
||||
}
|
||||
*/
|
||||
|
||||
const MOBILE_UA = 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36';
|
||||
const DefHeader = {'User-Agent': MOBILE_UA};
|
||||
var HOST;
|
||||
var KParams = {
|
||||
headers: {'User-Agent': MOBILE_UA},
|
||||
timeout: 5000
|
||||
};
|
||||
|
||||
async function init(cfg) {
|
||||
try {
|
||||
HOST = (cfg.ext?.host?.trim() || 'https://www.xcyycn.com').replace(/\/$/, '');
|
||||
KParams.headers['Referer'] = HOST;
|
||||
let parseTimeout = parseInt(cfg.ext?.timeout?.trim(), 10);
|
||||
if (parseTimeout > 0) {KParams.timeout = parseTimeout;}
|
||||
KParams.catesSet = cfg.ext?.catesSet?.trim() || '';
|
||||
KParams.tabsSet = cfg.ext?.tabsSet?.trim() || '';
|
||||
KParams.resHtml = await request(HOST);
|
||||
} catch (e) {
|
||||
console.error('初始化参数失败:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
try {
|
||||
let resHtml = KParams.resHtml;
|
||||
if (!resHtml) {throw new Error('源码为空');}
|
||||
let typeArr = cutStr(resHtml, 'hl-nav-item£>', '</li>', '', false, 0, true).filter(flt => flt.includes('/v/'));
|
||||
let classes = typeArr.map((it,idx) => {
|
||||
let cName = cutStr(it, '>', '<', `分类${idx+1}`);
|
||||
let cId = cutStr(it, '/v/', '.', `值${idx+1}`);
|
||||
return {type_name: cName, type_id: cId};
|
||||
});
|
||||
if (KParams.catesSet) {classes = ctSet(classes, KParams.catesSet);}
|
||||
let filters = {};
|
||||
try {
|
||||
const nameObj = {class: 'class,剧情', area: 'area,地区', lang: 'lang,语言', year: 'year,年份', letter: 'letter,字母', by: 'by,排序'};
|
||||
const regObj = {class: /\d+---([^-]+)-/, area: /\/\d+-([^-]+)-/, lang: /\d+----([^-]+)-/, year: /-([^-]+)\./, letter: /\d+-----([^-]+)-/, by: /\d+--([^-]+)-/};
|
||||
let resHtmlList = await Promise.all(
|
||||
classes.map(async (it) => {
|
||||
try {return await request(`${HOST}/vs/${it.type_id}-----------.html`);} catch (sErr) {return '';}
|
||||
})
|
||||
);
|
||||
classes.forEach((it,idx) => {
|
||||
let resfHtml = resHtmlList[idx];
|
||||
if (resfHtml) {
|
||||
let flValArr = cutStr(resfHtml, 'hl-filter-list', '</ul>', '', false, 0, true).slice(1);
|
||||
filters[it.type_id] = Object.entries(nameObj).map(([nObjk, nObjv]) => {
|
||||
let [kkey, kname] = nObjv.split(',');
|
||||
let tgVal = flValArr.find(fv => regObj[kkey].test(fv)) ?? '';
|
||||
if (kkey === 'by') {tgVal = cutStr(resfHtml, 'hl-rb-title', '</div>', '', false);}
|
||||
let tgValArr = cutStr(tgVal, '<a', '/a>', '', false, 0, true);
|
||||
let tValArr = kkey !== 'by' ? tgValArr.slice(1) : tgValArr;
|
||||
let kvalue = tValArr.map(el => {
|
||||
let n = cutStr(el, '>', '<', '空白');
|
||||
let v = n;
|
||||
if (kkey === 'by') {v = el.match(regObj[kkey])?.[1] ?? '';}
|
||||
return {n: n, v: v};
|
||||
});
|
||||
if (kkey !== 'by') {kvalue.unshift({n: '全部', v: ''});}
|
||||
return {key: kkey, name: kname, value: kvalue};
|
||||
}).filter(flt => flt.key && flt.value.length > 1);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
filters = {}
|
||||
}
|
||||
return JSON.stringify({class: classes, filters: filters});
|
||||
} catch (e) {
|
||||
console.error('获取分类失败:', e.message);
|
||||
return JSON.stringify({class: [], filters: {}});
|
||||
}
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
try {
|
||||
let resHtml = KParams.resHtml;
|
||||
let VODS = getVodList(resHtml);
|
||||
return JSON.stringify({list: VODS});
|
||||
} catch (e) {
|
||||
console.error('推荐页获取失败:', e.message);
|
||||
return JSON.stringify({list: []});
|
||||
}
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
try {
|
||||
pg = parseInt(pg, 10), pg = pg > 0 ? pg : 1;
|
||||
let fl = extend || {};
|
||||
let cateUrl = `${HOST}/vs/${fl.cateId || tid}-${fl.area ?? ''}-${fl.by ?? ''}-${fl.class ?? ''}-${fl.lang ?? ''}-${fl.letter ?? ''}---${pg}---${fl.year ?? ''}.html`;
|
||||
let resHtml = await request(cateUrl);
|
||||
let VODS = getVodList(resHtml);
|
||||
let limit = VODS.length;
|
||||
let pagecount = cutStr(resHtml, 'hl-page-total£/', '页', '1');
|
||||
pagecount = Number(pagecount);
|
||||
return JSON.stringify({list: VODS, page: pg, pagecount: pagecount, limit: limit, total: limit*pagecount});
|
||||
} catch (e) {
|
||||
console.error('类别页获取失败:', e.message);
|
||||
return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0});
|
||||
}
|
||||
}
|
||||
|
||||
async function search(wd, quick, pg) {
|
||||
try {
|
||||
pg = parseInt(pg, 10), pg = pg > 0 ? pg : 1;
|
||||
let searchUrl = `${HOST}/s${wd}/page/${pg}.html`;
|
||||
let resHtml = await request(searchUrl);
|
||||
let VODS = getVodList(resHtml);
|
||||
return JSON.stringify({list: VODS, page: pg, pagecount: 10, limit: 30, total: 300});
|
||||
} catch (e) {
|
||||
console.error('搜索页获取失败:', e.message);
|
||||
return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0});
|
||||
}
|
||||
}
|
||||
|
||||
function getVodList(khtml) {
|
||||
try {
|
||||
if (!khtml) {throw new Error('源码为空');}
|
||||
let kvods = [];
|
||||
let listArr = cutStr(khtml, 'hl-lazy', '</a>', '', false, 0, true).filter(flt => flt.includes('remarks'));
|
||||
for (let it of listArr) {
|
||||
let kname = cutStr(it, 'title="', '"', '名称');
|
||||
let kpic = cutStr(it, 'data-original="', '"', '图片');
|
||||
let kremarks = cutStr(it, 'remarks">', '</', '状态');
|
||||
let kid = cutStr(it, 'href="', '"');
|
||||
if (kid) {
|
||||
kvods.push({
|
||||
vod_name: kname,
|
||||
vod_pic: kpic,
|
||||
vod_remarks: kremarks,
|
||||
vod_id: `${kid}@${kname}@${kpic}@${kremarks}`
|
||||
});
|
||||
}
|
||||
}
|
||||
return kvods;
|
||||
} catch (e) {
|
||||
console.error(`生成视频列表失败:`, e.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function detail(ids) {
|
||||
try {
|
||||
let [id, kname, kpic, kremarks] = ids.split('@');
|
||||
let detailUrl = !/^http/.test(id) ? `${HOST}${id}` : id;
|
||||
let resHtml = await request(detailUrl);
|
||||
if (!resHtml) {throw new Error('源码为空');}
|
||||
let intros = cutStr(resHtml, '"clearfix">', '</ul>', '', false);
|
||||
let [ktabs, kurls] = [[], []];
|
||||
let zx_tabs = cutStr(resHtml, '<span class="hl-from', '/span>', '', false, 0, true).map((it,idx) => cutStr(it, '>', '<', `在线${idx+1}`) );
|
||||
ktabs.push(...zx_tabs);
|
||||
let zx_urls = cutStr(resHtml, 'hl-plays-list">', '</ul>', '', false, 0, true).map((item,idx) => cutStr(item, '<li', '</li>', '', false, 0, true).map(it => { return cutStr(it, '>', '</a>', 'noEpi') + '$' + HOST + cutStr(it, 'href="', '"', 'noUrl'); }).join('#') );
|
||||
kurls.push(...zx_urls);
|
||||
let xzArr = cutStr(resHtml, 'hl-downs-list hl', '</ul>', '', false, 0, true);
|
||||
if (xzArr[0]) {
|
||||
xzArr.forEach((item,idx) => {
|
||||
let siglUrl = cutStr(item, 'down_url', '>', '', false, 0, true).map(it => `${cutStr(it, 'file_name="', '"', 'noEpi')}$${cutStr(it, 'value="', '"', 'noUrl')}` ).join('#');
|
||||
ktabs.push(`下载线${idx+1}`);
|
||||
kurls.push(siglUrl);
|
||||
});
|
||||
}
|
||||
if (KParams.tabsSet) {
|
||||
let ktus = ktabs.map((it, idx) => { return {type_name: it, type_value: kurls[idx]} });
|
||||
ktus = ctSet(ktus, KParams.tabsSet);
|
||||
ktabs = ktus.map(it => it.type_name);
|
||||
kurls = ktus.map(it => it.type_value);
|
||||
}
|
||||
let VOD = {
|
||||
vod_id: detailUrl,
|
||||
vod_name: kname,
|
||||
vod_pic: kpic,
|
||||
vod_remarks: kremarks,
|
||||
type_name: cutStr(intros, '类型:', '</li>', '类型'),
|
||||
vod_year: cutStr(intros, '年份:', '</li>', '1000'),
|
||||
vod_area: cutStr(intros, '地区:', '</li>', '地区'),
|
||||
vod_lang: cutStr(intros, '语言:', '</li>', '语言'),
|
||||
vod_director: cutStr(intros, '导演:', '</li>', '导演'),
|
||||
vod_actor: cutStr(intros, '主演:', '</li>', '主演'),
|
||||
vod_content: cutStr(intros, '简介:', '</li>', kname),
|
||||
vod_play_from: ktabs.join('$$$'),
|
||||
vod_play_url: kurls.join('$$$')
|
||||
};
|
||||
return JSON.stringify({list: [VOD]});
|
||||
} catch (e) {
|
||||
console.error('详情页获取失败:', e.message);
|
||||
return JSON.stringify({list: []});
|
||||
}
|
||||
}
|
||||
|
||||
async function play(flag, ids, flags) {
|
||||
try {
|
||||
let kp = 0, kurl = '';
|
||||
if (/下载/.test(flag)) {
|
||||
kurl = ids;
|
||||
} else {
|
||||
let resHtml = await request(ids);
|
||||
let codeObj = safeParseJSON(cutStr(resHtml, 'var player_£=', '<', '', false));
|
||||
kurl = codeObj?.url ?? '';
|
||||
if (!/^http/.test(kurl)) {
|
||||
kurl = ids;
|
||||
kp = 1;
|
||||
}
|
||||
}
|
||||
return JSON.stringify({jx: 0, parse: kp, url: kurl, header: DefHeader});
|
||||
} catch (e) {
|
||||
console.error('播放失败:', e.message);
|
||||
return JSON.stringify({jx: 0, parse: 0, url: '', header: {}});
|
||||
}
|
||||
}
|
||||
|
||||
function ctSet(kArr, setStr) {
|
||||
try {
|
||||
if (!Array.isArray(kArr) || kArr.length === 0 || typeof setStr !== 'string' || !setStr) { throw new Error('第一参数需为非空数组,第二参数需为非空字符串'); }
|
||||
const set_arr = [...kArr];
|
||||
const arrNames = setStr.split('&');
|
||||
const filtered_arr = arrNames.map(item => set_arr.find(it => it.type_name === item)).filter(Boolean);
|
||||
return filtered_arr.length? filtered_arr : [set_arr[0]];
|
||||
} catch (e) {
|
||||
console.error('ctSet 执行异常:', e.message);
|
||||
return kArr;
|
||||
}
|
||||
}
|
||||
|
||||
function safeParseJSON(jStr){
|
||||
try {return JSON.parse(jStr);} catch(e) {return null;}
|
||||
}
|
||||
|
||||
function cutStr(str, prefix = '', suffix = '', defVal = '', clean = true, i = 0, all = false) {
|
||||
try {
|
||||
if (typeof str !== 'string') {throw new Error('被截取对象必须为字符串');}
|
||||
const cleanStr = cs => String(cs).replace(/<[^>]*?>/g, ' ').replace(/( |[\u0020\u00A0\u3000\s])+/g, ' ').trim().replace(/\s+/g, ' ');
|
||||
const esc = s => String(s).replace(/[.*+?${}()|[\]\\/^]/g, '\\$&');
|
||||
let pre = esc(prefix).replace(/£/g, '[^]*?'), end = esc(suffix);
|
||||
const regex = new RegExp(`${pre || '^'}([^]*?)${end || '$'}`, 'g');
|
||||
const matchIter = str.matchAll(regex);
|
||||
if (all) {
|
||||
let matchArr = [...matchIter];
|
||||
if (!matchArr.length) {return [defVal];}
|
||||
return matchArr.map(ela => ela[1] !== undefined ? (clean ? cleanStr(ela[1]) : ela[1]) : defVal);
|
||||
}
|
||||
const idx = parseInt(i, 10);
|
||||
if (isNaN(idx)) {throw new Error('序号必须为整数');}
|
||||
let tgResult, matchIdx = 0;
|
||||
if (idx >= 0) {
|
||||
for (let elt of matchIter) {
|
||||
if (matchIdx++ === idx) {
|
||||
tgResult = elt[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let absI = Math.abs(idx), ringBuf = new Array(absI), ringPtr = 0, ringCnt = 0;
|
||||
for (let elt of matchIter) {
|
||||
ringBuf[ringPtr] = elt[1];
|
||||
ringPtr = (ringPtr + 1) % absI;
|
||||
ringCnt = Math.min(ringCnt + 1, absI);
|
||||
matchIdx++;
|
||||
}
|
||||
tgResult = (matchIdx >= absI && ringCnt > 0) ? ringBuf[ringPtr % ringCnt] : undefined;
|
||||
}
|
||||
return tgResult !== undefined ? (clean ? (cleanStr(tgResult) || defVal) : tgResult) : defVal;
|
||||
} catch (e) {
|
||||
console.error(`字符串截取错误:`, e.message);
|
||||
return all ? ['cutErr'] : 'cutErr';
|
||||
}
|
||||
}
|
||||
|
||||
async function request(reqUrl, options = {}) {
|
||||
try {
|
||||
if (typeof reqUrl !== 'string' || !reqUrl.trim()) { throw new Error('reqUrl需为字符串且非空'); }
|
||||
if (typeof options !== 'object' || Array.isArray(options) || options === null) { throw new Error('options类型需为非null对象'); }
|
||||
options.method = options.method?.toUpperCase() || 'GET';
|
||||
if (['GET', 'HEAD'].includes(options.method)) {
|
||||
delete options.body;
|
||||
delete options.data;
|
||||
delete options.postType;
|
||||
}
|
||||
let {headers, timeout, ...restOpts} = options;
|
||||
const optObj = {
|
||||
headers: (typeof headers === 'object' && !Array.isArray(headers) && headers) ? headers : KParams.headers,
|
||||
timeout: parseInt(timeout, 10) > 0 ? parseInt(timeout, 10) : KParams.timeout,
|
||||
...restOpts
|
||||
};
|
||||
const res = await req(reqUrl, optObj);
|
||||
if (options.withHeaders) {
|
||||
const resHeaders = typeof res.headers === 'object' && !Array.isArray(res.headers) && res.headers ? res.headers : {};
|
||||
const resWithHeaders = { ...resHeaders, body: res?.content ?? '' };
|
||||
return JSON.stringify(resWithHeaders);
|
||||
}
|
||||
return res?.content ?? '';
|
||||
} catch (e) {
|
||||
console.error(`${reqUrl}→请求失败:`, e.message);
|
||||
return options?.withHeaders ? JSON.stringify({ body: '' }) : '';
|
||||
}
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init,
|
||||
home,
|
||||
homeVod,
|
||||
category,
|
||||
search,
|
||||
detail,
|
||||
play,
|
||||
proxy: null
|
||||
};
|
||||
}
|
||||
-250
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
title: '月光影视', author: '小可乐/v5.12.1'
|
||||
说明:可以不写ext,也可以写ext,ext支持的参数和格式参数如下
|
||||
"ext": {
|
||||
"host": "xxxx", //站点网址
|
||||
"timeout": 6000 //请求超时,单位毫秒
|
||||
}
|
||||
*/
|
||||
var HOST;
|
||||
const MOBILE_UA = 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36';
|
||||
const DefHeader = {'User-Agent': MOBILE_UA};
|
||||
const KParams = {
|
||||
headers: {'User-Agent': MOBILE_UA},
|
||||
timeout: 5000
|
||||
};
|
||||
|
||||
async function init(cfg) {
|
||||
try {
|
||||
let host = cfg.ext?.host?.trim() || 'https://www.dzwhs.com';
|
||||
HOST = host.replace(/\/$/, '');
|
||||
KParams.headers['Referer'] = HOST;
|
||||
let parseTimeout = parseInt(cfg.ext?.timeout?.trim(), 10);
|
||||
KParams.timeout = parseTimeout > 0 ? parseTimeout : 5000;
|
||||
KParams.resHtml = await request(HOST);
|
||||
} catch (e) {
|
||||
console.error('初始化参数失败:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
try {
|
||||
let resHtml = KParams.resHtml;
|
||||
if (!resHtml) {throw new Error('源码为空');}
|
||||
let classes = cutStr(resHtml, '/zwhstp', '/a>', '', false, 1, true).map(it => {
|
||||
let cName = cutStr(it, '>', '<', '分类名');
|
||||
let cId = cutStr(it, '/', '.', '分类值');
|
||||
return {type_name: cName, type_id: cId};
|
||||
});
|
||||
let filters = {
|
||||
"1":[
|
||||
{"key":"cateId","name":"类型","value":[{"n":"全部","v":"全部"},{"n":"动作片","v":"6"},{"n":"喜剧片","v":"7"},{"n":"爱情片","v":"8"},{"n":"科幻片","v":"9"},{"n":"恐怖片","v":"10"},{"n":"剧情片","v":"11"},{"n":"战争片","v":"12"},{"n":"纪录片","v":"13"},{"n":"悬疑片","v":"14"},{"n":"犯罪片","v":"15"},{"n":"奇幻片","v":"16"},{"n":"动画片","v":"31"},{"n":"预告片","v":"32"}]}
|
||||
],
|
||||
"2":[
|
||||
{"key":"cateId","name":"类型","value":[{"n":"全部","v":"全部"},{"n":"国产剧","v":"17"},{"n":"港台剧","v":"18"},{"n":"日韩剧","v":"20"},{"n":"欧美剧","v":"21"},{"n":"海外剧","v":"22"}]}
|
||||
],
|
||||
"3":[
|
||||
{"key":"cateId","name":"类型","value":[{"n":"全部","v":"全部"},{"n":"大陆综艺","v":"23"},{"n":"日韩综艺","v":"24"},{"n":"欧美综艺","v":"25"},{"n":"港台综艺","v":"26"}]}
|
||||
],
|
||||
"4":[
|
||||
{"key":"cateId","name":"类型","value":[{"n":"全部","v":"全部"},{"n":"国产动漫","v":"27"},{"n":"日韩动漫","v":"28"},{"n":"欧美动漫","v":"29"},{"n":"其他动漫","v":"30"}]}
|
||||
]
|
||||
};
|
||||
return JSON.stringify({class: classes, filters: filters});
|
||||
} catch (e) {
|
||||
console.error('获取分类失败:', e.message);
|
||||
return JSON.stringify({class: [], filters: {}});
|
||||
}
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
try {
|
||||
let resHtml = KParams.resHtml;
|
||||
let VODS = getVodList(resHtml);
|
||||
return JSON.stringify({list: VODS});
|
||||
} catch (e) {
|
||||
console.error('推荐页获取失败:', e.message);
|
||||
return JSON.stringify({list: []});
|
||||
}
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
try {
|
||||
pg = parseInt(pg, 10);
|
||||
pg = pg > 0 ? pg : 1;
|
||||
let cateUrl = `${HOST}/zwhstp/${extend?.cateId ?? tid}-${pg}.html`;
|
||||
let resHtml = await request(cateUrl);
|
||||
let VODS = getVodList(resHtml);
|
||||
let pagecount = 999;
|
||||
return JSON.stringify({list: VODS, page: pg, pagecount: pagecount, limit: 30, total: 30*pagecount});
|
||||
} catch (e) {
|
||||
console.error('类别页获取失败:', e.message);
|
||||
return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0});
|
||||
}
|
||||
}
|
||||
|
||||
async function search(wd, quick, pg) {
|
||||
try {
|
||||
pg = parseInt(pg, 10);
|
||||
pg = pg > 0 ? pg : 1;
|
||||
let searchUrl = `${HOST}/zwhstp/id.html?wd=${wd}&page=${pg}`;
|
||||
let resHtml = await request(searchUrl);
|
||||
let VODS = getVodList(resHtml);
|
||||
return JSON.stringify({list: VODS, page: pg, pagecount: 10, limit: 30, total: 300});
|
||||
} catch (e) {
|
||||
console.error('搜索页获取失败:', e.message);
|
||||
return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0});
|
||||
}
|
||||
}
|
||||
|
||||
function getVodList(khtml) {
|
||||
try {
|
||||
if (!khtml) {throw new Error('源码为空');}
|
||||
let kvods = [];
|
||||
let listArr = cutStr(khtml, 'lazyload"', '/a>', '', false, 1, true);
|
||||
for (let it of listArr) {
|
||||
let kname = cutStr(it, 'title="', '"', '名称');
|
||||
let kpic = cutStr(it, 'data-original="', '"', '图片');
|
||||
let kremarks = cutStr(it, 'text-right">', '<', '状态');
|
||||
kvods.push({
|
||||
vod_name: kname,
|
||||
vod_pic: kpic,
|
||||
vod_remarks: kremarks,
|
||||
vod_id: `${cutStr(it, 'href="', '"', 'Id')}@${kname}@${kpic}@${kremarks}`
|
||||
});
|
||||
}
|
||||
return kvods;
|
||||
} catch (e) {
|
||||
console.error(`生成视频列表失败:`, e.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function detail(ids) {
|
||||
try {
|
||||
let [id, kname, kpic, kremarks] = ids.split('@');
|
||||
let detailUrl = !/^http/.test(id) ? `${HOST}${id}` : id;
|
||||
let resHtml = await request(detailUrl);
|
||||
if (!resHtml) {throw new Error('源码为空');}
|
||||
let intros = cutStr(resHtml, 'stui-content col-pd', 'play-btn', '', false);
|
||||
let ktabs = cutStr(resHtml, 'pull-right"></span>', '/h3>', '', false, 1, true).map((it,idx) => cutStr(it, 'title">', '<', `线-${idx+1}`));
|
||||
let kurls = cutStr(resHtml, '"stui-content__playlist', '</ul>', '', false, 1, true).map(item => {
|
||||
let kurl = cutStr(item, '<a', '/a>', '', false, 1, true).map(it => { return cutStr(it, '>', '<', 'noEpi') + '$' + cutStr(it, 'href="', '"', 'noUrl'); });
|
||||
return kurl.join('#');
|
||||
});
|
||||
let VOD = {
|
||||
vod_id: detailUrl,
|
||||
vod_name: kname,
|
||||
vod_pic: kpic,
|
||||
type_name: cutStr(intros, '类型:', '<span', '类型'),
|
||||
vod_remarks: kremarks,
|
||||
vod_year: cutStr(intros, '年份:', '</p>', '1000'),
|
||||
vod_area: cutStr(intros, '地区:', '<span', '地区'),
|
||||
vod_lang: '语言',
|
||||
vod_director: cutStr(intros, '导演:', '</p>', '导演'),
|
||||
vod_actor: cutStr(intros, '主演:', '</p>', '主演'),
|
||||
vod_content: cutStr(intros, 'detail-content£>', '</span>', '简介'),
|
||||
vod_play_from: ktabs.join('$$$'),
|
||||
vod_play_url: kurls.join('$$$')
|
||||
};
|
||||
return JSON.stringify({list: [VOD]});
|
||||
} catch (e) {
|
||||
console.error('详情页获取失败:', e.message);
|
||||
return JSON.stringify({list: []});
|
||||
}
|
||||
}
|
||||
|
||||
async function play(flag, ids, flags) {
|
||||
try {
|
||||
let playUrl = !/^http/.test(ids) ? `${HOST}${ids}` : ids;
|
||||
let kp = 0;
|
||||
let resHtml = await request(playUrl);
|
||||
let kcode = safeParseJSON(cutStr(resHtml, 'var player_£=', '<', '', false));
|
||||
let kurl = kcode?.url ?? '';
|
||||
if (!/m3u8|mp4|mkv/.test(kurl)) {
|
||||
kp = 1;
|
||||
kurl = playUrl;
|
||||
}
|
||||
return JSON.stringify({jx: 0, parse: kp, url: kurl, header: DefHeader});
|
||||
} catch (e) {
|
||||
console.error('播放失败:', e.message);
|
||||
return JSON.stringify({jx: 0, parse: 0, url: '', header: {}});
|
||||
}
|
||||
}
|
||||
|
||||
function cutStr(str, prefix = '', suffix = '', defaultVal = 'cutFaile', clean = true, i = 1, all = false) {
|
||||
try {
|
||||
if (!str || typeof str !== 'string') {throw new Error('被截取对象需为非空字符串');}
|
||||
const dealStr = ds => String(ds).replace(/<[^>]*?>/g, ' ').replace(/( |\u00A0|\s)+/g, ' ').trim().replace(/\s+/g, ' ');
|
||||
const esc = s => String(s).replace(/[.*+?${}()|[\]\\/^]/g, '\\$&');
|
||||
let pre = esc(prefix).replace(/£/g, '[^]*?');
|
||||
let end = esc(suffix);
|
||||
let regex = new RegExp(`${pre ? pre : '^'}([^]*?)${end ? end : '$'}`, 'g');
|
||||
let matchArr = [...str.matchAll(regex)];
|
||||
if (all) {
|
||||
return matchArr.map(it => {
|
||||
const val = it[1] ?? defaultVal;
|
||||
return clean && val !== defaultVal ? dealStr(val) : val;
|
||||
});
|
||||
}
|
||||
i = parseInt(i, 10);
|
||||
if (isNaN(i) || i < 1) {throw new Error('序号需为大于0的整数');}
|
||||
i = i - 1;
|
||||
if (i >= matchArr.length) {throw new Error('序号越界');}
|
||||
let result = matchArr[i][1] ?? defaultVal;
|
||||
return clean && result !== defaultVal ? dealStr(result) : result;
|
||||
} catch (e) {
|
||||
console.error(`字符串截取失败:`, e.message);
|
||||
return all ? ['cutErr'] : 'cutErr';
|
||||
}
|
||||
}
|
||||
|
||||
function safeParseJSON(jStr){
|
||||
try {return JSON.parse(jStr);} catch(e) {return null;}
|
||||
}
|
||||
|
||||
async function request(reqUrl, options = {}) {
|
||||
try {
|
||||
if (typeof reqUrl !== 'string' || !reqUrl.trim()) { throw new Error('reqUrl需为字符串且非空'); }
|
||||
if (typeof options !== 'object' || Array.isArray(options) || !options) { throw new Error('options类型需为非null对象'); }
|
||||
options.method = options.method?.toLowerCase() || 'get';
|
||||
if (['get', 'head'].includes(options.method)) {
|
||||
delete options.data;
|
||||
delete options.postType;
|
||||
} else {
|
||||
options.data = options.data ?? '';
|
||||
options.postType = options.postType?.toLowerCase() || 'form';
|
||||
}
|
||||
let {headers, timeout, charset, toBase64 = false, ...restOpts } = options;
|
||||
const optObj = {
|
||||
headers: (typeof headers === 'object' && !Array.isArray(headers) && headers) ? headers : KParams.headers,
|
||||
timeout: parseInt(timeout, 10) > 0 ? parseInt(timeout, 10) : KParams.timeout,
|
||||
charset: charset?.toLowerCase() || 'utf-8',
|
||||
buffer: toBase64 ? 2 : 0,
|
||||
...restOpts
|
||||
};
|
||||
const res = await req(reqUrl, optObj);
|
||||
if (options.withHeaders) {
|
||||
const resHeaders = typeof res.headers === 'object' && !Array.isArray(res.headers) && res.headers ? res.headers : {};
|
||||
const resWithHeaders = { ...resHeaders, body: res?.content ?? '' };
|
||||
return JSON.stringify(resWithHeaders);
|
||||
}
|
||||
return res?.content ?? '';
|
||||
} catch (e) {
|
||||
console.error(`${reqUrl}→请求失败:`, e.message);
|
||||
return options?.withHeaders ? JSON.stringify({ body: '' }) : '';
|
||||
}
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init: init,
|
||||
home: home,
|
||||
homeVod: homeVod,
|
||||
category: category,
|
||||
search: search,
|
||||
detail: detail,
|
||||
play: play,
|
||||
proxy: null
|
||||
};
|
||||
}
|
||||
-429
@@ -1,429 +0,0 @@
|
||||
if (typeof Object.assign !== 'function') {
|
||||
Object.assign = function() {
|
||||
let target = arguments[0];
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
let source = arguments[i];
|
||||
for (let key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
}
|
||||
|
||||
// 通用免嗅探播放
|
||||
let common_lazy = `js:
|
||||
let html = request(input);
|
||||
let hconf = html.match(/r player_.*?=(.*?)</)[1];
|
||||
let json = JSON5.parse(hconf);
|
||||
let url = json.url;
|
||||
if (json.encrypt == '1') {
|
||||
url = unescape(url);
|
||||
} else if (json.encrypt == '2') {
|
||||
url = unescape(base64Decode(url));
|
||||
}
|
||||
if (/\\.(m3u8|mp4|m4a|mp3)/.test(url)) {
|
||||
input = {
|
||||
parse: 0,
|
||||
jx: 0,
|
||||
url: url,
|
||||
};
|
||||
} else {
|
||||
input = url && url.startsWith('http') && tellIsJx(url) ? {parse:0,jx:1,url:url}:input;
|
||||
}`;
|
||||
// 默认嗅探播放
|
||||
|
||||
let def_lazy = `js:
|
||||
input = { parse: 1, url: input, js: '' };`;
|
||||
// 采集站播放
|
||||
|
||||
let cj_lazy = `js:
|
||||
if (/\\.(m3u8|mp4)/.test(input)) {
|
||||
input = { parse: 0, url: input };
|
||||
} else {
|
||||
if (rule.parse_url.startsWith('json:')) {
|
||||
let purl = rule.parse_url.replace('json:', '') + input;
|
||||
let html = request(purl);
|
||||
let json = JSON.parse(html);
|
||||
if (json.url) {
|
||||
input = { parse: 0, url: json.url };
|
||||
}
|
||||
} else {
|
||||
input = rule.parse_url + input;
|
||||
}
|
||||
}`;
|
||||
|
||||
function getMubans() {
|
||||
const mubanDict = { // 模板字典
|
||||
mx: {
|
||||
title: '',
|
||||
host: '',
|
||||
url: '/vodshow/fyclass--------fypage---/',
|
||||
searchUrl: '/vodsearch/**----------fypage---/',
|
||||
class_parse: '.top_nav li;a&&Text;a&&href;.*/(.*?)/',
|
||||
searchable: 2,
|
||||
quickSearch: 0,
|
||||
filterable: 0,
|
||||
headers: {
|
||||
'User-Agent': 'MOBILE_UA',
|
||||
},
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true,
|
||||
推荐: '.cbox_list;*;*;*;*;*',
|
||||
一级: 'ul.vodlist li;a&&title;a&&data-original;.pic_text&&Text;a&&href',
|
||||
二级: {
|
||||
title: 'h2&&Text;.content_detail:eq(1)&&li&&a:eq(2)&&Text',
|
||||
img: '.vodlist_thumb&&data-original',
|
||||
desc: '.content_detail:eq(1)&&li:eq(1)&&Text;.content_detail:eq(1)&&li&&a&&Text;.content_detail:eq(1)&&li&&a:eq(1)&&Text;.content_detail:eq(1)&&li:eq(2)&&Text;.content_detail:eq(1)&&li:eq(3)&&Text',
|
||||
content: '.content_desc&&span&&Text',
|
||||
tabs: '.play_source_tab&&a',
|
||||
lists: '.content_playlist:eq(#id) li',
|
||||
},
|
||||
搜索: '*',
|
||||
},
|
||||
mxpro: {
|
||||
title: '',
|
||||
host: '', // homeUrl:'/',
|
||||
url: '/vodshow/fyclass--------fypage---.html',
|
||||
searchUrl: '/vodsearch/**----------fypage---.html',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
headers: { //网站的请求头,完整支持所有的,常带ua和cookies
|
||||
'User-Agent': 'MOBILE_UA', // "Cookie": "searchneed=ok"
|
||||
},
|
||||
class_parse: '.navbar-items li:gt(0):lt(10);a&&Text;a&&href;/(\\d+)',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true, // 推荐内容是否双层定位
|
||||
推荐: '.tab-list.active;a.module-poster-item.module-item;.module-poster-item-title&&Text;.lazyload&&data-original;.module-item-note&&Text;a&&href',
|
||||
一级: 'body a.module-poster-item.module-item;a&&title;.lazyload&&data-original;.module-item-note&&Text;a&&href',
|
||||
二级: {
|
||||
title: 'h1&&Text;.module-info-tag-link:eq(-1)&&Text',
|
||||
img: '.lazyload&&data-original||data-src||src',
|
||||
desc: '.module-info-item:eq(-2)&&Text;.module-info-tag-link&&Text;.module-info-tag-link:eq(1)&&Text;.module-info-item:eq(2)&&Text;.module-info-item:eq(1)&&Text',
|
||||
content: '.module-info-introduction&&Text',
|
||||
tabs: '.module-tab-item',
|
||||
lists: '.module-play-list:eq(#id) a',
|
||||
tab_text: 'div--small&&Text',
|
||||
},
|
||||
搜索: 'body .module-item;.module-card-item-title&&Text;.lazyload&&data-original;.module-item-note&&Text;a&&href;.module-info-item-content&&Text',
|
||||
},
|
||||
mxone5: {
|
||||
title: '',
|
||||
host: '',
|
||||
url: '/show/fyclass--------fypage---.html',
|
||||
searchUrl: '/search/**----------fypage---.html',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
class_parse: '.nav-menu-items&&li;a&&Text;a&&href;.*/(.*?)\.html',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true, // 推荐内容是否双层定位
|
||||
推荐: '.module-list;.module-items&&.module-item;a&&title;img&&data-src;.module-item-text&&Text;a&&href',
|
||||
一级: '.module-items .module-item;a&&title;img&&data-src;.module-item-text&&Text;a&&href',
|
||||
二级: {
|
||||
title: 'h1&&Text;.tag-link&&Text',
|
||||
img: '.module-item-pic&&img&&data-src',
|
||||
desc: '.video-info-items:eq(3)&&Text;.tag-link:eq(2)&&Text;.tag-link:eq(1)&&Text;.video-info-items:eq(1)&&Text;.video-info-items:eq(0)&&Text',
|
||||
content: '.vod_content&&Text',
|
||||
tabs: '.module-tab-item',
|
||||
lists: '.module-player-list:eq(#id)&&.scroll-content&&a',
|
||||
tab_text: 'div--small&&Text',
|
||||
},
|
||||
搜索: '.module-items .module-search-item;a&&title;img&&data-src;.video-serial&&Text;a&&href',
|
||||
},
|
||||
首图: {
|
||||
title: '',
|
||||
host: '',
|
||||
url: '/vodshow/fyclass--------fypage---/',
|
||||
searchUrl: '/vodsearch/**----------fypage---.html',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
headers: { //网站的请求头,完整支持所有的,常带ua和cookies
|
||||
'User-Agent': 'MOBILE_UA', // "Cookie": "searchneed=ok"
|
||||
},
|
||||
class_parse: '.myui-header__menu li.hidden-sm:gt(0):lt(7);a&&Text;a&&href;/(\\d+).html',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true, // 推荐内容是否双层定位
|
||||
推荐: 'ul.myui-vodlist.clearfix;li;a&&title;a&&data-original;.pic-text&&Text;a&&href',
|
||||
一级: '.myui-vodlist li;a&&title;a&&data-original;.pic-text&&Text;a&&href',
|
||||
二级: {
|
||||
title: '.myui-content__detail .title--span&&Text;.myui-content__detail p.data:eq(3)&&Text',
|
||||
img: '.myui-content__thumb .lazyload&&data-original',
|
||||
desc: '.myui-content__detail p.otherbox&&Text;.year&&Text;.myui-content__detail p.data:eq(4)&&Text;.myui-content__detail p.data:eq(2)&&Text;.myui-content__detail p.data:eq(0)&&Text',
|
||||
content: '.content&&Text',
|
||||
tabs: '.myui-panel__head&&li',
|
||||
// tabs: '.nav-tabs&&li',
|
||||
lists: '.myui-content__list:eq(#id) li',
|
||||
},
|
||||
搜索: '#searchList li;a&&title;.lazyload&&data-original;.pic-text&&Text;a&&href;.detail&&Text',
|
||||
},
|
||||
首图2: {
|
||||
title: '',
|
||||
host: '',
|
||||
url: '/list/fyclass-fypage.html',
|
||||
searchUrl: '/vodsearch/**----------fypage---.html',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
headers: {
|
||||
'User-Agent': 'UC_UA', // "Cookie": ""
|
||||
},
|
||||
class_parse: '.stui-header__menu li:gt(0):lt(7);a&&Text;a&&href;.*/(.*?).html',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true, // 推荐内容是否双层定位
|
||||
推荐: 'ul.stui-vodlist.clearfix;li;a&&title;.lazyload&&data-original;.pic-text&&Text;a&&href',
|
||||
一级: '.stui-vodlist li;a&&title;a&&data-original;.pic-text&&Text;a&&href',
|
||||
二级: {
|
||||
title: '.stui-content__detail .title&&Text;.stui-content__detail&&p:eq(-2)&&a&&Text',
|
||||
title1: '.stui-content__detail .title&&Text;.stui-content__detail&&p&&Text',
|
||||
img: '.stui-content__thumb .lazyload&&data-original',
|
||||
desc: '.stui-content__detail p&&Text;.stui-content__detail&&p:eq(-2)&&a:eq(2)&&Text;.stui-content__detail&&p:eq(-2)&&a:eq(1)&&Text;.stui-content__detail p:eq(2)&&Text;.stui-content__detail p:eq(1)&&Text',
|
||||
desc1: '.stui-content__detail p:eq(4)&&Text;;;.stui-content__detail p:eq(1)&&Text',
|
||||
content: '.detail&&Text',
|
||||
tabs: '.stui-pannel__head h3',
|
||||
tabs1: '.stui-vodlist__head h3',
|
||||
lists: '.stui-content__playlist:eq(#id) li',
|
||||
},
|
||||
搜索: 'ul.stui-vodlist__media,ul.stui-vodlist,#searchList li;a&&title;.lazyload&&data-original;.pic-text&&Text;a&&href;.detail&&Text',
|
||||
},
|
||||
默认: {
|
||||
title: '',
|
||||
host: '',
|
||||
url: '',
|
||||
searchUrl: '',
|
||||
searchable: 2,
|
||||
quickSearch: 0,
|
||||
filterable: 0,
|
||||
filter: '',
|
||||
filter_url: '',
|
||||
filter_def: {},
|
||||
headers: {
|
||||
'User-Agent': 'MOBILE_UA',
|
||||
},
|
||||
timeout: 5000,
|
||||
class_parse: '#side-menu li;a&&Text;a&&href;/(.*?)\.html',
|
||||
cate_exclude: '',
|
||||
play_parse: true,
|
||||
lazy: def_lazy,
|
||||
double: true,
|
||||
推荐: '列表1;列表2;标题;图片;描述;链接;详情',
|
||||
一级: '列表;标题;图片;描述;链接;详情',
|
||||
二级: {
|
||||
title: 'vod_name;vod_type',
|
||||
img: '图片链接',
|
||||
desc: '主要信息;年代;地区;演员;导演',
|
||||
content: '简介',
|
||||
tabs: '',
|
||||
lists: 'xx:eq(#id)&&a',
|
||||
tab_text: 'body&&Text',
|
||||
list_text: 'body&&Text',
|
||||
list_url: 'a&&href',
|
||||
},
|
||||
搜索: '列表;标题;图片;描述;链接;详情',
|
||||
},
|
||||
vfed: {
|
||||
title: '',
|
||||
host: '',
|
||||
url: '/index.php/vod/show/id/fyclass/page/fypage.html',
|
||||
searchUrl: '/index.php/vod/search/page/fypage/wd/**.html',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
headers: {
|
||||
'User-Agent': 'UC_UA',
|
||||
},
|
||||
class_parse: '.fed-pops-navbar&&ul.fed-part-rows&&a;a&&Text;a&&href;.*/(.*?).html',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true, // 推荐内容是否双层定位
|
||||
推荐: 'ul.fed-list-info.fed-part-rows;li;a.fed-list-title&&Text;a&&data-original;.fed-list-remarks&&Text;a&&href',
|
||||
一级: '.fed-list-info&&li;a.fed-list-title&&Text;a&&data-original;.fed-list-remarks&&Text;a&&href',
|
||||
二级: {
|
||||
title: 'h1.fed-part-eone&&Text;.fed-deta-content&&.fed-part-rows&&li&&Text',
|
||||
img: '.fed-list-info&&a&&data-original',
|
||||
desc: '.fed-deta-content&&.fed-part-rows&&li:eq(1)&&Text;.fed-deta-content&&.fed-part-rows&&li:eq(2)&&Text;.fed-deta-content&&.fed-part-rows&&li:eq(3)&&Text',
|
||||
content: '.fed-part-esan&&Text',
|
||||
tabs: '.fed-drop-boxs&&.fed-part-rows&&li',
|
||||
lists: '.fed-play-item:eq(#id)&&ul:eq(1)&&li',
|
||||
},
|
||||
搜索: '.fed-deta-info;h1&&Text;.lazyload&&data-original;.fed-list-remarks&&Text;a&&href;.fed-deta-content&&Text',
|
||||
},
|
||||
海螺3: {
|
||||
title: '',
|
||||
host: '',
|
||||
searchUrl: '/v_search/**----------fypage---.html',
|
||||
url: '/vod_____show/fyclass--------fypage---.html',
|
||||
headers: {
|
||||
'User-Agent': 'MOBILE_UA',
|
||||
},
|
||||
timeout: 5000,
|
||||
class_parse: 'body&&.hl-nav li:gt(0);a&&Text;a&&href;.*/(.*?).html',
|
||||
cate_exclude: '明星|专题|最新|排行',
|
||||
limit: 40,
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
double: true,
|
||||
推荐: '.hl-vod-list;li;a&&title;a&&data-original;.remarks&&Text;a&&href',
|
||||
一级: '.hl-vod-list&&.hl-list-item;a&&title;a&&data-original;.remarks&&Text;a&&href',
|
||||
二级: {
|
||||
title: '.hl-dc-title&&Text;.hl-dc-content&&li:eq(6)&&Text',
|
||||
img: '.hl-lazy&&data-original',
|
||||
desc: '.hl-dc-content&&li:eq(10)&&Text;.hl-dc-content&&li:eq(4)&&Text;.hl-dc-content&&li:eq(5)&&Text;.hl-dc-content&&li:eq(2)&&Text;.hl-dc-content&&li:eq(3)&&Text',
|
||||
content: '.hl-content-text&&Text',
|
||||
tabs: '.hl-tabs&&a',
|
||||
tab_text: 'a--span&&Text',
|
||||
lists: '.hl-plays-list:eq(#id)&&li',
|
||||
},
|
||||
搜索: '.hl-list-item;a&&title;a&&data-original;.remarks&&Text;a&&href',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
},
|
||||
海螺2: {
|
||||
title: '',
|
||||
host: '',
|
||||
searchUrl: '/index.php/vod/search/page/fypage/wd/**/',
|
||||
url: '/index.php/vod/show/id/fyclass/page/fypage/',
|
||||
headers: {
|
||||
'User-Agent': 'MOBILE_UA',
|
||||
},
|
||||
timeout: 5000,
|
||||
class_parse: '#nav-bar li;a&&Text;a&&href;id/(.*?)/',
|
||||
limit: 40,
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
double: true,
|
||||
推荐: '.list-a.size;li;a&&title;.lazy&&data-original;.bt&&Text;a&&href',
|
||||
一级: '.list-a&&li;a&&title;.lazy&&data-original;.list-remarks&&Text;a&&href',
|
||||
二级: {
|
||||
title: 'h2&&Text;.deployment&&Text',
|
||||
img: '.lazy&&data-original',
|
||||
desc: '.deployment&&Text',
|
||||
content: '.ec-show&&Text',
|
||||
tabs: '#tag&&a',
|
||||
lists: '.play_list_box:eq(#id)&&li',
|
||||
},
|
||||
搜索: '.search-list;a&&title;.lazy&&data-original;.deployment&&Text;a&&href',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
},
|
||||
短视: {
|
||||
title: '',
|
||||
host: '', // homeUrl:'/',
|
||||
url: '/channel/fyclass-fypage.html',
|
||||
searchUrl: '/search.html?wd=**',
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 0, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
headers: { //网站的请求头,完整支持所有的,常带ua和cookies
|
||||
'User-Agent': 'MOBILE_UA', // "Cookie": "searchneed=ok"
|
||||
},
|
||||
class_parse: '.menu_bottom ul li;a&&Text;a&&href;.*/(.*?).html',
|
||||
cate_exclude: '解析|动态',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
double: true, // 推荐内容是否双层定位
|
||||
推荐: '.indexShowBox;ul&&li;a&&title;img&&data-src;.s1&&Text;a&&href',
|
||||
一级: '.pic-list&&li;a&&title;img&&data-src;.s1&&Text;a&&href',
|
||||
二级: {
|
||||
title: 'h1&&Text;.content-rt&&p:eq(0)&&Text',
|
||||
img: '.img&&img&&data-src',
|
||||
desc: '.content-rt&&p:eq(1)&&Text;.content-rt&&p:eq(2)&&Text;.content-rt&&p:eq(3)&&Text;.content-rt&&p:eq(4)&&Text;.content-rt&&p:eq(5)&&Text',
|
||||
content: '.zkjj_a&&Text',
|
||||
tabs: '.py-tabs&&option',
|
||||
lists: '.player:eq(#id) li',
|
||||
},
|
||||
搜索: '.sr_lists&&ul&&li;h3&&Text;img&&data-src;.int&&p:eq(0)&&Text;a&&href',
|
||||
},
|
||||
短视2: {
|
||||
title: '',
|
||||
host: '',
|
||||
class_name: '电影&电视剧&综艺&动漫',
|
||||
class_url: '1&2&3&4',
|
||||
searchUrl: '/index.php/ajax/suggest?mid=1&wd=**&limit=50',
|
||||
searchable: 2,
|
||||
quickSearch: 0,
|
||||
headers: {
|
||||
'User-Agent': 'MOBILE_UA'
|
||||
},
|
||||
url: '/index.php/api/vod#type=fyclass&page=fypage',
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
filter_url: '',
|
||||
filter: {},
|
||||
filter_def: {},
|
||||
detailUrl: '/index.php/vod/detail/id/fyid.html',
|
||||
play_parse: true,
|
||||
lazy: common_lazy,
|
||||
limit: 6,
|
||||
推荐: '.list-vod.flex .public-list-box;a&&title;.lazy&&data-original;.public-list-prb&&Text;a&&href',
|
||||
一级: 'js:let body=input.split("#")[1];let t=Math.round(new Date/1e3).toString();let key=md5("DS"+t+"DCC147D11943AF75");let url=input.split("#")[0];body=body+"&time="+t+"&key="+key;print(body);fetch_params.body=body;let html=post(url,fetch_params);let data=JSON.parse(html);VODS=data.list.map(function(it){it.vod_pic=urljoin2(input.split("/i")[0],it.vod_pic);return it});',
|
||||
二级: {
|
||||
title: '.slide-info-title&&Text;.slide-info:eq(2)--strong&&Text',
|
||||
img: '.detail-pic&&data-original',
|
||||
desc: '.slide-info-remarks&&Text;.slide-info-remarks:eq(1)&&Text;.slide-info-remarks:eq(2)&&Text;.slide-info:eq(1)--strong&&Text;.info-parameter&&ul&&li:eq(3)&&Text',
|
||||
content: '#height_limit&&Text',
|
||||
tabs: '.anthology.wow.fadeInUp.animated&&.swiper-wrapper&&a',
|
||||
tab_text: 'a--span&&Text',
|
||||
lists: '.anthology-list-box:eq(#id) li',
|
||||
},
|
||||
搜索: 'json:list;name;pic;;id',
|
||||
},
|
||||
采集1: {
|
||||
title: '',
|
||||
host: '',
|
||||
homeTid: '13',
|
||||
homeUrl: '/api.php/provide/vod/?ac=detail&t={{rule.homeTid}}',
|
||||
detailUrl: '/api.php/provide/vod/?ac=detail&ids=fyid',
|
||||
searchUrl: '/api.php/provide/vod/?wd=**&pg=fypage',
|
||||
url: '/api.php/provide/vod/?ac=detail&pg=fypage&t=fyclass',
|
||||
headers: {
|
||||
'User-Agent': 'MOBILE_UA'
|
||||
},
|
||||
timeout: 5000, // class_name: '电影&电视剧&综艺&动漫',
|
||||
// class_url: '1&2&3&4',
|
||||
// class_parse:'js:let html=request(input);input=JSON.parse(html).class;',
|
||||
class_parse: 'json:class;',
|
||||
limit: 20,
|
||||
multi: 1,
|
||||
searchable: 2, //是否启用全局搜索,
|
||||
quickSearch: 1, //是否启用快速搜索,
|
||||
filterable: 0, //是否启用分类筛选,
|
||||
play_parse: true,
|
||||
parse_url: '',
|
||||
lazy: cj_lazy,
|
||||
推荐: '*',
|
||||
一级: 'json:list;vod_name;vod_pic;vod_remarks;vod_id;vod_play_from',
|
||||
二级: `js:
|
||||
let html=request(input);
|
||||
html=JSON.parse(html);
|
||||
let data=html.list;
|
||||
VOD=data[0];`,
|
||||
搜索: '*',
|
||||
},
|
||||
};
|
||||
return JSON.parse(JSON.stringify(mubanDict));
|
||||
}
|
||||
|
||||
var mubanDict = getMubans();
|
||||
var muban = getMubans();
|
||||
export default {
|
||||
muban,
|
||||
getMubans
|
||||
};
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
let host = 'https://www.ylys.tv';
|
||||
let headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
||||
"Referer": host + "/"
|
||||
};
|
||||
|
||||
async function init(cfg) {}
|
||||
|
||||
/**
|
||||
* 通用解析:不做过滤,不做干扰
|
||||
*/
|
||||
function getList(html) {
|
||||
let videos = [];
|
||||
let items = pdfa(html, ".module-item,.module-card-item");
|
||||
items.forEach(it => {
|
||||
let idMatch = it.match(/detail\/(\d+)/);
|
||||
let nameMatch = it.match(/title="(.*?)"/) || it.match(/<strong>(.*?)<\/strong>/);
|
||||
let picMatch = it.match(/data-original="(.*?)"/) || it.match(/src="(.*?)"/);
|
||||
|
||||
if (idMatch && nameMatch) {
|
||||
let pic = picMatch ? (picMatch[1] || picMatch[2]) : "";
|
||||
videos.push({
|
||||
"vod_id": idMatch[1],
|
||||
"vod_name": nameMatch[1].replace(/<.*?>/g, ""),
|
||||
"vod_pic": pic.startsWith('/') ? host + pic : pic,
|
||||
"vod_remarks": (it.match(/module-item-note">(.*?)<\/div>/) || ["",""])[1].replace(/<.*?>/g, "")
|
||||
});
|
||||
}
|
||||
});
|
||||
return videos;
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
return JSON.stringify({
|
||||
"class": [
|
||||
{"type_id":"1","type_name":"电影"},
|
||||
{"type_id":"2","type_name":"剧集"},
|
||||
{"type_id":"3","type_name":"综艺"},
|
||||
{"type_id":"4","type_name":"动漫"}
|
||||
],
|
||||
"filters": {
|
||||
"1":[{"key":"class","name":"类型","value":[{"n":"全部","v":""},{"n":"动作片","v":"6"},{"n":"喜剧片","v":"7"},{"n":"爱情片","v":"8"},{"n":"科幻片","v":"9"},{"n":"恐怖片","v":"11"}]}],
|
||||
"2":[{"key":"class","name":"类型","value":[{"n":"全部","v":""},{"n":"国产剧","v":"13"},{"n":"港台剧","v":"14"},{"n":"日剧","v":"15"},{"n":"韩剧","v":"33"},{"n":"欧美剧","v":"16"}]}],
|
||||
"3":[{"key":"class","name":"类型","value":[{"n":"全部","v":""},{"n":"内地综艺","v":"27"},{"n":"港台综艺","v":"28"},{"n":"日本综艺","v":"29"},{"n":"韩国综艺","v":"36"}]}],
|
||||
"4":[{"key":"class","name":"类型","value":[{"n":"全部","v":""},{"n":"国产动漫","v":"31"},{"n":"日本动漫","v":"32"},{"n":"欧美动漫","v":"42"},{"n":"其他动漫","v":"43"}]}]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
let resp = await req(host, { headers: 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 + "/vodtype/" + targetId + "/" + (parseInt(p) > 1 ? "page/" + p + "/" : "");
|
||||
let resp = await req(url, { headers: headers });
|
||||
return JSON.stringify({
|
||||
"list": getList(resp.content),
|
||||
"page": parseInt(p)
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
let url = host + '/voddetail/' + id + '/';
|
||||
let resp = await req(url, { headers: headers });
|
||||
let html = resp.content;
|
||||
|
||||
let playFrom = pdfa(html, ".module-tab-item").map(it => (it.match(/<span>(.*?)<\/span>/) || ["","线路"])[1]).join('$$$');
|
||||
let playUrl = pdfa(html, ".module-play-list-content").map(list =>
|
||||
pdfa(list, "a").map(a => {
|
||||
let n = (a.match(/<span>(.*?)<\/span>/) || ["","播放"])[1];
|
||||
let v = a.match(/href="\/play\/(.*?)\/"/);
|
||||
return n + '$' + (v ? v[1] : "");
|
||||
}).join('#')
|
||||
).join('$$$');
|
||||
|
||||
return JSON.stringify({
|
||||
list: [{
|
||||
'vod_id': id,
|
||||
'vod_name': (html.match(/<h1>(.*?)<\/h1>/) || ["", ""])[1],
|
||||
'vod_pic': (html.match(/data-original="(.*?)"/) || ["", ""])[1],
|
||||
'vod_content': (html.match(/introduction-content">.*?<p>(.*?)<\/p>/s) || ["", ""])[1].replace(/<.*?>/g, ""),
|
||||
'vod_play_from': playFrom,
|
||||
'vod_play_url': playUrl
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, quick, pg) {
|
||||
let p = pg || 1;
|
||||
let url = host + "/vodsearch/" + encodeURIComponent(wd) + "-------------/" + (parseInt(p) > 1 ? "page/" + p + "/" : "");
|
||||
let resp = await req(url, { headers: headers });
|
||||
return JSON.stringify({ list: getList(resp.content) });
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
let url = host + "/play/" + id + "/";
|
||||
let resp = await req(url, { headers: headers });
|
||||
let m3u8 = resp.content.match(/"url":"([^"]+\.m3u8)"/);
|
||||
if (m3u8) return JSON.stringify({ parse: 0, url: m3u8[1].replace(/\\/g, ""), header: headers });
|
||||
return JSON.stringify({ parse: 1, url: url, header: headers });
|
||||
}
|
||||
|
||||
export default { init, home, homeVod, category, detail, search, play };
|
||||
-150
@@ -1,150 +0,0 @@
|
||||
const host = 'https://www.haigui.tv';
|
||||
const headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
||||
"Referer": host + "/"
|
||||
};
|
||||
|
||||
async function init(cfg) {}
|
||||
|
||||
const m = (s, r, i = 1) => (s.match(r) || [])[i] || "";
|
||||
const fixPic = p => p && p.startsWith('/') ? host + p : p;
|
||||
|
||||
function getList(html) {
|
||||
return pdfa(html, ".module-item").map(it => {
|
||||
let id = m(it, /href="\/video\/(.*?)\/"/);
|
||||
let name = m(it, /title="(.*?)"/);
|
||||
if (!id || !name) return null;
|
||||
return {
|
||||
vod_id: id,
|
||||
vod_name: name,
|
||||
vod_pic: fixPic(m(it, /data-original="(.*?)"/) || m(it, /src="(.*?)"/)),
|
||||
vod_remarks: m(it, /module-item-note">(.*?)<\/div>/).replace(/<.*?>/g, "")
|
||||
};
|
||||
}).filter(Boolean);
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
const classes = [
|
||||
["dianying","电影"],["dianshiju","电视剧"],["zongyi","综艺"],
|
||||
["dongman","动漫"],["jilupian","纪录片"],["duanju","短剧"]
|
||||
].map(([id,name]) => ({type_id:id,type_name:name}));
|
||||
|
||||
const dict = {
|
||||
area: ["中国大陆","中国香港","中国台湾","美国","韩国","日本","泰国"],
|
||||
year: ["2025","2024","2023","2022","2021","2020"],
|
||||
lang: ["国语","英语","粤语","韩语","日语"]
|
||||
};
|
||||
|
||||
const filters = {};
|
||||
classes.forEach(c => {
|
||||
filters[c.type_id] = [
|
||||
{ key:"class", name:"类型", value:getSubClasses(c.type_id) },
|
||||
...Object.keys(dict).map(k => ({
|
||||
key:k,
|
||||
name:{area:"地区",year:"年份",lang:"语言"}[k],
|
||||
value:[{n:"全部",v:""}].concat(dict[k].map(v=>({n:v,v})))
|
||||
}))
|
||||
];
|
||||
});
|
||||
|
||||
return JSON.stringify({ class: classes, filters });
|
||||
}
|
||||
|
||||
function getSubClasses(tid) {
|
||||
const map = {
|
||||
dianying: [
|
||||
["dongzuopian","动作片"],["xijupian","喜剧片"],
|
||||
["aiqingpian","爱情片"],["kehuanpian","科幻片"],["kongbupian","恐怖片"]
|
||||
],
|
||||
dianshiju: [
|
||||
["guochanju","国产剧"],["gangtaiju","港台剧"],
|
||||
["rihanju","日韩剧"],["oumeiju","欧美剧"]
|
||||
]
|
||||
};
|
||||
return [{n:"全部",v:""}].concat((map[tid]||[]).map(([v,n])=>({n,v})));
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
const r = await req(host,{headers});
|
||||
return JSON.stringify({ list:getList(r.content) });
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend={}) {
|
||||
let p = pg || 1;
|
||||
let id = extend.class || tid;
|
||||
let url = `${host}/filter/${id}`;
|
||||
["area","lang","year"].forEach(k=>{
|
||||
if (extend[k]) url += `/${k}/${encodeURIComponent(extend[k])}`;
|
||||
});
|
||||
url += `/page/${p}/`;
|
||||
const r = await req(url,{headers});
|
||||
return JSON.stringify({ page:p, list:getList(r.content) });
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const r = await req(`${host}/video/${id}/`,{headers});
|
||||
const h = r.content;
|
||||
|
||||
const playFrom = pdfa(h,".module-tab-item")
|
||||
.map(it=>m(it,/<span>(.*?)<\/span>/)||"播放源")
|
||||
.join("$$$");
|
||||
|
||||
const playUrl = pdfa(h,".module-player-list").map(l =>
|
||||
pdfa(l,".module-blocklist a").map(it=>{
|
||||
let pid = m(it,/href=\"\/play\/(.*?)\/\"/);
|
||||
if (!pid) return null;
|
||||
return `${m(it,/<span>(.*?)<\/span>/)||"正片"}$${pid}`;
|
||||
}).filter(Boolean).join("#")
|
||||
).join("$$$");
|
||||
|
||||
return JSON.stringify({
|
||||
list:[{
|
||||
vod_id:id,
|
||||
vod_name:m(h,/page-title\">(.*?)<\/h1>/),
|
||||
vod_pic:fixPic(m(h,/video-cover.*?data-src=\"(.*?)\"/)||m(h,/video-cover.*?src=\"(.*?)\"/)),
|
||||
type_name:(
|
||||
m(h,/tag-link[^>]*>[\s\S]*?icon-cate-[^<]*<\/i>\s*([^<\n]+)/) ||
|
||||
m(h,/icon-cate-[^<]*<\/i>\s*([^<\n]+)/)
|
||||
).trim(),
|
||||
vod_year:m(h,/year\/(\d+)\//),
|
||||
vod_area:m(h,/area\/.*?\/ \">(.*?)\t/s).trim(),
|
||||
vod_director:m(h,/导演:<\/span>.*?<div.*?>(.*?)<\/div>/s).replace(/<.*?>|\//g,"").trim(),
|
||||
vod_actor:m(h,/主演:<\/span>.*?<div.*?>(.*?)<\/div>/s).replace(/<.*?>|\//g,"").trim(),
|
||||
vod_remarks:m(h,/备注:<\/span>.*?<div.*?>(.*?)<\/div>/),
|
||||
vod_content:m(h,/vod_content.*?<span>(.*?)<\/span>/s)||"暂无简介",
|
||||
vod_play_from:playFrom,
|
||||
vod_play_url:playUrl
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, quick, pg=1) {
|
||||
let url = `${host}/search/${encodeURIComponent(wd)}/${pg>1?`page/${pg}/`:""}`;
|
||||
const r = await req(url,{headers});
|
||||
const h = r.content;
|
||||
|
||||
const items = pdfa(h,".module-search-item") || pdfa(h,".module-item");
|
||||
|
||||
const list = items.map(it=>{
|
||||
let id = m(it,/\/video\/(.*?)\//);
|
||||
let name = m(it,/title=\"(.*?)\"/) || m(it,/alt=\"(.*?)\"/);
|
||||
if (!id || !name) return null;
|
||||
return {
|
||||
vod_id:id,
|
||||
vod_name:name,
|
||||
vod_pic:fixPic(m(it,/data-src=\"(.*?)\"/)||m(it,/data-original=\"(.*?)\"/)||m(it,/src=\"(.*?)\"/)),
|
||||
vod_remarks:m(it,/module-item-note\">(.*?)<\/div>/)||m(it,/video-serial\">(.*?)<\/span>/)
|
||||
};
|
||||
}).filter(Boolean);
|
||||
|
||||
return JSON.stringify({ page:pg, list });
|
||||
}
|
||||
|
||||
async function play(flag, id, flags) {
|
||||
const r = await req(`${host}/play/${id}/`,{headers});
|
||||
let u = m(r.content,/"url":"([^"]+\.m3u8[^"]*)"/);
|
||||
if (u) return JSON.stringify({ parse:0, url:u.replace(/\\/g,""), header:headers });
|
||||
return JSON.stringify({ parse:1, url:`${host}/play/${id}/`, header:headers });
|
||||
}
|
||||
|
||||
export default { init, home, homeVod, category, detail, search, play };
|
||||
-360
@@ -1,360 +0,0 @@
|
||||
/*
|
||||
title: '爱看机器人', author: '小可乐/v6.1.2'
|
||||
说明:可以不写ext,也可以写ext,ext支持的参数和格式参数如下
|
||||
"ext": {
|
||||
"host": "xxxx", //站点网址
|
||||
"timeout": 6000, //请求超时,单位毫秒
|
||||
"tabsSet": "线路2&线路1" //指定线路和顺序
|
||||
"tabsDeal": "量子&非凡@天堂>360#极速<新浪@优质>>优质无广&暴风>>暴风无广" //线路处理,优先级低于tabsSet,功能依次为"删除@排序@改名",功能用@分隔,优先级从高到低,排序中的#号表示反向排序从此开始,不理解自己试试就明白了
|
||||
}
|
||||
*/
|
||||
|
||||
const MOBILE_UA = 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36';
|
||||
const DefHeader = {'User-Agent': MOBILE_UA};
|
||||
var HOST;
|
||||
var KParams = {
|
||||
headers: {'User-Agent': MOBILE_UA},
|
||||
timeout: 8000,
|
||||
};
|
||||
|
||||
async function init(cfg) {
|
||||
try {
|
||||
HOST = (cfg.ext?.host?.trim() || 'https://v.aikanbot.com').replace(/\/$/, '');
|
||||
KParams.headers['Referer'] = HOST;
|
||||
let parseTimeout = parseInt(cfg.ext?.timeout?.trim(), 10);
|
||||
if (parseTimeout > 0) {KParams.timeout = parseTimeout;}
|
||||
KParams.tabsSet = cfg.ext?.tabsSet?.trim() || '';
|
||||
KParams.tabsDeal = cfg.ext?.tabsDeal?.trim() || '';
|
||||
} catch (e) {
|
||||
console.error('初始化参数失败:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function home(filter) {
|
||||
try {
|
||||
let kclassName = '电影$movie&剧集$tv&榜单$billboard';
|
||||
let classes = kclassName.split('&').map(it => {
|
||||
let [cName, cId] = it.split('$');
|
||||
return {type_name: cName, type_id: cId};
|
||||
});
|
||||
let filters = {
|
||||
"movie": [
|
||||
{"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": "豆瓣top250","v": "豆瓣top250"}]}
|
||||
],
|
||||
"tv": [
|
||||
{"key": "class","name": "剧情","value": [{"n": "热门","v": "热门"}, {"n": "美剧","v": "美剧"}, {"n": "英剧","v": "英剧"}, {"n": "韩剧","v": "韩剧"}, {"n": "日剧","v": "日剧"}, {"n": "国产剧","v": "国产剧"}, {"n": "港剧","v": "港剧"}, {"n": "日本动画","v": "日本动画"}, {"n": "综艺","v": "综艺"}, {"n": "纪录片","v": "纪录片"}]}
|
||||
]
|
||||
};
|
||||
return JSON.stringify({class: classes, filters: filters});
|
||||
} catch (e) {
|
||||
console.error('获取分类失败:', e.message);
|
||||
return JSON.stringify({class: [], filters: {}});
|
||||
}
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
try {
|
||||
let resHtml = await request(HOST);
|
||||
let VODS = getVodList(resHtml);
|
||||
return JSON.stringify({list: VODS});
|
||||
} catch (e) {
|
||||
console.error('推荐页获取失败:', e.message);
|
||||
return JSON.stringify({list: []});
|
||||
}
|
||||
}
|
||||
|
||||
async function category(tid, pg, filter, extend) {
|
||||
try {
|
||||
pg = parseInt(pg, 10), pg = pg > 0 ? pg : 1;
|
||||
let fl = extend || {};
|
||||
let suffix = pg === 1 ? '' : `-p-${pg}`;
|
||||
let cateUrl = tid === 'billboard' ? `${HOST}/billboard.html` : `${HOST}/hot/index-${tid}-${fl.class || '热门'}${suffix}.html`;
|
||||
let resHtml = await request(cateUrl);
|
||||
let VODS = getVodList(resHtml);
|
||||
let limit = VODS.length;
|
||||
let hasMore = cutStr(resHtml, 'page-more">', '</div>').includes('下一页');
|
||||
let pagecount = hasMore ? pg + 1 : pg;
|
||||
return JSON.stringify({list: VODS, page: pg, pagecount: pagecount, limit: limit, total: limit*pagecount});
|
||||
} catch (e) {
|
||||
console.error('类别页获取失败:', e.message);
|
||||
return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0});
|
||||
}
|
||||
}
|
||||
|
||||
async function search(wd, quick, pg) {
|
||||
try {
|
||||
pg = parseInt(pg, 10), pg = pg > 0 ? pg : 1;
|
||||
let suffix = pg === 1 ? '' : `&p=${pg}`;
|
||||
let searchUrl = `${HOST}/search?q=${wd}${suffix}`;
|
||||
let resHtml = await request(searchUrl);
|
||||
let VODS = getVodList(resHtml, true);
|
||||
return JSON.stringify({list: VODS, page: pg, pagecount: 10, limit: 30, total: 300});
|
||||
} catch (e) {
|
||||
console.error('搜索页获取失败:', e.message);
|
||||
return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0});
|
||||
}
|
||||
}
|
||||
|
||||
function getVodList(khtml, sch = false) {
|
||||
try {
|
||||
if (!khtml) {throw new Error('源码为空');}
|
||||
let kvods = [];
|
||||
let listArr = sch ? cutStr(khtml, 'media">', '</h5>', '', false, 0, true) : cutStr(khtml, '<a', '/a>', '', false, 0, true).filter(flt => flt.includes('alt='));
|
||||
let picProxy = 'https://img-p.aikanbot.com/proxy?url=';
|
||||
for (let it of listArr) {
|
||||
let kname = sch ? cutStr(it, 'title-text">', '<', '名称') : cutStr(it, 'alt="', '"', '名称');
|
||||
let kpic = `${picProxy}${cutStr(it, 'data-src="', '"', '图片')}`;
|
||||
let kremarks = sch ? cutStr(it, '[', ']', '状态') : '无状态';
|
||||
let kid = cutStr(it, 'href="', '"');
|
||||
if (kid) {
|
||||
kvods.push({
|
||||
vod_name: kname,
|
||||
vod_pic: kpic,
|
||||
vod_remarks: kremarks,
|
||||
vod_id: `${kid}@${kname}@${kpic}@${kremarks}`
|
||||
});
|
||||
}
|
||||
}
|
||||
return kvods;
|
||||
} catch (e) {
|
||||
console.error(`生成视频列表失败:`, e.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function detail(ids) {
|
||||
try {
|
||||
let [id, kname, kpic, kremarks] = ids.split('@');
|
||||
let detailUrl = !/^http/.test(id) ? `${HOST}${id}` : id;
|
||||
let resHtml = await request(detailUrl);
|
||||
if (!resHtml) {throw new Error('源码为空');}
|
||||
const tabName = {"dyttm3u8":"天堂","360zy":"360","iqym3u8":"爱奇艺","mtm3u8":"茅台","subm3u8":"速播","nnm3u8":"牛牛","okm3u8":"欧克","tym3u8":"TY","yym3u8":"歪歪","bfzym3u8":"暴风","1080zyk":"优质","kuaikan":"快看","lzm3u8":"量子","ffm3u8":"非凡","snm3u8":"索尼","qhm3u8":"奇虎","hym3u8":"虎牙","haiwaikan":"海外看","gsm3u8":"光速","zuidam3u8":"最大","bjm3u8":"八戒","wolong":"卧龙","xlm3u8":"新浪","yhm3u8":"樱花","tkm3u8":"天空","jsm3u8":"极速","wjm3u8":"无尽","sdm3u8":"闪电","kcm3u8":"快车","jinyingm3u8":"金鹰","fsm3u8":"飞速","tpm3u8":"淘片","lem3u8":"鱼乐","dbm3u8":"百度","tomm3u8":"番茄","ukm3u8":"优酷","ikm3u8":"爱坤","hnzym3u8":"红牛资源","hnm3u8":"红牛","68zy_m3u8":"六八","kdm3u8":"酷点","bdxm3u8":"北斗星","hhm3u8":"豪华","kbm3u8":"快播","mzm3u8":"MZ"};
|
||||
let [kdirector='', kactors=''] = cutStr(resHtml, '<h3£>', '</h3>', '', true, -1).split('/');
|
||||
let kid= cutStr(resHtml, 'current_id"£"', '"');
|
||||
let eToken= cutStr(resHtml, 'e_token"£"', '"');
|
||||
const getToken = (curtId, eToken) => {
|
||||
if (!curtId || !eToken || !/^\d+$/.test(curtId)) {return '';}
|
||||
let remainEToken = eToken;
|
||||
let finalToken = curtId.slice(-4).split('').map(it => {
|
||||
let startPos = (parseInt(it, 10) % 3) + 1;
|
||||
let endPos = startPos + 8;
|
||||
if (startPos >= remainEToken.length) {return '';}
|
||||
let segment = remainEToken.substring(startPos, endPos);
|
||||
remainEToken = remainEToken.substring(endPos);
|
||||
return segment;
|
||||
}).filter(Boolean).join('');
|
||||
return finalToken;
|
||||
};
|
||||
let token = getToken(kid, eToken);
|
||||
let detailUrl2 = `${HOST}/api/getResN?videoId=${kid}&mtype=2&token=${token}`;
|
||||
let resObj = safeParseJSON(await request(detailUrl2));
|
||||
let resList = resObj?.data?.list ?? [];
|
||||
let [ktabs, kurls] = [[], []];
|
||||
resList.forEach((item, idx) => {
|
||||
let resData = safeParseJSON(item.resData.replace(/#{2,}/g, '#'))?.[0] ?? {};
|
||||
let tab = resData?.flag || `线路${idx+1}`;
|
||||
ktabs.push(tabName[tab] || tab);
|
||||
kurls.push(resData?.url || 'noUrl');
|
||||
});
|
||||
ktabs = dealSameEle(ktabs);
|
||||
if (KParams.tabsSet || KParams.tabsDeal) {
|
||||
let ktus = ktabs.map((it, idx) => { return {type_name: it, type_value: kurls[idx]} });
|
||||
if (KParams.tabsSet) {
|
||||
ktus = ctSet(ktus, KParams.tabsSet);
|
||||
}
|
||||
if (KParams.tabsDeal) {
|
||||
let [x = '', y = '', z = ''] = KParams.tabsDeal.split('@');
|
||||
let tab_remove = ['','&'].includes(x.trim()) ? '' : x.trim();
|
||||
let tab_order = ['','#'].includes(y.trim()) ? '' : y.trim();
|
||||
let tab_rename = ['','&'].includes(z.trim()) ? '' : z.trim();
|
||||
ktus = dorDeal(ktus, tab_remove, tab_order, tab_rename);
|
||||
}
|
||||
ktabs = ktus.map(it => it.type_name);
|
||||
kurls = ktus.map(it => it.type_value);
|
||||
}
|
||||
let VOD = {
|
||||
vod_id: kid,
|
||||
vod_name: kname,
|
||||
vod_pic: kpic,
|
||||
vod_remarks: kremarks,
|
||||
type_name: '类型',
|
||||
vod_year: cutStr(resHtml, '<h3£>', '</h3>', '1000', true, -3),
|
||||
vod_area: cutStr(resHtml, '<h3£>', '</h3>', '地区', true, -2),
|
||||
vod_lang: '语言',
|
||||
vod_director: kdirector || '导演',
|
||||
vod_actor: kactors || '主演',
|
||||
vod_content: cutStr(resHtml, 'description" content="', '">', kname),
|
||||
vod_play_from: ktabs.join('$$$'),
|
||||
vod_play_url: kurls.join('$$$')
|
||||
};
|
||||
return JSON.stringify({list: [VOD]});
|
||||
} catch (e) {
|
||||
console.error('详情页获取失败:', e.message);
|
||||
return JSON.stringify({list: []});
|
||||
}
|
||||
}
|
||||
|
||||
async function play(flag, ids, flags) {
|
||||
try {
|
||||
let kp = /\.(m3u8|mp4|mkv)/.test(ids) ? 0 : 1;
|
||||
return JSON.stringify({jx: 0, parse: kp, url: ids, header: DefHeader});
|
||||
} catch (e) {
|
||||
console.error('播放失败:', e.message);
|
||||
return JSON.stringify({jx: 0, parse: 0, url: '', header: {}});
|
||||
}
|
||||
}
|
||||
|
||||
function dealSameEle(arr) {
|
||||
try {
|
||||
if (!Array.isArray(arr)) {throw new Error('输入参数非数组');}
|
||||
const countMap = new Map();
|
||||
let newArr = arr.map(item => {
|
||||
let count = countMap.get(item) || 0;
|
||||
let currentCount = count + 1;
|
||||
countMap.set(item, currentCount);
|
||||
return currentCount > 1 ? `${item}${currentCount}` : item;
|
||||
});
|
||||
return newArr;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function ctSet(kArr, setStr) {
|
||||
try {
|
||||
if (!Array.isArray(kArr) || kArr.length === 0 || typeof setStr !== 'string' || !setStr) { throw new Error('第一参数需为非空数组,第二参数需为非空字符串'); }
|
||||
const set_arr = [...kArr];
|
||||
const arrNames = setStr.split('&');
|
||||
const filtered_arr = arrNames.map(item => set_arr.find(it => it.type_name === item)).filter(Boolean);
|
||||
return filtered_arr.length? filtered_arr : [set_arr[0]];
|
||||
} catch (e) {
|
||||
console.error('ctSet 执行异常:', e.message);
|
||||
return kArr;
|
||||
}
|
||||
}
|
||||
|
||||
function dorDeal(kArr, strRemove, strOrder, strRename) {
|
||||
let dealed_arr = [...kArr];
|
||||
if (strRemove) {
|
||||
try {
|
||||
let removeArr = strRemove.split('&');
|
||||
const removeSet = new Set(removeArr);
|
||||
let filtered_arr = dealed_arr.filter(it => !removeSet.has(it.type_name));
|
||||
let retained_arr = filtered_arr.length ? filtered_arr : [dealed_arr[0]];
|
||||
dealed_arr = retained_arr;
|
||||
} catch (e) {
|
||||
console.error('删除失败:', e.message);
|
||||
}
|
||||
}
|
||||
if (strOrder) {
|
||||
try {
|
||||
let [a = '', b = ''] = strOrder.split('#', 2);
|
||||
let arrA = a.split('>').filter(Boolean);
|
||||
let arrB = b.split('<').filter(Boolean);
|
||||
let uqArrB = arrB.filter(it => !arrA.includes(it));
|
||||
let twMap = new Map();
|
||||
arrA.forEach((item, idx) => {twMap.set(item, { weight: 1, index: idx }); });
|
||||
uqArrB.forEach((item, idx) => {twMap.set(item, { weight: 3, index: idx }); });
|
||||
dealed_arr.forEach((it, idx) => { if (!twMap.has(it.type_name)) {twMap.set(it.type_name, { weight: 2, index: idx });} });
|
||||
let ordered_arr = [...dealed_arr].sort((a, b) => {
|
||||
let { weight: ta = 2, index: idxA = 0 } = twMap.get(a.type_name) ?? {};
|
||||
let { weight: tb = 2, index: idxB = 0 } = twMap.get(b.type_name) ?? {};
|
||||
if (ta !== tb) {return ta - tb;}
|
||||
return ta === 3 ? idxB - idxA : idxA - idxB;
|
||||
});
|
||||
dealed_arr = ordered_arr;
|
||||
} catch (e) {
|
||||
console.error('排序失败:', e.message);
|
||||
}
|
||||
}
|
||||
if (strRename) {
|
||||
try {
|
||||
const objRename = strRename.split('&').reduce((obj, p) => {
|
||||
let [k = '', v = ''] = p.split('>>', 2);
|
||||
if (k + v) {obj[k] = v;}
|
||||
return obj;
|
||||
}, {});
|
||||
let renamed_arr = dealed_arr.map(it => { return { ...it, type_name: objRename[it.type_name] || it.type_name } });
|
||||
dealed_arr = renamed_arr;
|
||||
} catch (e) {
|
||||
console.error('改名失败:', e.message);
|
||||
}
|
||||
}
|
||||
return dealed_arr;
|
||||
}
|
||||
|
||||
function safeParseJSON(jStr){
|
||||
try {return JSON.parse(jStr);} catch(e) {return null;}
|
||||
}
|
||||
|
||||
function cutStr(str, prefix = '', suffix = '', defVal = '', clean = true, i = 0, all = false) {
|
||||
try {
|
||||
if (typeof str !== 'string') {throw new Error('被截取对象必须为字符串');}
|
||||
const cleanStr = cs => String(cs).replace(/<[^>]*?>/g, ' ').replace(/( |[\u0020\u00A0\u3000\s])+/g, ' ').trim().replace(/\s+/g, ' ');
|
||||
const esc = s => String(s).replace(/[.*+?${}()|[\]\\/^]/g, '\\$&');
|
||||
let pre = esc(prefix).replace(/£/g, '[^]*?'), end = esc(suffix);
|
||||
const regex = new RegExp(`${pre || '^'}([^]*?)${end || '$'}`, 'g');
|
||||
const matchIter = str.matchAll(regex);
|
||||
if (all) {
|
||||
const matchArr = [...matchIter];
|
||||
return matchArr.length ? matchArr.map(ela => ela[1] !== undefined ? (clean ? (cleanStr(ela[1]) || defVal) : ela[1]) : defVal ) : [defVal];
|
||||
}
|
||||
const idx = parseInt(i, 10);
|
||||
if (isNaN(idx)) {throw new Error('序号必须为整数');}
|
||||
let tgResult, matchIdx = 0;
|
||||
if (idx >= 0) {
|
||||
for (let elt of matchIter) {
|
||||
if (matchIdx++ === idx) {tgResult = elt[1]; break;}
|
||||
}
|
||||
} else {
|
||||
const matchArr = [...matchIter];
|
||||
tgResult = matchArr.length ? matchArr[matchArr.length + idx]?.[1] : undefined;
|
||||
}
|
||||
return tgResult !== undefined ? (clean ? (cleanStr(tgResult) || defVal) : tgResult) : defVal;
|
||||
} catch (e) {
|
||||
console.error(`字符串截取错误:`, e.message);
|
||||
return all ? ['cutErr'] : 'cutErr';
|
||||
}
|
||||
}
|
||||
|
||||
async function request(reqUrl, options = {}) {
|
||||
try {
|
||||
if (typeof reqUrl !== 'string' || !reqUrl.trim()) { throw new Error('reqUrl需为字符串且非空'); }
|
||||
if (typeof options !== 'object' || Array.isArray(options) || options === null) { throw new Error('options类型需为非null对象'); }
|
||||
options.method = options.method?.toUpperCase() || 'GET';
|
||||
if (['GET', 'HEAD'].includes(options.method)) {
|
||||
delete options.body;
|
||||
delete options.data;
|
||||
delete options.postType;
|
||||
}
|
||||
let {headers, timeout, ...restOpts} = options;
|
||||
const optObj = {
|
||||
headers: (typeof headers === 'object' && !Array.isArray(headers) && headers) ? headers : KParams.headers,
|
||||
timeout: parseInt(timeout, 10) > 0 ? parseInt(timeout, 10) : KParams.timeout,
|
||||
...restOpts
|
||||
};
|
||||
const res = await req(reqUrl, optObj);
|
||||
if (options.withHeaders) {
|
||||
const resHeaders = typeof res.headers === 'object' && !Array.isArray(res.headers) && res.headers ? res.headers : {};
|
||||
const resWithHeaders = { ...resHeaders, body: res?.content ?? '' };
|
||||
return JSON.stringify(resWithHeaders);
|
||||
}
|
||||
return res?.content ?? '';
|
||||
} catch (e) {
|
||||
console.error(`${reqUrl}→请求失败:`, e.message);
|
||||
return options?.withHeaders ? JSON.stringify({ body: '' }) : '';
|
||||
}
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return {
|
||||
init,
|
||||
home,
|
||||
homeVod,
|
||||
category,
|
||||
search,
|
||||
detail,
|
||||
play,
|
||||
proxy: null
|
||||
};
|
||||
}
|
||||
-169
@@ -1,169 +0,0 @@
|
||||
import 'assets://js/lib/crypto-js.js';
|
||||
const { HOSTS, KEY, USER_AGENT } = {
|
||||
HOSTS: ["https://hnytxj.com","https://www.hkybqufgh.com","https://www.sizhengxt.com","https://www.sdzhgt.com","https://www.jiabaide.cn","https://m.9zhoukj.com","https://m.cqzuoer.com","https://www.hellosht52bwb.com"],
|
||||
KEY: "cb808529bae6b6be45ecfab29a4889bc",
|
||||
USER_AGENT: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.61 Safari/537.36"
|
||||
};
|
||||
let currentHost = '';
|
||||
const guid = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
const r = Math.random() * 16 | 0;
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||
});
|
||||
const md5 = s => CryptoJS.MD5(s).toString();
|
||||
const sha1 = s => CryptoJS.SHA1(s).toString();
|
||||
const toQueryString = obj => Object.keys(obj).filter(k => obj[k] != null && obj[k] !== '').map(k => `${k}=${obj[k]}`).join('&');
|
||||
const getHeaders = (params = {}) => {
|
||||
const t = Date.now().toString();
|
||||
const sign = sha1(md5(toQueryString({ ...params, key: KEY, t })));
|
||||
return {
|
||||
'User-Agent': USER_AGENT,
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'sign': sign,
|
||||
't': t,
|
||||
'deviceid': guid()
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeFieldName = k => {
|
||||
const l = k.toLowerCase();
|
||||
if (l.startsWith('vod') && l.length > 3) return 'vod_' + l.slice(3);
|
||||
if (l.startsWith('type') && l.length > 4) return 'type_' + l.slice(4);
|
||||
return l;
|
||||
};
|
||||
|
||||
const normalizeVodList = list => (list || []).map(item => {
|
||||
const res = {};
|
||||
for (const [k, v] of Object.entries(item || {})) if (v != null) res[normalizeFieldName(k)] = v;
|
||||
return res;
|
||||
});
|
||||
|
||||
async function reqSafe(url, options = {}) {
|
||||
try {
|
||||
const res = await req(url, options);
|
||||
return JSON.parse(res.content);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
async function init() {
|
||||
currentHost = HOSTS[Math.floor(Math.random() * HOSTS.length)];
|
||||
return true;
|
||||
}
|
||||
|
||||
async function home() {
|
||||
const [cRes, fRes] = await Promise.all([
|
||||
reqSafe(`${currentHost}/api/mw-movie/anonymous/get/filer/type`, { headers: getHeaders() }),
|
||||
reqSafe(`${currentHost}/api/mw-movie/anonymous/v1/get/filer/list`, { headers: getHeaders() })
|
||||
]);
|
||||
|
||||
const classes = (cRes.data || []).map(k => ({ type_name: k.typeName, type_id: k.typeId.toString() }));
|
||||
const fData = fRes.data || {};
|
||||
const baseSort = [{ n: "最近更新", v: "2" }, { n: "人气高低", v: "3" }, { n: "评分高低", v: "4" }];
|
||||
const filters = {};
|
||||
for (const [tid, d] of Object.entries(fData)) {
|
||||
const sortValues = tid === '1' ? baseSort.slice(1) : baseSort;
|
||||
const arr = [
|
||||
{ key: "type", name: "类型", value: (d.typeList || []).map(i => ({ n: i.itemText, v: i.itemValue })) },
|
||||
{ key: "area", name: "地区", value: (d.districtList || []).map(i => ({ n: i.itemText, v: i.itemText })) },
|
||||
{ key: "year", name: "年份", value: (d.yearList || []).map(i => ({ n: i.itemText, v: i.itemText })) },
|
||||
{ key: "lang", name: "语言", value: (d.languageList || []).map(i => ({ n: i.itemText, v: i.itemText })) },
|
||||
{ key: "sort", name: "排序", value: sortValues }
|
||||
];
|
||||
if (d.plotList?.length) arr.splice(1, 0, { key: "v_class", name: "剧情", value: d.plotList.map(i => ({ n: i.itemText, v: i.itemText })) });
|
||||
filters[tid] = arr;
|
||||
}
|
||||
return JSON.stringify({ class: classes, filters });
|
||||
}
|
||||
|
||||
async function homeVod() {
|
||||
const [r1, r2] = await Promise.all([
|
||||
reqSafe(`${currentHost}/api/mw-movie/anonymous/v1/home/all/list`, { headers: getHeaders() }),
|
||||
reqSafe(`${currentHost}/api/mw-movie/anonymous/home/hotSearch`, { headers: getHeaders() })
|
||||
]);
|
||||
let list = [];
|
||||
const data1 = r1.data || {};
|
||||
for (const k in data1) if (data1[k]?.list) list.push(...data1[k].list);
|
||||
if (Array.isArray(r2.data)) list.push(...r2.data);
|
||||
return JSON.stringify({ list: normalizeVodList(list) });
|
||||
}
|
||||
|
||||
async function category(tid, pg, _, ext = {}) {
|
||||
const params = {
|
||||
area: ext.area || '',
|
||||
filterStatus: "1",
|
||||
lang: ext.lang || '',
|
||||
pageNum: pg,
|
||||
pageSize: "30",
|
||||
sort: ext.sort || '1',
|
||||
sortBy: "1",
|
||||
type: ext.type || '',
|
||||
type1: tid,
|
||||
v_class: ext.v_class || '',
|
||||
year: ext.year || ''
|
||||
};
|
||||
|
||||
const url = `${currentHost}/api/mw-movie/anonymous/video/list?${toQueryString(params)}`;
|
||||
const res = await reqSafe(url, { headers: getHeaders(params) });
|
||||
const vodList = normalizeVodList(res.data?.list || []);
|
||||
return JSON.stringify({
|
||||
list: vodList,
|
||||
page: +pg,
|
||||
pagecount: 9999,
|
||||
limit: 90,
|
||||
total: 999999
|
||||
});
|
||||
}
|
||||
|
||||
async function detail(id) {
|
||||
const res = await reqSafe(`${currentHost}/api/mw-movie/anonymous/video/detail?id=${id}`, {
|
||||
headers: getHeaders({ id })
|
||||
});
|
||||
const vod = normalizeVodList([res.data])[0];
|
||||
if (!vod) {
|
||||
return JSON.stringify({ list: [{ vod_id: id, vod_name: '加载失败', vod_play_url: '' }] });
|
||||
}
|
||||
|
||||
vod.vod_play_from = '金牌影院';
|
||||
if (vod.episodelist?.length) {
|
||||
const name = vod.episodelist.length > 1 ? vod.episodelist[0].name : vod.vod_name;
|
||||
vod.vod_play_url = vod.episodelist.map(ep => `${name}$${id}@@${ep.nid}`).join('#');
|
||||
delete vod.episodelist;
|
||||
}
|
||||
return JSON.stringify({ list: [vod] });
|
||||
}
|
||||
|
||||
async function play(_, id) {
|
||||
const [vid, nid] = id.split('@@');
|
||||
const url = `${currentHost}/api/mw-movie/anonymous/v2/video/episode/url?clientType=1&id=${vid}&nid=${nid}`;
|
||||
const res = await reqSafe(url, { headers: getHeaders({ clientType: '1', id: vid, nid: nid }) });
|
||||
const urls = [];
|
||||
for (const item of res.data?.list || []) {
|
||||
urls.push(item.resolutionName, item.url);
|
||||
}
|
||||
return JSON.stringify({
|
||||
parse: 0,
|
||||
url: urls,
|
||||
header: {
|
||||
'User-Agent': USER_AGENT,
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'DNT': '1',
|
||||
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'Origin': currentHost,
|
||||
'Referer': currentHost + '/'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function search(wd, _, pg = "1") {
|
||||
const params = { keyword: wd, pageNum: pg, pageSize: "8", sourceCode: "1" };
|
||||
const url = `${currentHost}/api/mw-movie/anonymous/video/searchByWord?${toQueryString(params)}`;
|
||||
const res = await reqSafe(url, { headers: getHeaders(params) });
|
||||
const list = normalizeVodList(res.data?.result?.list || []);
|
||||
return JSON.stringify({ list, page: +pg });
|
||||
}
|
||||
|
||||
export function __jsEvalReturn() {
|
||||
return { init, home, homeVod, category, detail, play, proxy: null, search };
|
||||
}
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
let host = 'https://www.guipian360.com';
|
||||
let headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
||||
"Referer": host + "/"
|
||||
};
|
||||
|
||||
const extractVideos = html => {
|
||||
if (!html) return [];
|
||||
return pdfa(html, '.m-movies .u-movie').map(it => {
|
||||
const url = it.match(/href="([^"]+)"/)?.[1] || "";
|
||||
const id = url.match(/\/(\d+)\.html/)?.[1];
|
||||
let name = it.match(/title="([^"]+)"/)?.[1] || "";
|
||||
name = name.split('/')[0].trim().replace(/.*《([^》]+)》.*/, "$1");
|
||||
const pic = it.match(/src="([^"]+)"/)?.[1] || "";
|
||||
const remarks = it.match(/class="zhuangtai"[^>]*>([^<]+)/)?.[1] || "";
|
||||
return id && name ? {
|
||||
vod_id: id,
|
||||
vod_name: name,
|
||||
vod_pic: pic.startsWith('/') ? host + pic : pic,
|
||||
vod_remarks: remarks.trim()
|
||||
} : null;
|
||||
}).filter(Boolean);
|
||||
};
|
||||
|
||||
const home = async () => {
|
||||
const list = extractVideos((await req(host, { headers }))?.content || '');
|
||||
return JSON.stringify({
|
||||
class: [
|
||||
{type_id:"1",type_name:"鬼片大全"},{type_id:"6",type_name:"大陆鬼片"},{type_id:"9",type_name:"港台鬼片"},
|
||||
{type_id:"8",type_name:"林正英鬼片"},{type_id:"7",type_name:"日韩鬼片"},{type_id:"11",type_name:"欧美鬼片"},
|
||||
{type_id:"10",type_name:"泰国鬼片"},{type_id:"3",type_name:"恐怖片"},{type_id:"2",type_name:"电视剧"},
|
||||
{type_id:"12",type_name:"国产剧"},{type_id:"20",type_name:"港台剧"},{type_id:"13",type_name:"美剧"},
|
||||
{type_id:"14",type_name:"韩剧"},{type_id:"15",type_name:"日剧"},{type_id:"16",type_name:"泰剧"},
|
||||
{type_id:"22",type_name:"其它剧"},{type_id:"4",type_name:"动漫"}
|
||||
],
|
||||
filters: {},
|
||||
list
|
||||
});
|
||||
};
|
||||
|
||||
const homeVod = async () => {
|
||||
const list = extractVideos((await req(host, { headers }))?.content || '');
|
||||
return JSON.stringify({ list });
|
||||
};
|
||||
|
||||
const category = async (tid, pg, _, extend) => {
|
||||
const url = pg > 1 ? `${host}/list/${tid}_${pg}.html` : `${host}/list/${tid}.html`;
|
||||
const html = (await req(url, { headers }))?.content || '';
|
||||
const list = extractVideos(html);
|
||||
const m = html.match(/href="\/list\/\d+_(\d+)\.html"[^>]*>\.\.(\d+)<\/a>/);
|
||||
return JSON.stringify({ list, page: +pg, pagecount: m ? +m[1] : 999, limit: 20 });
|
||||
};
|
||||
|
||||
const detail = async id => {
|
||||
const html = (await req(`${host}/nv/${id}.html`, { headers }))?.content || '';
|
||||
if (!html) return JSON.stringify({ list: [] });
|
||||
|
||||
const tabs = pdfa(html, '#tv_tab li a').map(a => (a.match(/>([^<]+)/)?.[1] || "线路").trim());
|
||||
const urls = pdfa(html, '#tv_tab .list').map(list =>
|
||||
pdfa(list, 'ul.abc li a').map(a => {
|
||||
const name = (a.match(/>([^<]+)/)?.[1] || "播放").trim();
|
||||
const vid = (a.match(/href="\/play\/(.*?)\.html"/)?.[1] || "");
|
||||
return `${name}$${vid}`;
|
||||
}).join('#')
|
||||
);
|
||||
|
||||
if (!tabs.length || !urls.length) return JSON.stringify({ list: [] });
|
||||
|
||||
let vod_name = (html.match(/<h1>(.*?)<\/h1>/)?.[1] || "").split('/')[0].trim().replace(/.*《([^》]+)】?.*/, "$1");
|
||||
const m = s => (html.match(s) || ["", ""])[1].trim();
|
||||
const vod_pic = m(/<img[^>]+src="([^"]+)"[^>]*class="lazy"/);
|
||||
const vod_content = (html.match(/<p class="jianjie-p"[^>]*>([\s\S]*?)<\/p>/)?.[1] || "").replace(/<.*?>/g, "").trim() || "暂无简介";
|
||||
|
||||
return JSON.stringify({
|
||||
list: [{
|
||||
vod_id: id,
|
||||
vod_name,
|
||||
vod_pic: vod_pic.startsWith('/') ? host + vod_pic : vod_pic,
|
||||
vod_content,
|
||||
vod_director: m(/<li class="hidden-xs"><span>导演:<\/span>(.*?)<\/li>/),
|
||||
vod_actor: m(/<li class="hidden-xs"><span>主演:<\/span>(.*?)<\/li>/),
|
||||
vod_year: m(/<strong>(\d{4})年<\/strong>/),
|
||||
vod_area: m(/地区:<\/span><a[^>]*>(.*?)<\/a>/),
|
||||
vod_lang: m(/语言:<\/span>(.*?)<\/li>/),
|
||||
vod_play_from: tabs.join('$$$'),
|
||||
vod_play_url: urls.join('$$$')
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
const search = async (wd, _, pg = 1) => {
|
||||
const url = `${host}/vodsearch/${encodeURIComponent(wd)}----------${pg}---.html`;
|
||||
const list = extractVideos((await req(url, { headers }))?.content || '');
|
||||
return JSON.stringify({ list });
|
||||
};
|
||||
|
||||
const play = async (_, id) => {
|
||||
const html = (await req(`${host}/play/${id}.html`, { headers }))?.content || '';
|
||||
const m3u8 = html.match(/var now="([^"]+)";/);
|
||||
return JSON.stringify({
|
||||
parse: m3u8 ? 0 : 1,
|
||||
url: m3u8 ? m3u8[1] : `${host}/play/${id}.html`,
|
||||
header: headers
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
init: async () => {},
|
||||
home,
|
||||
homeVod,
|
||||
category,
|
||||
detail,
|
||||
search,
|
||||
play
|
||||
};
|
||||
Reference in new issue
Block a user