// ==UserScript== // @name 全网VIP视频免费破解去广告-强制修复版 // @namespace http://tampermonkey.net/ // @version 1.2 // @description 🔥全能解析终极版!【无广告+小窗屏蔽+极速解析】支持优酷/爱奇艺/腾讯/B站等全网VIP视频。自带接口测速、自动贴边、手机电脑双端完美兼容。 // @author 小哲(Gemini-3-pro辅助开发) // @icon https://v.qq.com/favicon.ico // @tag VIP解析 // @tag 视频破解 // @tag 去广告 // @tag 屏蔽小窗 // @match *://*.youku.com/* // @match *://*.iqiyi.com/* // @match *://*.iq.com/* // @match *://*.le.com/* // @match *://v.qq.com/* // @match *://m.v.qq.com/* // @match *://*.tudou.com/* // @match *://*.mgtv.com/* // @match *://tv.sohu.com/* // @match *://film.sohu.com/* // @match *://*.1905.com/* // @match *://*.bilibili.com/* // @match *://*.pptv.com/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @run-at document-end // @license MIT // ==/UserScript== (function() { 'use strict'; console.log('Gemini-VIP-Script: 脚本开始加载...'); // ================= ⚙️ 配置中心 ================= const DEFAULT_APIS = [ { name: "虾米 (推荐)", url: "https://jx.xmflv.com/?url=" }, { name: "虾米2 (备用)", url: "https://jx.xmflv.cc/?url=" }, { name: "纯净解析", url: "https://im1907.top/?jx=" }, { name: "B站专用", url: "https://jx.jsonplayer.com/player/?url=" }, { name: "咸鱼云", url: "https://jx.xymp4.cc/?url=" }, { name: "爱豆", url: "https://jx.aidouer.net/?url=" }, { name: "CHok", url: "https://www.gai4.com/?url=" }, { name: "OK解析", url: "https://okjx.cc/?url=" }, { name: "RDHK", url: "https://jx.rdhk.net/?v=" }, { name: "人人迷", url: "https://jx.blbo.cc:4433/?url=" }, { name: "思古3", url: "https://jsap.attakids.com/?url=" }, { name: "听乐", url: "https://jx.dj6u.com/?url=" }, { name: "YT", url: "https://jx.yangtu.top/?url=" } ]; const DEFAULT_CONFIG = { autoSnap: true, openInNewTab: true, embedMode: true, autoSync: true, antiMini: true, idleOpacity: true, shortcut: true, darkMode: 'auto', posPct: { x: 2, y: 30 }, lastApi: '', apis: DEFAULT_APIS, agreedDisclaimer: true, // 强制默认同意,防止弹窗不显示导致卡死 version: '1.2' }; // ================= 🧠 状态管理 ================= const State = { get: () => { try { const saved = GM_getValue('config', {}); // 强制修正坐标 if (!saved.posPct || isNaN(saved.posPct.x)) saved.posPct = { x: 2, y: 30 }; // 强制修正同意状态 saved.agreedDisclaimer = true; return { ...DEFAULT_CONFIG, ...saved }; } catch (e) { return DEFAULT_CONFIG; } }, set: (newConfig) => GM_setValue('config', newConfig), update: (key, value) => { const config = State.get(); config[key] = value; State.set(config); return config; } }; // ================= 🎨 UI 构建 ================= const CONTAINER_ID = 'gemini-vip-pro-force-v1-2'; // 清理旧版本残留 const oldContainer = document.getElementById('gemini-vip-pro-v1-0'); if(oldContainer) oldContainer.remove(); // 构建主容器 - 挂载到 html 而不是 body,层级更高 let container = document.getElementById(CONTAINER_ID); if (!container) { container = document.createElement('div'); container.id = CONTAINER_ID; (document.documentElement || document.body).appendChild(container); } const shadow = container.attachShadow({ mode: 'open' }); const getStyles = (isDark) => ` :host { --primary: #3B82F6; --primary-grad: linear-gradient(135deg, #3B82F6 0%, #7C3AED 100%); --warn: #EF4444; --success: #10B981; --warning: #F59E0B; --bg-blur: ${isDark ? 'rgba(30, 30, 30, 0.95)' : 'rgba(255, 255, 255, 0.95)'}; --text-main: ${isDark ? '#F3F4F6' : '#1F2937'}; --text-sub: ${isDark ? '#9CA3AF' : '#6B7280'}; --border: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(255,255,255,0.6)'}; --hover-bg: ${isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.04)'}; position: fixed; top: 0; left: 0; z-index: 2147483647; font-family: system> **Diagnosing the Visibility Problem** -ui, -apple-system, sans-serif; font-size: 14px; pointer-events: none; color: var(--text-main); width: 100vw; height: 100vh; overflow: visible; display: block !important; } .wrapper { position: absolute; width: 50px; height: 50px; pointer-events: auto; display: block !important; z-index: 2147483647; /* 强制初始位置,防止飞出屏幕 */ top: 30%; left: 10px; } .float-ball { width: 50px; height: 50px; background: var(--primary-grad); border-radius: 50%; box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4); cursor: pointer; display: flex; justify-content: center; align-items: center; transition: transform 0.2s, opacity 0.3s, filter 0.3s; border: 2px solid rgba(255,255,255,0.2); backdrop-filter: blur(4px); } .float-ball:hover { transform: scale(1.1); } .float-ball:active { transform: scale(0.95); } .float-ball.idle { opacity: 0.5; filter: grayscale(0.5); transform: scale(0.9); } .ball-icon { width: 24px; height: 24px; fill: white; transition: transform 0.3s; } .wrapper.active .ball-icon { transform: rotate(90deg); } .menu-panel { position: absolute; top: 0; width: 300px; background: var(--bg-blur); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-radius: 18px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); border: 1px solid var(--border); display: none; flex-direction: column; overflow: hidden; animation: menuIn 0.25s cubic-bezier(0.2, 0.8, 0.2, 1); } @keyframes menuIn { from { opacity: 0; transform: scale(0.95) translateY(-10px); } to { opacity: 1; transform: scale(1) translateY(0); } } .pos-right .menu-panel { right: 60px; left: auto; transform-origin: top right; } .pos-left .menu-panel { left: 60px; right: auto; transform-origin: top left; } .menu-header { padding: 16px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--hover-bg); } .app-name { font-weight: 800; font-size: 15px; background: var(--primary-grad); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .tools { display: flex; gap: 4px; } .icon-btn { width: 28px; height: 28px; border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; fill: var(--text-sub); } .icon-btn:hover { background: var(--hover-bg); fill: var(--primary); } .icon-btn.testing { animation: spin 1s linear infinite; fill: var(--primary); pointer-events: none; } @keyframes spin { 100% { transform: rotate(360deg); } } .content-view { display: none; padding: 15px; max-height: 360px; overflow-y: auto; } .content-view.active { display: block; animation: fadeIn 0.2s; } .alert-box { margin: 10px 12px 0 12px; padding: 10px; background: ${isDark ? 'rgba(239, 68, 68, 0.15)' : '#FEF2F2'}; border: 1px solid ${isDark ? 'rgba(239, 68, 68, 0.3)' : '#FECACA'}; border-radius: 10px; color: var(--warn); font-size: 12px; display: flex; gap: 8px; align-items: start; cursor: pointer; line-height: 1.4; } .api-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; } .api-item { padding: 12px 8px; border-radius: 10px; background: var(--hover-bg); border: 1px solid transparent; font-size: 13px; text-align: center; cursor: pointer; transition: all 0.2s; position: relative; color: var(--text-main) !important; font-weight: 500; display: flex; flex-direction: column; gap: 4px; } .api-item:hover { background: transparent; border-color: var(--primary); color: var(--primary) !important; transform: translateY(-2px); } .api-item.current { background: var(--primary-grad); color: white !important; } .ping-tag { font-size: 10px; font-weight: normal; opacity: 0.8; } .ping-green { color: var(--success); } .ping-yellow { color: var(--warning); } .ping-red { color: var(--warn); } .current .ping-tag { color: rgba(255,255,255,0.9); } .footer { padding: 10px; text-align: center; border-top: 1px solid var(--hover-bg); font-size: 11px; color: var(--text-sub); } .link { color: var(--primary); text-decoration: none; display: inline-flex; align-items: center; cursor: pointer; transition: 0.2s; } .link:hover { opacity: 0.8; } .set-row { display: flex; justify-content: space-between; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--hover-bg); } .toggle { width: 42px; height: 22px; background: ${isDark ? '#4B5563' : '#E5E7EB'}; border-radius: 20px; position: relative; cursor: pointer; transition: 0.3s; } .toggle::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; background: white; border-radius: 50%; transition: 0.3s; box-shadow: 0 1px 2px rgba(0,0,0,0.2); } .toggle.checked { background: var(--primary); } .toggle.checked::after { transform: translateX(20px); } .mode-switch { display: flex; background: var(--hover-bg); padding: 3px; border-radius: 8px; } .mode-btn { flex: 1; text-align: center; padding: 4px; font-size: 12px; cursor: pointer; border-radius: 6px; color: var(--text-sub); transition: 0.2s; } .mode-btn.active { background: var(--bg-blur); color: var(--primary); font-weight: bold; } .toast { position: fixed; top: 40%; left: 50%; transform: translate(-50%, -50%); background: rgba(0,0,0,0.9); color: white; padding: 12px 24px; border-radius: 50px; opacity: 0; pointer-events: none; transition: 0.3s; z-index: 2147483647; } .toast.show { opacity: 1; transform: translate(-50%, -60%); } `; const styleElement = document.createElement('style'); shadow.appendChild(styleElement); function updateTheme() { const config = State.get(); let isDark = config.darkMode === 'auto' ? (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) : (config.darkMode === 'dark'); styleElement.textContent = getStyles(isDark); } const ICONS = { play: ``, close: ``, gear: ``, edit: ``, back: ``, cross: ``, speed: `` }; const wrapper = document.createElement('div'); wrapper.className = 'wrapper'; const ball = document.createElement('div'); ball.className = 'float-ball'; ball.innerHTML = ICONS.play; ball.title = 'VIP解析'; const menu = document.createElement('div'); menu.className = 'menu-panel'; const toast = document.createElement('div'); toast.className = 'toast'; // 强制注册命令 GM_registerMenuCommand("♻️ 重置悬浮球位置", () => { State.update('posPct', { x: 2, y: 30 }); location.reload(); }); GM_registerMenuCommand("🔨 强制渲染 UI", () => { launchUI(); showToast('已强制重新渲染'); }); function init() { console.log('Gemini-VIP: Init...'); launchUI(); // 直接启动,不检查免责声明 if (State.get().antiMini) injectAntiMiniStyles(); setupUrlListener(); } // ================= ⚡ 测速核心逻辑 ================= function testLatency(url) { return new Promise(resolve => { const start = Date.now(); GM_xmlhttpRequest({ method: 'GET', url: url, timeout: 3000, headers: { 'Cache-Control': 'no-cache' }, onload: (res) => { const time = Date.now() - start; if (res.status >= 200 && res.status < 400) resolve(time); else resolve(-1); }, onerror: () => resolve(-1), ontimeout: () => resolve(-1) }); }); } async function runSpeedTest() { const btn = menu.querySelector('#btn-speed'); if(btn.classList.contains('testing')) return; btn.classList.add('testing'); showToast('🚀 开始智能测速...'); const items = menu.querySelectorAll('.api-item'); const tasks = Array.from(items).map(async (item) => { const url = item.dataset.url; const tag = item.querySelector('.ping-tag'); tag.textContent = '检测中...'; tag.className = 'ping-tag'; const testUrl = url.includes('?') ? url : (url + '?'); const ms = await testLatency(testUrl); if (ms === -1) { tag.textContent = '超时/故障'; tag.classList.add('ping-red'); } else { tag.textContent = ms + 'ms'; if(ms < 500) tag.classList.add('ping-green'); else if(ms < 1500) tag.classList.add('ping-yellow'); else tag.classList.add('ping-red'); } }); await Promise.all(tasks); btn.classList.remove('testing'); showToast('✅ 测速完成'); } // ================= 🔮 核心:全局天眼 & 防小窗系统 ================= let overlayUpdateTimer = null; function safeOpen(baseUrl, name) { const config = State.update('lastApi', baseUrl); const targetUrl = baseUrl + location.href; if (config.embedMode) { showToast(`📺 正在覆盖解析: ${name}`); toggleMenu(false); setTimeout(() => coverPlayerGlobal(targetUrl), 200); } else { showToast(`🚀 正在新标签页解析: ${name}`); setTimeout(() => { config.openInNewTab ? window.open(targetUrl, '_blank') : location.href = targetUrl; toggleMenu(false); }, 500); } } function findVideoElement() { const video = document.querySelector('video'); if (video) return video; const selectors = ['#player', '.player-container', '#mod_player', '#bilibili-player', '.iqp-player', '#mgtv-player-wrap']; for (let sel of selectors) { const el = document.querySelector(sel); if (el && el.clientWidth > 100) return el; } return null; } function injectAntiMiniStyles() { if (!document.getElementById('gemini-anti-mini-style')) { const style = document.createElement('style'); style.id = 'gemini-anti-mini-style'; style.textContent = ` .txp_player_mini, .txp_mini_player, .txp-pip-player, .txp-player-mini-container { display: none !important; } .bilibili-player-video-float, .mini-player, .bpx-player-container[data-screen="mini"] { display: none !important; } .mini-player, .yp-player-mini, .iqp-player-mini, .iqp-player.mini, .pip-mode, .float-player { display: none !important; } .mgtv-player-mini, .mgtv-pip-player, .mini-player-mask { display: none !important; } #mini-player, .player-mini { display: none !important; } `; document.head.appendChild(style); } } function removeAntiMiniStyles() { const s = document.getElementById('gemini-anti-mini-style'); if(s) s.remove(); } function coverPlayerGlobal(url) { const targetEl = findVideoElement(); if (!targetEl) { showToast('❌ 未找到播放器,尝试弹窗播放'); window.open(url, '_blank'); return; } if (State.get().antiMini) injectAntiMiniStyles(); if(window.muteInterval) clearInterval(window.muteInterval); window.muteInterval = setInterval(() => { document.querySelectorAll('video').forEach(v => { if (!v.muted || !v.paused) { v.muted = true; v.pause(); v.volume = 0; } }); }, 1500); let overlayId = 'gemini-global-overlay'; let overlay = document.getElementById(overlayId); if (!overlay) { overlay = document.createElement('div'); overlay.id = overlayId; overlay.style.cssText = ` position: absolute; z-index: 2147483646; background: #000; display: flex; flex-direction: column; overflow: hidden; `; const toolbar = document.createElement('div'); toolbar.style.cssText = `height: 0; position: absolute; top:0; right:0; z-index: 2147483648;`; toolbar.innerHTML = `
✕ 退出
`; toolbar.querySelector('#btn-close-overlay').onclick = closeOverlay; overlay.appendChild(toolbar); document.body.appendChild(overlay); } const oldFrame = overlay.querySelector('iframe'); if(oldFrame) oldFrame.remove(); const iframe = document.createElement('iframe'); iframe.src = url; iframe.style.cssText = `width: 100%; height: 100%; border: none; background: black;`; iframe.allow = "fullscreen; autoplay"; overlay.appendChild(iframe); updateOverlayPosition(targetEl, overlay); if(overlayUpdateTimer) clearInterval(overlayUpdateTimer); overlayUpdateTimer = setInterval(() => updateOverlayPosition(targetEl, overlay), 300); showToast('✅ 解析成功!已屏蔽原视频'); } function updateOverlayPosition(targetEl, overlay) { if (!targetEl || !overlay || !document.body.contains(targetEl)) { closeOverlay(); return; } const rect = targetEl.getBoundingClientRect(); if (rect.width > 0 && rect.height > 0) { overlay.style.display = 'flex'; const top = rect.top + window.scrollY; const left = rect.left + window.scrollX; overlay.style.top = top + 'px'; overlay.style.left = left + 'px'; overlay.style.width = rect.width + 'px'; overlay.style.height = rect.height + 'px'; } } function closeOverlay() { const overlay = document.getElementById('gemini-global-overlay'); if (overlay) overlay.remove(); if (window.muteInterval) clearInterval(window.muteInterval); if (overlayUpdateTimer) clearInterval(overlayUpdateTimer); } // ================= 🕹️ 交互系统 ================= function setupUrlListener() { let lastUrl = location.href; setInterval(() => { if (location.href !== lastUrl) { lastUrl = location.href; const config = State.get(); if (config.autoSync && config.embedMode && document.getElementById('gemini-global-overlay')) { showToast('🔄 正在同步新剧集...'); coverPlayerGlobal(location.href); } } }, 1000); document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeOverlay(); }); } function launchUI() { updateTheme(); // 强制显示 wrapper.style.display = 'block'; renderPos(); renderMenu(); document.addEventListener('keydown', (e) => { if (State.get().shortcut && e.altKey && e.code === 'KeyQ') toggleMenu(); }); window.addEventListener('resize', () => renderPos()); } function renderMenu() { const config = State.get(); menu.innerHTML = `
🚨
安全提醒:切勿相信视频内任何广告!
${config.apis.map(api => `
${api.name || '未知接口'} 未检测
`).join('')}
${config.apis.map((api, idx) => `
${api.name || '未知'}
`).join('')}
页内覆盖播放
屏蔽迷你小窗
换集自动同步
新标签页打开
自动贴边
闲置自动透明
模式
☀️
🌗
🌙
`; bindEvents(); } function bindEvents() { const switchView = (id) => { menu.querySelectorAll('.content-view').forEach(v => v.classList.remove('active')); menu.querySelector(`#${id}`).classList.add('active'); menu.querySelector('#btn-back')?.remove(); if (id !== 'view-home') { const b = document.createElement('div'); b.innerHTML = ICONS.back; b.className = 'icon-btn'; b.id = 'btn-back'; b.onclick = () => renderMenu(); menu.querySelector('.menu-header').prepend(b); } }; menu.querySelector('#alert-bar').onclick = () => alert('请勿相信视频内任何广告!'); // 简化弹窗 menu.querySelector('#btn-speed').onclick = () => runSpeedTest(); menu.querySelector('#btn-edit').onclick = () => switchView('view-edit'); menu.querySelector('#btn-set').onclick = () => switchView('view-set'); menu.querySelector('#btn-close').onclick = () => toggleMenu(false); menu.querySelectorAll('.api-item').forEach(i => i.onclick = (e) => { e.stopPropagation(); safeOpen(i.dataset.url, i.dataset.name); }); menu.querySelectorAll('.mode-btn').forEach(b => b.onclick = () => { State.update('darkMode', b.dataset.mode); updateTheme(); renderMenu(); }); menu.querySelectorAll('.toggle').forEach(t => t.onclick = () => { const k = t.dataset.key; const newVal = !t.classList.contains('checked'); State.update(k, newVal); t.classList.toggle('checked'); if(k==='idleOpacity') resetIdle(); if(k==='antiMini') { newVal ? injectAntiMiniStyles() : removeAntiMiniStyles(); showToast(newVal ? '🚫 已屏蔽迷你小窗' : '👀 已恢复迷你小窗'); } }); menu.querySelector('#btn-add-api')?.addEventListener('click', () => { const n=menu.querySelector('#new-name').value, u=menu.querySelector('#new-url').value; if(n&&u) { const c=State.get(); c.apis.push({name:n, url:u}); State.set(c); renderMenu(); menu.querySelector('#btn-edit').click(); } }); menu.querySelectorAll('.btn-del').forEach(b => b.onclick = () => { const c=State.get(); c.apis.splice(b.dataset.idx,1); State.set(c); renderMenu(); menu.querySelector('#btn-edit').click(); }); } function showToast(msg) { toast.textContent = msg; toast.classList.add('show'); setTimeout(() => toast.classList.remove('show'), 2000); } // --- 交互系统 --- let isMenuOpen = false, idleTimer; function renderPos() { const c = State.get(), w = window.innerWidth, h = window.innerHeight; // 强制修正 if(!c.posPct || isNaN(c.posPct.x) || isNaN(c.posPct.y)) c.posPct = { x: 2, y: 30 }; let x = (c.posPct.x/100)*w, y = (c.posPct.y/100)*h; x = Math.min(Math.max(0, x), w - 50); y = Math.min(Math.max(0, y), h - 50); if(isNaN(x)) x = 20; if(isNaN(y)) y = 200; wrapper.style.left = x + 'px'; wrapper.style.top = y + 'px'; wrapper.style.display = 'block'; // 强制显示 if (x > w / 2) { wrapper.classList.add('pos-right'); wrapper.classList.remove('pos-left'); } else { wrapper.classList.add('pos-left'); wrapper.classList.remove('pos-right'); } } function toggleMenu(s) { isMenuOpen = s!==undefined?s:!isMenuOpen; if(isMenuOpen) { updateTheme(); renderMenu(); renderPos(); menu.style.display='flex'; ball.innerHTML=ICONS.close; ball.style.opacity='1'; ball.style.transform='scale(0.9)'; } else { menu.style.display='none'; ball.innerHTML=ICONS.play; ball.style.transform='scale(1)'; resetIdle(); } } function resetIdle() { ball.classList.remove('idle'); clearTimeout(idleTimer); if(State.get().idleOpacity && !isMenuOpen) idleTimer=setTimeout(()=>ball.classList.add('idle'),3000); } // 拖拽 let isDrag=false, sX, sY, sL, sT, moved=false; const onMove = (e) => { if(!isDrag) return; e.preventDefault(); const c = e.touches?e.touches[0]:e, dx = c.clientX-sX, dy = c.clientY-sY; if(Math.abs(dx)>2||Math.abs(dy)>2) moved=true; if(moved) { let nx = sL+dx, ny = sT+dy; wrapper.style.left = Math.min(Math.max(0, nx), window.innerWidth-50)+'px'; wrapper.style.top = Math.min(Math.max(0, ny), window.innerHeight-50)+'px'; } }; const onEnd = () => { if(!isDrag) return; isDrag=false; ball.style.cursor='pointer'; if(!moved) { toggleMenu(); return; } wrapper.style.transition='all 0.4s cubic-bezier(0.18, 0.89, 0.32, 1.28)'; const r = wrapper.getBoundingClientRect(), w=window.innerWidth, h=window.innerHeight; let fx = r.left; if(State.get().autoSnap) fx = (fx+25 < w/2) ? 10 : (w-60); wrapper.style.left = fx+'px'; State.update('posPct', {x: (fx/w)*100, y: (r.top/h)*100}); setTimeout(renderPos, 410); }; const onStart = (e) => { if((e.type==='mousedown'&&e.button!==0)|| (e.target!==ball && !ball.contains(e.target))) return; const c = e.touches?e.touches[0]:e; sX=c.clientX; sY=c.clientY; const r = wrapper.getBoundingClientRect(); sL=r.left; sT=r.top; moved=false; isDrag=true; ball.style.cursor='grabbing'; wrapper.style.transition='none'; resetIdle(); }; ball.addEventListener('mousedown', onStart); ball.addEventListener('touchstart', onStart, {passive:false}); document.addEventListener('mousemove', onMove, {passive:false}); document.addEventListener('touchmove', onMove, {passive:false}); document.addEventListener('mouseup', onEnd); document.addEventListener('touchend', onEnd); ball.addEventListener('mouseup', e => { if(e.button===1) { e.preventDefault(); const c=State.get(); c.lastApi?safeOpen(c.lastApi,'上次接口'):toggleMenu(true); } }); document.addEventListener('click', e => { if(isMenuOpen && !container.contains(e.target)) toggleMenu(false); }); wrapper.appendChild(ball); wrapper.appendChild(menu); wrapper.appendChild(toast); shadow.appendChild(wrapper); init(); })();