// ==UserScript== // @name GitHub Xget 下载加速器 - 增强优化版 // @namespace http://tampermonkey.net/ // @version 3.3 // @description 自动加速 GitHub、GitLab、Gitea 等平台的文件下载,支持多平台和自定义加速域名,增强版功能 | UP:毕加索自画像 // @author Xget | Enhanced & Optimized by 毕加索自画像 // @match https://github.com/* // @match https://gist.github.com/* // @match https://gitlab.com/* // @match https://gitea.com/* // @match https://codeberg.org/* // @match https://sourceforge.net/* // @match https://android.googlesource.com/* // @match https://huggingface.co/* // @match https://civitai.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com // @grant GM_setValue // @grant GM_setValues // @grant GM_getValue // @grant GM_getValues // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @connect * // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/559674/GitHub%20Xget%20%E4%B8%8B%E8%BD%BD%E5%8A%A0%E9%80%9F%E5%99%A8%20-%20%E5%A2%9E%E5%BC%BA%E4%BC%98%E5%8C%96%E7%89%88.user.js // @updateURL https://update.greasyfork.icu/scripts/559674/GitHub%20Xget%20%E4%B8%8B%E8%BD%BD%E5%8A%A0%E9%80%9F%E5%99%A8%20-%20%E5%A2%9E%E5%BC%BA%E4%BC%98%E5%8C%96%E7%89%88.meta.js // ==/UserScript== (function() { 'use strict'; // 预设加速源列表(type: xget 使用 /prefix/path 格式,ghproxy 使用 /fullurl 格式) // platforms: 支持的平台列表,'all' 表示支持所有平台 // 注意:公共加速源稳定性无法保证,强烈建议自建! const PRESET_ACCELERATORS = [ { domain: 'xget.xi-xu.me', name: '⭐ Xget 官方', type: 'xget', testPath: '/gh/robots.txt', platforms: 'all', description: '全平台 | 官方实例' }, { domain: 'gh.llkk.cc', name: 'LLKK', type: 'ghproxy', testPath: '/https://github.com/robots.txt', platforms: ['github.com', 'raw.githubusercontent.com', 'gist.github.com', 'codeload.github.com', 'objects.githubusercontent.com'], description: '仅 GitHub | 相对稳定' }, { domain: 'github.moeyy.xyz', name: 'Moeyy', type: 'ghproxy', testPath: '/https://github.com/robots.txt', platforms: ['github.com', 'raw.githubusercontent.com', 'gist.github.com', 'codeload.github.com', 'objects.githubusercontent.com'], description: '仅 GitHub | 知名度高' } ]; // 自建部署链接 const SELF_HOST_LINKS = { xget: 'https://github.com/xixu-me/xget', ghproxy: 'https://github.com/hunshcn/gh-proxy' }; // 配置项 const CONFIG = { // 默认加速域名 defaultDomain: 'xget.xi-xu.me', // 默认加速类型 defaultType: 'xget', // 是否启用加速 enabled: GM_getValue('xget_enabled', true), // 自定义加速域名 customDomain: GM_getValue('xget_custom_domain', ''), // 自定义加速类型(xget 或 ghproxy) customType: GM_getValue('xget_custom_type', 'xget'), // 用户自定义加速源列表 userAccelerators: GM_getValue('xget_user_accelerators', []), // 是否显示通知 showNotification: GM_getValue('xget_show_notification', true), // 统计数据 stats: GM_getValue('xget_stats', { total: 0, success: 0, failed: 0 }), // 白名单模式(false 为黑名单模式) whitelistMode: GM_getValue('xget_whitelist_mode', false), // 排除列表(域名或路径模式) excludeList: GM_getValue('xget_exclude_list', []), // 是否自动检测加速服务可用性 autoCheck: GM_getValue('xget_auto_check', true), // 服务器状态缓存(避免频繁检测) serverStatus: GM_getValue('xget_server_status', { available: true, lastCheck: 0 }), // 调试模式 debug: GM_getValue('xget_debug', false), // 最大重试次数 maxRetries: GM_getValue('xget_max_retries', 2), // 强力拦截模式(会调用 stopImmediatePropagation,和旧版本保持一致) strongIntercept: GM_getValue('xget_strong_intercept', true) }; // 可下载文件扩展名白名单 const DOWNLOAD_EXTENSIONS = [ // 压缩包 'zip', 'tar', 'gz', 'bz2', '7z', 'rar', 'xz', 'tgz', // 安装包 'exe', 'dmg', 'deb', 'rpm', 'msi', 'pkg', 'apk', 'appimage', // 模型文件 'bin', 'safetensors', 'pt', 'pth', 'ckpt', 'h5', 'onnx', 'pb', 'model', // 其他 'iso', 'img', 'jar', 'war' ]; // 平台配置(添加前缀和下载 URL 模式) const PLATFORM_CONFIG = { 'github.com': { prefix: 'gh', name: 'GitHub', patterns: [ /\/releases\/download\//, /\/archive\/.*\.(zip|tar\.gz|tar)$/, /\/raw\//, /\/.*\/.*\/.*\.(exe|dmg|deb|rpm|msi|pkg|apk|zip|tar\.gz|tar\.bz2|7z|rar)$/ ] }, // GitHub 源码包下载(Download ZIP / tarball) 'codeload.github.com': { prefix: 'gh', name: 'GitHub', patterns: [ /\/zip\//, /\/tar\.gz\//, /\/tar\// ] }, // GitHub Raw 文件下载(raw host 基本都是文件内容) 'raw.githubusercontent.com': { prefix: 'gh', name: 'GitHub', patterns: [ /.*/ ] }, // GitHub Release 资产下载(常见会跳到 objects host) 'objects.githubusercontent.com': { prefix: 'gh', name: 'GitHub', patterns: [ /.*/ ] }, 'gist.github.com': { prefix: 'gist', name: 'GitHub Gist', patterns: [ /\/raw\//, /\/download/ ] }, 'gitlab.com': { prefix: 'gl', name: 'GitLab', patterns: [ /\/-\/archive\//, /\/-\/project\/.*\/uploads\//, /\/uploads\// ] }, 'gitea.com': { prefix: 'gitea', name: 'Gitea', patterns: [ /\/archive\//, /\/raw\//, /\/releases\/download\// ] }, 'codeberg.org': { prefix: 'codeberg', name: 'Codeberg', patterns: [ /\/archive\//, /\/raw\//, /\/releases\/download\// ] }, 'sourceforge.net': { prefix: 'sf', name: 'SourceForge', patterns: [ /\/files\//, /\/downloads\// ] }, 'android.googlesource.com': { prefix: 'aosp', name: 'AOSP', patterns: [ /\/\+archive\// ] }, 'huggingface.co': { prefix: 'hf', name: 'Hugging Face', patterns: [ /\/resolve\//, /\/.*\/.*\/(blob|resolve)\/.*\.(bin|safetensors|pt|pth|ckpt|h5|onnx|pb|model)$/ ] }, 'civitai.com': { prefix: 'civitai', name: 'Civitai', patterns: [ /\/api\/download\// ] } }; // 调试日志 function debugLog(...args) { if (CONFIG.debug) { console.log('[Xget Debug]', new Date().toLocaleTimeString(), ...args); } } // 节流函数 function throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // 防抖函数 function debounce(func, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } // 统计落盘(防止频繁写入存储) const saveStatsDebounced = debounce(() => { try { if (typeof GM_setValues === 'function') { GM_setValues({ xget_stats: CONFIG.stats }); } else { GM_setValue('xget_stats', CONFIG.stats); } } catch (e) { // 回退到单值写入 GM_setValue('xget_stats', CONFIG.stats); } }, 600); // 指示器内容更新 function renderIndicator() { const el = CONFIG._indicatorEl; if (!el) return; el.innerHTML = `
⚡ Xget 加速已启用
`; } // 获取当前使用的加速域名 function getAcceleratorDomain() { return CONFIG.customDomain || CONFIG.defaultDomain; } // 获取当前使用的加速类型 function getAcceleratorType() { return CONFIG.customType || CONFIG.defaultType; } // 获取所有可用的加速源(预设 + 用户自定义) function getAllAccelerators() { return [...PRESET_ACCELERATORS, ...CONFIG.userAccelerators]; } // 根据域名获取加速源配置 function getAcceleratorByDomain(domain) { return getAllAccelerators().find(a => a.domain === domain); } // 获取当前平台配置 function getCurrentPlatform() { const hostname = window.location.hostname; return PLATFORM_CONFIG[hostname]; } // 编译排除规则 function compileExcludeMatchers(list) { const matchers = []; for (const raw of (list || [])) { const pattern = String(raw || '').trim(); if (!pattern) continue; // 支持 /.../flags 形式 if (pattern.startsWith('/') && pattern.lastIndexOf('/') > 0) { const lastSlash = pattern.lastIndexOf('/'); const body = pattern.slice(1, lastSlash); const flags = pattern.slice(lastSlash + 1); try { matchers.push({ type: 'regex', raw: pattern, re: new RegExp(body, flags) }); continue; } catch (e) { debugLog('排除规则正则解析失败,降级为包含匹配:', pattern, e); } } // 支持直接 RegExp 字符串(不带 / /) try { matchers.push({ type: 'regex', raw: pattern, re: new RegExp(pattern) }); } catch { matchers.push({ type: 'substr', raw: pattern, s: pattern }); } } return matchers; } function refreshExcludeMatchers() { CONFIG._excludeMatchers = compileExcludeMatchers(CONFIG.excludeList); } // 判断是否在排除列表中 function isExcluded(url) { const matchers = CONFIG._excludeMatchers || []; return matchers.some(m => { if (m.type === 'regex') return m.re.test(url); return url.includes(m.s); }); } // 检查是否为可下载文件扩展名 function hasDownloadableExtension(pathname) { const lowerPath = pathname.toLowerCase(); return DOWNLOAD_EXTENSIONS.some(ext => lowerPath.endsWith('.' + ext)); } // 下载链接检测 - 优化版 function isDownloadLink(url, element) { try { const urlObj = new URL(url); const platform = PLATFORM_CONFIG[urlObj.hostname]; if (!platform) { debugLog('平台不支持:', urlObj.hostname); return false; } // 检查是否在排除列表中 if (isExcluded(url)) { debugLog('URL 在排除列表中:', url); return false; } // 检查元素是否有 download 属性 if (element && (element.download || element.hasAttribute('download'))) { debugLog('检测到 download 属性'); return true; } // 检查文件扩展名 const hasValidExt = hasDownloadableExtension(urlObj.pathname); // 使用平台特定的正则模式匹配 const matchesPattern = platform.patterns.some(pattern => pattern.test(urlObj.pathname)); // 改为 OR:pattern 命中或扩展名命中即认为是下载(减少漏判) const isDownload = matchesPattern || hasValidExt; debugLog('链接检测结果:', { url, hasValidExt, matchesPattern, isDownload }); return isDownload; } catch (e) { debugLog('链接检测错误:', e); return false; } } // 检查加速源是否支持指定平台 function isAcceleratorSupportPlatform(accelerator, hostname) { if (!accelerator) return true; if (accelerator.platforms === 'all') return true; if (Array.isArray(accelerator.platforms)) { return accelerator.platforms.includes(hostname); } return true; } // 转换 URL 为加速 URL function convertToAcceleratorURL(originalUrl) { try { const url = new URL(originalUrl); const platform = PLATFORM_CONFIG[url.hostname]; if (!platform) { debugLog('无法转换: 平台不支持'); return originalUrl; } const acceleratorDomain = getAcceleratorDomain(); const acceleratorType = getAcceleratorType(); const accelerator = getAcceleratorByDomain(acceleratorDomain); // 检查当前加速源是否支持该平台 if (!isAcceleratorSupportPlatform(accelerator, url.hostname)) { debugLog('当前加速源不支持该平台:', url.hostname); // 如果不支持,尝试回退到 xget 官方 const xgetOfficial = PRESET_ACCELERATORS.find(a => a.domain === 'xget.xi-xu.me'); if (xgetOfficial) { const pathAndQuery = url.pathname + url.search + url.hash; const fallbackUrl = `https://${xgetOfficial.domain}/${platform.prefix}${pathAndQuery}`; debugLog('回退到 Xget 官方:', fallbackUrl); return fallbackUrl; } return originalUrl; } let acceleratedUrl; if (acceleratorType === 'ghproxy') { // ghproxy 格式: https://domain/https://github.com/path acceleratedUrl = `https://${acceleratorDomain}/${originalUrl}`; } else { // xget 格式: https://domain/prefix/path const pathAndQuery = url.pathname + url.search + url.hash; acceleratedUrl = `https://${acceleratorDomain}/${platform.prefix}${pathAndQuery}`; } debugLog('URL 转换:', { original: originalUrl, accelerated: acceleratedUrl, type: acceleratorType }); return acceleratedUrl; } catch (e) { console.error('URL 转换失败:', e); return originalUrl; } } // 带重试的 URL 转换 async function convertWithRetry(originalUrl) { const maxRetries = CONFIG.maxRetries; let lastError = null; for (let i = 0; i <= maxRetries; i++) { try { const convertedUrl = convertToAcceleratorURL(originalUrl); // 验证转换后的URL是否有效 if (convertedUrl && convertedUrl !== originalUrl) { debugLog(`URL 转换成功 (尝试 ${i + 1}/${maxRetries + 1})`); return convertedUrl; } throw new Error('转换结果无效'); } catch (e) { lastError = e; debugLog(`URL 转换重试 ${i + 1}/${maxRetries + 1}:`, e); // 等待一小段时间再重试 if (i < maxRetries) { await new Promise(resolve => setTimeout(resolve, 500)); } } } console.error('URL 转换最终失败:', lastError); return originalUrl; } // 检测加速服务器可用性 - 优化版 async function checkServerAvailability() { // 如果最近 5 分钟内检查过,使用缓存结果 const now = Date.now(); if (now - CONFIG.serverStatus.lastCheck < 5 * 60 * 1000) { debugLog('使用缓存的服务器状态:', CONFIG.serverStatus.available); return CONFIG.serverStatus.available; } try { const domain = getAcceleratorDomain(); const accelerator = getAcceleratorByDomain(domain); // 根据加速源类型使用不同的测试路径 const testPath = accelerator?.testPath || (getAcceleratorType() === 'ghproxy' ? '/https://github.com/robots.txt' : '/gh/robots.txt'); const testUrl = `https://${domain}${testPath}`; debugLog('开始检测服务器可用性:', testUrl); return new Promise((resolve) => { const timeout = setTimeout(() => { debugLog('服务器检测超时'); updateServerStatus(false); resolve(false); }, 3000); GM_xmlhttpRequest({ method: 'GET', headers: { 'Range': 'bytes=0-0', 'Cache-Control': 'no-cache' }, url: testUrl, timeout: 3000, onload: function(response) { clearTimeout(timeout); // 更严格的状态码判断(Range 可能返回 206) const available = (response.status >= 200 && response.status < 400) || response.status === 206; debugLog('服务器响应:', { status: response.status, available }); updateServerStatus(available); resolve(available); }, onerror: function(error) { clearTimeout(timeout); debugLog('服务器检测错误:', error); updateServerStatus(false); resolve(false); }, ontimeout: function() { clearTimeout(timeout); debugLog('服务器检测超时'); updateServerStatus(false); resolve(false); } }); }); } catch (e) { console.error('服务器可用性检查失败:', e); updateServerStatus(false); return false; } } // 更新服务器状态缓存 function updateServerStatus(available) { CONFIG.serverStatus = { available, lastCheck: Date.now() }; GM_setValue('xget_server_status', CONFIG.serverStatus); debugLog('服务器状态已更新:', CONFIG.serverStatus); // 同步更新指示器 renderIndicator(); } // 更新统计数据 function updateStats(success) { CONFIG.stats.total++; if (success) { CONFIG.stats.success++; } else { CONFIG.stats.failed++; } // 防抖写入,减少存储 IO saveStatsDebounced(); debugLog('统计数据已更新:', CONFIG.stats); // 同步更新指示器 renderIndicator(); } // 显示通知 function showNotification(message, type = 'info', duration = 3000) { if (!CONFIG.showNotification) return; const colors = { success: '#10b981', info: '#3b82f6', warning: '#f59e0b', error: '#ef4444' }; const notification = document.createElement('div'); notification.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 15px 20px; background: ${colors[type] || colors.info}; color: white; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); z-index: 10000; font-size: 14px; max-width: 300px; animation: slideIn 0.3s ease-out; cursor: pointer; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; `; notification.textContent = message; // 点击关闭 notification.addEventListener('click', () => { notification.style.animation = 'slideIn 0.3s ease-out reverse'; setTimeout(() => notification.remove(), 300); }); // 添加动画样式 if (!document.getElementById('xget-notification-style')) { const style = document.createElement('style'); style.id = 'xget-notification-style'; style.textContent = ` @keyframes slideIn { from { transform: translateX(400px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } `; document.head.appendChild(style); } document.body.appendChild(notification); setTimeout(() => { notification.style.animation = 'slideIn 0.3s ease-out reverse'; setTimeout(() => notification.remove(), 300); }, duration); } // 拦截下载链接 - 核心功能 function interceptDownloadLinks() { const platform = getCurrentPlatform(); if (!platform || !CONFIG.enabled) return; debugLog('开始拦截下载链接:', platform.name); // 使用节流优化性能 const handleClick = throttle(async function(e) { // 仅拦截普通左键点击;避免影响 Ctrl/⌘/Shift 打开新标签等行为 if (e.button !== 0) return; if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return; // 使用 closest 更高效地查找链接元素 const target = e.target.closest('a[href]'); if (!target?.href) return; const href = target.href; // 精确检测是否为下载链接 if (!isDownloadLink(href, target)) return; debugLog('检测到下载链接:', href); // 如果启用了自动检测,先检查服务器可用性 if (CONFIG.autoCheck) { const available = await checkServerAvailability(); if (!available) { showNotification('⚠️ 加速服务暂不可用,使用原始链接下载', 'warning'); updateStats(false); return; // 不拦截,使用原始链接 } } // 阻止默认行为和事件传播 e.preventDefault(); e.stopPropagation(); if (CONFIG.strongIntercept) { e.stopImmediatePropagation(); } const acceleratedUrl = await convertWithRetry(href); if (acceleratedUrl !== href) { showNotification(`🚀 已启用 ${platform.name} 加速下载`, 'success', 2000); updateStats(true); // 创建隐藏链接并触发 const link = document.createElement('a'); link.href = acceleratedUrl; link.download = target.download || ''; link.target = '_blank'; link.rel = 'noopener noreferrer'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } else { showNotification('⚠️ URL 转换失败,使用原始链接', 'warning'); updateStats(false); window.open(href, '_blank', 'noopener,noreferrer'); } }, 300); // 使用捕获阶段确保最先处理 document.addEventListener('click', handleClick, true); debugLog('事件监听器已注册'); } // 添加页面指示器 - 增强版 function addPageIndicator() { const platform = getCurrentPlatform(); if (!platform || !CONFIG.enabled) return; const indicator = document.createElement('div'); indicator.id = 'xget-indicator'; indicator.style.cssText = ` position: fixed; bottom: 20px; right: 20px; padding: 10px 15px; background: rgba(16, 185, 129, 0.95); color: white; border-radius: 8px; font-size: 12px; z-index: 9999; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); cursor: pointer; transition: all 0.3s; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; `; // 保存指示器引用 CONFIG._indicatorEl = indicator; // 初始渲染指示器内容 renderIndicator(); indicator.addEventListener('mouseenter', () => { indicator.style.transform = 'scale(1.05)'; indicator.style.background = 'rgba(16, 185, 129, 1)'; }); indicator.addEventListener('mouseleave', () => { indicator.style.transform = 'scale(1)'; indicator.style.background = 'rgba(16, 185, 129, 0.95)'; }); indicator.addEventListener('click', () => { const stats = CONFIG.stats; const successRate = stats.total > 0 ? ((stats.success / stats.total) * 100).toFixed(1) : 0; showNotification( `域名: ${getAcceleratorDomain()}\n总计: ${stats.total} | 成功: ${stats.success} | 失败: ${stats.failed}\n成功率: ${successRate}%`, 'info', 5000 ); }); document.body.appendChild(indicator); // 服务器状态指示 if (!CONFIG.serverStatus.available) { const statusDot = document.createElement('div'); statusDot.style.cssText = ` position: absolute; top: 5px; right: 5px; width: 8px; height: 8px; background: #ef4444; border-radius: 50%; animation: pulse 2s infinite; `; indicator.appendChild(statusDot); if (!document.getElementById('xget-pulse-style')) { const pulseStyle = document.createElement('style'); pulseStyle.id = 'xget-pulse-style'; pulseStyle.textContent = ` @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } `; document.head.appendChild(pulseStyle); } } debugLog('页面指示器已添加'); } // 设置菜单命令 - 增强版 function setupMenuCommands() { // 切换启用/禁用 GM_registerMenuCommand(CONFIG.enabled ? '❌ 禁用加速' : '✅ 启用加速', function() { CONFIG.enabled = !CONFIG.enabled; GM_setValue('xget_enabled', CONFIG.enabled); showNotification(CONFIG.enabled ? '加速已启用' : '加速已禁用', 'success'); location.reload(); }); // 设置加速域名 - 增强版选择界面 GM_registerMenuCommand('⚙️ 设置加速域名', function() { showAcceleratorSelector(); }); // 查看统计信息 GM_registerMenuCommand('📊 查看统计', function() { showStatsPanel(); }); // 管理排除列表 GM_registerMenuCommand('🚫 管理排除列表', function() { showExcludeListPanel(); }); // 切换自动检测 - 移到高级设置 // 手动检测服务器 GM_registerMenuCommand('🔍 检测服务器状态', async function() { showNotification('正在检测服务器状态...', 'info', 2000); CONFIG.serverStatus.lastCheck = 0; const available = await checkServerAvailability(); showNotification( available ? '✅ 加速服务器可用' : '❌ 加速服务器不可用', available ? 'success' : 'error', 3000 ); }); // 测试加速链接 GM_registerMenuCommand('🧪 测试转换', function() { showTestPanel(); }); // 设置重试次数 GM_registerMenuCommand('🔁 高级设置', function() { showAdvancedSettingsPanel(); }); } // 通用模态框创建函数 function createModal(id, title, content, options = {}) { // 移除已存在的模态框 const existing = document.getElementById(id); if (existing) existing.remove(); const overlay = document.createElement('div'); overlay.id = id; overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 10001; display: flex; justify-content: center; align-items: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; animation: xgetFadeIn 0.2s ease-out; `; const panel = document.createElement('div'); panel.style.cssText = ` background: white; border-radius: 16px; padding: 24px; max-width: ${options.maxWidth || '450px'}; width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: 0 25px 80px rgba(0, 0, 0, 0.35); animation: xgetSlideUp 0.3s ease-out; `; panel.innerHTML = `

