/* eslint-disable no-undef */
// ==UserScript==
// @name VIP视频解析
// @namespace mofiter.xinngsf
// @version 1.6.7
// @description 添加的解析按钮样式与原站一致,不会产生突兀感,支持多个解析接口切换,支持自定义接口,支持站内站外解析,支持 Tampermonkey、Violentmonkey
// @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
// @match https://v.qq.com/tv/*
// @match https://v.qq.com/x/*
// @match https://www.iqiyi.com/v*
// @match https://v.youku.com/v_show/*
// @match https://tv.sohu.com/*
// @match https://film.sohu.com/album/*
// @match https://www.mgtv.com/b/*
// @author xinngsf mofiter
// @match http://v.pptv.com/show/*
// @match https://v.pptv.com/show/*
// @match http://www.le.com/ptv/vplay/*
// @match https://www.le.com/ptv/vplay/*
// @noframes
// @grant unsafeWindow
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @updateURL https://gitee.com/xinggsf/gm/raw/master/jx-mv-vip.user.js
// ==/UserScript==
//原版:https://greasyfork.org/scripts/373063
'use strict';
const { protocol, hostname:host, pathname } = location;
const url = `${protocol}//${host}${pathname}`;
const vs = document.getElementsByTagName('video');
const videoPlayer =
`
`;
let playerCSS, posCSS, jiexiDIV, userIntfs;
const interfaces = [
// 88看 必须修改请求头referer为https://www.mgtv1.net/ 示例网址:https://www.bilibili.com/bangumi/play/ss39418
{name:"88看",type:3,url:"https://v1.shankuwang.com/?v="},
{name:"parwix",type:3,url:"https://jx.parwix.com:4433/player/analysis.php?v="},
{name:"虾米",type:3,url:"https://jx.xmflv.com/?url="},
{name:"诺讯",type:3,url:"https://www.nxflv.com/?url="},
{name:"m3u8.tv",type:3,url:"https://jx.m3u8.tv/jiexi/?url="},
{name:"黑云",type:3,url: "https://jiexi.380k.com/?url="},
{name:"爱豆",type:3,url:"https://jx.aidouer.net/?url="},
{name:"sugan",type:3,url:"https://api.suganjx.com/index/?url="}, // Youku
{name:"m1907",type:3,url:"https://z1.m1907.cn/?jx="},
{name:"OK云",type:3,url:"https://api.okjx.cc:3389/m33/?url="},
{name:"猪蹄",type:3,url:"https://jx.iztyy.com/svip/?url="},
{name:"盘古",type:3,url:"https://www.pangujiexi.cc/jiexi.php?url="},
{name:"ergan",type:3,url:"https://jx.ergan.top/?url="}, // https://www.iqiyi.com/v_19rrjvu2dc.html
// {name:"久播",type:1,url:"https://jx.jiubojx.com/vip.php?url="},
{name:"思古",type:3,url:"https://api.sigujx.com/?url="},
{name:"代代",type:3,url:"https://api.daidaitv.com/index/?url="},
// {name:"菜鸟",type:3,url: "https://jiexi.bm6ig.cn/?url="},
// {name:"tv920",type:3,url:"https://api.tv920.com/jx/?url="},
// {name:"石头云",type:3,url:"https://jiexi.071811.cc/jx.php?url="},
{name:"1717yun",type:3,url:"https://www.1717yun.com/jx/ty.php?url="},
// {name:"金桥",type:3,url:"https://www.jqaaa.com/jx.php?url="},
// {name:"618g",type:3,url:"https://jx.618g.com/?url="},
// {name:"大亨影院",type:2,url:"http://jx.oopw.top/?url="}
];
const hasDOM = css => $(css).length > 0;
const delayReload = () => {
setTimeout(location.reload.bind(location), 1000);
};
const rawPlay = HTMLVideoElement.prototype.play;
const innerParse = function(li) {
HTMLVideoElement.prototype.play = function() {
return this.clientWidth > 99 ? rawPlay.call(this) : new Promise(() => {})
};
// const audioCtx = new AudioContext();
// audioCtx.close();
$(vs).remove();
if (this instanceof Node) li = this;
const e = $(playerCSS).empty().append(videoPlayer);
const s = li.getAttribute('data-url') || interfaces[0].url + url;
e.find("#iframe-player").attr("src", s);
};
const hideElements = el => !!el.hide();
class TaskPool { //简易任务池
constructor(isFree) {
const tasks = new Map();
const timer = setInterval(() => {
for (let [i, cb] of tasks) {
let ret, a = i;
if (typeof i == 'string') {
a = $(i);
if (i.split(',').length > a.length) continue;
ret = cb(a);
}
else if (typeof i == 'object') ret = cb($(i));
else ret = cb(i);
if (!ret) tasks.delete(i);
}
if (isFree && !tasks.size) {
clearInterval(timer);
this._tasks = null;
}
}, 500);
this._tasks = tasks;
}
//wait for do something. Key = css selector or element or number; cb = function($el) { return true: wait again }
add(key, cb = hideElements) {
if (!key) key = this._tasks.size + 1;
this._tasks.set(key, cb);
}
}
const tasks = new TaskPool(true);
const showSetting = () => {
if (!hasDOM('#jiexi-setting')) {
GM_addStyle(`#jiexi-setting legend,table,table th,td{text-align:center;}`);
const container = $(
``);
$('body').append(container);
if (userIntfs.length > 0) {
const trList = userIntfs.map(item => `
${item.name} |
${item.url} |
${item.type} |
|
`).join('');
container.find("#interface-table").append($(trList));
}
}
$("#cancel-button").click(function () {
this.closest("#jiexi-setting").remove();
});
$("#save_button").click(function () {
const tr = $(this).closest('tr');
var interface_name = tr.find("#interface-name").val().trim();
var interface_url = tr.find("#interface-url").val().trim();
var interface_type = tr.find('input[name="interface-type"]:checked').val() | 0;
if (interface_name == "") {
alert("请输入接口名称");
return;
}
if (interface_url == "") {
alert(" 请输入接口地址");
return;
}
if (!interface_url.startsWith("http")) {
alert(" 请输入以 http 或 https 开头的接口地址");
return;
}
if ((interface_type & 1) && !interface_url.startsWith("https")) {
alert("站内解析只支持以 https 开头的接口地址,请修改接口类型");
return;
}
var canSave = !userIntfs.some(item => interface_name === item.name);
if (canSave) {
userIntfs.push({
"name": interface_name,
"url": interface_url,
"type": interface_type
});
GM_setValue("user_interface", userIntfs);
location.reload();
} else {
alert("已存在同名接口,请修改接口名称");
}
});
$(".delete-button").click(function () {
const pp = this.closest('tr');
const del_name = pp.firstChild.innerHTML;
userIntfs.forEach((k, i) => { // a.splice(a.findIndex(k => k.name == del_name), 1);
if (del_name == k.name) userIntfs.splice(i, 1);
});
GM_setValue("user_interface", userIntfs);
pp.remove();
$(`#_gm__vipJX li:contains("${del_name}")`).remove();
});
};
const router = {
["www.iqiyi.com"]() {
playerCSS = "#flashbox";
posCSS = ".func-item.func-like-v1";
GM_addStyle(
`.fn-iqiyi-jiexi li {
color: #ccc; text-align: center; width: 60px; cursor: pointer;
line-height: 20px; float:left; border:1px solid gray;
border-radius:8px; padding:0 4px; margin:4px 2px;
}
#_gm__vipJX a {color: #ccc}
.fn-iqiyi-jiexi > .qy-popup-box {
background-color:#2e2e2e; border:1px solid gray;
}
#flashbox { z-index: 400 !important }
.func-item.fn-jiexi-main:hover > div { display: block }
.fn-iqiyi-jiexi {
display:none;position:absolute;left:-50px;
text-align:center;z-index:2147483647;
}
.iqiyi_JX:hover {color: #6ba430}
#_gm__vipJX li:hover, #_gm__vipJX a:hover {color: #01be07}`);
const iqiyi_jiexi = $(
``);
this.wait = el => {
$(posCSS).replaceWith(iqiyi_jiexi)[0].addEventListener('click', ev => {
const e = ev.target;
if (e.matches('li[data-url]')) {
ev.stopPropagation();
innerParse(e);
}
});
//.find("li[data-url], .fn-iqiyi-jiexi-text").click(innerParse);
};
tasks.add(".qy-player-vippay-popup, .black-screen");
},
["v.qq.com"]() {
playerCSS = "#mod_player";
posCSS = ".action_wrap.cf";
GM_addStyle(
`.fn-qq-jiexi {
background-color:#2e2e2e; width:auto; left:-50px; border:1px solid gray;
}
.fn-qq-jiexi li {
text-align:center; width:60px; line-height:20px; float:left;
border:1px solid gray; border-radius:8px; padding:0 4px;
color:#999; cursor: pointer; margin:4px 2px;
}
.fn-qq-jiexi a { color:#999; }
#_gm__vipJX li:hover {color:#fe6527}`
);
const qq_jiexi = $(
``);
this.wait = el => {
const { type_name, vipPage } = unsafeWindow.COVER_INFO;
if (type_name === "电影") {
$(".mod_figure_list .list_item").click(delayReload);
} else if (type_name === "电视剧" || type_name === "动漫") {
$('.mod_episode .item').click(delayReload);
$(".mod_episode_filter").click(() => {
$('.mod_episode .item').click(delayReload);
});
}
$(".action_share, .action_qrcode, .action_more").remove();
el.filter(posCSS).append(qq_jiexi)
.on("mouseover mouseout", () => {
qq_jiexi.toggleClass("open");
})
.find(".fn-qq-jiexi-text, li[data-url]").click(ev => {
unsafeWindow.fetch = x => new Promise((_, fail) => fail());
$('.txp_btn_play[data-status=pause]').click();
$("body").unbind('keydown keyup');
innerParse(ev.target);
});
};
tasks.add(".mod_vip_popup,.tvip_layer,#mask_layer");
},
["v.youku.com"]() {
playerCSS = '#ykPlayer';
posCSS = "ul.play-fn";
GM_addStyle(
`.fn-youku-jiexi li {
text-align:center;width:60px;line-height:20px;
float:left;border:1px solid gray;border-radius:3px;
padding:0 4px;margin:4px 2px; cursor: pointer;
}
#_gm__vipJX a {color:#ccc}
.fn-youku-jiexi > .fn-panel {
border:1px solid gray; min-width:100%;
}
#_gm__vipJX li:hover, #_gm__vipJX a:hover {color:#2592ff}`
);
const youku_jiexi = $(
`
解析
${jiexiDIV}
`);
this.wait = el => {
$('li.fn-phonewatch').hide();
el.filter(posCSS).append(youku_jiexi)
.find(".fn-youku-jiexi-text, li[data-url]").click(function() {
$('.control-play-icon.control-pause-icon').click();
innerParse(this);
});
};
},
["www.mgtv.com"]() {
playerCSS ="#mgtv-player-wrap";
posCSS = ".logolist";
GM_addStyle(
`.fn-mgtv-jiexi:hover > .extend { display: block }
.fn-mgtv-jiexi li {
color:#ccc;text-align:center;width:60px;line-height:20px;float:left;
border:1px solid gray;border-radius:8px;padding:0 4px;margin:4px 2px; cursor: pointer;
}
#_gm__vipJX a {color:#ccc}
.fn-mgtv-jiexi > .extend {
display:none;top:-5px;left:-50px;text-align:center;position:relative;
}
#_gm__vipJX li:hover {color:#ff6f00}
#_gm__vipJX a:hover {color:#ff6f00 !important}
.v-panel-extend > .fn-panel {
background-color:#2e2e2e;width:auto;border:1px solid gray;
}`);
const mgtv_jiexi = $(
``);
this.wait = el => {
$(".aside-tabbox li").click(delayReload);
el.filter(posCSS).empty().append(mgtv_jiexi)
.find(".fn-mgtv-jiexi-text, li[data-url]").click(innerParse);
};
},
["tv.sohu.com"]() {
playerCSS = '#player';
posCSS = ".vBox-tb.cfix";
GM_addStyle(
`.fn-sohu-jiexi li{
color:#333; text-align:center; width:60px; line-height:20px;
float:left; border:1px solid gray; border-radius:8px;
padding:0 4px; margin:4px 2px; cursor: pointer;
}
/* .vBox.vBox-play:hover > div {display: block} */
.fn-sohu-jiexi {
display: none;background-color:#2e2e2e;border:1px solid gray;
padding:0;margin:0 0 0 0;line-height:25px;min-width:100% important;
}
#_gm__vipJX li:hover {color:#e33c30}`
);
const sohu_jiexi = $(
``);
sohu_jiexi.click(() => {
sohu_jiexi.children(".fn-sohu-jiexi").toggle();
});
this.wait = el => {
playerCSS = el.filter(playerCSS);
el.filter(posCSS).prepend(sohu_jiexi)
.find("li[data-url]").click(innerParse);
};
tasks.add(".x-video-adv,.x-player-mask,#player_vipTips");
},
["film.sohu.com"]() {
playerCSS = "#playerWrap";
posCSS = ".player-content-info";
GM_addStyle(
`.fn-sohu-jiexi li {
color:#ccc; text-align:center; width:60px; cursor: pointer;
line-height:20px; float:left; border:1px solid gray;
border-radius:8px; padding:0 4px; margin:4px 2px;
}
#_gm__vipJX a {color:#ccc}
.action-item.jiexi:hover > div {display: block}
.fn-sohu-jiexi {
display:none;background-color:#2e2e2e;border:1px solid gray;
width:auto;text-align:center;margin-left:-61px;
}
#_gm__vipJX li:hover, #_gm__vipJX a:hover {color:#ee3c3a}`
);
const sohu_film_jiexi = $(
``);
this.wait = el => {
el.filter(posCSS).prepend(sohu_film_jiexi)
.find(".fn-sohu-jiexi-text, li[data-url]").click(innerParse);
};
},
["www.le.com"]() {
playerCSS = "#le_playbox";
posCSS = ".interact_area";
GM_addStyle(
`.fn-le-jiexi {
display:none;background-color:#2e2e2e;border:1px solid gray;
width:auto;position:absolute;top:45px;border-top:2px solid #E42112;
box-shadow:0 2px 6px 0 rgba(0,0,0,.1);left:-40px;
}
.fn-le-jiexi li {
color:#ccc;text-align:center;width:60px;line-height:20px;
float:left;border:1px solid gray;border-radius:8px;
padding:0 5px;margin:4px 2px; height:25px;
}
.le-jiexi-main:hover > div {display: block}
#_gm__vipJX li:hover {color:#e42013}`
);
const le_jiexi = $(
`
解析
${jiexiDIV}
`);
this.wait = el => {
el.filter(posCSS).prepend(le_jiexi)
.find(".fn-le-jiexi-text, li[data-url]").click(innerParse);
};
},
["v.pptv.com"]() {
playerCSS = "#pptv_playpage_box";
posCSS = ".module-video2016-ops ul";
GM_addStyle(
`#fn-pptv-jiexi li {
color:#ccc;text-align:center;
width:60px;line-height:20px;float:left;border:1px solid gray;
border-radius:8px;padding:0 4px;margin:4px 2px;
}
#_gm__vipJX li:hover, #_gm__vipJX a:hover {color:#39f}
#_gm__vipJX a {color:#ccc;display:inline;padding:0 4px;}
#pptv-jiexi-btn:hover>div {display: block}
#fn-pptv-jiexi {
display:none; position:absolute; top:50px;
background-color:#444; border:1px solid gray;
}`);
const pptv_jiexi = $(
`
解析
${jiexiDIV}
`
);
this.wait = el => {
el.filter(posCSS).prepend(pptv_jiexi)
.find(".pptv_jiexi-text, li[data-url]").click(innerParse);
};
}
};
const init = () => {
GM_registerMenuCommand("自定义 VIP 视频解析接口", showSetting);
userIntfs = GM_getValue("user_interface", []);
userIntfs.length && interfaces.push.apply(interfaces, userIntfs);
let outLi = '', inLi = '';
for (const k of interfaces) {
const addr = k.url.trim() + url;
if (k.type & 1) inLi += `${k.name}`;
if (k.type & 2) outLi += `${k.name}`;
}
jiexiDIV = ``;
router[host] && router[host]();
tasks.add(`${playerCSS},${posCSS}`, router.wait);
};
init();