// ==UserScript== // @name 网页加速器(可以让老爷爷坐飞机的快) // @namespace https://docs.scriptcat.org/ // @version 1.1.1 // @description try to take over the world! // @author You // @match https://*/* // @grant none // @noframes // ==/UserScript== (function() { 'use strict'; // Your code here... })(); // ==UserScript== // @name 网页加速器(可以让老爷爷坐飞机的快) // @namespace https://docs.scriptcat.org/ // @version 1.1.1 // @description try to take over the world! // @author You // @match https://*/* // @grant none // @noframes // ==/UserScript== /* eslint-disable */ (function(global) { 'use strict'; // 配置命名空间,避免冲突 if (global.HyperNav) return; class HyperNav { constructor() { this.name = 'HyperNav Accelerator'; this.version = '2.0.0'; // 核心配置 this.config = { enabled: true, mode: 'balanced', // 'balanced', 'aggressive', 'conservative' prefetchMethod: 'speculative', // 'speculative', 'intent', 'viewport' maxConcurrent: 3, delay: 150, threshold: 0.25, timeout: 3000, maxLinks: 50, cacheSize: 100, learnUserBehavior: true, respectDataSaver: true, respectNetworkType: true }; // 状态管理 this.state = { initialized: false, active: false, linksObserved: 0, linksPrefetched: 0, linksPredicted: 0, cacheHits: 0, userBehavior: {}, sessionStart: Date.now() }; // 缓存系统 this.cache = { urls: new Map(), timestamps: new Map(), sizes: new Map() }; // 忽略规则 this.ignorePatterns = { // URL路径模式 path: [ /\/api\//i, /\/ajax\//i, /\/auth\//i, /\/login\//i, /\/logout\//i, /\/signin\//i, /\/signout\//i, /\/register\//i, /\/checkout\//i, /\/cart\//i, /\/payment\//i, /\/download\//i, /\/upload\//i, /\/export\//i, /\/import\//i, /\/admin\//i, /\/dashboard\//i, /\/profile\//i, /\/settings\//i, /\/delete\//i, /\/edit\//i, /\/create\//i ], // 文件扩展名 extensions: [ /\.(zip|rar|7z|tar|gz|bz2|xz)$/i, /\.(pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odp)$/i, /\.(mp4|avi|mkv|mov|wmv|flv|webm|mpg|mpeg)$/i, /\.(mp3|wav|flac|aac|ogg|wma)$/i, /\.(exe|msi|dmg|pkg|deb|rpm|apk|ipa)$/i, /\.(iso|img|bin|dmg|toast)$/i, /\.(torrent|magnet)$/i ], // 协议 protocols: [ /^javascript:/i, /^mailto:/i, /^tel:/i, /^sms:/i, /^data:/i, /^file:/i, /^blob:/i, /^market:/i ], // 域名 domains: [ /(google-analytics|googletagmanager|doubleclick|facebook\.net)\./i, /(analytics|stats|metrics|tracking)\./i, /(adserver|adsystem|adservice)\./i ], // 查询参数 queries: [ /[?&](logout|signout|delete|remove|clear|reset|unsubscribe)=/i, /[?&](action=(delete|remove|logout|unsubscribe))/i, /[?&](confirm|verify|token|auth)=/i ] }; // 智能预测模型 this.predictor = { patterns: {}, weights: { distance: 0.3, frequency: 0.4, recency: 0.2, similarity: 0.1 }, learn: (link, clicked) => { const url = link.href; if (!this.predictor.patterns[url]) { this.predictor.patterns[url] = { clicks: 0, impressions: 0, lastSeen: 0, firstSeen: Date.now() }; } this.predictor.patterns[url].impressions++; if (clicked) { this.predictor.patterns[url].clicks++; } this.predictor.patterns[url].lastSeen = Date.now(); }, predict: (link) => { const url = link.href; const pattern = this.predictor.patterns[url]; if (!pattern) return 0.1; const age = Date.now() - pattern.firstSeen; const recency = Date.now() - pattern.lastSeen; let score = 0; // 点击率 const ctr = pattern.clicks / pattern.impressions; score += ctr * this.predictor.weights.frequency; // 最近性 const recencyScore = Math.max(0, 1 - (recency / (24 * 60 * 60 * 1000))); score += recencyScore * this.predictor.weights.recency; // 相似性(基于URL路径) const currentPath = window.location.pathname; const linkPath = new URL(url).pathname; const pathSimilarity = this.calculateSimilarity(currentPath, linkPath); score += pathSimilarity * this.predictor.weights.similarity; return Math.min(1, Math.max(0.1, score)); }, cleanup: () => { const now = Date.now(); const oneWeek = 7 * 24 * 60 * 60 * 1000; for (const url in this.predictor.patterns) { if (now - this.predictor.patterns[url].lastSeen > oneWeek) { delete this.predictor.patterns[url]; } } } }; // 网络感知 this.network = { connection: navigator.connection || navigator.mozConnection || navigator.webkitConnection, getType: () => { if (!this.network.connection) return 'unknown'; return this.network.connection.effectiveType || 'unknown'; }, isSlow: () => { if (!this.config.respectNetworkType) return false; const type = this.network.getType(); return type === 'slow-2g' || type === '2g' || type === '3g'; }, isMobile: () => { if (!this.network.connection) return false; return this.network.connection.type === 'cellular' || this.network.connection.type === 'bluetooth' || this.network.connection.type === 'wimax'; }, hasSaveData: () => { if (!this.config.respectDataSaver) return false; if (!this.network.connection) return false; return this.network.connection.saveData === true; }, shouldThrottle: () => { return this.network.isSlow() || this.network.hasSaveData() || this.network.isMobile(); } }; // 初始化 this.init(); } calculateSimilarity(str1, str2) { if (str1 === str2) return 1; if (!str1 || !str2) return 0; const longer = str1.length > str2.length ? str1 : str2; const shorter = str1.length > str2.length ? str2 : str1; if (longer.length === 0) return 1; const editDistance = this.levenshteinDistance(longer, shorter); return (longer.length - editDistance) / parseFloat(longer.length); } levenshteinDistance(a, b) { if (a.length === 0) return b.length; if (b.length === 0) return a.length; const matrix = []; for (let i = 0; i <= b.length; i++) { matrix[i] = [i]; } for (let j = 0; j <= a.length; j++) { matrix[0][j] = j; } for (let i = 1; i <= b.length; i++) { for (let j = 1; j <= a.length; j++) { if (b.charAt(i - 1) === a.charAt(j - 1)) { matrix[i][j] = matrix[i - 1][j - 1]; } else { matrix[i][j] = Math.min( matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1 ); } } } return matrix[b.length][a.length]; } shouldIgnore(url) { try { const urlObj = new URL(url, window.location.origin); // 检查协议 for (const pattern of this.ignorePatterns.protocols) { if (pattern.test(urlObj.protocol)) { this.log('Ignore - Protocol', url); return true; } } // 检查域名 for (const pattern of this.ignorePatterns.domains) { if (pattern.test(urlObj.hostname)) { this.log('Ignore - Domain', url); return true; } } // 检查路径 for (const pattern of this.ignorePatterns.path) { if (pattern.test(urlObj.pathname)) { this.log('Ignore - Path', url); return true; } } // 检查扩展名 for (const pattern of this.ignorePatterns.extensions) { if (pattern.test(urlObj.pathname)) { this.log('Ignore - Extension', url); return true; } } // 检查查询参数 for (const pattern of this.ignorePatterns.queries) { if (pattern.test(urlObj.search)) { this.log('Ignore - Query', url); return true; } } // 检查是否跨域(可配置) if (urlObj.origin !== window.location.origin) { // 可以在这里添加跨域检查逻辑 } return false; } catch (e) { this.log('Error parsing URL', url, e); return true; } } async prefetchUrl(url, priority = 'low') { if (this.shouldIgnore(url)) { return false; } // 检查缓存 if (this.cache.urls.has(url)) { const cached = this.cache.urls.get(url); if (Date.now() - cached.timestamp < 5 * 60 * 1000) { // 5分钟缓存 this.state.cacheHits++; this.log('Cache hit', url); return true; } } // 网络条件检查 if (this.network.shouldThrottle()) { this.log('Throttled due to network conditions', url); return false; } // 并发控制 if (this.state.activePrefetches >= this.config.maxConcurrent) { this.log('Throttled due to concurrency limit', url); return false; } try { this.state.activePrefetches = (this.state.activePrefetches || 0) + 1; // 使用fetch API进行预加载 const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); const response = await fetch(url, { method: 'HEAD', mode: 'cors', credentials: 'include', signal: controller.signal, headers: { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'X-Purpose': 'prefetch' } }); clearTimeout(timeoutId); if (response.ok) { // 检查内容类型 const contentType = response.headers.get('content-type') || ''; if (!contentType.includes('text/html') && !contentType.includes('application/xhtml+xml')) { this.log('Ignore - Not HTML', url, contentType); return false; } // 缓存结果 this.cache.urls.set(url, { timestamp: Date.now(), size: parseInt(response.headers.get('content-length') || '0'), type: contentType }); this.state.linksPrefetched++; this.log('Prefetch success', url); // 触发成功事件 this.triggerEvent('prefetch:success', { url, priority }); return true; } else { this.log('Prefetch failed', url, response.status); this.triggerEvent('prefetch:failed', { url, status: response.status }); return false; } } catch (error) { this.log('Prefetch error', url, error); this.triggerEvent('prefetch:error', { url, error }); return false; } finally { this.state.activePrefetches--; } } async prefetchLink(link) { if (!link || !link.href) return; const url = link.href; // 学习用户行为 if (this.config.learnUserBehavior) { this.predictor.learn(link, false); } // 计算预测分数 const score = this.config.learnUserBehavior ? this.predictor.predict(link) : 0.5; // 根据配置模式调整阈值 let threshold = 0.3; switch (this.config.mode) { case 'aggressive': threshold = 0.1; break; case 'conservative': threshold = 0.5; break; } if (score >= threshold) { await this.prefetchUrl(url, 'auto'); } } observeLinks() { if (!this.config.enabled || !this.state.initialized) { return; } // 创建观察器 this.observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const link = entry.target; this.observeLink(link); } }); }, { root: null, rootMargin: '50px', threshold: this.config.threshold }); // 观察所有链接 const links = document.querySelectorAll('a[href]:not([href^="#"])'); links.forEach(link => { this.observer.observe(link); }); this.state.linksObserved = links.length; // 添加鼠标悬停预测 if (this.config.prefetchMethod === 'intent') { this.addHoverListeners(links); } } observeLink(link) { if (link._hypernavObserved) return; link._hypernavObserved = true; // 添加点击监听 link.addEventListener('click', (e) => { if (this.config.learnUserBehavior) { this.predictor.learn(link, true); } // 记录点击事件 this.triggerEvent('link:clicked', { url: link.href, timestamp: Date.now() }); }, { once: true }); // 预加载链接 this.schedulePrefetch(link); } schedulePrefetch(link) { if (this.prefetchScheduled) return; this.prefetchScheduled = true; // 使用requestIdleCallback进行智能调度 requestIdleCallback(() => { this.prefetchLink(link); this.prefetchScheduled = false; }, { timeout: this.config.timeout }); } addHoverListeners(links) { let hoverTimer = null; links.forEach(link => { link.addEventListener('mouseenter', () => { clearTimeout(hoverTimer); hoverTimer = setTimeout(() => { this.prefetchLink(link); }, 100); }); link.addEventListener('mouseleave', () => { clearTimeout(hoverTimer); }); link.addEventListener('touchstart', () => { clearTimeout(hoverTimer); hoverTimer = setTimeout(() => { this.prefetchLink(link); }, 300); }, { passive: true }); }); } triggerEvent(eventName, data) { const event = new CustomEvent(`hypernav:${eventName}`, { detail: data }); window.dispatchEvent(event); } log(...args) { if (this.config.debug) { console.log('[HyperNav]', ...args); } } getStats() { const now = Date.now(); const sessionDuration = (now - this.state.sessionStart) / 1000; return { enabled: this.config.enabled, mode: this.config.mode, prefetchMethod: this.config.prefetchMethod, linksObserved: this.state.linksObserved, linksPrefetched: this.state.linksPrefetched, cacheHits: this.state.cacheHits, cacheSize: this.cache.urls.size, networkType: this.network.getType(), networkSlow: this.network.isSlow(), hasSaveData: this.network.hasSaveData(), sessionDuration: `${Math.round(sessionDuration)}s`, predictionPatterns: Object.keys(this.predictor.patterns).length }; } updateConfig(newConfig) { Object.assign(this.config, newConfig); this.saveConfig(); if (newConfig.enabled === false && this.observer) { this.observer.disconnect(); this.state.active = false; } else if (newConfig.enabled === true && !this.state.active) { this.observeLinks(); } } saveConfig() { try { localStorage.setItem('hypernav-config', JSON.stringify(this.config)); } catch (e) { this.log('Failed to save config', e); } } loadConfig() { try { const saved = localStorage.getItem('hypernav-config'); if (saved) { Object.assign(this.config, JSON.parse(saved)); } } catch (e) { this.log('Failed to load config', e); } } init() { if (this.state.initialized) return; this.loadConfig(); // 等待页面加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.start()); } else { this.start(); } this.state.initialized = true; } start() { if (!this.config.enabled) { this.log('HyperNav is disabled'); return; } if (this.network.hasSaveData()) { this.log('Save-Data enabled, throttling'); this.config.maxConcurrent = 1; } if (this.network.isSlow()) { this.log('Slow network detected, throttling'); this.config.maxConcurrent = 1; this.config.delay = 500; } this.observeLinks(); this.state.active = true; this.log('HyperNav started', this.config); // 定期清理 setInterval(() => { this.predictor.cleanup(); // 清理旧缓存 const now = Date.now(); for (const [url, data] of this.cache.urls.entries()) { if (now - data.timestamp > 30 * 60 * 1000) { // 30分钟 this.cache.urls.delete(url); } } }, 5 * 60 * 1000); // 每5分钟清理一次 } destroy() { if (this.observer) { this.observer.disconnect(); } this.state.active = false; this.state.initialized = false; this.log('HyperNav destroyed'); } } // 初始化 global.HyperNav = new HyperNav(); // 导出API global.hypernav = { enable: () => global.HyperNav.updateConfig({ enabled: true }), disable: () => global.HyperNav.updateConfig({ enabled: false }), getStats: () => global.HyperNav.getStats(), config: global.HyperNav.config, prefetch: (url) => global.HyperNav.prefetchUrl(url, 'manual') }; // 开发工具集成 if (typeof GM_registerMenuCommand === 'function') { GM_registerMenuCommand('📊 HyperNav Stats', () => { const stats = global.HyperNav.getStats(); GM_notification({ text: JSON.stringify(stats, null, 2), title: 'HyperNav Statistics', timeout: 5000 }); }); GM_registerMenuCommand('⚡ Toggle HyperNav', () => { global.HyperNav.updateConfig({ enabled: !global.HyperNav.config.enabled }); GM_notification({ text: `HyperNav ${global.HyperNav.config.enabled ? 'Enabled' : 'Disabled'}`, title: 'HyperNav', timeout: 2000 }); }); } })(typeof window !== 'undefined' ? window : this); /* eslint-disable */ (function(global) { 'use strict'; // 配置命名空间,避免冲突 if (global.HyperNav) return; class HyperNav { constructor() { this.name = 'HyperNav Accelerator'; this.version = '2.0.0'; // 核心配置 this.config = { enabled: true, mode: 'balanced', prefetchMethod: 'speculative', maxConcurrent: 3, delay: 150, threshold: 0.25, timeout: 3000, maxLinks: 50, cacheSize: 100, learnUserBehavior: true, respectDataSaver: true, respectNetworkType: true, uiEnabled: true, // 新增:UI开关 uiPosition: 'bottom-right', // 新增:UI位置 uiCompact: false // 新增:紧凑模式 }; // 状态管理 this.state = { initialized: false, active: false, linksObserved: 0, linksPrefetched: 0, linksPredicted: 0, cacheHits: 0, userBehavior: {}, sessionStart: Date.now(), uiVisible: false }; // ... 其他现有代码保持不变 ... } // ... 现有方法保持不变 ... // 新增:创建UI控制面板 createControlPanel() { if (!this.config.uiEnabled) return; // 创建Shadow DOM隔离样式 const container = document.createElement('div'); const shadow = container.attachShadow({ mode: 'open' }); // 样式 const style = document.createElement('style'); style.textContent = ` .hypernav-panel { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 12px; position: fixed; z-index: 2147483647; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; } .hypernav-panel.minimized { width: 40px; height: 40px; } .hypernav-panel.expanded { width: 320px; min-height: 400px; } .toggle-btn { width: 100%; height: 100%; border: none; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; } .toggle-btn:hover { transform: scale(1.05); } .toggle-btn:active { transform: scale(0.95); } .header { padding: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; display: flex; justify-content: space-between; align-items: center; } .title { display: flex; align-items: center; gap: 8px; } .title h2 { margin: 0; font-size: 16px; font-weight: 600; } .badge { background: rgba(255, 255, 255, 0.2); padding: 2px 8px; border-radius: 12px; font-size: 10px; } .close-btn { background: none; border: none; color: white; cursor: pointer; padding: 4px; border-radius: 4px; transition: background 0.2s; } .close-btn:hover { background: rgba(255, 255, 255, 0.2); } .content { padding: 16px; max-height: 400px; overflow-y: auto; } .section { margin-bottom: 20px; } .section-title { font-size: 12px; font-weight: 600; color: #666; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; } .stats-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 16px; } .stat-item { background: #f5f5f5; padding: 8px; border-radius: 6px; text-align: center; } .stat-value { font-size: 18px; font-weight: 700; color: #667eea; margin-bottom: 2px; } .stat-label { font-size: 10px; color: #666; } .control-group { margin-bottom: 12px; } .control-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .control-label { font-size: 12px; color: #333; } .switch { position: relative; display: inline-block; width: 40px; height: 20px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 20px; } .slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .slider { background-color: #667eea; } input:checked + .slider:before { transform: translateX(20px); } .select { width: 120px; padding: 4px 8px; border: 1px solid #ddd; border-radius: 4px; background: white; font-size: 12px; } .slider-control { display: flex; align-items: center; gap: 8px; } .range-slider { width: 100px; } .range-value { min-width: 30px; text-align: center; font-size: 12px; } .buttons { display: flex; gap: 8px; margin-top: 16px; } .btn { flex: 1; padding: 8px 12px; border: none; border-radius: 6px; background: #f5f5f5; color: #333; cursor: pointer; font-size: 12px; transition: all 0.2s; } .btn:hover { background: #e5e5e5; } .btn-primary { background: #667eea; color: white; } .btn-primary:hover { background: #5a6fd8; } .network-indicator { display: flex; align-items: center; gap: 8px; padding: 8px; background: #f5f5f5; border-radius: 6px; margin-top: 12px; } .indicator { width: 8px; height: 8px; border-radius: 50%; } .indicator.good { background: #4caf50; } .indicator.warning { background: #ff9800; } .indicator.bad { background: #f44336; } .footer { padding: 12px 16px; background: #f9f9f9; border-top: 1px solid #eee; text-align: center; color: #999; font-size: 10px; } .drag-handle { position: absolute; top: 0; left: 0; right: 0; height: 20px; cursor: move; background: rgba(0,0,0,0.1); border-radius: 12px 12px 0 0; } /* 紧凑模式 */ .hypernav-panel.compact { width: 280px; } .compact .content { padding: 12px; } .compact .stat-item { padding: 6px; } .compact .stat-value { font-size: 16px; } /* 响应式 */ @media (max-width: 480px) { .hypernav-panel.expanded { width: 100%; height: 100%; border-radius: 0; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; } } `; shadow.appendChild(style); // 创建面板结构 const panel = document.createElement('div'); panel.className = `hypernav-panel ${this.config.uiCompact ? 'compact' : ''}`; // 拖动支持 let isDragging = false; let startX, startY, startLeft, startTop; const dragHandle = document.createElement('div'); dragHandle.className = 'drag-handle'; dragHandle.addEventListener('mousedown', (e) => { isDragging = true; startX = e.clientX; startY = e.clientY; const rect = panel.getBoundingClientRect(); startLeft = rect.left; startTop = rect.top; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); const onMouseMove = (e) => { if (!isDragging) return; const dx = e.clientX - startX; const dy = e.clientY - startY; panel.style.left = (startLeft + dx) + 'px'; panel.style.top = (startTop + dy) + 'px'; }; const onMouseUp = () => { isDragging = false; document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); this.savePanelPosition(panel.style.left, panel.style.top); }; // 面板内容 panel.innerHTML = `