// ==UserScript==
// @name 🫧404小站 — 🎬VIP追剧神器 | 完全免费 | 支持多平台
// @namespace http://tampermonkey.net/
// @version 3.0.0
// @description ▶在线VIP视频解析工具 |free| 支持多平台【爱奇艺】【腾讯视频】【优酷土豆】【芒果TV】【乐视视频】【哔哩哔哩】【搜狐视频】等常见平台。✨50+解析接口任选 ✨内嵌播放无广告 ✨智能切集追剧 ✨自定义播放器尺寸 ✨一键自动解析
// @author yyy.
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_addStyle
// @grant GM_notification
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_openInTab
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11
// @run-at document-start
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTE2IDMuNWMtNi45IDAtMTIuNSA1LjYtMTIuNSAxMi41UzkuMSAyOC41IDE2IDI4LjUgMjguNSAyMi45IDI4LjUgMTYgMjIuOSAzLjUgMTYgMy41eiIgZmlsbD0iI2ZmNjliNCIvPjxwYXRoIGQ9Ik0xNiA2LjVjLTUuMiAwLTkuNSA0LjMtOS41IDkuNXM0LjMgOS41IDkuNSA5LjUgOS41LTQuMyA5LjUtOS41LTQuMy05LjUtOS41LTkuNXptMCAxNmMtMy42IDAtNi41LTIuOS02LjUtNi41czIuOS02LjUgNi41LTYuNSA2LjUgMi45IDYuNSA2LjUtMi45IDYuNS02LjUgNi41eiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xMiAxNWgydjJoLTJ6bTQtMmgzdjJoLTN6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTE0IDIyaC0ydjJoMnoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJNMTggMjJoLTJ2MmgyeiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xNSAyN2gydjJoLTJ6IiBmaWxsPSIjZmZmIi8+PC9zdmc+
// ==/UserScript==
/*
┏┓ ┏┓
┏┛┻━━━━━━┛ ┻┓
┃ ┃
┃ ━ ┃
┃ ┳┛ ┗┳ ┃
┃ ┃
┃ ┻ ┃
┃ ┃
┗━━━┓ ┏━┛Codes are far away from bugs with the animal protecting
┃ ┃ 神兽保佑,代码无bug
┃ ┃
┃ ┗━━━┓
┃ ┣┓
┃ ┏┛
┗┓┓┏━┳┓┏┛
┃┫┫ ┃┫┫
┗┻┛ ┗┻┛
*/
(function() {
'use strict';
const parseApis = [
{"name": "七哥", "type": "1,3", "url": "https://jx.nnxv.cn/tv.php?url=", "recommended": true},
{"name": "虾米", "type": "1,3", "url": "https://jx.xmflv.cc/?url=", "recommended": true},
{"name": "纯净1", "type": "1,2,3", "url": "https://im1907.top/?jx="},
{"name": "B站1", "type": "1,3", "url": "https://jx.jsonplayer.com/player/?url="},
{"name": "爱豆", "type": "1,3", "url": "https://jx.aidouer.net/?url="},
{"name": "BL", "type": "1,3", "url": "https://vip.bljiex.com/?v="},
{"name": "冰豆", "type": "1,3", "url": "https://api.qianqi.net/vip/?url="},
{"name": "百域", "type": "1,3", "url": "https://jx.618g.com/?url="},
{"name": "CK", "type": "1,3", "url": "https://www.ckplayer.vip/jiexi/?url="},
{"name": "CHok", "type": "1,3", "url": "https://www.gai4.com/?url="},
{"name": "ckmov", "type": "1,3", "url": "https://www.ckmov.vip/api.php?url="},
{"name": "H8", "type": "1,3", "url": "https://www.h8jx.com/jiexi.php?url="},
{"name": "JY", "type": "1,3", "url": "https://jx.playerjy.com/?url="},
{"name": "解析", "type": "1,3", "url": "https://ckmov.ccyjjd.com/ckmov/?url="},
{"name": "解析la", "type": "1,3", "url": "https://api.jiexi.la/?url="},
{"name": "老板", "type": "1,3", "url": "https://vip.laobandq.com/jiexi.php?url="},
{"name": "MAO", "type": "1,3", "url": "https://www.mtosz.com/m3u8.php?url="},
{"name": "M3U8", "type": "1,3", "url": "https://jx.m3u8.tv/jiexi/?url="},
{"name": "诺讯", "type": "1,3", "url": "https://www.nxflv.com/?url="},
{"name": "OK", "type": "1,3", "url": "https://okjx.cc/?url="},
{"name": "PM", "type": "1,3", "url": "https://www.playm3u8.cn/jiexi.php?url="},
{"name": "盘古", "type": "1,3", "url": "https://www.pangujiexi.cc/jiexi.php?url="},
{"name": "RDHK", "type": "1,3", "url": "https://jx.rdhk.net/?v="},
{"name": "人人迷", "type": "1,3", "url": "https://jx.blbo.cc:4433/?url="},
{"name": "思云", "type": "1,3", "url": "https://jx.ap2p.cn/?url="},
{"name": "思古3", "type": "1,3", "url": "https://jsap.attakids.com/?url="},
{"name": "听乐", "type": "1,3", "url": "https://jx.dj6u.com/?url="},
{"name": "维多", "type": "1,3", "url": "https://jx.ivito.cn/?url="},
{"name": "YT", "type": "1,3", "url": "https://jx.yangtu.top/?url="},
{"name": "云端", "type": "1,3", "url": "https://sb.5gseo.net/?url="},
{"name": "0523", "type": "1,3", "url": "https://go.yh0523.cn/y.cy?url="},
{"name": "17云", "type": "1,3", "url": "https://www.1717yun.com/jx/ty.php?url="},
{"name": "180", "type": "1,3", "url": "https://jx.000180.top/jx/?url="},
{"name": "4K", "type": "1,3", "url": "https://jx.4kdv.com/?url="},
{"name": "8090", "type": "1,3", "url": "https://www.8090g.cn/?url="},
{"name": "剖元", "type": "1,3", "url": "https://www.pouyun.com/?url="},
{"name": "全民", "type": "1,3", "url": "https://43.240.74.102:4433?url="},
{"name": "夜幕", "type": "1,3", "url": "https://www.yemu.xyz/?url="},
{"name": "M3U8TV", "type": "1,3", "url": "https://jx.m3u8.tv/jiexi/?url="},
{"name": "playm3u8", "type": "1,3", "url": "https://www.playm3u8.cn/jiexi.php?url="},
{"name": "综合", "type": "1,3", "url": "https://jx.jsonplayer.com/player/?url="},
{"name": "im1907", "type": "2", "url": "https://im1907.top/?jx="},
{"name": "云析(带选集)", "type": "2", "url": "https://jx.yparse.com/index.php?url="},
];
const uniqueApis = [];
const seenUrls = new Set();
parseApis.forEach(api => {
if (!seenUrls.has(api.url)) {
seenUrls.add(api.url);
uniqueApis.push(api);
}
});
let customApis = GM_getValue("custom_parse_apis", []);
let allApis = [...uniqueApis, ...customApis];
const vipBoxId = 'vip_jx_box_' + Math.ceil(Math.random() * 100000000);
const DEFAULT_STYLE = {
bgColor: '#3f4149',
fontColor: '#DCDCDC',
opacity: 0.95,
width: '380px'
};
const DEFAULT_PLAYER_SIZE = {
minHeight: '600px',
width: '1000px',
aspectRatio: 'auto' // 可选: '16:9', '4:3', 'auto'
};
const DEFAULT_SHORTCUT = {
toggle: 'v',
refresh: 'r',
style: 's'
};
const CONFIG = {
vipBoxId: vipBoxId,
autoPlayerKey: "auto_player_key_" + window.location.host,
autoPlayerVal: "auto_player_value_" + window.location.host,
flag: "flag_vip",
currentTypeKey: "current_type_key_" + window.location.host,
panelPosKey: "vip_panel_pos_" + window.location.host,
customStyleKey: "vip_custom_style_" + vipBoxId,
customShortcutKey: "vip_custom_shortcut_" + vipBoxId,
customPlayerSizeKey: "vip_custom_player_size_" + vipBoxId,
shortcut: GM_getValue("vip_custom_shortcut_" + vipBoxId, DEFAULT_SHORTCUT)
};
const DOM_CACHE = {
vipBox: null,
vipList: null,
vipTab: null,
donateTab: null,
simpleApiList: null,
complexApiList: null,
addApiForm: null,
styleSetPanel: null,
shortcutSetPanel: null,
playerSizeSetPanel: null,
autoParseSetPanel: null,
apiNameInput: null,
apiUrlInput: null,
apiTypeSelect: null
};
// 全局播放器控制
let globalPlayerCloseBtn = null;
let globalPlayerHideTimer = null;
let globalMouseMoveHandler = null;
let currentParseContainer = null; // 当前解析播放器容器
let currentOriginalContainer = null; // 当前原视频容器
let lastPageUrl = window.location.href; // 记录上次的URL
GM_addStyle(`
#${CONFIG.vipBoxId} {
cursor: pointer;
position: fixed;
top: 120px;
left: 0px;
z-index: 9999999;
text-align: left;
transition: left 0.3s ease;
}
#${CONFIG.vipBoxId}.visible {
left: 0px;
}
#${CONFIG.vipBoxId} .img_box {
width: 32px;
height: 32px;
line-height: 32px;
text-align: center;
background-color: lightgreen;
margin: 10px 0px;
color: white;
font-size: 16px;
font-weight: bold;
border-radius: 5px;
}
#${CONFIG.vipBoxId} .vip_list {
display: none;
position: absolute;
border-radius: 5px;
left: 32px;
top: 0;
text-align: center;
border: 1px solid white;
padding: 10px 0px;
max-height: 80vh;
overflow-y: auto;
opacity: 0;
transform: translateX(-10px);
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
}
#${CONFIG.vipBoxId} .vip_list.visible {
display: block;
opacity: 1;
transform: translateX(0);
}
#${CONFIG.vipBoxId} .vip_list ul {
padding-left: 10px;
margin: 0;
}
#${CONFIG.vipBoxId} .vip_list li {
border-radius: 2px;
font-size: 12px;
text-align: center;
width: calc(25% - 14px);
line-height: 21px;
float: left;
border: 1px solid gray;
padding: 0 4px;
margin: 4px 2px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
opacity: 0;
transform: translateY(10px);
cursor: pointer;
}
#${CONFIG.vipBoxId} .vip_list.visible li {
opacity: 1;
transform: translateY(0);
transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0.1s;
}
#${CONFIG.vipBoxId} .complex-api-list li {
width: calc(50% - 14px);
}
#${CONFIG.vipBoxId} .vip_list li:hover {
border: 1px solid #1c84c6;
}
#${CONFIG.vipBoxId} .vip_list::-webkit-scrollbar {
width: 5px;
height: 1px;
}
#${CONFIG.vipBoxId} .vip_list::-webkit-scrollbar-thumb {
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: #A8A8A8;
}
#${CONFIG.vipBoxId} .vip_list::-webkit-scrollbar-track {
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: #F1F1F1;
}
#${CONFIG.vipBoxId} li.selected {
border: 1px solid #1c84c6;
}
#${CONFIG.vipBoxId} #vip_auto {
background-color: #ff69b4;
}
#${CONFIG.vipBoxId} #add_api_btn, #${CONFIG.vipBoxId} #open-style-set-btn, #${CONFIG.vipBoxId} #open-shortcut-set-btn, #${CONFIG.vipBoxId} #open-player-size-set-btn, #${CONFIG.vipBoxId} #open-auto-parse-set-btn {
background-color: #36383f;
color: #ccc;
border: 1px solid #5a5a5a;
font-size: 12px;
width: auto;
padding: 6px 12px;
margin-top: 5px;
border-radius: 3px;
cursor: pointer;
margin-left: 5px;
}
#${CONFIG.vipBoxId} #add_api_btn:hover, #${CONFIG.vipBoxId} #open-style-set-btn:hover, #${CONFIG.vipBoxId} #open-shortcut-set-btn:hover, #${CONFIG.vipBoxId} #open-player-size-set-btn:hover, #${CONFIG.vipBoxId} #open-auto-parse-set-btn:hover {
background-color: #42444a;
}
.mode-toggle {
cursor: pointer;
margin-left: 2px;
}
.section-title {
font-weight: bold;
font-size: 14px;
padding: 5px 0px;
clear: both;
opacity: 0;
transform: translateY(10px);
}
#${CONFIG.vipBoxId} .vip_list.visible .section-title {
opacity: 1;
transform: translateY(0);
transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0.05s;
}
#${CONFIG.vipBoxId} #donate_section {
clear: both;
margin-top: 10px;
padding: 10px;
text-align: center;
border-top: 1px solid #555;
opacity: 0;
transform: translateY(10px);
}
#${CONFIG.vipBoxId} .vip_list.visible #donate_section {
opacity: 1;
transform: translateY(0);
transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0.15s;
}
#${CONFIG.vipBoxId} #donate_section .donate-title {
font-size: 12px;
margin-bottom: 5px;
}
#${CONFIG.vipBoxId} #qr-code-img {
max-width: 100px;
max-height: 100px;
margin-top: 5px;
border: 1px solid #ddd;
background: white;
}
#${CONFIG.vipBoxId} .tab-header {
display: flex;
}
#${CONFIG.vipBoxId} .tab-button {
flex: 1;
padding: 5px 0;
border: none;
cursor: pointer;
outline: none;
font-size: 12px;
background: none;
}
#${CONFIG.vipBoxId} .tab-button.active {
font-weight: bold;
color: #1c84c6 !important;
}
#${CONFIG.vipBoxId} .tab-divider {
width: 1px;
background-color: #5a5a5a;
margin: 5px 0;
}
#${CONFIG.vipBoxId} .tab-content {
display: none;
}
#${CONFIG.vipBoxId} .tab-content.active {
display: block;
}
#${CONFIG.vipBoxId} .add-api-form {
padding: 10px;
border-radius: 4px;
margin: 10px;
display: none;
}
#${CONFIG.vipBoxId} .add-api-form input,
#${CONFIG.vipBoxId} .add-api-form select,
#vip-style-set-panel input,
#vip-shortcut-set-panel input,
#vip-player-size-set-panel input,
#vip-player-size-set-panel select,
#vip-auto-parse-set-panel select {
width: 100%;
padding: 6px;
margin: 5px 0;
border-radius: 3px;
border: 1px solid #5a5a5a;
background-color: #2c2e34;
color: #ccc;
}
#${CONFIG.vipBoxId} .add-api-form button {
padding: 8px 12px;
margin: 5px 2px;
border: none;
border-radius: 3px;
cursor: pointer;
background-color: #1c84c6;
color: white;
font-size: 12px;
}
#${CONFIG.vipBoxId} .add-api-form .cancel-btn {
background-color: #72747a;
}
#vip-style-set-panel, #vip-shortcut-set-panel, #vip-player-size-set-panel, #vip-auto-parse-set-panel {
padding: 10px;
margin: 10px;
border-top: 1px solid #555;
display: none;
}
#vip-style-set-panel .style-item, #vip-shortcut-set-panel .shortcut-item, #vip-player-size-set-panel .style-item, #vip-auto-parse-set-panel .auto-parse-item {
display: flex;
align-items: center;
margin: 8px 0;
gap: 8px;
}
#vip-style-set-panel .style-item label, #vip-shortcut-set-panel .shortcut-item label, #vip-player-size-set-panel .style-item label, #vip-auto-parse-set-panel .auto-parse-item label {
font-size: 12px;
width: 80px;
text-align: left;
}
#vip-style-set-panel .style-item input, #vip-shortcut-set-panel .shortcut-item input, #vip-player-size-set-panel .style-item input, #vip-player-size-set-panel .style-item select, #vip-auto-parse-set-panel .auto-parse-item select {
flex: 1;
padding: 4px;
}
#vip-style-set-panel button,
#vip-shortcut-set-panel button,
#vip-player-size-set-panel button,
#vip-auto-parse-set-panel button {
width: 40%;
padding: 8px 12px;
margin: 5px 1%;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
display: inline-block;
}
#reset-style-btn, #reset-shortcut-btn, #reset-player-size-btn, #disable-auto-parse-btn {
background: #ff69b4 !important;
color: white !important;
}
#save-player-size-btn, #save-auto-parse-btn, #save-shortcut-btn, #save-style-btn {
background: #1c84c6 !important;
color: white !important;
}
.shortcut-tip {
font-size: 10px;
color: #ccc;
margin-top: 5px;
text-align: left;
line-height: 1.4;
}
/* 播放器控制按钮样式 */
.vip-player-close-btn {
position: absolute;
top: 15px;
right: 15px;
z-index: 10000000;
width: auto;
height: auto;
padding: 5px 10px;
background: transparent;
border: none;
cursor: pointer;
font-size: 32px;
color: rgba(255, 255, 255, 0.8);
transition: all 0.3s ease;
opacity: 1;
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
pointer-events: auto;
}
.vip-player-close-btn:hover {
color: rgba(255, 255, 255, 1);
transform: scale(1.2);
}
.vip-player-close-btn.hidden {
opacity: 0;
pointer-events: none;
}
.vip-player-tip {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 10000000;
background: transparent;
color: rgba(255, 255, 255, 0.9);
padding: 0;
border-radius: 0;
font-size: 14px;
border: none;
transition: opacity 0.5s ease;
text-shadow: 0 2px 4px rgba(0,0,0,0.8);
pointer-events: none;
}
.vip-mouse-catcher {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999999;
pointer-events: auto;
}
.vip-mouse-catcher.inactive {
pointer-events: none;
}
`);
function findTargetElement(targetContainer) {
const body = window.document;
let tabContainer;
let tryTime = 0;
const maxTryTime = 120;
let startTimestamp;
return new Promise((resolve, reject) => {
function tryFindElement(timestamp) {
if (!startTimestamp) {
startTimestamp = timestamp;
}
const elapsedTime = timestamp - startTimestamp;
if (elapsedTime >= 500) {
tabContainer = body.querySelector(targetContainer);
if (tabContainer) {
resolve(tabContainer);
} else if (++tryTime === maxTryTime) {
reject();
} else {
startTimestamp = timestamp;
}
}
if (!tabContainer && tryTime < maxTryTime) {
requestAnimationFrame(tryFindElement);
}
}
requestAnimationFrame(tryFindElement);
});
}
function encodeVideoUrl(url) {
if (!url) return '';
return encodeURIComponent(url).replace(/%20/g, '+');
}
function renderApiLists() {
if (!DOM_CACHE.vipTab) return;
let simpleApisHtml = "
[内嵌播放+弹窗无选集]
";
let complexApisHtml = "[弹窗带选集]
";
allApis.forEach((item, index) => {
const types = item.type.split(',');
const name = item.name;
if (types.includes("1") || types.includes("3")) {
if ((types.includes("1") || types.includes("3")) && !types.includes("2")) {
if (types.includes("1") && types.includes("3")) {
simpleApisHtml += `- ${name} | 内嵌
`;
} else if (types.includes("1")) {
simpleApisHtml += `- ${name} | 内嵌
`;
} else if (types.includes("3")) {
simpleApisHtml += `- ${name} | 弹窗
`;
}
}
if (types.includes("1") && types.includes("2") && types.includes("3")) {
simpleApisHtml += `- ${name} | 内嵌
`;
}
}
if (types.includes("2")) {
complexApisHtml += `- ${name}
`;
}
});
simpleApisHtml += "
";
complexApisHtml += "
";
const tabContent = DOM_CACHE.vipTab.innerHTML;
const descText = tabContent.match(/([\s\S]*?<\/div>)/)[0];
DOM_CACHE.vipTab.innerHTML = simpleApisHtml + complexApisHtml + descText;
DOM_CACHE.simpleApiList = DOM_CACHE.vipTab.querySelector('.simple-api-list');
DOM_CACHE.complexApiList = DOM_CACHE.vipTab.querySelector('.complex-api-list');
applyPanelStyle();
}
function applyPanelStyle(style = null) {
const customStyle = style || GM_getValue(CONFIG.customStyleKey, DEFAULT_STYLE);
if (!DOM_CACHE.vipList) return;
const fontColor = customStyle.fontColor;
const bgColor = customStyle.bgColor;
// 应用背景色和字体色
DOM_CACHE.vipList.style.backgroundColor = bgColor;
DOM_CACHE.vipList.style.color = fontColor;
DOM_CACHE.vipList.style.opacity = customStyle.opacity;
DOM_CACHE.vipList.style.width = customStyle.width;
// 应用到所有子元素
DOM_CACHE.vipList.querySelectorAll('.section-title').forEach(el => {
el.style.color = fontColor;
});
DOM_CACHE.vipList.querySelectorAll('.api-item').forEach(el => {
el.style.color = fontColor;
el.style.borderColor = 'rgba(128,128,128,0.5)';
});
DOM_CACHE.vipList.querySelectorAll('.mode-toggle').forEach(el => {
el.style.color = '#1c84c6';
});
DOM_CACHE.vipList.querySelectorAll('.tab-button').forEach(el => {
if (!el.classList.contains('active')) {
el.style.color = fontColor;
}
});
DOM_CACHE.vipList.querySelectorAll('.tab-header').forEach(el => {
el.style.backgroundColor = bgColor;
});
DOM_CACHE.vipList.querySelectorAll('#donate_section').forEach(el => {
el.style.color = fontColor;
});
DOM_CACHE.vipList.querySelectorAll('.add-api-form').forEach(el => {
el.style.backgroundColor = bgColor;
});
// 应用到样式设置面板
if (DOM_CACHE.styleSetPanel) {
DOM_CACHE.styleSetPanel.style.backgroundColor = bgColor;
DOM_CACHE.styleSetPanel.style.color = fontColor;
}
// 应用到快捷键设置面板
if (DOM_CACHE.shortcutSetPanel) {
DOM_CACHE.shortcutSetPanel.style.backgroundColor = bgColor;
DOM_CACHE.shortcutSetPanel.style.color = fontColor;
}
// 应用到播放器尺寸设置面板
if (DOM_CACHE.playerSizeSetPanel) {
DOM_CACHE.playerSizeSetPanel.style.backgroundColor = bgColor;
DOM_CACHE.playerSizeSetPanel.style.color = fontColor;
}
// 应用到自动解析设置面板
if (DOM_CACHE.autoParseSetPanel) {
DOM_CACHE.autoParseSetPanel.style.backgroundColor = bgColor;
DOM_CACHE.autoParseSetPanel.style.color = fontColor;
}
GM_setValue(CONFIG.customStyleKey, customStyle);
}
function createStyleSetPanel() {
if (DOM_CACHE.styleSetPanel) return;
const customStyle = GM_getValue(CONFIG.customStyleKey, DEFAULT_STYLE);
const panel = document.createElement('div');
panel.id = 'vip-style-set-panel';
panel.innerHTML = `
`;
DOM_CACHE.donateTab.appendChild(panel);
DOM_CACHE.styleSetPanel = panel;
// 实时预览功能
panel.querySelector('#style-bgcolor').addEventListener('input', (e) => {
applyPanelStyle({
...GM_getValue(CONFIG.customStyleKey, DEFAULT_STYLE),
bgColor: e.target.value
});
});
panel.querySelector('#style-fontcolor').addEventListener('input', (e) => {
applyPanelStyle({
...GM_getValue(CONFIG.customStyleKey, DEFAULT_STYLE),
fontColor: e.target.value
});
});
panel.querySelector('#style-opacity').addEventListener('input', (e) => {
applyPanelStyle({
...GM_getValue(CONFIG.customStyleKey, DEFAULT_STYLE),
opacity: e.target.value
});
});
panel.querySelector('#style-width').addEventListener('blur', (e) => {
if (!e.target.value) return;
applyPanelStyle({
...GM_getValue(CONFIG.customStyleKey, DEFAULT_STYLE),
width: e.target.value
});
});
// 保存按钮
panel.querySelector('#save-style-btn').addEventListener('click', () => {
const bgColor = panel.querySelector('#style-bgcolor').value;
const fontColor = panel.querySelector('#style-fontcolor').value;
const opacity = panel.querySelector('#style-opacity').value;
const width = panel.querySelector('#style-width').value;
const newStyle = { bgColor, fontColor, opacity, width };
GM_setValue(CONFIG.customStyleKey, newStyle);
applyPanelStyle(newStyle);
Swal.fire({
title: '保存成功',
text: '样式设置已保存',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
});
// 重置按钮
panel.querySelector('#reset-style-btn').addEventListener('click', () => {
applyPanelStyle(DEFAULT_STYLE);
panel.querySelector('#style-bgcolor').value = DEFAULT_STYLE.bgColor;
panel.querySelector('#style-fontcolor').value = DEFAULT_STYLE.fontColor;
panel.querySelector('#style-opacity').value = DEFAULT_STYLE.opacity;
panel.querySelector('#style-width').value = DEFAULT_STYLE.width;
Swal.fire({
title: '重置成功',
text: '已恢复默认样式',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
});
}
function createShortcutSetPanel() {
if (DOM_CACHE.shortcutSetPanel) return;
const customShortcut = GM_getValue(CONFIG.customShortcutKey, DEFAULT_SHORTCUT);
const panel = document.createElement('div');
panel.id = 'vip-shortcut-set-panel';
panel.innerHTML = `
提示:仅支持单字母/数字,使用方式为 Alt + 自定义键
`;
DOM_CACHE.donateTab.appendChild(panel);
DOM_CACHE.shortcutSetPanel = panel;
panel.querySelector('#save-shortcut-btn').addEventListener('click', () => {
const toggle = panel.querySelector('#shortcut-toggle').value.trim().toLowerCase();
const refresh = panel.querySelector('#shortcut-refresh').value.trim().toLowerCase();
const style = panel.querySelector('#shortcut-style').value.trim().toLowerCase();
if (!toggle || !refresh || !style) {
Swal.fire('提示', '快捷键不能为空!', 'warning');
return;
}
const newShortcut = { toggle, refresh, style };
GM_setValue(CONFIG.customShortcutKey, newShortcut);
CONFIG.shortcut = newShortcut;
Swal.fire({
title: '保存成功',
text: '快捷键已保存,立即生效',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
});
panel.querySelector('#reset-shortcut-btn').addEventListener('click', () => {
GM_setValue(CONFIG.customShortcutKey, DEFAULT_SHORTCUT);
CONFIG.shortcut = DEFAULT_SHORTCUT;
panel.querySelector('#shortcut-toggle').value = DEFAULT_SHORTCUT.toggle;
panel.querySelector('#shortcut-refresh').value = DEFAULT_SHORTCUT.refresh;
panel.querySelector('#shortcut-style').value = DEFAULT_SHORTCUT.style;
Swal.fire({
title: '重置成功',
text: '已恢复默认快捷键',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
});
}
function createPlayerSizeSetPanel() {
if (DOM_CACHE.playerSizeSetPanel) return;
const customSize = GM_getValue(CONFIG.customPlayerSizeKey, DEFAULT_PLAYER_SIZE);
// 提取数字部分
const widthNum = customSize.width.replace('px', '');
const heightNum = customSize.minHeight.replace('px', '');
const panel = document.createElement('div');
panel.id = 'vip-player-size-set-panel';
panel.innerHTML = `
px
px
提示:修改后立即生效,下次解析时应用新尺寸
`;
DOM_CACHE.donateTab.appendChild(panel);
DOM_CACHE.playerSizeSetPanel = panel;
panel.querySelector('#save-player-size-btn').addEventListener('click', () => {
const width = panel.querySelector('#player-width').value.trim();
const minHeight = panel.querySelector('#player-min-height').value.trim();
const aspectRatio = panel.querySelector('#player-aspect-ratio').value;
if (!minHeight || !width) {
Swal.fire('提示', '请输入宽度和最小高度!', 'warning');
return;
}
// 自动添加px单位
const newSize = {
width: width + 'px',
minHeight: minHeight + 'px',
aspectRatio
};
GM_setValue(CONFIG.customPlayerSizeKey, newSize);
Swal.fire({
title: '保存成功',
text: '播放器尺寸已保存,下次解析时生效',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
});
panel.querySelector('#reset-player-size-btn').addEventListener('click', () => {
GM_setValue(CONFIG.customPlayerSizeKey, DEFAULT_PLAYER_SIZE);
panel.querySelector('#player-width').value = DEFAULT_PLAYER_SIZE.width.replace('px', '');
panel.querySelector('#player-min-height').value = DEFAULT_PLAYER_SIZE.minHeight.replace('px', '');
panel.querySelector('#player-aspect-ratio').value = DEFAULT_PLAYER_SIZE.aspectRatio;
Swal.fire({
title: '重置成功',
text: '已恢复默认尺寸',
icon: 'success',
timer: 1500,
showConfirmButton: false
});
});
}
function createAutoParseSetPanel() {
if (DOM_CACHE.autoParseSetPanel) return;
const panel = document.createElement('div');
panel.id = 'vip-auto-parse-set-panel';
// 构建接口选项列表(只包含支持内嵌播放的接口)
let optionsHtml = '
';
allApis.forEach((api, index) => {
if (api.type.includes("1")) {
optionsHtml += `
`;
}
});
const currentIndex = GM_getValue(CONFIG.autoPlayerVal, 0);
const isAutoEnabled = !!GM_getValue(CONFIG.autoPlayerKey, null);
panel.innerHTML = `
提示:选择后点击保存,然后通过顶部"开/关"按钮控制自动解析
`;
DOM_CACHE.donateTab.appendChild(panel);
DOM_CACHE.autoParseSetPanel = panel;
// 设置当前选中的接口
const selectElement = panel.querySelector('#auto-parse-api-select');
selectElement.value = currentIndex;
// 保存并开启按钮
panel.querySelector('#save-auto-parse-btn').addEventListener('click', () => {
const selectedIndex = parseInt(selectElement.value);
if (selectedIndex === -1) {
Swal.fire('提示', '请先选择一个解析接口!', 'warning');
return;
}
const selectedApi = allApis[selectedIndex];
GM_setValue(CONFIG.autoPlayerVal, selectedIndex);
Swal.fire({
title: '保存成功',
html: `已设置
${selectedApi.name} 为自动解析接口
通过顶部"开/关"按钮控制自动解析`,
icon: 'success',
timer: 2000,
showConfirmButton: false
});
// 更新自动解析按钮的提示
const autoBtn = DOM_CACHE.vipBox.querySelector("#vip_auto");
if (autoBtn && !!GM_getValue(CONFIG.autoPlayerKey, null)) {
autoBtn.title = `自动解析源:${selectedApi.name}`;
}
});
// 关闭自动解析按钮
panel.querySelector('#disable-auto-parse-btn').addEventListener('click', () => {
GM_setValue(CONFIG.autoPlayerKey, null);
Swal.fire({
title: '已关闭自动解析',
text: '刷新页面后生效',
icon: 'info',
timer: 1500,
showConfirmButton: false
});
// 更新自动解析按钮状态
const autoBtn = DOM_CACHE.vipBox.querySelector("#vip_auto");
if (autoBtn) {
autoBtn.innerHTML = "关";
autoBtn.title = "点击开启自动解析";
}
setTimeout(() => {
window.location.reload();
}, 1500);
});
}
function clearOriginalVideoSound() {
// 第一步:立即清除所有媒体元素
const clearMedia = () => {
// 清除所有video和audio标签
const allVideos = document.querySelectorAll('video');
const allAudios = document.querySelectorAll('audio');
allVideos.forEach(media => {
try {
// 多重保险措施
media.muted = true;
media.pause();
media.volume = 0;
// 移除所有事件监听器(防止自动播放)
media.onplay = (e) => { e.preventDefault(); media.pause(); };
media.onplaying = (e) => { e.preventDefault(); media.pause(); };
media.onvolumechange = (e) => { media.muted = true; media.volume = 0; };
// 清除src
if (media.src) {
media.removeAttribute('src');
media.src = '';
}
// 清除source标签
const sources = media.querySelectorAll('source');
sources.forEach(s => s.remove());
if (media.load) media.load();
// 隐藏视频元素
media.style.display = 'none';
media.style.visibility = 'hidden';
media.style.opacity = '0';
} catch (e) {
console.log('清除视频失败:', e);
}
});
allAudios.forEach(media => {
try {
media.muted = true;
media.pause();
media.volume = 0;
media.onplay = (e) => { e.preventDefault(); media.pause(); };
if (media.src) {
media.removeAttribute('src');
media.src = '';
}
if (media.load) media.load();
media.style.display = 'none';
} catch (e) {
console.log('清除音频失败:', e);
}
});
// 清除iframe中的媒体
const iframes = document.querySelectorAll('iframe');
iframes.forEach(iframe => {
try {
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
if (iframeDoc) {
const iframeVideos = iframeDoc.querySelectorAll('video, audio');
iframeVideos.forEach(m => {
m.muted = true;
m.pause();
m.volume = 0;
m.onplay = (e) => { e.preventDefault(); m.pause(); };
});
}
} catch (e) {
// 跨域iframe无法访问
}
});
// 清除特定播放器容器中的媒体
const playerContainers = [
"#player", "#mod_player", "#player-container", ".container-player",
"#mgtv-player-wrap", "#player_module", "#bilibiliPlayer",
"#bilibili-player", "#flashbox", ".m-video-player-wrap",
".intl-video-wrap", ".td-playbox", "#pptv_playpage_box",
".w-video", "#flashContent", "#vodPlayer", ".prism-player",
"#playerCon", ".video-player", "#J_prismPlayer", ".txp_video"
];
playerContainers.forEach(selector => {
const container = document.querySelector(selector);
if (container) {
const innerMedia = container.querySelectorAll('video, audio');
innerMedia.forEach(m => {
m.muted = true;
m.pause();
m.volume = 0;
m.onplay = (e) => { e.preventDefault(); m.pause(); };
if (m.src) {
m.removeAttribute('src');
m.src = '';
}
});
}
});
};
// 立即执行一次
clearMedia();
// 阻止所有媒体播放的全局监听器
const preventPlay = (e) => {
const target = e.target;
if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
// 检查是否是我们的解析iframe
const isOurIframe = target.closest('iframe')?.src?.includes('jx.') ||
target.closest('#vip-video-container');
if (!isOurIframe) {
e.preventDefault();
e.stopPropagation();
target.pause();
target.muted = true;
target.volume = 0;
}
}
};
// 添加全局事件监听器(捕获阶段)
document.addEventListener('play', preventPlay, true);
document.addEventListener('playing', preventPlay, true);
document.addEventListener('volumechange', (e) => {
const target = e.target;
if (target.tagName === 'VIDEO' || target.tagName === 'AUDIO') {
const isOurIframe = target.closest('iframe')?.src?.includes('jx.') ||
target.closest('#vip-video-container');
if (!isOurIframe) {
target.muted = true;
target.volume = 0;
}
}
}, true);
// 持续监控并清除(前10秒每300ms一次,之后每1秒一次,共持续30秒)
let timer = 0;
const fastInterval = setInterval(() => {
clearMedia();
timer++;
if (timer >= 33) { // 10秒
clearInterval(fastInterval);
// 切换到慢速监控
let slowTimer = 0;
const slowInterval = setInterval(() => {
clearMedia();
slowTimer++;
if (slowTimer >= 20) { // 20秒
clearInterval(slowInterval);
// 移除全局事件监听器
document.removeEventListener('play', preventPlay, true);
document.removeEventListener('playing', preventPlay, true);
}
}, 1000);
}
}, 300);
// 使用MutationObserver监控DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) { // 元素节点
if (node.tagName === 'VIDEO' || node.tagName === 'AUDIO') {
node.muted = true;
node.pause();
node.volume = 0;
node.onplay = (e) => { e.preventDefault(); node.pause(); };
node.style.display = 'none';
}
// 检查子元素
const childMedia = node.querySelectorAll?.('video, audio');
childMedia?.forEach(m => {
m.muted = true;
m.pause();
m.volume = 0;
m.onplay = (e) => { e.preventDefault(); m.pause(); };
m.style.display = 'none';
});
}
});
});
});
// 开始观察
observer.observe(document.body, {
childList: true,
subtree: true
});
// 30秒后停止观察
setTimeout(() => {
observer.disconnect();
}, 30000);
}
function createVipButton() {
if (document.getElementById(CONFIG.vipBoxId)) return;
let currentType = GM_getValue(CONFIG.currentTypeKey, "1");
let simpleApisHtml = "
[内嵌播放+弹窗无选集]
";
let complexApisHtml = "[弹窗带选集]
";
allApis.forEach((item, index) => {
const types = item.type.split(',');
const name = item.name;
if (types.includes("1") || types.includes("3")) {
if ((types.includes("1") || types.includes("3")) && !types.includes("2")) {
if (types.includes("1") && types.includes("3")) {
simpleApisHtml += `- ${name} | 内嵌
`;
} else if (types.includes("1")) {
simpleApisHtml += `- ${name} | 内嵌
`;
} else if (types.includes("3")) {
simpleApisHtml += `- ${name} | 弹窗
`;
}
}
if (types.includes("1") && types.includes("2") && types.includes("3")) {
simpleApisHtml += `- ${name} | 内嵌
`;
}
}
if (types.includes("2")) {
complexApisHtml += `- ${name}
`;
}
});
simpleApisHtml += "
";
complexApisHtml += "
";
let customAndDonateHtml = `
`;
let autoPlay = !!GM_getValue(CONFIG.autoPlayerKey, null) ? "开" : "关";
const vipBox = document.createElement('div');
vipBox.id = CONFIG.vipBoxId;
vipBox.innerHTML = `
VIP
${simpleApisHtml}
${complexApisHtml}
📖 使用说明:
1、解析视频:点击内嵌播放接口即可解析当前视频(推荐"七哥"或"虾米")
2、播放模式:点击接口名称右侧的"内嵌/弹窗"可切换播放模式
3、解析切集后:解析完切换新集数后会自动关闭旧播放器,如开启自动解析则自动解析新集数
4、自动解析:在"自动解析设置"中选择接口(默认七哥),点击顶部"开/关"按钮控制
5、自定义设置:可自定义面板样式、快捷键、播放器尺寸、添加解析接口等
6、快捷键:Alt+V 呼出/隐藏浮标,Alt+R 刷新接口,Alt+S 打开样式设置
${customAndDonateHtml}
${autoPlay}
`;
const savePos = GM_getValue(CONFIG.panelPosKey, { top: 120, left: 0 });
vipBox.style.top = savePos.top + 'px';
vipBox.style.left = savePos.left + 'px';
findTargetElement('body')
.then((container) => {
container.appendChild(vipBox);
initDOMCache(vipBox);
if (!!GM_getValue(CONFIG.autoPlayerKey, null)) {
setTimeout(() => {
autoPlayVideo();
}, 2500);
}
})
.catch(() => {
document.body.appendChild(vipBox);
initDOMCache(vipBox);
if (!!GM_getValue(CONFIG.autoPlayerKey, null)) {
setTimeout(() => {
autoPlayVideo();
}, 2500);
}
});
}
function initDOMCache(vipBox) {
DOM_CACHE.vipBox = vipBox;
DOM_CACHE.vipList = vipBox.querySelector('.vip_list');
DOM_CACHE.vipTab = vipBox.querySelector('#vip-tab');
DOM_CACHE.donateTab = vipBox.querySelector('#donate-tab');
DOM_CACHE.addApiForm = vipBox.querySelector('#add-api-form');
DOM_CACHE.apiNameInput = vipBox.querySelector('#api-name');
DOM_CACHE.apiUrlInput = vipBox.querySelector('#api-url');
DOM_CACHE.apiTypeSelect = vipBox.querySelector('#api-type');
DOM_CACHE.simpleApiList = vipBox.querySelector('.simple-api-list');
DOM_CACHE.complexApiList = vipBox.querySelector('.complex-api-list');
createStyleSetPanel();
createShortcutSetPanel();
createPlayerSizeSetPanel();
createAutoParseSetPanel();
applyPanelStyle();
bindEvents();
}
function togglePlayMode(element) {
const listItem = element.closest('.api-item');
const modes = listItem.dataset.modes.split(',');
const currentMode = listItem.dataset.currentMode;
let nextModeIndex = modes.indexOf(currentMode) + 1;
if (nextModeIndex >= modes.length) nextModeIndex = 0;
const nextMode = modes[nextModeIndex];
let modeText = nextMode === "1" ? "内嵌" : "弹窗";
element.textContent = modeText;
listItem.dataset.currentMode = nextMode;
}
function bindEvents() {
const vipBox = DOM_CACHE.vipBox;
const vipList = DOM_CACHE.vipList;
vipBox.querySelector(".vip_icon").addEventListener("mouseover", () => {
vipBox.classList.add("visible");
vipList.classList.add("visible");
setTimeout(() => {
const items = vipList.querySelectorAll('li, .section-title, #donate_section');
items.forEach((item, index) => {
setTimeout(() => {
item.style.transitionDelay = '0ms';
}, index * 30);
});
}, 50);
});
vipBox.querySelector(".vip_icon").addEventListener("mouseout", (e) => {
// 检查鼠标是否移动到vipList上
const relatedTarget = e.relatedTarget;
if (relatedTarget && (vipList.contains(relatedTarget) || relatedTarget === vipList)) {
return; // 如果移动到列表上,不隐藏
}
vipList.classList.remove("visible");
vipBox.classList.remove("visible");
const items = vipList.querySelectorAll('li, .section-title, #donate_section');
items.forEach(item => {
item.style.transitionDelay = '';
});
});
// vipList的鼠标事件
vipList.addEventListener("mouseenter", () => {
vipBox.classList.add("visible");
vipList.classList.add("visible");
});
vipList.addEventListener("mouseleave", () => {
vipList.classList.remove("visible");
vipBox.classList.remove("visible");
const items = vipList.querySelectorAll('li, .section-title, #donate_section');
items.forEach(item => {
item.style.transitionDelay = '';
});
});
const tabButtons = vipBox.querySelectorAll(".tab-button");
tabButtons.forEach(button => {
button.addEventListener("click", function() {
tabButtons.forEach(btn => btn.classList.remove("active"));
vipBox.querySelectorAll(".tab-content").forEach(content => content.classList.remove("active"));
this.classList.add("active");
const tabId = this.getAttribute("data-tab");
vipBox.querySelector(`#${tabId}-tab`).classList.add("active");
});
});
vipBox.querySelector('#open-style-set-btn').addEventListener('click', (e) => {
e.stopPropagation();
const stylePanel = DOM_CACHE.styleSetPanel;
const isVisible = stylePanel.style.display === 'block';
// 隐藏所有设置面板
DOM_CACHE.addApiForm.style.display = 'none';
DOM_CACHE.styleSetPanel.style.display = 'none';
DOM_CACHE.shortcutSetPanel.style.display = 'none';
DOM_CACHE.playerSizeSetPanel.style.display = 'none';
DOM_CACHE.autoParseSetPanel.style.display = 'none';
// 切换当前面板
stylePanel.style.display = isVisible ? 'none' : 'block';
});
vipBox.querySelector('#open-shortcut-set-btn').addEventListener('click', (e) => {
e.stopPropagation();
const shortcutPanel = DOM_CACHE.shortcutSetPanel;
const isVisible = shortcutPanel.style.display === 'block';
// 隐藏所有设置面板
DOM_CACHE.addApiForm.style.display = 'none';
DOM_CACHE.styleSetPanel.style.display = 'none';
DOM_CACHE.shortcutSetPanel.style.display = 'none';
DOM_CACHE.playerSizeSetPanel.style.display = 'none';
DOM_CACHE.autoParseSetPanel.style.display = 'none';
// 切换当前面板
shortcutPanel.style.display = isVisible ? 'none' : 'block';
});
vipBox.querySelector('#open-player-size-set-btn').addEventListener('click', (e) => {
e.stopPropagation();
const playerSizePanel = DOM_CACHE.playerSizeSetPanel;
const isVisible = playerSizePanel.style.display === 'block';
// 隐藏所有设置面板
DOM_CACHE.addApiForm.style.display = 'none';
DOM_CACHE.styleSetPanel.style.display = 'none';
DOM_CACHE.shortcutSetPanel.style.display = 'none';
DOM_CACHE.playerSizeSetPanel.style.display = 'none';
DOM_CACHE.autoParseSetPanel.style.display = 'none';
// 切换当前面板
playerSizePanel.style.display = isVisible ? 'none' : 'block';
});
vipBox.querySelector('#open-auto-parse-set-btn').addEventListener('click', (e) => {
e.stopPropagation();
const autoParsePanel = DOM_CACHE.autoParseSetPanel;
const isVisible = autoParsePanel.style.display === 'block';
// 隐藏所有设置面板
DOM_CACHE.addApiForm.style.display = 'none';
DOM_CACHE.styleSetPanel.style.display = 'none';
DOM_CACHE.shortcutSetPanel.style.display = 'none';
DOM_CACHE.playerSizeSetPanel.style.display = 'none';
DOM_CACHE.autoParseSetPanel.style.display = 'none';
// 切换当前面板
autoParsePanel.style.display = isVisible ? 'none' : 'block';
});
const addApiBtn = vipBox.querySelector("#add_api_btn");
if (addApiBtn) {
addApiBtn.addEventListener("click", function(e) {
e.stopPropagation();
const isVisible = DOM_CACHE.addApiForm.style.display === "block";
// 隐藏所有设置面板
DOM_CACHE.addApiForm.style.display = 'none';
DOM_CACHE.styleSetPanel.style.display = 'none';
DOM_CACHE.shortcutSetPanel.style.display = 'none';
DOM_CACHE.playerSizeSetPanel.style.display = 'none';
DOM_CACHE.autoParseSetPanel.style.display = 'none';
// 切换当前面板
DOM_CACHE.addApiForm.style.display = isVisible ? "none" : "block";
});
}
const saveApiBtn = vipBox.querySelector("#save-api-btn");
if (saveApiBtn) {
saveApiBtn.addEventListener("click", function(e) {
e.stopPropagation();
const name = DOM_CACHE.apiNameInput.value.trim();
const url = DOM_CACHE.apiUrlInput.value.trim();
const type = DOM_CACHE.apiTypeSelect.value;
if (!name || !url) {
alert('请填写完整信息');
return;
}
if (!url.includes('?url=') && !url.includes('&url=')) {
alert('接口地址必须包含 "?url=" 或 "&url=" 参数占位符');
return;
}
const newApi = { name, type, url };
customApis.push(newApi);
allApis = [...uniqueApis, ...customApis];
GM_setValue("custom_parse_apis", customApis);
DOM_CACHE.addApiForm.reset();
DOM_CACHE.addApiForm.style.display = "none";
renderApiLists();
Swal.fire('添加成功', '自定义接口已添加,直接使用无需刷新!', 'success');
});
}
const cancelApiBtn = vipBox.querySelector("#cancel-api-btn");
if (cancelApiBtn) {
cancelApiBtn.addEventListener("click", function(e) {
e.stopPropagation();
DOM_CACHE.addApiForm.style.display = "none";
});
}
vipBox.querySelector('#vip-tab').addEventListener("click", (e) => {
if (e.target.classList.contains('mode-toggle')) {
togglePlayMode(e.target);
return;
}
const apiItem = e.target.closest('.api-item');
if (!apiItem) return;
const index = parseInt(apiItem.getAttribute("data-index"));
const videoObj = allApis[index];
let apiType;
if (apiItem.classList.contains('combined-simple')) {
apiType = apiItem.dataset.currentMode;
} else {
apiType = apiItem.getAttribute("data-mode");
}
if (apiType === "1") {
// 保存选中的接口索引(用于自动解析)
GM_setValue(CONFIG.autoPlayerVal, index);
GM_setValue(CONFIG.flag, "true");
playVideo(videoObj, true, encodeVideoUrl(window.location.href));
vipBox.querySelectorAll(".api-item").forEach(li => li.classList.remove("selected"));
apiItem.classList.add("selected");
// 更新自动解析按钮的提示
if (!!GM_getValue(CONFIG.autoPlayerKey, null)) {
vipBox.querySelector("#vip_auto").title = `自动解析源:${videoObj.name}`;
}
} else {
const encodedUrl = encodeVideoUrl(window.location.href);
const parseUrl = videoObj.url + encodedUrl;
GM_openInTab(parseUrl, {active: true, insert: true, setParent: true});
}
});
vipBox.querySelector("#vip_auto").addEventListener("click", function() {
if (!!GM_getValue(CONFIG.autoPlayerKey, null)) {
// 如果已开启,点击关闭
GM_setValue(CONFIG.autoPlayerKey, null);
this.innerHTML = "关";
this.title = "点击开启自动解析";
Swal.fire({
title: '已关闭自动解析',
text: '刷新页面后生效',
icon: 'info',
timer: 1500,
showConfirmButton: false
});
setTimeout(() => {
window.location.reload();
}, 1500);
} else {
// 检查是否已设置接口
const selectedIndex = GM_getValue(CONFIG.autoPlayerVal, 0);
const selectedApi = allApis[selectedIndex];
if (!selectedApi || !selectedApi.type.includes("1")) {
Swal.fire({
title: '请先设置自动解析接口',
text: '点击下方"自动解析设置"按钮选择解析接口',
icon: 'info',
confirmButtonText: '知道了'
});
return;
}
// 开启自动解析
GM_setValue(CONFIG.autoPlayerKey, "true");
this.innerHTML = "开";
this.title = `自动解析源:${selectedApi.name}`;
Swal.fire({
title: '已开启自动解析',
html: `使用
${selectedApi.name} 自动解析
刷新页面后生效`,
icon: 'success',
timer: 1500,
showConfirmButton: false
});
setTimeout(() => {
window.location.reload();
}, 1500);
}
});
vipBox.addEventListener("mousedown", function(e) {
if (e.button !== 0) return;
const target = e.target;
const vipIcon = vipBox.querySelector(".vip_icon");
const autoBtn = vipBox.querySelector("#vip_auto");
if (vipBox.querySelector(".vip_list").contains(target)) return;
if (!vipIcon.contains(target) && target !== autoBtn) return;
e.preventDefault();
vipBox.style.cursor = "move";
const oldTransition = vipBox.style.transition;
vipBox.style.transition = "none";
const positionDiv = vipBox.getBoundingClientRect();
let distenceX = e.clientX - positionDiv.left;
let distenceY = e.clientY - positionDiv.top;
document.addEventListener("mousemove", moveHandler);
document.addEventListener("mouseup", upHandler);
function moveHandler(e) {
let x = e.clientX - distenceX;
let y = e.clientY - distenceY;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
if (x < 0) x = 0;
else if (x > windowWidth - vipBox.offsetWidth - 100) {
x = windowWidth - vipBox.offsetWidth - 100;
}
if (y < 0) y = 0;
else if (y > windowHeight - vipBox.offsetHeight) {
y = windowHeight - vipBox.offsetHeight;
}
vipBox.style.left = x + "px";
vipBox.style.top = y + "px";
}
function upHandler() {
document.removeEventListener("mousemove", moveHandler);
document.removeEventListener("mouseup", upHandler);
vipBox.style.cursor = "pointer";
vipBox.style.transition = oldTransition;
GM_setValue(CONFIG.panelPosKey, {
left: parseInt(vipBox.style.left),
top: parseInt(vipBox.style.top)
});
}
});
}
function addCustomApi() {
Swal.fire({
title: '添加自定义解析接口',
html: `
`,
confirmButtonText: '添加',
focusConfirm: false,
preConfirm: () => {
const name = document.getElementById('api-name').value;
const url = document.getElementById('api-url').value;
const type = document.getElementById('api-type').value;
if (!name || !url) {
Swal.showValidationMessage('请填写完整信息');
return false;
}
if (!url.includes('?url=') && !url.includes('&url=')) {
Swal.showValidationMessage('接口地址必须包含 "?url=" 或 "&url=" 参数占位符');
return false;
}
return { name, url, type };
}
}).then(result => {
if (result.isConfirmed) {
const newApi = {
name: result.value.name,
type: result.value.type,
url: result.value.url
};
customApis.push(newApi);
allApis = [...uniqueApis, ...customApis];
GM_setValue("custom_parse_apis", customApis);
renderApiLists();
Swal.fire('添加成功', '自定义接口已添加,直接使用无需刷新!', 'success');
}
});
}
function playVideo(videoObj, isEmbed, encodedUrl = null) {
if (!isEmbed) return;
clearOriginalVideoSound();
const finalUrl = encodedUrl || encodeVideoUrl(window.location.href);
const parseUrl = videoObj.url + finalUrl;
// 获取自定义播放器尺寸
const playerSize = GM_getValue(CONFIG.customPlayerSizeKey, DEFAULT_PLAYER_SIZE);
const containers = [
"#player", "#mod_player", "#player-container", ".container-player",
"#mgtv-player-wrap", "#player_module", "#bilibiliPlayer",
"#bilibili-player", "#flashbox", ".m-video-player-wrap",
".intl-video-wrap", ".td-playbox", "#pptv_playpage_box",
".w-video", "#flashContent", "#vodPlayer"
];
let containerFound = false;
for (let selector of containers) {
const container = document.querySelector(selector);
if (container) {
containerFound = true;
// 暂停并静音原视频(而不是清空容器)
const originalVideos = container.querySelectorAll('video, audio');
originalVideos.forEach(media => {
media.pause();
media.muted = true;
media.volume = 0;
});
// 保存原始样式
const originalDisplay = container.style.display;
const originalVisibility = container.style.visibility;
const originalPosition = container.style.position;
// 隐藏原视频容器
container.style.display = 'none';
// 创建解析播放器容器(插入到原容器后面)
const parseContainer = document.createElement("div");
parseContainer.id = "vip-parse-player-container";
parseContainer.style.cssText = `
position: relative;
width: 100%;
height: 100%;
background: #000;
`;
// 插入到原容器后面
container.parentNode.insertBefore(parseContainer, container.nextSibling);
// 创建包装容器
const wrapper = document.createElement("div");
wrapper.id = "vip-player-wrapper";
wrapper.style.cssText = `
position: relative;
width: ${playerSize.width};
height: 100%;
min-height: ${playerSize.minHeight};
background: #000;
margin: 0 auto;
${playerSize.aspectRatio !== 'auto' ? `aspect-ratio: ${playerSize.aspectRatio.replace(':', '/')};` : ''}
`;
// 创建鼠标捕获层(覆盖在iframe上方)
const mouseCatcher = document.createElement("div");
mouseCatcher.className = "vip-mouse-catcher";
// 创建关闭按钮
const closeBtn = document.createElement("div");
closeBtn.className = "vip-player-close-btn";
closeBtn.innerHTML = "×";
closeBtn.title = "关闭解析";
// 保存到全局变量以便URL变化时清理
currentParseContainer = parseContainer;
currentOriginalContainer = container;
// 保存到全局变量
globalPlayerCloseBtn = closeBtn;
let mouseMoveInterval = null;
// 清除旧的监听器(如果存在)
if (globalMouseMoveHandler) {
document.removeEventListener('mousemove', globalMouseMoveHandler, true);
document.body.removeEventListener('mousemove', globalMouseMoveHandler, true);
window.removeEventListener('mousemove', globalMouseMoveHandler, true);
}
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
}
// 显示按钮的函数
const showCloseBtn = () => {
if (globalPlayerCloseBtn) {
globalPlayerCloseBtn.classList.remove('hidden');
mouseCatcher.classList.add('inactive'); // 鼠标移动时让捕获层失效,可以点击iframe
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
}
globalPlayerHideTimer = setTimeout(() => {
if (globalPlayerCloseBtn) {
globalPlayerCloseBtn.classList.add('hidden');
mouseCatcher.classList.remove('inactive'); // 隐藏后重新激活捕获层
}
}, 3000);
}
};
// 鼠标捕获层的移动事件
mouseCatcher.addEventListener('mousemove', showCloseBtn);
mouseCatcher.addEventListener('mouseenter', showCloseBtn);
// 全局鼠标移动监听(用于播放器外部)
globalMouseMoveHandler = function(e) {
showCloseBtn();
};
closeBtn.onclick = () => {
// 清除轮询
if (mouseMoveInterval) {
clearInterval(mouseMoveInterval);
mouseMoveInterval = null;
}
// 移除全局鼠标监听
if (globalMouseMoveHandler) {
document.removeEventListener('mousemove', globalMouseMoveHandler, true);
document.body.removeEventListener('mousemove', globalMouseMoveHandler, true);
window.removeEventListener('mousemove', globalMouseMoveHandler, true);
globalMouseMoveHandler = null;
}
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
globalPlayerHideTimer = null;
}
globalPlayerCloseBtn = null;
currentParseContainer = null;
currentOriginalContainer = null;
// 移除解析播放器容器
parseContainer.remove();
// 恢复原视频容器显示
container.style.display = originalDisplay;
container.style.visibility = originalVisibility;
// 原视频保持暂停状态,用户可以手动播放
Swal.fire({
title: '已关闭解析播放器',
text: '原视频已恢复显示(暂停状态),可以手动播放',
icon: 'success',
timer: 2000,
showConfirmButton: false
});
};
// 创建提示信息
const tipDiv = document.createElement("div");
tipDiv.className = "vip-player-tip";
tipDiv.innerHTML = `点击播放器全屏按钮获得最佳体验`;
// 3秒后自动隐藏提示
setTimeout(() => {
tipDiv.style.opacity = '0';
setTimeout(() => tipDiv.remove(), 500);
}, 3000);
// 创建iframe播放器
const iframe = document.createElement("iframe");
iframe.src = parseUrl;
iframe.style.cssText = `
border: none;
width: 100%;
height: 100%;
min-height: ${playerSize.minHeight};
`;
iframe.allowFullscreen = true;
iframe.allow = "autoplay; fullscreen; picture-in-picture";
// 组装元素
wrapper.appendChild(iframe);
wrapper.appendChild(mouseCatcher); // 鼠标捕获层在iframe上方
wrapper.appendChild(closeBtn);
wrapper.appendChild(tipDiv);
parseContainer.appendChild(wrapper);
// 添加全局鼠标移动监听(用于播放器外部区域)
setTimeout(() => {
document.addEventListener('mousemove', globalMouseMoveHandler, true);
document.body.addEventListener('mousemove', globalMouseMoveHandler, true);
window.addEventListener('mousemove', globalMouseMoveHandler, true);
}, 100);
// 初始显示3秒后隐藏
globalPlayerHideTimer = setTimeout(() => {
if (globalPlayerCloseBtn) {
globalPlayerCloseBtn.classList.add('hidden');
mouseCatcher.classList.remove('inactive');
}
}, 3000);
break;
}
}
if (!containerFound) {
// 如果没找到容器,创建全屏容器
const container = document.createElement("div");
container.id = "vip-video-container";
container.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999999;
background-color: black;
`;
// 创建鼠标捕获层
const mouseCatcher = document.createElement("div");
mouseCatcher.className = "vip-mouse-catcher";
// 创建关闭按钮
const closeBtn = document.createElement("div");
closeBtn.className = "vip-player-close-btn";
closeBtn.innerHTML = "×";
closeBtn.title = "关闭解析";
// 保存到全局变量
globalPlayerCloseBtn = closeBtn;
// 清除旧的监听器
if (globalMouseMoveHandler) {
document.removeEventListener('mousemove', globalMouseMoveHandler, true);
document.body.removeEventListener('mousemove', globalMouseMoveHandler, true);
window.removeEventListener('mousemove', globalMouseMoveHandler, true);
}
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
}
// 显示按钮的函数
const showCloseBtn = () => {
if (globalPlayerCloseBtn) {
globalPlayerCloseBtn.classList.remove('hidden');
mouseCatcher.classList.add('inactive');
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
}
globalPlayerHideTimer = setTimeout(() => {
if (globalPlayerCloseBtn) {
globalPlayerCloseBtn.classList.add('hidden');
mouseCatcher.classList.remove('inactive');
}
}, 3000);
}
};
// 鼠标捕获层的移动事件
mouseCatcher.addEventListener('mousemove', showCloseBtn);
mouseCatcher.addEventListener('mouseenter', showCloseBtn);
// 全局鼠标移动监听
globalMouseMoveHandler = function(e) {
showCloseBtn();
};
closeBtn.onclick = () => {
// 移除全局鼠标监听
if (globalMouseMoveHandler) {
document.removeEventListener('mousemove', globalMouseMoveHandler, true);
document.body.removeEventListener('mousemove', globalMouseMoveHandler, true);
window.removeEventListener('mousemove', globalMouseMoveHandler, true);
globalMouseMoveHandler = null;
}
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
globalPlayerHideTimer = null;
}
globalPlayerCloseBtn = null;
container.remove();
// 询问是否刷新
Swal.fire({
title: '关闭解析播放器',
html: '原视频播放器需要刷新页面才能恢复正常
(因为播放器的JavaScript状态已被清除)',
icon: 'question',
showCancelButton: true,
confirmButtonText: '刷新页面',
cancelButtonText: '直接关闭',
confirmButtonColor: '#3085d6',
cancelButtonColor: '#6c757d'
}).then((result) => {
if (result.isConfirmed) {
window.location.reload();
}
});
};
const iframe = document.createElement("iframe");
iframe.src = parseUrl;
iframe.style.cssText = `
border: none;
width: 100%;
height: 100%;
`;
iframe.allowFullscreen = true;
iframe.allow = "autoplay; fullscreen; picture-in-picture";
container.appendChild(iframe);
container.appendChild(mouseCatcher);
container.appendChild(closeBtn);
document.body.appendChild(container);
// 添加全局鼠标移动监听
setTimeout(() => {
document.addEventListener('mousemove', globalMouseMoveHandler, true);
document.body.addEventListener('mousemove', globalMouseMoveHandler, true);
window.addEventListener('mousemove', globalMouseMoveHandler, true);
}, 100);
// 初始显示3秒后隐藏
globalPlayerHideTimer = setTimeout(() => {
if (globalPlayerCloseBtn) {
globalPlayerCloseBtn.classList.add('hidden');
mouseCatcher.classList.remove('inactive');
}
}, 3000);
}
}
function autoPlayVideo() {
let index = GM_getValue(CONFIG.autoPlayerVal, 0);
let autoObj = allApis[index];
if (autoObj && autoObj.type.includes("1")) {
playVideo(autoObj, true, encodeVideoUrl(window.location.href));
const vipBox = DOM_CACHE.vipBox;
if (vipBox) {
const selectedItem = vipBox.querySelector(`.api-item[data-index="${index}"]`);
if (selectedItem) {
selectedItem.classList.add("selected");
}
vipBox.querySelector("#vip_auto").title = `自动解析源:${autoObj.name}`;
}
}
}
// 监听URL变化,自动关闭旧的解析播放器
function monitorUrlChange() {
setInterval(() => {
const currentUrl = window.location.href;
if (currentUrl !== lastPageUrl) {
console.log('检测到URL变化,关闭旧的解析播放器');
lastPageUrl = currentUrl;
// 清理旧的播放器
if (currentParseContainer) {
currentParseContainer.remove();
currentParseContainer = null;
}
// 恢复原视频容器
if (currentOriginalContainer) {
currentOriginalContainer.style.display = '';
currentOriginalContainer.style.visibility = '';
currentOriginalContainer = null;
}
// 清理全局变量
if (globalMouseMoveHandler) {
document.removeEventListener('mousemove', globalMouseMoveHandler, true);
document.body.removeEventListener('mousemove', globalMouseMoveHandler, true);
window.removeEventListener('mousemove', globalMouseMoveHandler, true);
globalMouseMoveHandler = null;
}
if (globalPlayerHideTimer) {
clearTimeout(globalPlayerHideTimer);
globalPlayerHideTimer = null;
}
globalPlayerCloseBtn = null;
// 如果开启了自动解析,延迟后重新解析
if (!!GM_getValue(CONFIG.autoPlayerKey, null)) {
setTimeout(() => {
autoPlayVideo();
}, 2500);
}
}
}, 500); // 每500ms检查一次URL
}
function waitForBody() {
if (document.body) {
createVipButton();
} else {
requestAnimationFrame(waitForBody);
}
}
document.addEventListener('keydown', (e) => {
if (!e.altKey) return;
const vipBox = DOM_CACHE.vipBox;
if (!vipBox) return;
switch (e.key.toLowerCase()) {
case CONFIG.shortcut.toggle:
e.preventDefault();
vipBox.style.display = vipBox.style.display === 'none' ? 'block' : 'none';
if (vipBox.style.display === 'block') {
vipBox.classList.add('visible');
vipBox.querySelector('.vip_list').classList.add('visible');
}
break;
case CONFIG.shortcut.refresh:
e.preventDefault();
customApis = GM_getValue("custom_parse_apis", []);
allApis = [...uniqueApis, ...customApis];
renderApiLists();
Swal.fire('刷新成功', '接口列表已重新加载!', 'success');
break;
case CONFIG.shortcut.style:
e.preventDefault();
const stylePanel = DOM_CACHE.styleSetPanel;
if (stylePanel) {
stylePanel.style.display = stylePanel.style.display === 'block' ? 'none' : 'block';
DOM_CACHE.vipBox.querySelector('.tab-button[data-tab="donate"]').click();
}
break;
}
});
(function registerMenu() {
GM_registerMenuCommand('🎬 VIP解析窗口', function() {
const vipBox = document.getElementById(CONFIG.vipBoxId);
if (vipBox) {
vipBox.style.display = "block";
vipBox.querySelector(".vip_list").style.display = "block";
} else {
createVipButton();
}
}, 'v');
GM_registerMenuCommand('📊 脚本状态', function() {
const version = GM_info.script.version;
alert('当前版本:' + version + '\\n解析工具已启动,支持多平台VIP视频解析\\n共整合 '+ allApis.length +' 个解析接口\\n支持样式自定义、快捷键自定义、接口动态添加!');
});
})();
const util = {
findTargetEle: (targetEle) => findTargetElement(targetEle)
};
const SUPPORT_HOSTS = [
"iqiyi.com", "youku.com", "v.qq.com", "mgtv.com", "bilibili.com",
"le.com", "sohu.com", "pptv.com", "1905.com", "iq.com",
"qq.com", "tudou.com"
];
const host = window.location.hostname;
const isSupportSite = SUPPORT_HOSTS.some(h => host.includes(h));
if (isSupportSite) {
util.findTargetEle('body')
.then(() => {
createVipButton();
monitorUrlChange(); // 启动URL监听
})
.catch(() => {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
waitForBody();
monitorUrlChange(); // 启动URL监听
});
} else {
waitForBody();
monitorUrlChange(); // 启动URL监听
}
});
}
})();