// ==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 = `