Skip to content

Commit

Permalink
support pie script
Browse files Browse the repository at this point in the history
  • Loading branch information
Hiram committed May 4, 2024
1 parent a0e3b2c commit d236076
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/main/core/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ const ipcListen = () => {
}
});

ipcMain.handle('sniffer-media', async (_, url) => {
ipcMain.handle('sniffer-media', async (_, url, script) => {
const ua = setting.find({ key: "ua" }).value;
const res = await puppeteerInElectron(url, ua);
const res = await puppeteerInElectron(url, script, ua);
return res;
});

Expand Down
53 changes: 41 additions & 12 deletions src/main/utils/pie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,22 @@ const isVideoUrl = (reqUrl) => {
return reqUrl.match(urlRegex) && !isExcludedUrl(reqUrl);
}


const puppeteerInElectron = async (url: string, ua: string | null = null): Promise<PieResponse> => {
const puppeteerInElectron = async (url: string, script: string = '', ua: string | null = null): Promise<PieResponse> => {
logger.info(`[sniffer] sniffer url: ${url}`);
logger.info(`[sniffer] sniffer script: ${script}`);
logger.info(`[sniffer] sniffer ua: ${ua}`);

try {
const browser = await pie.connect(app, puppeteer as any); // 连接puppeteer
snifferWindow = new BrowserWindow({ show: false }); // 创建无界面窗口
snifferWindow = new BrowserWindow({ show: true }); // 创建无界面窗口
snifferWindow.webContents.setAudioMuted(true); // 设置窗口静音
const page = await pie.getPage(browser, snifferWindow); // 获取页面

if (ua) await page.setUserAgent(ua); // 设置ua

await page.setRequestInterception(true); // 开启请求拦截

return new Promise((resolve, reject) => {
return new Promise(async(resolve, reject) => {
page.on('request', async(req) => {
const reqUrl = req.url(); // 请求url

Expand All @@ -73,15 +73,19 @@ const puppeteerInElectron = async (url: string, ua: string | null = null): Promi

await page.close();
await browser.disconnect();
req.abort().catch((e) => console.error(e));
req.abort().catch((e) => logger.error(e));
resolve(handleResponse(200, 'sucess', { url: reqUrl, header: headers }));
}

if (req.isInterceptResolutionHandled()) return; // 已处理过的请求不再处理
if (req.resourceType() === 'image') {
req.abort().catch((err) => console.error(err));
if (req.method().toLowerCase() === 'head') {
req.abort().catch((err) => logger.error(err));
}
const resourceTypesToAbort = ['image', 'stylesheet', 'font'];
if (resourceTypesToAbort.includes(req.resourceType())) {
req.abort().catch((err) => logger.error(err));
} else {
req.continue().catch((err) => console.error(err));
req.continue().catch((err) => logger.error(err));
}
});

Expand All @@ -95,11 +99,36 @@ const puppeteerInElectron = async (url: string, ua: string | null = null): Promi
}, 15000);
}

page.goto(url).catch(e => reject(e));
await page.goto(url, { waitUntil: 'domcontentloaded' }).catch(err => reject(err));
if (script) {
try {
logger.info(`[pie]start run script`)
const js_code = `
(function() {
var scriptTimer;
var scriptCounter = 0;
scriptTimer = setInterval(function() {
if (location.href !== 'about:blank') {
scriptCounter += 1;
console.log('---第' + scriptCounter + '次执行script[' + location.href + ']---');
${script}
clearInterval(scriptTimer);
scriptCounter = 0;
console.log('---执行script成功---');
}
}, 200);
})();
`;
await page.evaluateOnNewDocument(script=js_code);
await page.evaluate(js_code);
} catch (err) {
logger.info(`[pie][error]run script: ${err}`);
}
}
});
} catch (e) {
return handleResponse(500, 'fail', e as Error);
} catch (err) {
return handleResponse(500, 'fail', err as Error);
}
};

export default puppeteerInElectron;
export default puppeteerInElectron;
26 changes: 12 additions & 14 deletions src/renderer/src/pages/Play.vue
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ import 'v3-infinite-loading/lib/style.css';
import 'xgplayer/es/plugins/danmu/index.css';
import Base64 from 'crypto-js/enc-base64';
import Utf8 from 'crypto-js/enc-utf8.js';
import Utf8 from 'crypto-js/enc-utf8';
import DPlayer from 'dplayer';
import flvjs from 'flv.js';
Expand Down Expand Up @@ -878,8 +878,8 @@ const fetchHipyPlayUrlHelper = async (site: { [key: string]: any }, flag: string
try {
const playRes = await fetchHipyPlayUrl(site, flag, url);
playUrl = playRes.url;
script = playRes.js?Base64.stringify(Utf8.parse(playRes.js)):'';
extra = playRes.parse_extra||extra;
script = playRes.js ? Base64.stringify(Utf8.parse(playRes.js)) : '';
extra = playRes.parse_extra || extra;
console.log(`[detail][hipy][return]${playUrl}`);
} catch (err) {
console.log(`[detail][hipy][error]${err}`);
Expand All @@ -902,8 +902,8 @@ const fetchT3PlayUrlHelper = async (flag: string, id: string, flags: string[] =
};
playUrl = playRes.url;
script = playRes.js?Base64.stringify(Utf8.parse(playRes.js)):'';
extra = playRes.parse_extra||extra;
script = playRes.js ? Base64.stringify(Utf8.parse(playRes.js)) : '';
extra = playRes.parse_extra || extra;
console.log(`[detail][t3][return]${playUrl}`);
} catch (err) {
console.log(`[detail][t3][error]${err}`);
Expand Down Expand Up @@ -1017,9 +1017,9 @@ const initFilmPlayer = async (isFirst) => {
tmp.url = url;
tmp.sourceUrl = url;
let playerUrl = url;
let script:string = '';
let extra:string = '';
let playData: object = {playUrl:url,script:'',extra:''};
let script: string = '';
let extra: string = '';
let playData: object = { playUrl: url, script: '',extra: ''};
if (site.playUrl) {
playerUrl = await fetchJsonPlayUrlHelper(site.playUrl, url);
Expand Down Expand Up @@ -1084,12 +1084,10 @@ const initFilmPlayer = async (isFirst) => {
console.log(`[detail][sniffer][reveal]尝试提取播放链接,type:${site.type}`);
try {
MessagePlugin.info('嗅探资源中, 如10s没有结果请换源,咻咻咻!');
let snifferPlayUrl:string = url;
if(snifferMode.type === 'custom'){
let snifferTool = new URL(snifferMode.url);
let snifferApi = snifferTool.origin + snifferTool.pathname;
snifferPlayUrl = `${snifferApi}?url=${url}&script=${script}${extra}`;
}
let snifferPlayUrl: string = url;
let snifferTool = new URL(snifferMode.url);
let snifferApi = snifferTool.origin + snifferTool.pathname;
snifferPlayUrl = `${snifferApi}?url=${url}&script=${script}${extra}`;
playerUrl = await sniffer(snifferMode.type, snifferPlayUrl);
createPlayer(playerUrl);
} catch (err) {
Expand Down
20 changes: 9 additions & 11 deletions src/renderer/src/pages/film/Detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
<script setup lang="ts">
import jsonpath from 'jsonpath';
import Base64 from 'crypto-js/enc-base64';
import Utf8 from 'crypto-js/enc-utf8.js';
import Utf8 from 'crypto-js/enc-utf8';
import {
HeartIcon,
HeartFilledIcon,
Expand Down Expand Up @@ -236,7 +236,7 @@ const fetchHipyPlayUrlHelper = async (site: { [key: string]: any }, flag: string
try {
const playRes = await fetchHipyPlayUrl(site, flag, url);
playUrl = playRes.url;
script = playRes.js?Base64.stringify(Utf8.parse(playRes.js)):'';
script = playRes.js ? Base64.stringify(Utf8.parse(playRes.js)) : '';
extra = playRes.parse_extra||extra;
console.log(`[detail][hipy][return]${playUrl}`);
} catch (err) {
Expand All @@ -260,7 +260,7 @@ const fetchT3PlayUrlHelper = async (flag: string, id: string, flags: string[] =
};
playUrl = playRes.url;
script = playRes.js?Base64.stringify(Utf8.parse(playRes.js)):'';
script = playRes.js ? Base64.stringify(Utf8.parse(playRes.js)) : '';
extra = playRes.parse_extra||extra;
console.log(`[detail][t3][return]${playUrl}`);
} catch (err) {
Expand Down Expand Up @@ -344,9 +344,9 @@ const gotoPlay = async (item) => {
const { snifferMode } = set.value;
let playerUrl = url;
let script:string = '';
let extra:string = '';
let playData: object = {playUrl:url,script:'',extra:''};
let script: string = '';
let extra: string = '';
let playData: object = { playUrl: url, script: '', extra: ''};
if (playUrl) {
playerUrl = await fetchJsonPlayUrlHelper(playUrl, url);
Expand Down Expand Up @@ -410,11 +410,9 @@ const gotoPlay = async (item) => {
try {
MessagePlugin.info('嗅探资源中, 如10s没有结果请换源,咻咻咻!');
let snifferPlayUrl:string = url;
if(snifferMode.type === 'custom'){
let snifferTool = new URL(snifferMode.url);
let snifferApi = snifferTool.origin + snifferTool.pathname;
snifferPlayUrl = `${snifferApi}?url=${url}&script=${script}${extra}`;
}
let snifferTool = new URL(snifferMode.url);
let snifferApi = snifferTool.origin + snifferTool.pathname;
snifferPlayUrl = `${snifferApi}?url=${url}&script=${script}${extra}`;
playerUrl = await sniffer(snifferMode.type, snifferPlayUrl);
if (playerUrl) callSysPlayer(playerUrl);
} catch (err) {
Expand Down
58 changes: 44 additions & 14 deletions src/renderer/src/utils/sniffer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import axios from 'axios';
import { nanoid } from 'nanoid';
import Base64 from 'crypto-js/enc-base64';
import Utf8 from 'crypto-js/enc-utf8';

const { getCurrentWindow } = require('@electron/remote');
const win = getCurrentWindow();
Expand All @@ -15,12 +17,17 @@ const isExcludedUrl = (reqUrl) => {
);
}

const snifferPie = async (url: string): Promise<string> => {
const getQueryParam = (url: string, paramName: string) => {
const searchParams = new URLSearchParams(new URL(url).search);
return searchParams.get(paramName);
}

const snifferPie = async (url: string, script: string): Promise<string> => {
console.log('[detail][sniffer][pie][start]: pie嗅探流程开始');
let data: string = '';

try {
const res = await window.electron.ipcRenderer.invoke('sniffer-media', url);
const res = await window.electron.ipcRenderer.invoke('sniffer-media', url, script);

if (res.code === 200) {
data = res.data.url;
Expand All @@ -39,13 +46,13 @@ const snifferPie = async (url: string): Promise<string> => {
const createIframe = (iframeId: string, url: string): Promise<{ iframeRef: HTMLIFrameElement, contentWindow: Window | null }> => {
return new Promise((resolve) => {
const iframeRef = document.createElement("iframe");
iframeRef.style.height = '0';
iframeRef.style.width = '0';
iframeRef.style.position = 'fixed';
iframeRef.style.top = '-10px';
iframeRef.style.left = '-10px';
// iframeRef.style.height = '0';
// iframeRef.style.width = '0';
// iframeRef.style.position = 'fixed';
// iframeRef.style.top = '-10px';
// iframeRef.style.left = '-10px';
iframeRef.id = iframeId;
iframeRef.setAttribute("frameborder", "0");
// iframeRef.setAttribute("frameborder", "0");
iframeRef.src = url;

iframeRef.onload = () => {
Expand All @@ -60,18 +67,37 @@ const removeIframe = (iframeId: string): void => {
const iframeRef = document.getElementById(iframeId);
if (iframeRef && iframeRef.parentNode) {
iframeRef.parentNode.removeChild(iframeRef);

// 清理可能存在的事件监听器等
iframeRef.onload = null;
iframeRef.onerror = null;
iframeRef.onabort = null;
}
};

const snifferIframe = async (url: string, totalTime: number = 15000, speeder: number = 250): Promise<string> => {
const snifferIframe = async (url: string, script: string, totalTime: number = 15000, speeder: number = 250): Promise<string> => {
win.webContents.setAudioMuted(true); // 静音
const iframeId = nanoid();
const iframeWindow = await createIframe(iframeId, url);
// if (script) {
// const js_code = `
// (function() {
// var scriptTimer;
// var scriptCounter = 0;
// scriptTimer = setInterval(function() {
// if (location.href !== 'about:blank') {
// scriptCounter += 1;
// console.log('---第' + scriptCounter + '次执行script[' + location.href + ']---');
// ${script}
// clearInterval(scriptTimer);
// scriptCounter = 0;
// console.log('---执行script成功---');
// }
// }, 2000);
// })();
// `;
// iframeWindow.contentWindow!.eval(js_code);
// }

const totalCounter = totalTime / speeder; // 计算总次数

Expand All @@ -80,6 +106,7 @@ const snifferIframe = async (url: string, totalTime: number = 15000, speeder: nu
let data = '';

const checkResourceName = (resourceName: string) => {
// console.log('https://v3-cha.toutiaovod.com/1583f35430641ba3ca5b9c9411e45d57/6636a17c/video/tos/cn/tos-cn-v-0004/owPbPen5Q8AqRdBIIeDDKdAFArL9bRGBmvXRgm/?a=13&ch=0&cr=0&dr=0&net=5&cd=0%7C0%7C0%7C0&br=1014&bt=1014&cs=0&ds=3&ft=WG6aM0-ERR0sLOC3NNn2Nc.xBiGNbLpAP5sU_4jJPUwJNv7TGW&mime_type=video_mp4&qs=13&rc=M3M5eGQ6ZmhlcjMzNDczM0BpM3M5eGQ6ZmhlcjMzNDczM0BlYXJtcjRfaWRgLS1kLTBzYSNlYXJtcjRfaWRgLS1kLTBzcw%3D%3D&btag=80000200078030&dy_q=1714844945&l=202405050149052CDB97F0CB25211326A4'.match(urlRegex) && !isExcludedUrl('https://v3-cha.toutiaovod.com/1583f35430641ba3ca5b9c9411e45d57/6636a17c/video/tos/cn/tos-cn-v-0004/owPbPen5Q8AqRdBIIeDDKdAFArL9bRGBmvXRgm/?a=13&ch=0&cr=0&dr=0&net=5&cd=0%7C0%7C0%7C0&br=1014&bt=1014&cs=0&ds=3&ft=WG6aM0-ERR0sLOC3NNn2Nc.xBiGNbLpAP5sU_4jJPUwJNv7TGW&mime_type=video_mp4&qs=13&rc=M3M5eGQ6ZmhlcjMzNDczM0BpM3M5eGQ6ZmhlcjMzNDczM0BlYXJtcjRfaWRgLS1kLTBzYSNlYXJtcjRfaWRgLS1kLTBzcw%3D%3D&btag=80000200078030&dy_q=1714844945&l=202405050149052CDB97F0CB25211326A4'))
return resourceName.match(urlRegex) && !isExcludedUrl(resourceName);
// const formatIndex = videoFormats.findIndex((format) => resourceName.toLowerCase().includes(format));
// return formatIndex > -1;
Expand Down Expand Up @@ -130,7 +157,7 @@ const snifferIframe = async (url: string, totalTime: number = 15000, speeder: nu

const snifferCustom = async (url: string): Promise<string> => {
let data: string = '';
try {
try {
const res = await axios.get(url);
if (res.data.code === 200) {
data = res.data.url;
Expand All @@ -149,14 +176,17 @@ const snifferCustom = async (url: string): Promise<string> => {
// 嗅探
const sniffer = async (type: string, url: string): Promise<string> => {
let data: string = '';
let script = getQueryParam(url, 'script');
if (script) script = Base64.parse(script).toString(Utf8);
const realUrl = getQueryParam(url, 'url');
if (type === 'iframe') {
data = await snifferIframe(url);
data = await snifferIframe(realUrl!, script!);
} else if (type === 'pie') {
data = await snifferPie(url);
data = await snifferPie(realUrl!, script!);
} else if (type === 'custom') {
data = await snifferCustom(url);
}
return data;
};

export default sniffer;
export default sniffer;

0 comments on commit d236076

Please sign in to comment.