2025-04-12 16:42:49 +08:00

124 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

document.addEventListener('DOMContentLoaded', () => {
const detectBrowser = (ua) => {
let name = 'unknown', version = 'unknown';
// 优先级检测:微信 -> QQ -> 小米 -> Edge -> Firefox -> Chrome -> Safari
const weChatMatch = ua.match(/MicroMessenger\/([\d.]+)/i);
if (weChatMatch) return { name: 'wechat', version: weChatMatch[1] };
const qqMatch = ua.match(/QQ\/([\d.]+)/i);
if (qqMatch) return { name: 'qq', version: qqMatch[1] };
const xiaomiMatch = ua.match(/MiuiBrowser\/([\d.]+)/i);
if (xiaomiMatch) return { name: 'xiaomi', version: xiaomiMatch[1] };
const edgeMatch = ua.match(/Edg\/([\d.]+)/i);
if (edgeMatch) return { name: 'edge', version: edgeMatch[1] };
const firefoxMatch = ua.match(/Firefox\/([\d.]+)/i);
if (firefoxMatch) return { name: 'firefox', version: firefoxMatch[1] };
const chromeMatch = ua.match(/Chrome\/([\d.]+)/i);
if (chromeMatch) return { name: 'chrome', version: chromeMatch[1] };
if (/Safari\//i.test(ua) && !/Chrome|Edg/i.test(ua)) {
const safariVer = ua.match(/Version\/([\d.]+)/i);
return { name: 'safari', version: safariVer ? safariVer[1] : 'unknown' };
}
return { name, version };
};
const collectData = async () => {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
let osName = 'unknown', osVersion = 'unknown', cpuArch = 'unknown';
let uaCH = '{}';
// 1. UA Client Hints
if (hardwareTracker.ua_ch_enabled && navigator.userAgentData) {
try {
const hints = await navigator.userAgentData.getHighEntropyValues([
'platform',
'platformVersion',
'architecture',
'model',
'uaFullVersion',
'brands'
]);
uaCH = JSON.stringify(hints);
// 从 hints 中提取操作系统和 CPU 信息
osName = (hints.platform || '').toLowerCase();
osVersion = hints.platformVersion || 'unknown';
cpuArch = hints.architecture || 'unknown';
} catch (e) {
console.error('[硬件追踪] UA CH 获取失败:', e);
}
}
// 2. 后备User-Agent 字符串解析
if (osName === 'unknown' || osVersion === 'unknown') {
const ua = navigator.userAgent;
if (/Windows NT 10/.test(ua)) { osName = 'windows'; osVersion = '10'; }
else if (/Mac OS X 10_15/.test(ua)) { osName = 'macos'; osVersion = 'Catalina'; }
else if (/iPhone OS 16_/.test(ua)) { osName = 'ios'; osVersion = '16'; }
}
// 3. Windows 和 macOS 版本映射
if (osName === 'windows') {
const major = parseInt(osVersion.split('.')[0], 10) || 0;
osVersion = major >= 13 ? '11' : major > 0 ? '10' : '8.1';
}
if (osName === 'macos') {
const map = { '13': 'Ventura', '12': 'Monterey', '11': 'Big Sur', '10.15': 'Catalina' };
osVersion = map[osVersion.split('.')[0]] || osVersion;
}
// 4. CPU 架构后备检测
if (cpuArch === 'unknown') {
cpuArch = navigator.platform.includes('Win64') ? 'x64'
: /arm|aarch64/i.test(navigator.userAgent) ? 'arm'
: 'x86';
}
// 5. GPU 检测
let gpuVendor = 'unknown', gpuModel = 'unknown';
try {
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
if (gl) {
const info = gl.getExtension('WEBGL_debug_renderer_info');
gpuVendor = gl.getParameter(info.UNMASKED_VENDOR_WEBGL);
gpuModel = gl.getParameter(info.UNMASKED_RENDERER_WEBGL);
}
} catch (e) { /* 静默失败 */ }
// 6. 浏览器检测
const { name: browserName, version: browserVersion } = detectBrowser(navigator.userAgent);
// 7. 提交到后端
fetch(hardwareTracker.ajax_url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
action: 'hardware_tracker',
security: hardwareTracker.security,
os_name: osName,
os_version: osVersion,
cpu_arch: cpuArch,
cpu_cores: navigator.hardwareConcurrency || 0,
gpu_vendor: gpuVendor,
gpu_model: gpuModel,
timezone: timezone,
browser_name: browserName,
browser_version: browserVersion,
ua_ch: uaCH
})
});
};
setTimeout(() => {
collectData().catch(error => {
console.error('收集失败:', error);
});
}, 10);
});