// ==UserScript== // @name xyDouYinTools 抖音沉浸式优化 // @namespace https://greasyfork.org/zh-CN/users/1513167-%E9%83%A7%E5%B1%B1%E6%9D%8E%E5%92%B8%E9%B1%BC // @version 0.28.1 // @description 美化抖音界面 一个偏沉浸式观感(最大程度全屏化) + 纯鼠标刷视频的抖音网页端增强脚本:尽量让视频当主角,UI少打扰;同时把高频操作塞到鼠标手势里,省得手来回摸键盘。 // @author lxy // @license MIT // @match https://www.douyin.com/* // @match https://live.douyin.com/* // @match https://www.douyin.com/follow/live/* // @run-at document-start // @grant none // @downloadURL https://update.greasyfork.icu/scripts/548904/xyDouYinTools%20%E6%8A%96%E9%9F%B3%E6%B2%89%E6%B5%B8%E5%BC%8F%E4%BC%98%E5%8C%96.user.js // @updateURL https://update.greasyfork.icu/scripts/548904/xyDouYinTools%20%E6%8A%96%E9%9F%B3%E6%B2%89%E6%B5%B8%E5%BC%8F%E4%BC%98%E5%8C%96.meta.js // ==/UserScript== (function() { 'use strict'; const FEATURE = { SIDEBAR: 1, STYLES: 1, NAVIGATION: 1, LIVE: 1, HIDE_ELEMENTS: 1, ADS: 1, MOUSE: 1, LOADING: 1, PERFORMANCE: 1 }; const DEBUG = { LOG_LEVEL: 3, MODULES: { SIDEBAR: 0, STYLES: 0, NAVIGATION: 1, LIVE: 0, HIDE_ELEMENTS: 1, ADS: 1, MOUSE: 0, LOADING: 0, PERFORMANCE: 1 } }; const LS_PREFIX = 'xyDYTools_feature_'; (function loadFeatureFlags() { try { Object.keys(FEATURE).forEach(k => { const v = localStorage.getItem(LS_PREFIX + k); if (v === '0') FEATURE[k] = 0; if (v === '1') FEATURE[k] = 1; }); } catch (_) {} })(); const nativeConsole = { log: console.log.bind(console), warn: console.warn.bind(console), error: console.error.bind(console), info: console.info.bind(console), time: console.time ? console.time.bind(console) : null, timeEnd: console.timeEnd ? console.timeEnd.bind(console) : null }; if (DEBUG.LOG_LEVEL === 0) { ['log', 'warn', 'error', 'info'].forEach(type => { console[type] = function() {}; }); } function ts() { return new Date().toLocaleTimeString(); } const logger = { log(module, message, ...args) { if (DEBUG.LOG_LEVEL >= 3 && DEBUG.MODULES[module]) nativeConsole.log( `[${ts()}] [DouYinTools] [${module}]`, message, ...args); }, warn(module, message, ...args) { if (DEBUG.LOG_LEVEL >= 2 && DEBUG.MODULES[module]) nativeConsole.warn( `[${ts()}] [DouYinTools] [${module}]`, message, ...args); }, error(module, message, ...args) { if (DEBUG.LOG_LEVEL >= 1 && DEBUG.MODULES[module]) nativeConsole.error( `[${ts()}] [DouYinTools] [${module}]`, message, ...args); }, info(module, message, ...args) { if (DEBUG.LOG_LEVEL >= 3 && DEBUG.MODULES[module]) nativeConsole.info( `[${ts()}] [DouYinTools] [${module}]`, message, ...args); }, initModule(module) { if (DEBUG.LOG_LEVEL >= 3 && DEBUG.MODULES[module]) nativeConsole.log( `[${ts()}] [DouYinTools] [${module}] 模块初始化开始`); }, moduleReady(module) { if (DEBUG.LOG_LEVEL >= 3 && DEBUG.MODULES[module]) nativeConsole.log( `[${ts()}] [DouYinTools] [${module}] 模块初始化完成`); } }; const performanceTracker = { startTime: performance.now(), moduleTimes: {}, moduleStartTimes: {}, start(module) { if (FEATURE.PERFORMANCE && DEBUG.MODULES.PERFORMANCE && DEBUG.LOG_LEVEL >= 3) { this.moduleStartTimes[module] = performance.now(); logger.log('PERFORMANCE', `开始执行: ${module}`); } }, end(module) { if (!(FEATURE.PERFORMANCE && DEBUG.MODULES.PERFORMANCE && DEBUG.LOG_LEVEL >= 3)) return 0; if (!this.moduleStartTimes[module]) return 0; const duration = performance.now() - this.moduleStartTimes[module]; this.moduleTimes[module] = duration; logger.log('PERFORMANCE', `${module} 执行完成, 耗时: ${duration.toFixed(2)}ms`); delete this.moduleStartTimes[module]; return duration; }, getTotalTime() { return (performance.now() - this.startTime).toFixed(2); }, printPerformanceReport() { if (!(FEATURE.PERFORMANCE && DEBUG.MODULES.PERFORMANCE && DEBUG.LOG_LEVEL >= 3)) return; const totalTime = this.getTotalTime(); const entries = Object.entries(this.moduleTimes).sort((a, b) => b[1] - a[1]); const sum = entries.reduce((acc, [, t]) => acc + t, 0); nativeConsole.log('\n' + '='.repeat(60)); nativeConsole.log('%c🎯 抖音工具脚本性能报告', 'color: #4CAF50; font-size: 16px; font-weight: bold;'); nativeConsole.log('='.repeat(60)); nativeConsole.log('%c📊 模块执行时间统计:', 'color: #2196F3; font-weight: bold;'); entries.forEach(([module, time]) => { const percent = sum > 0 ? ((time / sum) * 100).toFixed(1) : '0.0'; nativeConsole.log(` ${module}: ${time.toFixed(2)}ms (${percent}%)`); }); nativeConsole.log('%c⏱️ 总运行时间统计:', 'color: #FF9800; font-weight: bold;'); nativeConsole.log(` 脚本总运行时间: ${totalTime}ms`); nativeConsole.log(` 模块总耗时: ${sum.toFixed(2)}ms`); nativeConsole.log('%c⚙️ 调试配置:', 'color: #9C27B0; font-weight: bold;'); nativeConsole.log(` 日志级别: ${DEBUG.LOG_LEVEL}`); nativeConsole.log( ` 输出模块: ${Object.keys(DEBUG.MODULES).filter(m => DEBUG.MODULES[m]).length}/${Object.keys(DEBUG.MODULES).length}` ); nativeConsole.log('%c🧩 功能开关:', 'color: #795548; font-weight: bold;'); Object.keys(FEATURE).forEach(k => nativeConsole.log(` ${k}: ${FEATURE[k] ? '✅ 开启' : '❌ 关闭'}`)); nativeConsole.log('='.repeat(60) + '\n'); return totalTime; } }; function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } function normText(s) { return String(s || '').replace(/\s+/g, ' ').trim(); } function isVisible(el) { if (!el) return false; const st = getComputedStyle(el); if (st.display === 'none' || st.visibility === 'hidden' || Number(st.opacity) === 0) return false; const r = el.getBoundingClientRect(); if (r.width < 5 || r.height < 5) return false; return r.bottom > 0 && r.top < window.innerHeight && r.right > 0 && r.left < window.innerWidth; } function dispatchKeyEvent(type, key, repeat) { const code = key.length === 1 ? `Key${key.toUpperCase()}` : key; const k = key.length === 1 ? key : (key === 'ArrowDown' ? 'ArrowDown' : key); const keyCode = key.length === 1 ? key.charCodeAt(0) : (key === 'ArrowDown' ? 40 : 0); const ev = new KeyboardEvent(type, { key: k, code, keyCode, which: keyCode, bubbles: true, cancelable: true, repeat: !!repeat }); document.dispatchEvent(ev); } function keyDown(key, repeat) { dispatchKeyEvent('keydown', key, repeat); } function keyUp(key) { dispatchKeyEvent('keyup', key, false); } function createLoadingScreen() { performanceTracker.start('LOADING_SCREEN'); logger.initModule('LOADING'); if (!FEATURE.LOADING) { logger.moduleReady('LOADING'); performanceTracker.end('LOADING_SCREEN'); return; } const EXIST_ID = 'tm-fullscreen-loader'; if (document.getElementById(EXIST_ID)) { logger.moduleReady('LOADING'); performanceTracker.end('LOADING_SCREEN'); return; } const FADE_MS = 450; const MIN_SHOW_MS = 250; const MAX_SHOW_MS = 12000; const ESC_TO_CLOSE = true; const CLICK_TO_CLOSE = true; window.__xyDYToolsBoot = window.__xyDYToolsBoot || { styles: false, safeStyles: false, nav: false, ads: false, hide: false, inited: false }; if (!document.getElementById('tm-fullscreen-loader-style')) { const style = document.createElement('style'); style.id = 'tm-fullscreen-loader-style'; style.textContent = `#tm-fullscreen-loader{position:fixed;inset:0;background:rgba(0,0,0,0.92);z-index:999999;display:flex;justify-content:center;align-items:center;flex-direction:column;opacity:1;transition:opacity ${FADE_MS}ms ease;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);}#tm-fullscreen-loader .tm-spinner{width:52px;height:52px;border:5px solid rgba(255,255,255,0.26);border-radius:50%;border-top-color:#fff;animation:tm_spin 0.95s linear infinite;}#tm-fullscreen-loader .tm-loading-text{color:#fff;margin-top:18px;font-family:Arial,sans-serif;}#tm-fullscreen-loader .s1{font-size:18px;font-weight:600;letter-spacing:0.5px;}#tm-fullscreen-loader .s2{color:rgba(255,255,255,0.62);font-size:13px;margin-top:10px;max-width:min(560px, 86vw);text-align:center;line-height:1.45;}#tm-fullscreen-loader .hint{color:rgba(255,255,255,0.45);font-size:12px;margin-top:14px;text-align:center;}@keyframes tm_spin{to{transform:rotate(360deg);}}`; (document.head || document.documentElement).appendChild(style); } const loader = document.createElement('div'); loader.id = EXIST_ID; loader.innerHTML = `

