// ==UserScript== // @name 环境API探测器 (自适应主题) // @namespace https://your-namespace/ // @version 1.2 // @description 检测并打印当前用户脚本环境支持的API,UI自动适配暗色模式 // @author You // @match *://*/* // @grant unsafeWindow // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // @grant GM_setClipboard // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_getTab // @grant GM_saveTab // @grant GM_getTabs // @grant GM_notification // @grant GM_openInTab // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getResourceText // @grant GM_getResourceURL // @grant GM_log // @grant GM.info // @run-at document-end // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/564906/%E7%8E%AF%E5%A2%83API%E6%8E%A2%E6%B5%8B%E5%99%A8%20%28%E8%87%AA%E9%80%82%E5%BA%94%E4%B8%BB%E9%A2%98%29.user.js // @updateURL https://update.greasyfork.icu/scripts/564906/%E7%8E%AF%E5%A2%83API%E6%8E%A2%E6%B5%8B%E5%99%A8%20%28%E8%87%AA%E9%80%82%E5%BA%94%E4%B8%BB%E9%A2%98%29.meta.js // ==/UserScript== (function() { 'use strict'; const isIframe = window.self !== window.top; const output = []; // 1. 打印基础环境信息 output.push('=== 环境API探测器 ==='); output.push(`🌐 页面地址: ${window.location.href}`); output.push(`🖥️ 用户代理: ${navigator.userAgent}`); output.push(`📦 脚本管理器: ${typeof GM !== 'undefined' ? `检测到GM对象:${Object.keys(GM)}` : '未检测到'} | ${typeof GM_info !== 'undefined' ? 'GM_info版本: ' + GM_info.script.version : '无GM_info'}`); output.push(`🔲 是否在iframe中: ${isIframe}`); output.push(''); // 2. 检测 GM_* API (Tampermonkey 风格) output.push('=== 油猴 GM_* API 支持情况 ==='); const gmApis = [ 'GM_addStyle', 'GM_setValue', 'GM_getValue', 'GM_deleteValue', 'GM_listValues', 'GM_addValueChangeListener', 'GM_removeValueChangeListener', 'GM_setClipboard', 'GM_xmlhttpRequest', 'GM_download', 'GM_getTab', 'GM_saveTab', 'GM_getTabs', 'GM_notification', 'GM_openInTab', 'GM_registerMenuCommand', 'GM_unregisterMenuCommand', 'GM_getResourceText', 'GM_getResourceURL', 'GM_log', 'GM.info' ]; gmApis.forEach(api => { const exists = typeof unsafeWindow[api] !== 'undefined' || (api === 'GM.info' && typeof GM_info !== 'undefined'); output.push(`${exists ? '✅' : '❌'} ${api}`); }); output.push(''); // 3. 检测 GM.xxx API (Violentmonkey / Userscripts 风格) output.push('=== 油猴 GM.xxx API 支持情况 ==='); const gmDotApis = ['setValue', 'getValue', 'deleteValue', 'listValues', 'xmlHttpRequest', 'notification']; if (typeof GM !== 'undefined') { gmDotApis.forEach(api => { const exists = typeof GM[api] !== 'undefined'; output.push(`${exists ? '✅' : '❌'} GM.${api}`); }); } else { output.push('❌ 未检测到 GM 对象'); } output.push(''); // 4. 检测 Web 存储 API output.push('=== Web 存储 API 支持情况 ==='); const storageApis = ['localStorage', 'sessionStorage', 'indexedDB']; storageApis.forEach(api => { let supported = false; try { supported = typeof window[api] !== 'undefined'; } catch(e) {} output.push(`${supported ? '✅' : '❌'} ${api}`); }); output.push(''); // 5. 检测其他关键 API output.push('=== 其他关键 API 支持情况 ==='); const otherApis = ['fetch', 'Promise', 'MutationObserver', 'console.log']; otherApis.forEach(api => { let supported = false; try { if (api.includes('.')) { const [obj, prop] = api.split('.'); supported = window[obj] && typeof window[obj][prop] !== 'undefined'; } else { supported = typeof window[api] !== 'undefined'; } } catch(e) {} output.push(`${supported ? '✅' : '❌'} ${api}`); }); // 6. 输出结果到控制台 console.log(output.join('\n')); // 7. 判断是否为暗色模式 (根据系统偏好或网页背景色) const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const bgColor = window.getComputedStyle(document.body).backgroundColor; const rgbValues = bgColor.match(/\d+/g); let isPageDark = false; if (rgbValues && rgbValues.length >= 3) { const [r, g, b] = rgbValues.map(Number); // 简单亮度计算,值越小表示越暗 const brightness = (r * 299 + g * 587 + b * 114) / 1000; isPageDark = brightness < 128; } const useDarkTheme = prefersDark || isPageDark; // 8. 创建适配主题的浮动面板 const theme = useDarkTheme ? { name: 'dark', panelBg: '#1e1e1e', panelBorder: '#444', headerBg: '#333', headerColor: '#eee', contentColor: '#d4d4d4', successColor: '#4caf50', failColor: '#f44336' } : { name: 'light', panelBg: '#ffffff', panelBorder: '#ccc', headerBg: '#f5f5f5', headerColor: '#333', contentColor: '#222', successColor: 'green', failColor: 'red' }; GM_addStyle(` #api-detector-panel { position: fixed !important; top: 20px !important; right: 20px !important; width: 80vw !important; max-height: 80vh !important; background: ${theme.panelBg} !important; border: 1px solid ${theme.panelBorder} !important; border-radius: 8px !important; box-shadow: 0 6px 30px rgba(0,0,0,0.25) !important; z-index: 2147483647 !important; /* 最高优先级 */ font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important; font-size: 13px !important; line-height: 1.5 !important; overflow: auto !important; /* 禁止选择文本,避免误操作 */ user-select: none !important; } #api-detector-header { background: ${theme.headerBg} !important; color: ${theme.headerColor} !important; padding: 12px 16px !important; font-weight: bold !important; border-bottom: 1px solid ${theme.panelBorder} !important; display: flex !important; justify-content: space-between !important; align-items: center !important; } #api-detector-content { padding: 16px !important; white-space: pre-wrap !important; color: ${theme.contentColor} !important; overflow-wrap: break-word !important; } #api-detector-close { color: ${theme.headerColor} !important; cursor: pointer !important; font-size: 22px !important; line-height: 1 !important; padding: 0 4px !important; opacity: 0.8 !important; } #api-detector-close:hover { opacity: 1 !important; } /* 针对暗色/亮色主题的自定义符号颜色 */ .api-detector-success { color: ${theme.successColor} !important; } .api-detector-fail { color: ${theme.failColor} !important; } `); // 处理输出文本,为符号添加样式类 const finalHtml = output.join('\n') .replace(/\n/g, '
') .replace(/✅/g, '') .replace(/❌/g, ''); // 创建并插入面板 const panel = document.createElement('div'); panel.id = 'api-detector-panel'; panel.innerHTML = `
环境API探测器 (${theme.name}主题) ×
${finalHtml}
`; document.body.appendChild(panel); // 关闭按钮事件 panel.querySelector('#api-detector-close').addEventListener('click', () => { document.body.removeChild(panel); }); // 可选:添加一个“复制到剪贴板”的按钮(增强功能) const copyBtn = document.createElement('button'); copyBtn.textContent = '📋 复制报告'; copyBtn.style.cssText = ` margin-left: 10px; padding: 4px 8px; font-size: 12px; cursor: pointer; background: ${theme.headerBg}; color: ${theme.headerColor}; border: 1px solid ${theme.panelBorder}; border-radius: 4px; `; copyBtn.addEventListener('click', () => { navigator.clipboard.writeText(output.join('\n')).then(() => { const originalText = copyBtn.textContent; copyBtn.textContent = '✅ 已复制!'; setTimeout(() => copyBtn.textContent = originalText, 1500); }).catch(err => { console.error('复制失败:', err); copyBtn.textContent = '❌ 复制失败'; setTimeout(() => copyBtn.textContent = '📋 复制报告', 1500); }); }); panel.querySelector('#api-detector-header').appendChild(copyBtn); })();