您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Lightweight privacy protection with tracking script blocking, precise video player detection, and Tampermonkey optimization
// ==UserScript== // @name Ultimate Privacy Shield // @version 4.0.5 // @description Lightweight privacy protection with tracking script blocking, precise video player detection, and Tampermonkey optimization // @license MIT // @author Boris Likhachev // @match *://*/* // @grant GM_getValue // @grant GM_setValue // @grant none // @namespace https://gf.qytechs.cn/users/764793 // ==/UserScript== (function() { 'use strict'; const stats = { cleanedUrls: 0, trackersBlocked: 0, errorsDetected: 0, videoEventsProcessed: 0, adGuardBlocks: 0 }; const debugMode = GM_getValue('upsDebugMode', false); const fastPathMode = GM_getValue('fastPathMode', true); const debugLog = (message) => { if (debugMode) console.log(`[UPS ${new Date().toISOString()}] ${message}`); }; const loadConfig = () => { const defaultConfig = { userDisabledSites: [], lastUpdated: Date.now(), customVideoSelectors: [], blockedTrackerDomains: [ 'google-analytics.com', 'doubleclick.net', 'facebook.com', 'hotjar.com', 'mixpanel.com', 'amplitude.com', 'googletagmanager.com' ], trackerKeywords: ['trackevent', 'analytics', 'collect', 'beacon'], allowedVideoScripts: ['video-search-pc.js', 'phub.js', 'player'] }; try { const storedConfig = GM_getValue('upsConfig', null); if (!storedConfig || storedConfig.lastUpdated < Date.now() - 30 * 24 * 60 * 60 * 1000) { debugLog('Config outdated or missing, using default'); return defaultConfig; } storedConfig.userDisabledSites = []; // Force reset debugLog(`Loaded config with userDisabledSites: ${JSON.stringify(storedConfig.userDisabledSites)}`); return { ...defaultConfig, ...storedConfig }; } catch (error) { debugLog(`Error in loadConfig: ${error.message}`); return defaultConfig; } }; const config = loadConfig(); const saveConfig = (config) => { try { config.lastUpdated = Date.now(); GM_setValue('upsConfig', config); } catch (error) { debugLog(`Error in saveConfig: ${error.message}`); } }; const runWhenIdle = (callback) => { try { if ('requestIdleCallback' in window) { window.requestIdleCallback(callback, { timeout: 1500 }); } else { setTimeout(callback, 500); } } catch (error) { debugLog(`Error in runWhenIdle: ${error.message}`); stats.errorsDetected++; } }; const getRealHostname = () => { try { const hostname = new URL(window.location.href).hostname; if (hostname === 'local.adguard.org') { const realUrl = document.referrer || document.querySelector('meta[property="og:url"]')?.content || window.location.href; const realHostname = new URL(realUrl).hostname; debugLog(`AdGuard proxy detected, resolved hostname: ${realHostname}`); return realHostname; } return hostname; } catch (error) { debugLog(`Error detecting hostname: ${error.message}`); return window.location.hostname; } }; const isSiteDisabled = () => config.userDisabledSites.includes(getRealHostname()); const blockTrackingScripts = () => { try { const scripts = document.querySelectorAll('script[src]'); for (const script of scripts) { const src = script.src.toLowerCase(); if ( config.blockedTrackerDomains.some(domain => src.includes(domain)) || config.trackerKeywords.some(keyword => src.includes(keyword)) ) { if (!config.allowedVideoScripts.some(allowed => src.includes(allowed))) { script.remove(); stats.trackersBlocked++; debugLog(`Blocked tracking script: ${src || 'inline'}`); } } } const observer = new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.tagName === 'SCRIPT' && node.src) { const src = node.src.toLowerCase(); if ( config.blockedTrackerDomains.some(domain => src.includes(domain)) || config.trackerKeywords.some(keyword => src.includes(keyword)) ) { if (!config.allowedVideoScripts.some(allowed => src.includes(allowed))) { node.remove(); stats.trackersBlocked++; debugLog(`Blocked dynamic script: ${src}`); } } } } } }); observer.observe(document.head, { childList: true }); debugLog('Tracking script blocker initialized'); } catch (error) { debugLog(`Error in blockTrackingScripts: ${error.message}`); stats.errorsDetected++; } }; const blockCanvasFingerprinting = () => { try { const originalGetContext = HTMLCanvasElement.prototype.getContext; HTMLCanvasElement.prototype.getContext = function(type, attributes) { if (type === '2d' || type === 'webgl') { debugLog('Canvas access detected, applying noise'); const ctx = originalGetContext.apply(this, arguments); if (ctx) { const originalFillText = ctx.fillText; ctx.fillText = function(...args) { args[0] += String.fromCharCode(Math.random() * 5); return originalFillText.apply(this, args); }; const originalGetImageData = ctx.getImageData; ctx.getImageData = function(...args) { const data = originalGetImageData.apply(this, args); for (let i = 0; i < data.data.length; i += 4) { data.data[i] += Math.random() * 2 - 1; } return data; }; } return ctx; } return originalGetContext.apply(this, arguments); }; debugLog('Canvas fingerprinting protection enabled'); } catch (error) { debugLog(`Error in blockCanvasFingerprinting: ${error.message}`); stats.errorsDetected++; } }; const blockAudioFingerprinting = () => { try { if (window.AudioContext || window.webkitAudioContext) { window.AudioContext = window.webkitAudioContext = () => { debugLog('AudioContext access blocked'); throw new Error('AudioContext blocked by UPS'); }; Object.defineProperty(window, 'AudioContext', { value: undefined, writable: false }); Object.defineProperty(window, 'webkitAudioContext', { value: undefined, writable: false }); debugLog('Audio fingerprinting protection enabled'); } } catch (error) { debugLog(`Error in blockAudioFingerprinting: ${error.message}`); stats.errorsDetected++; } }; const blockWebGPU = () => { try { if (window.GPU) { Object.defineProperty(window, 'GPU', { value: undefined, writable: false }); debugLog('WebGPU blocked'); } } catch (error) { debugLog(`Error in blockWebGPU: ${error.message}`); stats.errorsDetected++; } }; const blockWebTransport = () => { try { if (window.WebTransport) { window.WebTransport = () => { throw new Error('WebTransport blocked by UPS'); }; Object.defineProperty(window, 'WebTransport', { value: undefined, writable: false }); debugLog('WebTransport blocked'); } } catch (error) { debugLog(`Error in blockWebTransport: ${error.message}`); stats.errorsDetected++; } }; const blockPrivacySandbox = () => { try { if (document.browsingTopics) { document.browsingTopics = () => Promise.resolve([]); debugLog('Privacy Sandbox Topics API blocked'); } if (window.Fledge) { window.Fledge = undefined; debugLog('Privacy Sandbox FLEDGE API blocked'); } } catch (error) { debugLog(`Error in blockPrivacySandbox: ${error.message}`); stats.errorsDetected++; } }; const detectTrackingParams = (url) => { try { const urlObj = new URL(url); const paramsToRemove = []; for (const [param, value] of urlObj.searchParams) { if ( (param.includes('id') || param.includes('track') || param.length > 10) && value.length > 20 && /[0-9a-f]{8}/.test(value) ) { paramsToRemove.push(param); } } paramsToRemove.forEach(param => urlObj.searchParams.delete(param)); return urlObj.toString(); } catch { return url; } }; const cleanFirstPartyUrls = () => { try { const links = document.querySelectorAll('a[href]:not([data-ups-cleaned])'); for (const link of links) { if (!link.href.startsWith('javascript:')) { const cleaned = detectTrackingParams(link.href); if (cleaned !== link.href) { link.href = cleaned; link.dataset.upsCleaned = 'true'; stats.cleanedUrls++; debugLog(`Cleaned URL: ${link.href}`); } } } } catch (error) { debugLog(`Error in cleanFirstPartyUrls: ${error.message}`); stats.errorsDetected++; } }; const debounce = (func, wait) => { let timeout; return (...args) => { clearTimeout(timeout); timeout = setTimeout(() => func(...args), wait); }; }; const cleanFirstPartyUrlsDebounced = debounce(cleanFirstPartyUrls, 200); const observeLinks = () => { try { const observer = new MutationObserver(() => { if (Math.random() > 0.3) return; // Reduced frequency cleanFirstPartyUrlsDebounced(); }); observer.observe(document.body, { childList: true, subtree: true }); } catch (error) { debugLog(`Error in observeLinks: ${error.message}`); stats.errorsDetected++; } }; const videoPlayerModule = { selectors: [ 'video', '.video-player', '.vjs-control-bar', '.plyr__controls', '.jwplayer', '.shaka-controls-container', '.ytp-progress-bar', '.player-controls', '.twitch-player', '.hls-player', '.dash-player', '[data-player]', '[data-vimeo-id]', '[data-video-id]', '[data-twitch-id]' ], isVideoPlayerInterface(element) { try { if (!element) return false; const tagName = element.tagName.toLowerCase(); if (tagName === 'video') return true; const styles = window.getComputedStyle(element); return ( ['absolute', 'fixed'].includes(styles.position) || parseInt(styles.zIndex, 10) > 1 || ['pointer', 'progress'].includes(styles.cursor) || ['button', 'input', 'div', 'span'].includes(tagName) && ( element.className.toLowerCase().includes('control') || element.className.toLowerCase().includes('progress') || element.hasAttribute('aria-label') && element.getAttribute('aria-label').toLowerCase().includes('play') || element.hasAttribute('role') && ['slider', 'progressbar'].includes(element.getAttribute('role').toLowerCase()) ) ); } catch (error) { debugLog(`Error in isVideoPlayerInterface: ${error.message}`); return false; } }, isWithinPlayerBounds(x, y) { try { for (const bounds of config.videoPlayerBounds || []) { if (x >= bounds.left && x <= bounds.right && y >= bounds.top && y <= bounds.bottom) { return true; } } return false; } catch (error) { debugLog(`Error in isWithinPlayerBounds: ${error.message}`); return false; } }, updatePlayerBounds() { try { const selectors = this.selectors.concat(config.customVideoSelectors).join(', '); const players = document.querySelectorAll(selectors); config.videoPlayerBounds = []; players.forEach(player => { const rect = player.getBoundingClientRect(); if (rect.width > 50 && rect.height > 50) { // Filter small elements config.videoPlayerBounds.push({ left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom }); } }); saveConfig(config); } catch (error) { debugLog(`Error in updatePlayerBounds: ${error.message}`); } }, observePlayers() { try { const observer = new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE && node.matches(this.selectors.join(', '))) { this.updatePlayerBounds(); } } } }); observer.observe(document.body, { childList: true, subtree: true }); debugLog('Video player observer initialized'); } catch (error) { debugLog(`Error in observePlayers: ${error.message}`); stats.errorsDetected++; } }, discoverAdaptiveSelectors() { try { const videos = document.querySelectorAll('video'); videos.forEach(video => { const parent = video.closest('div, section, article'); if (parent && parent.className && !this.selectors.includes(`.${parent.className.split(' ')[0]}`)) { const className = parent.className.split(' ')[0]; if (className && !config.customVideoSelectors.includes(`.${className}`)) { config.customVideoSelectors.push(`.${className}`); saveConfig(config); } } }); } catch (error) { debugLog(`Error in discoverAdaptiveSelectors: ${error.message}`); } } }; const protectVideoPlayerEvents = () => { try { const criticalEvents = ['click', 'mousedown', 'mouseup', 'timeupdate', 'progress', 'playing', 'volumechange']; const originalAddEventListener = EventTarget.prototype.addEventListener; EventTarget.prototype.addEventListener = function(type, listener, options) { if (criticalEvents.includes(type)) { const context = this; const wrappedListener = (...args) => { const event = args[0]; if ( event.target.tagName.toLowerCase() === 'video' || videoPlayerModule.isVideoPlayerInterface(event.target) || (event.clientX !== undefined && event.clientY !== undefined && videoPlayerModule.isWithinPlayerBounds(event.clientX, event.clientY)) ) { stats.videoEventsProcessed++; return listener.apply(context, args); } return listener.apply(context, args); }; return originalAddEventListener.call(this, type, wrappedListener, { ...options, passive: true }); } return originalAddEventListener.apply(this, arguments); }; debugLog('Video player event protection enabled'); } catch (error) { debugLog(`Error in protectVideoPlayerEvents: ${error.message}`); stats.errorsDetected++; } }; const adGuardModule = { detectBlockedResources() { try { const resources = document.querySelectorAll('script[src], link[href][rel="stylesheet"]'); resources.forEach(resource => { resource.addEventListener('error', () => { stats.adGuardBlocks++; debugLog(`Detected blocked resource: ${resource.src || resource.href}`); }, { passive: true }); }); } catch (error) { debugLog(`Error in detectBlockedResources: ${error.message}`); } } }; const detectSiteErrors = () => { try { const errorListener = (event) => { stats.errorsDetected++; debugLog(`Site error: ${event.message}`); }; window.addEventListener('error', errorListener, { passive: true }); window.addEventListener('unhandledrejection', errorListener, { passive: true }); } catch (error) { debugLog(`Error in detectSiteErrors: ${error.message}`); stats.errorsDetected++; } }; const init = () => { try { if (isSiteDisabled()) { debugLog('UPS disabled for this site'); return; } debugLog('Starting UPS initialization'); Object.defineProperty(navigator, 'webdriver', { value: false, writable: false }); Object.defineProperty(window, 'Date', { value: class extends Date { getTimezoneOffset() { return 0; } }, writable: false }); blockCanvasFingerprinting(); blockAudioFingerprinting(); blockWebGPU(); blockWebTransport(); blockPrivacySandbox(); blockTrackingScripts(); protectVideoPlayerEvents(); detectSiteErrors(); videoPlayerModule.observePlayers(); adGuardModule.detectBlockedResources(); runWhenIdle(() => { observeLinks(); videoPlayerModule.updatePlayerBounds(); videoPlayerModule.discoverAdaptiveSelectors(); }); window.addEventListener('load', cleanFirstPartyUrlsDebounced, { passive: true, once: true }); debugLog('UPS initialization complete'); } catch (error) { debugLog(`Initialization error: ${error.message}`); stats.errorsDetected++; } }; if (document.readyState === 'complete') { init(); } else { window.addEventListener('DOMContentLoaded', init, { passive: true, once: true }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址