${title}

${content}
`; // 添加动画样式 if (!document.getElementById('xget-modal-animations')) { const style = document.createElement('style'); style.id = 'xget-modal-animations'; style.textContent = ` @keyframes xgetFadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes xgetSlideUp { from { opacity: 0; transform: translateY(20px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); } } @keyframes xgetSlideOut { from { opacity: 1; transform: translateY(0) scale(1); } to { opacity: 0; transform: translateY(20px) scale(0.95); } } `; document.head.appendChild(style); } overlay.appendChild(panel); document.body.appendChild(overlay); // 关闭功能 const closeModal = () => { panel.style.animation = 'xgetSlideOut 0.2s ease-out forwards'; overlay.style.animation = 'xgetFadeIn 0.2s ease-out reverse forwards'; setTimeout(() => overlay.remove(), 200); }; panel.querySelector('.xget-modal-close').addEventListener('click', closeModal); panel.querySelector('.xget-modal-close').addEventListener('mouseenter', (e) => e.target.style.color = '#1f2937'); panel.querySelector('.xget-modal-close').addEventListener('mouseleave', (e) => e.target.style.color = '#9ca3af'); overlay.addEventListener('click', (e) => { if (e.target === overlay) closeModal(); }); return { overlay, panel, close: closeModal }; } // 统计面板 function showStatsPanel() { const stats = CONFIG.stats; const successRate = stats.total > 0 ? ((stats.success / stats.total) * 100).toFixed(1) : 0; const domain = getAcceleratorDomain(); const content = `
${stats.total}
总下载
${stats.success}
成功
${stats.failed}
失败
成功率 ${successRate}%
当前加速域名 ${domain}
服务器状态 ${CONFIG.serverStatus.available ? '✅ 可用' : '❌ 不可用'}
调试模式 ${CONFIG.debug ? '开启' : '关闭'}
🎨 增强优化版 UP:毕加索自画像
`; const { panel, close } = createModal('xget-stats-panel', '📊 加速统计', content); panel.querySelector('#xget-reset-stats-btn').addEventListener('click', () => { if (confirm('确定要重置所有统计数据吗?')) { CONFIG.stats = { total: 0, success: 0, failed: 0 }; GM_setValue('xget_stats', CONFIG.stats); showNotification('统计数据已重置', 'success'); close(); setTimeout(() => showStatsPanel(), 300); } }); } // 排除列表面板 function showExcludeListPanel() { const content = `
💡 每行一个规则,支持正则表达式(如 /test/)或普通文本匹配
`; const { panel, close } = createModal('xget-exclude-panel', '🚫 排除列表', content); const textarea = panel.querySelector('#xget-exclude-textarea'); textarea.addEventListener('focus', () => textarea.style.borderColor = '#10b981'); textarea.addEventListener('blur', () => textarea.style.borderColor = '#e5e7eb'); panel.querySelector('#xget-exclude-save-btn').addEventListener('click', () => { const newList = textarea.value.split('\n').filter(x => x.trim()); CONFIG.excludeList = newList; GM_setValue('xget_exclude_list', newList); refreshExcludeMatchers(); showNotification(`已保存 ${newList.length} 条排除规则`, 'success'); close(); }); panel.querySelector('#xget-exclude-clear-btn').addEventListener('click', () => { textarea.value = ''; }); } // 测试转换面板 function showTestPanel() { const content = `
`; const { panel } = createModal('xget-test-panel', '🧪 测试 URL 转换', content); const input = panel.querySelector('#xget-test-input'); input.addEventListener('focus', () => input.style.borderColor = '#3b82f6'); input.addEventListener('blur', () => input.style.borderColor = '#e5e7eb'); panel.querySelector('#xget-test-btn').addEventListener('click', () => { const testUrl = input.value.trim(); if (!testUrl) { showNotification('请输入 URL', 'warning'); return; } const converted = convertToAcceleratorURL(testUrl); const isDownload = isDownloadLink(testUrl, null); const resultDiv = panel.querySelector('#xget-test-result'); panel.querySelector('#xget-test-original').textContent = testUrl; panel.querySelector('#xget-test-converted').textContent = converted; panel.querySelector('#xget-test-isdownload').innerHTML = isDownload ? '✅ 是' : '❌ 否'; panel.querySelector('#xget-test-type').textContent = getAcceleratorType(); resultDiv.style.display = 'block'; }); // 回车触发测试 input.addEventListener('keypress', (e) => { if (e.key === 'Enter') panel.querySelector('#xget-test-btn').click(); }); } // 高级设置面板 function showAdvancedSettingsPanel() { const content = `
重试次数
URL 转换失败时的重试次数
${CONFIG.maxRetries}
显示通知
下载加速时显示提示通知
自动检测服务器
下载前检测加速服务器可用性
调试模式
在控制台输出详细日志
强力拦截模式
阻止其他脚本干扰下载拦截
`; const { panel, close } = createModal('xget-advanced-panel', '🔧 高级设置', content); // 重试次数按钮 let retryValue = CONFIG.maxRetries; const retryDisplay = panel.querySelector('#xget-retry-value'); panel.querySelectorAll('.xget-retry-btn').forEach(btn => { btn.addEventListener('click', () => { if (btn.dataset.action === 'plus' && retryValue < 5) retryValue++; if (btn.dataset.action === 'minus' && retryValue > 0) retryValue--; retryDisplay.textContent = retryValue; }); }); // 开关样式更新 const updateToggle = (checkbox) => { const span = checkbox.nextElementSibling; const dot = span.querySelector('span'); span.style.background = checkbox.checked ? '#10b981' : '#cbd5e1'; dot.style.left = checkbox.checked ? '25px' : '3px'; }; panel.querySelectorAll('input[type="checkbox"]').forEach(checkbox => { checkbox.addEventListener('change', () => updateToggle(checkbox)); }); // 保存按钮 panel.querySelector('#xget-save-advanced-btn').addEventListener('click', () => { CONFIG.maxRetries = retryValue; CONFIG.showNotification = panel.querySelector('#xget-notification-toggle').checked; CONFIG.autoCheck = panel.querySelector('#xget-autocheck-toggle').checked; CONFIG.debug = panel.querySelector('#xget-debug-toggle').checked; CONFIG.strongIntercept = panel.querySelector('#xget-strong-toggle').checked; GM_setValue('xget_max_retries', CONFIG.maxRetries); GM_setValue('xget_show_notification', CONFIG.showNotification); GM_setValue('xget_auto_check', CONFIG.autoCheck); GM_setValue('xget_debug', CONFIG.debug); GM_setValue('xget_strong_intercept', CONFIG.strongIntercept); showNotification('设置已保存', 'success'); close(); }); } // 显示加速源选择器界面 function showAcceleratorSelector() { // 移除已存在的选择器 const existing = document.getElementById('xget-accelerator-selector'); if (existing) existing.remove(); const currentDomain = getAcceleratorDomain(); const allAccelerators = getAllAccelerators(); // 创建遮罩层 const overlay = document.createElement('div'); overlay.id = 'xget-accelerator-selector'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 10001; display: flex; justify-content: center; align-items: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; `; // 创建选择器面板 const panel = document.createElement('div'); panel.style.cssText = ` background: white; border-radius: 12px; padding: 24px; max-width: 500px; width: 90%; max-height: 80vh; overflow-y: auto; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); `; panel.innerHTML = `