加载中...

正在等抖音自身加载 + 脚本正在接管抖音界面

${ESC_TO_CLOSE ? '按 ESC 可关闭 / ' : ''}${CLICK_TO_CLOSE ? '点一下也能关' : ''}

UI正在挨打,场面会略显混乱

`; document.documentElement.appendChild(loader); let removed = false; const startAt = Date.now(); const remove = (reason) => { if (removed) return; removed = true; const cost = Date.now() - startAt; logger.log('LOADING', `加载界面移除:${reason},展示 ${cost}ms`); loader.style.opacity = '0'; setTimeout(() => { try { loader.remove(); } catch (_) {} try { document.getElementById('tm-fullscreen-loader-style')?.remove(); } catch (_) {} }, FADE_MS + 30); }; const safeRemove = (reason) => { const elapsed = Date.now() - startAt; const wait = Math.max(0, MIN_SHOW_MS - elapsed); setTimeout(() => remove(reason), wait); }; function isBootReady() { const b = window.__xyDYToolsBoot || {}; return !!b.inited; } function isDomReady() { return document.readyState === 'interactive' || document.readyState === 'complete'; } const POLL_MS = 120; const AFTER_READY_MS = 1200; (function poll() { if (removed) return; if (isDomReady() && isBootReady()) { setTimeout(() => { requestAnimationFrame(() => requestAnimationFrame(() => safeRemove('BOOT_READY'))); }, AFTER_READY_MS); return; } setTimeout(poll, POLL_MS); })(); setTimeout(() => safeRemove('MAX_SHOW_TIMEOUT'), MAX_SHOW_MS); if (ESC_TO_CLOSE) { window.addEventListener('keydown', function onKey(e) { if (e.key === 'Escape') { window.removeEventListener('keydown', onKey, true); safeRemove('ESC'); } }, true); } if (CLICK_TO_CLOSE) loader.addEventListener('click', () => safeRemove('CLICK'), { once: true }); logger.moduleReady('LOADING'); performanceTracker.end('LOADING_SCREEN'); } /* ========================= SIDEBAR(修复版) 你这个“抽风”核心点基本就俩: 1) mousemove 里只看 x<=hoverWidth,会把“鼠标已经在侧栏里”的情况当成“离开左侧边缘”,从而立刻排队隐藏 2) MutationObserver 盯整个 documentElement subtree,抖音一更新 DOM 你就疯狂重绑监听,状态来回抖 下面这版:用 RAF 限频 + 用“鼠标是否在侧栏矩形内”来决定显隐 + 只在侧栏节点变更时重绑 ========================= */ const SIDEBAR_CONFIG = { hoverDelay: 240, hoverWidth: 18, storageKey: 'hide_sidebar', lockKey: 'hide_sidebar_lock', repairKey: 'xyDYTools_sidebar_repair_v1' }; let sidebarHoverEnabled = false; let sidebarHideTimer = null; let sidebarVisible = false; let sidebarElCache = null; let sidebarBindToken = 0; let rafMovePending = false; let lastMoveX = 0; let lastMoveY = 0; function safeLSGet(key) { try { return localStorage.getItem(key); } catch (_) { return null; } } function safeLSSet(key, val) { try { localStorage.setItem(key, val); } catch (_) {} } function safeLSDel(key) { try { localStorage.removeItem(key); } catch (_) {} } function pickSidebarEl() { return ( document.querySelector('#douyin-navigation') || document.querySelector('[data-e2e="douyin-navigation"]') || null ); } function isSidebarLocked() { return safeLSGet(SIDEBAR_CONFIG.lockKey) === 'true'; } function isHideSidebarWanted() { return safeLSGet(SIDEBAR_CONFIG.storageKey) === 'true'; } function setSidebarHiddenOnRoot(hidden) { if (hidden) { document.documentElement.classList.add('xy-hide-sidebar'); sidebarVisible = false; } else { document.documentElement.classList.remove('xy-hide-sidebar'); sidebarVisible = true; } } (function injectSidebarStyle() { if (document.getElementById('xy-sidebar-style')) return; const style = document.createElement('style'); style.id = 'xy-sidebar-style'; style.textContent = ` html.xy-hide-sidebar #douyin-navigation{display:none !important;} html.xy-hide-sidebar [data-e2e="douyin-navigation"]{display:none !important;} html.xy-hide-sidebar #douyin-navigation, html.xy-hide-sidebar [data-e2e="douyin-navigation"]{ transition:none !important; } html.xy-hide-sidebar #douyin-navigation *, html.xy-hide-sidebar [data-e2e="douyin-navigation"] *{ pointer-events:none !important; } html:not(.xy-hide-sidebar) #douyin-navigation{display:block !important;} html:not(.xy-hide-sidebar) [data-e2e="douyin-navigation"]{display:block !important;} `; (document.head || document.documentElement).appendChild(style); })(); (function sidebarLSRepairOnce() { const mark = safeLSGet(SIDEBAR_CONFIG.repairKey); if (mark === '1') return; const a = safeLSGet(SIDEBAR_CONFIG.storageKey); const b = safeLSGet(SIDEBAR_CONFIG.lockKey); if (a !== null && a !== 'true' && a !== 'false') safeLSDel(SIDEBAR_CONFIG.storageKey); if (b !== null && b !== 'true' && b !== 'false') safeLSDel(SIDEBAR_CONFIG.lockKey); if (safeLSGet(SIDEBAR_CONFIG.lockKey) === 'true') safeLSSet(SIDEBAR_CONFIG.storageKey, 'true'); safeLSSet(SIDEBAR_CONFIG.repairKey, '1'); })(); function clearSidebarTimers() { if (sidebarHideTimer) { clearTimeout(sidebarHideTimer); sidebarHideTimer = null; } } function mouseInsideSidebarRect(x, y) { const el = sidebarElCache || pickSidebarEl(); if (!el) return false; const r = el.getBoundingClientRect(); if (r.width <= 0 || r.height <= 0) return false; return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom; } function shouldShowSidebarByMouse(x, y) { if (!sidebarHoverEnabled) return false; if (isSidebarLocked()) return false; if (!isHideSidebarWanted()) return false; if (x <= SIDEBAR_CONFIG.hoverWidth) return true; if (mouseInsideSidebarRect(x, y)) return true; return false; } function scheduleHideIfNeeded(x, y) { if (!sidebarHoverEnabled) return; if (isSidebarLocked()) return; const wantHide = isHideSidebarWanted(); if (!wantHide) { setSidebarHiddenOnRoot(false); clearSidebarTimers(); return; } const shouldShow = shouldShowSidebarByMouse(x, y); if (shouldShow) { clearSidebarTimers(); if (!sidebarVisible) setSidebarHiddenOnRoot(false); return; } if (!sidebarVisible) return; clearSidebarTimers(); sidebarHideTimer = setTimeout(() => { sidebarHideTimer = null; if (!isHideSidebarWanted()) return; const x2 = lastMoveX; const y2 = lastMoveY; if (shouldShowSidebarByMouse(x2, y2)) return; setSidebarHiddenOnRoot(true); }, SIDEBAR_CONFIG.hoverDelay); } function onPointerMove(e) { if (!FEATURE.SIDEBAR) return; if (!sidebarHoverEnabled) return; if (isSidebarLocked()) return; lastMoveX = e.clientX; lastMoveY = e.clientY; if (rafMovePending) return; rafMovePending = true; requestAnimationFrame(() => { rafMovePending = false; scheduleHideIfNeeded(lastMoveX, lastMoveY); }); } function bindSidebarHoverOnce() { const token = ++sidebarBindToken; document.removeEventListener('pointermove', onPointerMove, true); document.addEventListener('pointermove', onPointerMove, { passive: true, capture: true }); setTimeout(() => { if (token !== sidebarBindToken) return; sidebarElCache = pickSidebarEl(); }, 0); } function watchSidebarMount() { let lastEl = null; let debounce = null; const ensure = () => { const el = pickSidebarEl(); if (el && el !== lastEl) { lastEl = el; sidebarElCache = el; bindSidebarHoverOnce(); scheduleHideIfNeeded(lastMoveX || 9999, lastMoveY || 9999); } }; const ob = new MutationObserver(() => { if (!FEATURE.SIDEBAR) return; if (debounce) return; debounce = setTimeout(() => { debounce = null; ensure(); }, 180); }); const root = document.body || document.documentElement; if (root) ob.observe(root, { childList: true, subtree: true }); setInterval(() => { if (!FEATURE.SIDEBAR) return; ensure(); }, 2500); } function setSidebarLock(locked) { safeLSSet(SIDEBAR_CONFIG.lockKey, locked ? 'true' : 'false'); if (locked) { safeLSSet(SIDEBAR_CONFIG.storageKey, 'true'); sidebarHoverEnabled = false; clearSidebarTimers(); setSidebarHiddenOnRoot(true); logger.log('SIDEBAR', '已锁定隐藏'); return; } sidebarHoverEnabled = true; const wantHide = isHideSidebarWanted(); setSidebarHiddenOnRoot(!!wantHide); bindSidebarHoverOnce(); logger.log('SIDEBAR', '已解锁'); } function initSidebarState() { performanceTracker.start('SIDEBAR_INIT'); logger.initModule('SIDEBAR'); if (!FEATURE.SIDEBAR) { setSidebarHiddenOnRoot(false); sidebarHoverEnabled = false; clearSidebarTimers(); logger.moduleReady('SIDEBAR'); performanceTracker.end('SIDEBAR_INIT'); return; } if (isSidebarLocked()) { safeLSSet(SIDEBAR_CONFIG.storageKey, 'true'); setSidebarHiddenOnRoot(true); sidebarHoverEnabled = false; clearSidebarTimers(); logger.moduleReady('SIDEBAR'); performanceTracker.end('SIDEBAR_INIT'); return; } sidebarHoverEnabled = true; const wantHide = isHideSidebarWanted(); setSidebarHiddenOnRoot(!!wantHide); bindSidebarHoverOnce(); watchSidebarMount(); logger.moduleReady('SIDEBAR'); performanceTracker.end('SIDEBAR_INIT'); } function initSidebarToggle() { performanceTracker.start('SIDEBAR_SETUP'); logger.initModule('SIDEBAR'); initSidebarState(); logger.moduleReady('SIDEBAR'); performanceTracker.end('SIDEBAR_SETUP'); } window.xyDYTools = window.xyDYTools || {}; window.xyDYTools.sidebar = window.xyDYTools.sidebar || {}; window.xyDYTools.sidebar.clearLS = function() { safeLSDel(SIDEBAR_CONFIG.storageKey); safeLSDel(SIDEBAR_CONFIG.lockKey); safeLSDel(SIDEBAR_CONFIG.repairKey); return 'ok'; }; /* ========================= */ function injectStyles() { performanceTracker.start('STYLES_INJECTION'); logger.initModule('STYLES'); if (!FEATURE.STYLES) { logger.moduleReady('STYLES'); performanceTracker.end('STYLES_INJECTION'); return; } if (!document.head) { setTimeout(injectStyles, 100); return; } if (document.getElementById('douyin-dynamic-styles')) { logger.moduleReady('STYLES'); performanceTracker.end('STYLES_INJECTION'); return; } const style = document.createElement('style'); style.id = 'douyin-dynamic-styles'; style.innerHTML = ` .wUFzLKZF.danmakuContainer,.xgplayer-immersive-switch-setting.immersive-switch{display:none !important;} #douyin-header{ background:rgba(0,0,0,0.10) !important; backdrop-filter:blur(5px) !important; -webkit-backdrop-filter:blur(5px) !important; position:fixed; top:0;left:0;width:100%; z-index:1000; border-bottom:1px solid rgba(255,255,255,0.10) !important; will-change:transform; } html.tm-nav-autohide #douyin-header{ transform:translateY(-100%); transition:transform 0.28s ease; } html.tm-nav-autohide #douyin-header.show{transform:translateY(0);} html:not(.tm-nav-autohide) #relatedVideoCard{padding-top:60px !important;} #douyin-right-container{padding:0 !important;} .ES4ZDMnf.N07M3gwz.isDark.nUy2mwhv.tC5Oyw9g{background:transparent !important;backdrop-filter:blur(5px) !important;-webkit-backdrop-filter:blur(5px) !important;} .P2uoik9n .basePlayerContainer:not(.highlightPlayer) .xgplayer-controls{background-image:none !important;background:rgba(255,255,255,0.06) !important;backdrop-filter:blur(1px) saturate(1.1) !important;-webkit-backdrop-filter:blur(1px) saturate(1.1) !important;border:1px solid rgba(255,255,255,0.06) !important;box-shadow:none !important;transition:background 0.18s ease,backdrop-filter 0.18s ease,-webkit-backdrop-filter 0.18s ease,border-color 0.18s ease !important;} .P2uoik9n .basePlayerContainer:not(.highlightPlayer) .xgplayer-controls:hover{background:rgba(255,255,255,0.16) !important;backdrop-filter:blur(16px) saturate(1.8) !important;-webkit-backdrop-filter:blur(16px) saturate(1.8) !important;border-color:rgba(255,255,255,0.10) !important;} .xgplayer-controls.show{transform:translateY(0);} #video-info-wrap{opacity:0.3 !important;transition:opacity 0.3s ease !important;} #video-info-wrap:hover{opacity:1 !important;} .video-info-mask,.UXyEyqbq.UdkDK3ea.DZKZZklc{display:none !important;} .xg-video-container{height:100% !important;margin:auto 0 !important;bottom:0 !important;} .L1TH4HdO.d6KxRih3.positionBox,.L1TH4HdO.positionBox{display:none !important;} .nM3w4mVK.byAYwK4P.fullscreen_capture_feedback._z4WuFBP.NdwOHaIw{height:100% !important;border-radius:0 !important;} .nM3w4mVK .kkbhJDRa{width:calc(100%) !important;height:calc(100%) !important;border-radius:0 !important;} #sliderVideo,#sliderVideo::before,#sliderVideo::after{border-radius:0 !important;clip-path:none !important;-webkit-clip-path:none !important;mask:none !important;-webkit-mask:none !important;} #slider-card{border-radius:0 !important;overflow:visible !important;} .PsHhivd9.sHGvkSIn,.Q6VYnosf.userMenuPanelShadowAnimation,.yZlWL2BG,.vtP34xIV.sRPWIReI *,.vlXyJ9Hj,.h3JxiXCd.ZiQxU1tx *,.N3mRyy_g.popShadowAnimation,.F_XLoeLO.c64lf7w4,.ScTolygy.q1kuhAxH,.eBcBNgnP.PHb7B2cG,.k9soqkkm{ background:rgba(255,255,255,0.25) !important; backdrop-filter:blur(10px) saturate(180%) !important; -webkit-backdrop-filter:blur(10px) saturate(180%) !important; border-radius:12px !important; border:1px solid rgba(255,255,255,0.6) !important; box-shadow:0 4px 12px rgba(0,0,0,0.05),inset 0 1px 0 rgba(255,255,255,0.6) !important; color:rgba(0,0,0,0.85) !important; } .PsHhivd9.sHGvkSIn,.Q6VYnosf.userMenuPanelShadowAnimation,.yZlWL2BG *,.vlXyJ9Hj,.N3mRyy_g.popShadowAnimation *,.F_XLoeLO.c64lf7w4 *,.ScTolygy.q1kuhAxH *,.eBcBNgnP.PHb7B2cG *,.k9soqkkm *{ color:rgba(0,0,0,0.85) !important; text-shadow:0 1px 1px rgba(255,255,255,0.35); } .semi-button.semi-button-primary.semi-button-size-small.B7L9kG57{ background:rgba(180,30,45,0.75) !important; backdrop-filter:blur(8px) saturate(120%) !important; -webkit-backdrop-filter:blur(8px) saturate(120%) !important; color:rgba(255,255,255,0.95) !important; border:1px solid rgba(255,255,255,0.25) !important; border-radius:999px !important; font-weight:600; } .semi-button.semi-button-primary.semi-button-size-small.B7L9kG57:hover{ background:rgba(255,77,79,0.9) !important; transform:translateY(-1px); box-shadow:0 4px 10px rgba(0,0,0,0.2) !important; } `; document.head.appendChild(style); logger.moduleReady('STYLES'); performanceTracker.end('STYLES_INJECTION'); } function injectSafeStyles() { performanceTracker.start('SAFE_STYLES'); logger.initModule('STYLES'); if (!FEATURE.STYLES) { logger.moduleReady('STYLES'); performanceTracker.end('SAFE_STYLES'); return; } const styleId = 'douyin-safe-styles'; let style = document.getElementById(styleId); if (!style) { style = document.createElement('style'); style.id = styleId; if (!document.head) { setTimeout(injectSafeStyles, 100); return; } document.head.appendChild(style); } style.textContent = `.xgplayer-playswitch.recommend-out-switch-btn{visibility:hidden !important;opacity:0 !important;}.fullscreen_capture_feedback{padding-right:0 !important;}`; logger.moduleReady('STYLES'); performanceTracker.end('SAFE_STYLES'); } function initTopNavigation() { performanceTracker.start('NAVIGATION_INIT'); logger.initModule('NAVIGATION'); if (!FEATURE.NAVIGATION) { document.documentElement.classList.remove('tm-nav-autohide'); const h = document.getElementById('douyin-header'); if (h) h.classList.add('show'); logger.moduleReady('NAVIGATION'); performanceTracker.end('NAVIGATION_INIT'); return; } let header = null; let lastMouseY = 9999; let showTimeout = null; let hideTimeout = null; let inactivityTimer = null; let bound = false; function findHeader() { header = document.getElementById('douyin-header'); return !!header; } function showHeader() { if (!header) return; clearTimeout(hideTimeout); hideTimeout = null; if (showTimeout) return; showTimeout = setTimeout(() => { if (!header) return; header.classList.add('show'); showTimeout = null; }, 0); } function hideHeader() { if (!header) return; clearTimeout(showTimeout); showTimeout = null; if (hideTimeout) return; hideTimeout = setTimeout(() => { if (!header) return; header.classList.remove('show'); hideTimeout = null; }, 160); } function resetInactivity() { clearTimeout(inactivityTimer); inactivityTimer = setTimeout(() => { if (lastMouseY > 120) hideHeader(); }, 1200); } function onMouseMove(e) { lastMouseY = e.clientY; if (e.clientY <= 14) { showHeader(); resetInactivity(); } } function onWindowOut(e) { if (!e.relatedTarget && !e.toElement) hideHeader(); } function bindOnce() { if (bound) return; bound = true; document.addEventListener('mousemove', onMouseMove, true); window.addEventListener('blur', hideHeader, true); document.addEventListener('mouseout', onWindowOut, true); window.addEventListener('scroll', () => { if (lastMouseY > 120) hideHeader(); }, { passive: true }); } function enable() { document.documentElement.classList.add('tm-nav-autohide'); showHeader(); setTimeout(() => { if (lastMouseY > 120) hideHeader(); }, 800); } function boot() { if (!findHeader()) { setTimeout(boot, 700); return; } bindOnce(); enable(); logger.moduleReady('NAVIGATION'); performanceTracker.end('NAVIGATION_INIT'); } boot(); (function watchRebuild() { const ob = new MutationObserver(() => { if (!FEATURE.NAVIGATION) return; const h = document.getElementById('douyin-header'); if (h && h !== header) { header = h; showHeader(); setTimeout(() => { if (lastMouseY > 120) hideHeader(); }, 600); } }); ob.observe(document.documentElement, { childList: true, subtree: true }); })(); } const LIVE_CONFIG = { debounceDelay: 3000 }; let lastPressTime = 0; let liveCheckInterval; function isElementVisible(el) { if (!el) return false; const rect = el.getBoundingClientRect(); return (rect.width > 0 && rect.height > 0 && rect.top >= 0 && rect.left >= 0 && rect.bottom <= window .innerHeight && rect.right <= window.innerWidth); } function startLiveCheck() { performanceTracker.start('LIVE_DETECTION'); logger.initModule('LIVE'); if (!FEATURE.LIVE) { logger.moduleReady('LIVE'); performanceTracker.end('LIVE_DETECTION'); return; } if (liveCheckInterval) clearInterval(liveCheckInterval); liveCheckInterval = setInterval(() => { const liveIndicators = document.querySelectorAll( '.live-indicator, [data-e2e="live-indicator"]'); const visibleLive = Array.from(liveIndicators).filter(isElementVisible); if (visibleLive.length > 0) { const now = Date.now(); if (now - lastPressTime >= LIVE_CONFIG.debounceDelay) { keyDown('ArrowDown', false); lastPressTime = now; } } }, 1000); logger.moduleReady('LIVE'); performanceTracker.end('LIVE_DETECTION'); } const HIDE_CONFIG = { textsToHide: ['充钻石', '客户端', '壁纸', '投稿', '更多'], maxRetry: 5 }; let hideRetryCount = 0; function hideElements() { performanceTracker.start('ELEMENTS_HIDING'); logger.initModule('HIDE_ELEMENTS'); if (!FEATURE.HIDE_ELEMENTS) { logger.moduleReady('HIDE_ELEMENTS'); performanceTracker.end('ELEMENTS_HIDING'); return; } let foundCount = 0; document.querySelectorAll('.jenVD1aU, .iQdAxsPk, .xgplayer-playswitch').forEach(item => { const text = (item.textContent || '').trim(); if (HIDE_CONFIG.textsToHide.some(t => text.includes(t))) { const parent = item.closest('.Xu0nlrYh') || item.closest('div'); if (parent) { parent.style.visibility = 'hidden'; parent.style.opacity = '0'; parent.style.pointerEvents = 'none'; foundCount++; } } }); const wallpaper = document.querySelector('.xFzvM6nY, .iQdAxsPk'); if (wallpaper) { const p = wallpaper.closest('div'); if (p) { p.style.visibility = 'hidden'; foundCount++; } } if (foundCount < 4 && hideRetryCount < HIDE_CONFIG.maxRetry) { hideRetryCount++; setTimeout(hideElements, 3000); } logger.moduleReady('HIDE_ELEMENTS'); performanceTracker.end('ELEMENTS_HIDING'); } function setupElementHider() { performanceTracker.start('ELEMENTS_MONITOR'); logger.initModule('HIDE_ELEMENTS'); if (!FEATURE.HIDE_ELEMENTS) { logger.moduleReady('HIDE_ELEMENTS'); performanceTracker.end('ELEMENTS_MONITOR'); return; } let checkInterval = null; let successCount = 0; function hideElementsPersistent() { let foundCount = 0; document.querySelectorAll('.jenVD1aU, .iQdAxsPk').forEach(item => { const text = (item.textContent || '').trim(); if (HIDE_CONFIG.textsToHide.some(t => text.includes(t))) { const parent = item.closest('.Xu0nlrYh') || item.closest('div'); if (parent && parent.style.display !== 'none') { parent.style.display = 'none'; foundCount++; } } }); const wallpapers = document.querySelectorAll('.xFzvM6nY, .iQdAxsPk'); wallpapers.forEach(wallpaper => { const parent = wallpaper.closest('div'); if (parent && parent.style.display !== 'none') { parent.style.display = 'none'; foundCount++; } }); if (foundCount > 0) { successCount++; if (successCount > 3 && checkInterval) { clearInterval(checkInterval); checkInterval = setInterval(hideElementsPersistent, 5000); } } } hideElementsPersistent(); checkInterval = setInterval(hideElementsPersistent, 1000); const observer = new MutationObserver(hideElementsPersistent); if (document.body) { observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); } logger.moduleReady('HIDE_ELEMENTS'); performanceTracker.end('ELEMENTS_MONITOR'); } const AD_CONFIG = { blockedKeywords: ['影视', '电影', '电视剧', '观影', '好剧', '狂飙'], blockedAuthors: ['@王者荣耀'], debounceDelay: 3000, stableTries: 6, stableGap: 80 }; try { const kw = localStorage.getItem('xyDYTools_ads_keywords'); if (kw) AD_CONFIG.blockedKeywords = kw.split(/[\n,,]+/g).map(v => v.trim()).filter(Boolean); } catch (_) {} try { const ba = localStorage.getItem('xyDYTools_ads_blockedAuthors'); if (ba) AD_CONFIG.blockedAuthors = ba.split(/[\n,,]+/g).map(v => v.trim()).filter(Boolean); } catch (_) {} let lastSkipTime = 0; let adObserver = null; let adCheckTimer = null; function pickBestBySelector(selector) { const list = Array.from(document.querySelectorAll(selector)); if (!list.length) return null; let best = null; let bestScore = -Infinity; for (const el of list) { if (!isVisible(el)) continue; const r = el.getBoundingClientRect(); const area = r.width * r.height; const score = area * 0.001 + (window.innerHeight - r.bottom) * 0.5 + (window.innerWidth - r.left) * 0.05; if (score > bestScore) { bestScore = score; best = el; } } return best; } function getVideoDescriptionNow() { const el = pickBestBySelector('[data-e2e="video-desc"]'); if (!el) return ''; return normText(el.textContent); } async function getVideoDescriptionStable() { let last = ''; for (let i = 0; i < AD_CONFIG.stableTries; i++) { if (i > 0) await sleep(AD_CONFIG.stableGap); const cur = getVideoDescriptionNow(); if (!cur) { last = ''; continue; } await sleep(AD_CONFIG.stableGap); const cur2 = getVideoDescriptionNow(); if (cur2 && cur2 === cur) return cur2; last = cur2 || cur; } return last; } function getAuthorIdNow() { const el = pickBestBySelector('[data-e2e="feed-video-nickname"]'); if (!el) return ''; return normText(el.textContent); } async function getAuthorIdStable() { let last = ''; for (let i = 0; i < AD_CONFIG.stableTries; i++) { if (i > 0) await sleep(AD_CONFIG.stableGap); const cur = getAuthorIdNow(); if (!cur) { last = ''; continue; } await sleep(AD_CONFIG.stableGap); const cur2 = getAuthorIdNow(); if (cur2 && cur2 === cur) return cur2; last = cur2 || cur; } return last; } function showBlockNotice(reason) { if (!FEATURE.ADS) return; const notice = document.createElement('div'); notice.textContent = `[屏蔽] ${reason}`; Object.assign(notice.style, { position: 'fixed', bottom: '20px', left: '50%', transform: 'translateX(-50%)', background: 'rgba(0,0,0,0.7)', color: '#fff', padding: '8px 12px', borderRadius: '20px', zIndex: 9999, fontSize: '14px', maxWidth: '80%' }); document.body.appendChild(notice); setTimeout(() => notice.remove(), 2000); } function hitKeyword(desc) { const d = String(desc || '').toLowerCase(); return AD_CONFIG.blockedKeywords.find(k => d.includes(String(k).toLowerCase())) || ''; } function hitAuthor(author) { const a = normText(author).toLowerCase(); if (!a) return ''; for (const raw of (AD_CONFIG.blockedAuthors || [])) { const p = normText(raw).toLowerCase(); if (!p) continue; if (a.includes(p)) return raw; } return ''; } function skipVideo(reasonText) { const now = Date.now(); if (now - lastSkipTime < AD_CONFIG.debounceDelay) return; lastSkipTime = now; try { keyDown('r', false); } catch (_) {} try { keyUp('r'); } catch (_) {} if (reasonText) showBlockNotice(reasonText); } async function checkAndHandleVideo() { if (!FEATURE.ADS) return; const [desc, author] = await Promise.all([ getVideoDescriptionStable(), getAuthorIdStable() ]); const a = hitAuthor(author); if (a) { skipVideo(`作者命中:${a}`); return; } const k1 = hitKeyword(desc); const k2 = hitKeyword(author); if (k1 || k2) skipVideo(`关键词命中:"${k1 || k2}"`); } function scheduleAdCheck() { if (!FEATURE.ADS) return; if (adCheckTimer) return; adCheckTimer = setTimeout(async () => { adCheckTimer = null; try { await checkAndHandleVideo(); } catch (_) {} }, 120); } function observeVideo() { performanceTracker.start('ADS_OBSERVER'); logger.initModule('ADS'); if (!FEATURE.ADS) { logger.moduleReady('ADS'); performanceTracker.end('ADS_OBSERVER'); return; } if (adObserver) adObserver.disconnect(); const target = document.body || document.documentElement; if (!target) { setTimeout(observeVideo, 800); return; } adObserver = new MutationObserver(() => scheduleAdCheck()); adObserver.observe(target, { childList: true, subtree: true }); scheduleAdCheck(); logger.moduleReady('ADS'); performanceTracker.end('ADS_OBSERVER'); } window.xyDYTools = window.xyDYTools || {}; window.xyDYTools.getDescNow = function() { return getVideoDescriptionNow(); }; window.xyDYTools.getDescStable = async function() { return await getVideoDescriptionStable(); }; window.xyDYTools.getAuthorNow = function() { return getAuthorIdNow(); }; window.xyDYTools.getAuthorStable = async function() { return await getAuthorIdStable(); }; window.xyDYTools.forceCheck = async function() { await checkAndHandleVideo(); return 'checked'; }; window.xyDYTools.setBlockedAuthors = function(arr) { AD_CONFIG.blockedAuthors = Array.isArray(arr) ? arr : AD_CONFIG.blockedAuthors; return AD_CONFIG.blockedAuthors; }; window.xyDYTools.addBlockedAuthor = function(one) { const v = normText(one); if (!v) return AD_CONFIG.blockedAuthors; if (!AD_CONFIG.blockedAuthors.some(x => normText(x) === v)) AD_CONFIG.blockedAuthors.push(v); return AD_CONFIG.blockedAuthors; }; window.xyDYTools.listAllDescNodes = function() { const list = Array.from(document.querySelectorAll('[data-e2e="video-desc"]')); return list.map((el, i) => { const r = el.getBoundingClientRect(); return { index: i, text: normText(el.textContent), visible: isVisible(el), rect: { top: r.top, left: r.left, width: r.width, height: r.height } }; }); }; window.xyDYTools.listAllAuthorNodes = function() { const list = Array.from(document.querySelectorAll('[data-e2e="feed-video-nickname"]')); return list.map((el, i) => { const r = el.getBoundingClientRect(); return { index: i, text: normText(el.textContent), visible: isVisible(el), rect: { top: r.top, left: r.left, width: r.width, height: r.height } }; }); }; window.xyDYTools.printADDebug = async function() { const time = new Date().toLocaleTimeString(); const nowDesc = window.xyDYTools.getDescNow(); const nowAuthor = window.xyDYTools.getAuthorNow(); const stableDesc = await window.xyDYTools.getDescStable(); const stableAuthor = await window.xyDYTools.getAuthorStable(); console.log('==== AD DEBUG ===='); console.log('time:', time); console.log('nowAuthor:', nowAuthor); console.log('stableAuthor:', stableAuthor); console.log('nowDesc:', nowDesc); console.log('stableDesc:', stableDesc); console.log('blockedAuthors:', AD_CONFIG.blockedAuthors); console.log('blockedKeywords:', AD_CONFIG.blockedKeywords); console.log('=================='); return { time, nowAuthor, stableAuthor, nowDesc, stableDesc }; }; const MOUSE_CONFIG = { swipeThreshold: 200, clickMaxMove: 5, clickMaxTime: 300, longPressTime: 500 }; let startX = 0; let startY = 0; let startTime = 0; let isMouseDown = false; let isSwiping = false; let blockClick = false; let longPressTimer = null; let isLongPressing = false; function mouseKeyDown(key, repeat) { if (!FEATURE.MOUSE) return; keyDown(key, repeat); } function mouseKeyUp(key) { if (!FEATURE.MOUSE) return; keyUp(key); } function likeVideo() { const video = document.querySelector('video'); if (!video) return; const wasPlaying = !video.paused; mouseKeyDown('z', false); if (wasPlaying) { setTimeout(() => { if (video.paused) video.play(); }, 100); } } function handleSwipe(direction) { if (!FEATURE.MOUSE) return; if (direction === 'left') likeVideo(); if (direction === 'right') mouseKeyDown('r', false); } document.addEventListener('mousedown', function(e) { if (!FEATURE.MOUSE) return; startX = e.clientX; startY = e.clientY; startTime = Date.now(); isMouseDown = true; isSwiping = false; blockClick = false; isLongPressing = false; if (e.button === 1) { e.preventDefault(); e.stopPropagation(); mouseKeyDown('x', false); return; } if (e.button === 0) { longPressTimer = setTimeout(() => { if (isMouseDown && !isSwiping) { isLongPressing = true; blockClick = true; mouseKeyDown('d', true); } }, MOUSE_CONFIG.longPressTime); } }, true); document.addEventListener('mousemove', function(e) { if (!FEATURE.MOUSE) return; if (!isMouseDown) return; if (isLongPressing) return; const deltaX = e.clientX - startX; const deltaY = e.clientY - startY; if (!isSwiping) { if (Math.abs(deltaX) > MOUSE_CONFIG.swipeThreshold || Math.abs(deltaY) > MOUSE_CONFIG .swipeThreshold) { isSwiping = true; blockClick = true; if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } const direction = Math.abs(deltaX) > Math.abs(deltaY) ? (deltaX > 0 ? 'right' : 'left') : (deltaY > 0 ? 'down' : 'up'); handleSwipe(direction); } } }, true); document.addEventListener('mouseup', function(e) { if (!FEATURE.MOUSE) return; if (!isMouseDown) return; if (e.button === 0) { if (longPressTimer) { clearTimeout(longPressTimer); longPressTimer = null; } if (isLongPressing) { mouseKeyUp('d'); e.preventDefault(); e.stopPropagation(); } } const endX = e.clientX; const endY = e.clientY; const deltaX = endX - startX; const deltaY = endY - startY; const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); const duration = Date.now() - startTime; if (distance >= MOUSE_CONFIG.clickMaxMove || duration >= MOUSE_CONFIG.clickMaxTime || isSwiping || isLongPressing) { e.preventDefault(); e.stopPropagation(); } isMouseDown = false; isSwiping = false; isLongPressing = false; setTimeout(() => { blockClick = false; }, 50); }, true); document.addEventListener('click', function(e) { if (!FEATURE.MOUSE) return; if (blockClick) { e.stopPropagation(); e.preventDefault(); } }, true); document.addEventListener('keydown', (e) => { if (!e.altKey || e.ctrlKey || e.shiftKey) return; const key = e.key.toUpperCase(); if (key === '1') { e.preventDefault(); e.stopPropagation(); setSidebarLock(!isSidebarLocked()); } }, true); function initSettingsModal() { (function injectUIStyle() { if (document.getElementById('xydytools-ui-style')) return; const style = document.createElement('style'); style.id = 'xydytools-ui-style'; style.textContent = ` #xydytools-modal{position:fixed;inset:0;z-index:9999999;display:none;} #xydytools-modal.show{display:block;} #xydytools-modal .mask{position:absolute;inset:0;background:rgba(0,0,0,0.55);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);} #xydytools-modal .panel{ position:absolute;left:50%;top:50%;transform:translate(-50%,-50%); width:min(520px, 92vw); max-height:min(640px, 82vh); overflow:auto; background:rgba(255,255,255,0.28); border:1px solid rgba(255,255,255,0.55); border-radius:16px; box-shadow:0 16px 60px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.55); color:rgba(0,0,0,0.88); } #xydytools-modal .hd{ position:sticky;top:0;z-index:1; display:flex;align-items:center;justify-content:space-between;gap:12px; padding:14px 14px 10px; background:linear-gradient(to bottom, rgba(255,255,255,0.38), rgba(255,255,255,0.18)); backdrop-filter:blur(10px) saturate(180%); -webkit-backdrop-filter:blur(10px) saturate(180%); border-bottom:1px solid rgba(255,255,255,0.35); border-top-left-radius:16px;border-top-right-radius:16px; } #xydytools-modal .title{display:flex;align-items:center;gap:10px;font-weight:800;letter-spacing:0.2px;} #xydytools-modal .sub{margin-left:26px;margin-top:2px;font-size:12px;color:rgba(0,0,0,0.55);} #xydytools-modal .close{ width:34px;height:34px;border-radius:12px; display:flex;align-items:center;justify-content:center; cursor:pointer;user-select:none; background:rgba(255,255,255,0.35); border:1px solid rgba(255,255,255,0.45); transition:transform .12s ease, background .12s ease; } #xydytools-modal .close:hover{background:rgba(255,255,255,0.48);transform:translateY(-1px);} #xydytools-modal .close:active{transform:translateY(0px) scale(0.98);} #xydytools-modal .bd{padding:12px 14px 14px;} #xydytools-modal .hint{ font-size:12px;color:rgba(0,0,0,0.58); padding:10px 12px;border-radius:12px; background:rgba(255,255,255,0.26); border:1px solid rgba(255,255,255,0.35); margin-bottom:12px; } #xydytools-modal .list{display:flex;flex-direction:column;gap:10px;} #xydytools-modal .row{ display:flex;align-items:center;justify-content:space-between;gap:12px; padding:10px 12px;border-radius:14px; background:rgba(255,255,255,0.22); border:1px solid rgba(255,255,255,0.32); } #xydytools-modal .row .l{display:flex;flex-direction:column;gap:4px;min-width:0;} #xydytools-modal .row .name{font-weight:700;font-size:14px;} #xydytools-modal .row .desc{ font-size:12px;color:rgba(0,0,0,0.55); white-space:nowrap;overflow:hidden;text-overflow:ellipsis; max-width:320px; } #xydytools-modal .toggle{position:relative;display:inline-block;width:58px;height:32px;} #xydytools-modal .toggle input{opacity:0;width:0;height:0;position:absolute;} #xydytools-modal .slider{ position:absolute;inset:0;background:#d1d1d6;border-radius:999px; cursor:pointer;-webkit-tap-highlight-color:transparent;user-select:none; transition:background .2s .25s; } #xydytools-modal .slider:before{ content:'';position:absolute;top:3px;left:3px;width:26px;height:26px;border-radius:50%; background:#fff;box-shadow:0 2px 6px rgba(0,0,0,.2); transition:transform .25s cubic-bezier(.4,0,.2,1); } #xydytools-modal .toggle input:checked + .slider{background:#34c759;} #xydytools-modal .toggle input:checked + .slider:before{transform:translateX(26px);} #xydytools-modal .toggle input:focus + .slider{box-shadow:0 0 0 3px rgba(52,199,89,.3);} #xydytools-modal .adsBox{ margin-top:10px; padding:10px 12px; border-radius:14px; background:rgba(255,255,255,0.20); border:1px solid rgba(255,255,255,0.30); display:none; } #xydytools-modal .adsBox.show{display:block;} #xydytools-modal .adsBox .t{font-weight:800;font-size:13px;margin-bottom:6px;} #xydytools-modal .adsBox .d{font-size:12px;color:rgba(0,0,0,0.55);margin-bottom:8px;line-height:1.4;} #xydytools-modal .adsBox textarea{ width:100%; min-height:74px; resize:vertical; padding:10px 10px; border-radius:12px; background:rgba(255,255,255,0.35); border:1px solid rgba(255,255,255,0.45); outline:none; color:rgba(0,0,0,0.88); font-size:12px; line-height:1.45; } #xydytools-modal .adsBox textarea:focus{box-shadow:0 0 0 3px rgba(52,199,89,.20);} #xydytools-modal .adsBox .ops{display:flex;gap:10px;margin-top:8px;align-items:center;} #xydytools-modal .adsBox .btn{ padding:7px 12px; border-radius:999px; background:rgba(0,0,0,0.75); color:#fff; border:1px solid rgba(255,255,255,0.25); cursor:pointer; user-select:none; font-size:12px; } #xydytools-modal .adsBox .btn:active{transform:scale(0.98);} #xydytools-modal .adsBox .tip{font-size:12px;color:rgba(0,0,0,0.55);} `; (document.head || document.documentElement).appendChild(style); })(); const FEATURE_META = [{ k: 'SIDEBAR', name: '侧栏', desc: '隐藏/悬停弹出/锁定隐藏' }, { k: 'STYLES', name: '样式美化', desc: '玻璃拟态 + 播放器控件优化' }, { k: 'NAVIGATION', name: '顶部栏智能', desc: '靠近顶部显示,离开自动收起' }, { k: 'LIVE', name: '直播跳过(未实装)', desc: '检测直播标识并跳过' }, { k: 'HIDE_ELEMENTS', name: '隐藏杂项', desc: '充钻石/壁纸/投稿等' }, { k: 'ADS', name: '关键词屏蔽', desc: '作者信息,视频信息命中关键词就跳过' }, { k: 'MOUSE', name: '鼠标手势', desc: '左滑点赞/右滑R/中键X/左键长按D' }, { k: 'LOADING', name: '加载遮罩', desc: '加载提示层' }, { k: 'PERFORMANCE', name: '性能统计', desc: '模块耗时统计与报告' } ]; function ensureModal() { let modal = document.getElementById('xydytools-modal'); if (modal) return modal; modal = document.createElement('div'); modal.id = 'xydytools-modal'; modal.innerHTML = `
`; document.documentElement.appendChild(modal); const hide = () => { modal.classList.remove('show'); document.documentElement.style.overflow = ''; }; modal.querySelector('.mask').addEventListener('click', hide, true); modal.querySelector('.close').addEventListener('click', hide, true); window.addEventListener('keydown', (e) => { if (modal.classList.contains('show') && e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); hide(); } }, true); return modal; } function renderModal() { const modal = ensureModal(); const list = modal.querySelector('#xydytools-list'); list.innerHTML = ''; FEATURE_META.forEach(item => { const row = document.createElement('div'); row.className = 'row'; row.innerHTML = `
${item.name}
${item.desc}
`; list.appendChild(row); const input = row.querySelector('input'); if (item.k === 'ADS') { const LS_ADS_KW = 'xyDYTools_ads_keywords'; const LS_ADS_AUTH = 'xyDYTools_ads_blockedAuthors'; function parseList(s) { return String(s || '').split(/[\n,,]+/g).map(v => v.trim()).filter(Boolean); } function joinList(arr) { return (Array.isArray(arr) ? arr : []).join('\n'); } let kw = []; let ba = []; try { const kwRaw = localStorage.getItem(LS_ADS_KW); kw = kwRaw ? parseList(kwRaw) : (AD_CONFIG.blockedKeywords || []); } catch (_) { kw = (AD_CONFIG.blockedKeywords || []); } try { const baRaw = localStorage.getItem(LS_ADS_AUTH); ba = baRaw ? parseList(baRaw) : (AD_CONFIG.blockedAuthors || []); } catch (_) { ba = (AD_CONFIG.blockedAuthors || []); } const box = document.createElement('div'); box.className = 'adsBox' + (FEATURE.ADS ? ' show' : ''); box.innerHTML = `
关键词库(简介 + 作者名共用)
一行一个;支持逗号分隔。命中就屏蔽。
作者黑名单(可选)
填作者名关键词,命中就屏蔽。
保存
恢复默认
保存后立刻生效
`; list.appendChild(box); const kwEl = box.querySelector('textarea.kw'); const baEl = box.querySelector('textarea.ba'); function applyToConfig() { AD_CONFIG.blockedKeywords = parseList(kwEl.value); AD_CONFIG.blockedAuthors = parseList(baEl.value); } box.querySelector('.save').addEventListener('click', () => { try { localStorage.setItem(LS_ADS_KW, kwEl.value); } catch (_) {} try { localStorage.setItem(LS_ADS_AUTH, baEl.value); } catch (_) {} applyToConfig(); try { scheduleAdCheck(); } catch (_) {} }, true); box.querySelector('.reset').addEventListener('click', () => { kwEl.value = joinList(['影视', '电影', '电视剧', '观影', '好剧', '狂飙']); baEl.value = joinList(['@王者荣耀']); try { localStorage.removeItem(LS_ADS_KW); } catch (_) {} try { localStorage.removeItem(LS_ADS_AUTH); } catch (_) {} applyToConfig(); try { scheduleAdCheck(); } catch (_) {} }, true); input.addEventListener('change', () => box.classList.toggle('show', !!FEATURE.ADS), true); } input.addEventListener('change', () => { const v = input.checked ? 1 : 0; FEATURE[item.k] = v; try { localStorage.setItem(LS_PREFIX + item.k, String(v)); } catch (_) {} if (item.k === 'STYLES') { if (!v) { try { document.getElementById('douyin-dynamic-styles')?.remove(); } catch (_) {} try { document.getElementById('douyin-safe-styles')?.remove(); } catch (_) {} } else { try { injectStyles(); } catch (_) {} try { injectSafeStyles(); } catch (_) {} } } if (item.k === 'NAVIGATION') { if (!v) { document.documentElement.classList.remove('tm-nav-autohide'); const h = document.getElementById('douyin-header'); if (h) h.classList.add('show'); } else { try { initTopNavigation(); } catch (_) {} } } if (item.k === 'ADS') { if (!v) { try { adObserver && adObserver.disconnect(); } catch (_) {} } else { try { observeVideo(); checkAndHandleVideo(); } catch (_) {} } } if (item.k === 'LIVE') { if (!v) { try { liveCheckInterval && clearInterval(liveCheckInterval); } catch (_) {} } else { try { startLiveCheck(); } catch (_) {} } } }, true); }); } function showModal() { const modal = ensureModal(); renderModal(); modal.classList.add('show'); document.documentElement.style.overflow = 'hidden'; } window.addEventListener('keydown', (e) => { if (!e.altKey || e.ctrlKey || e.shiftKey) return; if ((e.key || '').toLowerCase() !== 'x') return; e.preventDefault(); e.stopPropagation(); showModal(); }, true); } (function dySilentDislikeAndNoLive() { if (window.__dySilentMenuBound) return; window.__dySilentMenuBound = true; let running = false; document.addEventListener('mousemove', (e) => { window.__dyLastMouseX = e.clientX; window.__dyLastMouseY = e.clientY; }, true); (function injectSilentMenuStyle() { if (document.getElementById('dy-silent-menu-style')) return; const style = document.createElement('style'); style.id = 'dy-silent-menu-style'; style.textContent = `html.dy-silent-menu div[id="qgmiQqfW"]{opacity:0 !important;transition:none !important;}`; (document.head || document.documentElement).appendChild(style); })(); function fireFullClick(el) { if (!el) return false; el.dispatchEvent(new MouseEvent('mousemove', { bubbles: true })); el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, button: 0, buttons: 1 })); el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, button: 0, buttons: 0 })); el.click(); return true; } function findMenuItemByText(text) { const nodes = Array.from(document.querySelectorAll('.JyNO_DD4')); return nodes.find(n => (n.textContent || '').trim() === text) || null; } function waitMenuItem(text, timeoutMs) { return new Promise(resolve => { const t0 = Date.now(); const hit = findMenuItemByText(text); if (hit) return resolve(hit); const ob = new MutationObserver(() => { const n = findMenuItemByText(text); if (n) { ob.disconnect(); resolve(n); } else if (Date.now() - t0 > timeoutMs) { ob.disconnect(); resolve(null); } }); ob.observe(document.documentElement, { childList: true, subtree: true }); setTimeout(() => { ob.disconnect(); resolve(findMenuItemByText(text)); }, timeoutMs + 50); }); } function triggerRightClick() { let x = window.__dyLastMouseX; let y = window.__dyLastMouseY; if (typeof x !== 'number' || typeof y !== 'number') { x = Math.floor(window.innerWidth * 0.5); y = Math.floor(window.innerHeight * 0.5); } const el = document.elementFromPoint(x, y) || document.body; const down = { bubbles: true, cancelable: true, view: window, button: 2, buttons: 2, clientX: x, clientY: y }; const up = { bubbles: true, cancelable: true, view: window, button: 2, buttons: 0, clientX: x, clientY: y }; el.dispatchEvent(new MouseEvent('mousedown', down)); el.dispatchEvent(new MouseEvent('contextmenu', down)); el.dispatchEvent(new MouseEvent('mouseup', up)); document.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window, button: 0, buttons: 0, clientX: x, clientY: y })); } async function runSilentBlock() { if (running) return; running = true; try { document.documentElement.classList.add('dy-silent-menu'); triggerRightClick(); const a = await waitMenuItem('不感兴趣', 2500); if (a) fireFullClick(a); await sleep(80); const b = await waitMenuItem('不想看直播', 2500); if (b) fireFullClick(b); } finally { setTimeout(() => { document.documentElement.classList.remove('dy-silent-menu'); running = false; }, 200); } } document.addEventListener('keydown', (e) => { if (e.altKey && !e.ctrlKey && !e.shiftKey && (e.key === 'f' || e.key === 'F')) { e.preventDefault(); e.stopPropagation(); runSilentBlock(); } }, true); })(); function initializeScript() { performanceTracker.start('TOTAL_INIT'); createLoadingScreen(); try { initSidebarToggle(); } catch (_) {} try { injectStyles(); window.__xyDYToolsBoot.styles = true; } catch (_) {} try { injectSafeStyles(); window.__xyDYToolsBoot.safeStyles = true; } catch (_) {} try { initSettingsModal(); } catch (_) {} if (window.location.host === 'www.douyin.com') { try { initTopNavigation(); window.__xyDYToolsBoot.nav = true; } catch (_) {} } try { hideElements(); window.__xyDYToolsBoot.hide = true; } catch (_) {} try { observeVideo(); window.__xyDYToolsBoot.ads = true; } catch (_) {} try { checkAndHandleVideo(); } catch (_) {} window.__xyDYToolsBoot.inited = true; try { startLiveCheck(); } catch (_) {} if (document.readyState === 'complete') setupElementHider(); else window.addEventListener('load', setupElementHider); setTimeout(() => { performanceTracker.printPerformanceReport(); performanceTracker.end('TOTAL_INIT'); }, 2000); } initializeScript(); window.douyinPerformance = performanceTracker; })();