// ==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 = "
[内嵌播放+弹窗无选集]
"; 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 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 打开样式设置
${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监听 } }); } })();