⚙️ 选择加速源

当前使用: ${currentDomain}
💡 提示:全平台 支持 GitHub、GitLab、Hugging Face 等所有平台; 仅 GitHub 在其他平台会自动回退到 Xget 官方
📡 预设加速源
👤 自定义加速源
🚀 推荐自建加速服务
公共加速源稳定性无法保证,建议使用 Cloudflare Workers 免费自建:
⭐ Xget (全平台) gh-proxy (仅GitHub)
`; overlay.appendChild(panel); document.body.appendChild(overlay); // 渲染预设加速源列表 const presetList = panel.querySelector('#xget-preset-list'); PRESET_ACCELERATORS.forEach(acc => { presetList.appendChild(createAcceleratorItem(acc, currentDomain, false)); }); // 渲染自定义加速源列表 const customList = panel.querySelector('#xget-custom-list'); if (CONFIG.userAccelerators.length === 0) { customList.innerHTML = '
暂无自定义加速源
'; } else { CONFIG.userAccelerators.forEach(acc => { customList.appendChild(createAcceleratorItem(acc, currentDomain, true)); }); } // 关闭按钮 panel.querySelector('#xget-close-btn').addEventListener('click', () => overlay.remove()); overlay.addEventListener('click', (e) => { if (e.target === overlay) overlay.remove(); }); // 添加自定义加速源 panel.querySelector('#xget-add-custom-btn').addEventListener('click', () => { showAddCustomAcceleratorDialog(); }); // 测试所有加速源 panel.querySelector('#xget-test-all-btn').addEventListener('click', async () => { const btn = panel.querySelector('#xget-test-all-btn'); btn.disabled = true; btn.textContent = '⏳ 测试中...'; const results = await testAllAccelerators(); const resultDiv = panel.querySelector('#xget-test-result'); resultDiv.style.display = 'block'; const availableCount = results.filter(r => r.available).length; if (availableCount > 0) { resultDiv.style.background = '#d1fae5'; resultDiv.style.color = '#065f46'; resultDiv.innerHTML = `✅ 测试完成: ${availableCount}/${results.length} 个加速源可用`; } else { resultDiv.style.background = '#fee2e2'; resultDiv.style.color = '#991b1b'; resultDiv.innerHTML = `❌ 测试完成: 所有加速源均不可用`; } btn.disabled = false; btn.textContent = '🔍 测试所有加速源'; // 更新列表中的状态指示 updateAcceleratorListStatus(results); }); } // 创建加速源列表项 function createAcceleratorItem(acc, currentDomain, isCustom) { const item = document.createElement('div'); const isSelected = acc.domain === currentDomain; const platformInfo = acc.platforms === 'all' ? '全平台' : (acc.description || '仅 GitHub'); item.style.cssText = ` display: flex; align-items: center; justify-content: space-between; padding: 12px; margin-bottom: 8px; background: ${isSelected ? '#ecfdf5' : '#f9fafb'}; border: 2px solid ${isSelected ? '#10b981' : 'transparent'}; border-radius: 8px; cursor: pointer; transition: all 0.2s; `; item.dataset.domain = acc.domain; item.innerHTML = `
${acc.name} ${isSelected ? '✓' : ''}
${acc.domain}
${acc.type} ${platformInfo}
${isCustom ? '' : ''}
`; // 选择加速源 item.addEventListener('click', (e) => { if (e.target.classList.contains('xget-delete-btn')) return; selectAccelerator(acc); }); // 删除自定义加速源 if (isCustom) { item.querySelector('.xget-delete-btn').addEventListener('click', (e) => { e.stopPropagation(); if (confirm(`确定要删除加速源 "${acc.name}" 吗?`)) { deleteCustomAccelerator(acc.domain); } }); } return item; } // 选择加速源 function selectAccelerator(acc) { CONFIG.customDomain = acc.domain; CONFIG.customType = acc.type; GM_setValue('xget_custom_domain', acc.domain); GM_setValue('xget_custom_type', acc.type); // 重置服务器状态缓存 CONFIG.serverStatus.lastCheck = 0; GM_setValue('xget_server_status', CONFIG.serverStatus); // 根据平台支持情况显示不同提示 let message = `已切换到 ${acc.name}`; if (acc.platforms !== 'all') { message += `\n⚠️ 该加速源仅支持 GitHub,其他平台将自动回退到 Xget 官方`; showNotification(message, 'warning', 4000); } else { showNotification(message, 'success'); } // 关闭选择器并刷新页面 const selector = document.getElementById('xget-accelerator-selector'); if (selector) selector.remove(); setTimeout(() => location.reload(), 800); } // 显示添加自定义加速源对话框 function showAddCustomAcceleratorDialog() { const name = prompt('请输入加速源名称:'); if (!name) return; const domain = prompt('请输入加速源域名 (不含 https://):'); if (!domain) return; const typeChoice = prompt('请选择加速源类型:\n1. xget (格式: /gh/path,通常支持多平台)\n2. ghproxy (格式: /https://github.com/path,通常仅支持 GitHub)\n\n输入 1 或 2:', '1'); if (!typeChoice) return; const type = typeChoice === '1' ? 'xget' : 'ghproxy'; const testPath = type === 'ghproxy' ? '/https://github.com/robots.txt' : '/gh/robots.txt'; const platformChoice = prompt('请选择支持的平台:\n1. 全平台 (GitHub, GitLab, Hugging Face 等)\n2. 仅 GitHub\n\n输入 1 或 2:', type === 'xget' ? '1' : '2'); if (!platformChoice) return; const platforms = platformChoice === '1' ? 'all' : ['github.com', 'raw.githubusercontent.com', 'gist.github.com', 'codeload.github.com', 'objects.githubusercontent.com']; const description = platformChoice === '1' ? '支持所有平台' : '仅支持 GitHub'; const newAcc = { domain: domain.trim().replace(/^https?:\/\//, '').replace(/\/$/, ''), name: name.trim(), type: type, testPath: testPath, platforms: platforms, description: description }; // 检查是否已存在 if (getAllAccelerators().some(a => a.domain === newAcc.domain)) { showNotification('该加速源已存在', 'error'); return; } CONFIG.userAccelerators.push(newAcc); GM_setValue('xget_user_accelerators', CONFIG.userAccelerators); showNotification(`已添加加速源: ${newAcc.name}`, 'success'); // 刷新选择器 showAcceleratorSelector(); } // 删除自定义加速源 function deleteCustomAccelerator(domain) { CONFIG.userAccelerators = CONFIG.userAccelerators.filter(a => a.domain !== domain); GM_setValue('xget_user_accelerators', CONFIG.userAccelerators); // 如果删除的是当前使用的加速源,重置为默认 if (CONFIG.customDomain === domain) { CONFIG.customDomain = ''; CONFIG.customType = 'xget'; GM_setValue('xget_custom_domain', ''); GM_setValue('xget_custom_type', 'xget'); } showNotification('已删除加速源', 'success'); showAcceleratorSelector(); } // 测试所有加速源 async function testAllAccelerators() { const allAccelerators = getAllAccelerators(); const results = []; for (const acc of allAccelerators) { const testUrl = `https://${acc.domain}${acc.testPath}`; const available = await testSingleAccelerator(testUrl); results.push({ domain: acc.domain, available }); } return results; } // 测试单个加速源 function testSingleAccelerator(testUrl) { return new Promise((resolve) => { const timeout = setTimeout(() => resolve(false), 5000); GM_xmlhttpRequest({ method: 'HEAD', url: testUrl, timeout: 5000, onload: function(response) { clearTimeout(timeout); resolve(response.status >= 200 && response.status < 400); }, onerror: function() { clearTimeout(timeout); resolve(false); }, ontimeout: function() { clearTimeout(timeout); resolve(false); } }); }); } // 更新加速源列表状态指示 function updateAcceleratorListStatus(results) { results.forEach(result => { const item = document.querySelector(`[data-domain="${result.domain}"]`); if (item) { const indicator = item.querySelector('.xget-status-indicator'); if (indicator) { indicator.style.background = result.available ? '#10b981' : '#ef4444'; } } }); } // 在控制台显示艺术字 Logo(优雅的署名方式) function showConsoleBanner() { const styles = [ 'color: #10b981; font-size: 16px; font-weight: bold;', 'color: #3b82f6; font-size: 12px;', 'color: #6b7280; font-size: 11px;' ]; console.log('%c⚡ Xget 加速器增强优化版', styles[0]); console.log('%c🎨 UP:毕加索自画像', styles[1]); console.log('%c✨ 感谢使用本增强版脚本 | v3.3', styles[2]); } // 彩蛋:特殊组合键显示作者信息 function setupEasterEgg() { let keySequence = []; const secretCode = ['x', 'g', 'e', 't']; // 输入 "xget" 触发 document.addEventListener('keydown', (e) => { keySequence.push(e.key.toLowerCase()); if (keySequence.length > secretCode.length) { keySequence.shift(); } if (keySequence.join('') === secretCode.join('')) { showAuthorInfo(); keySequence = []; } }); } // 显示作者信息(彩蛋触发) function showAuthorInfo() { const modal = document.createElement('div'); modal.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 16px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); z-index: 10001; text-align: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; animation: fadeInScale 0.3s ease-out; `; modal.innerHTML = `
🎨
Xget 加速器增强优化版
Enhanced & Optimized Edition v3.3
✨ UP 主
毕加索自画像
感谢使用本增强版脚本
已优化:性能、稳定性、错误处理
点击任意处关闭
`; // 添加动画 if (!document.getElementById('xget-modal-style')) { const style = document.createElement('style'); style.id = 'xget-modal-style'; style.textContent = ` @keyframes fadeInScale { from { opacity: 0; transform: translate(-50%, -50%) scale(0.9); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } } `; document.head.appendChild(style); } // 点击关闭 modal.addEventListener('click', () => { modal.style.animation = 'fadeInScale 0.2s ease-out reverse'; setTimeout(() => modal.remove(), 200); }); document.body.appendChild(modal); } // 初始化 function init() { // 显示控制台 Banner showConsoleBanner(); // 设置彩蛋 setupEasterEgg(); debugLog('Xget 加速器增强优化版初始化开始'); debugLog('配置:', CONFIG); console.log('🎨 Xget 加速器增强优化版已加载 - UP:毕加索自画像 | v3.2'); setupMenuCommands(); if (CONFIG.enabled) { interceptDownloadLinks(); // 延迟添加指示器,确保页面已加载 setTimeout(() => { addPageIndicator(); }, 1000); const domain = getAcceleratorDomain(); console.log(`Xget 加速已启用 - 域名: ${domain}`); console.log(`统计: 成功 ${CONFIG.stats.success} / 总计 ${CONFIG.stats.total}`); debugLog('初始化完成'); } else { debugLog('加速功能已禁用'); } } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();