// ==UserScript== // @name 通用数据同步脚本 // @namespace http://tampermonkey.net/ // @version 2.0 // @description 通用数据同步服务客户端,支持自动检测项目和账号 // @author Hermes // @match *://*/* // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_notification // @connect 47.122.126.244 // ==/UserScript== (function() { 'use strict'; // ==================== 配置区 ==================== const CONFIG = { serverUrl: 'http://47.122.126.244:5001', password: 'admin123123123', // 自动检测配置 autoDetect: true, // 是否自动检测项目名和账号 tag: 'auto', // 'auto' 表示自动检测,或手动指定如 'tingwu:ykaayk@qq.com' type: 'cookie', // cookie/token/credential/session/custom // 过期配置 expiresIn: 604800, // 7天(秒) // 其他配置 autoSync: false, // 是否自动同步(页面加载后自动上传) syncInterval: 0, // 定时同步间隔(秒,0 表示不定时同步) }; // ==================== 项目检测规则 ==================== const PROJECT_RULES = [ { name: 'tingwu', match: (url) => url.includes('tingwu.aliyun.com'), getAccount: () => { // 从页面提取账号信息 const emailElement = document.querySelector('[data-account]'); if (emailElement) return emailElement.getAttribute('data-account'); // 从 localStorage 提取 try { const userData = JSON.parse(localStorage.getItem('user_data') || '{}'); return userData.email || userData.username || 'unknown'; } catch {} return 'unknown'; }, loginUrl: 'https://tingwu.aliyun.com/' }, { name: 'wechat', match: (url) => url.includes('mp.weixin.qq.com'), getAccount: () => { const accountElement = document.querySelector('.account_info_text'); return accountElement ? accountElement.textContent.trim() : 'admin'; }, loginUrl: 'https://mp.weixin.qq.com/' }, // 添加更多项目... ]; // ==================== 核心功能 ==================== /** * 自动检测项目和账号 */ function autoDetectTag() { const url = window.location.href; for (const rule of PROJECT_RULES) { if (rule.match(url)) { const account = rule.getAccount(); return { tag: `${rule.name}:${account}`, loginUrl: rule.loginUrl, project: rule.name, account: account }; } } return { tag: 'unknown:unknown', loginUrl: window.location.origin, project: 'unknown', account: 'unknown' }; } /** * 获取当前页面的 Cookie 数据 */ function getCookieData() { const cookies = document.cookie.split(';').map(c => { const [name, ...valueParts] = c.trim().split('='); return { name: name, value: valueParts.join('='), domain: window.location.hostname, path: '/' }; }).filter(c => c.name); return { cookies: cookies, raw_cookie: document.cookie, user_agent: navigator.userAgent, url: window.location.href }; } /** * 上传数据到服务器 */ function uploadData(tag, type, data, metadata) { const payload = { password: CONFIG.password, tag: tag, type: type, data: data, metadata: metadata }; GM_xmlhttpRequest({ method: 'POST', url: `${CONFIG.serverUrl}/api/data`, headers: { 'Content-Type': 'application/json' }, data: JSON.stringify(payload), onload: function(response) { if (response.status === 200) { const result = JSON.parse(response.responseText); console.log('✅ 数据同步成功:', result); GM_notification({ title: '数据同步成功', text: `Tag: ${tag}\n时间: ${result.timestamp}`, timeout: 3000 }); } else { console.error('❌ 数据同步失败:', response.responseText); GM_notification({ title: '数据同步失败', text: `状态码: ${response.status}`, timeout: 5000 }); } }, onerror: function(error) { console.error('❌ 网络错误:', error); GM_notification({ title: '网络错误', text: '无法连接到同步服务器', timeout: 5000 }); } }); } /** * 同步当前页面数据 */ function syncData() { let tag = CONFIG.tag; let loginUrl = window.location.origin; // 自动检测 if (CONFIG.autoDetect || tag === 'auto') { const detected = autoDetectTag(); tag = detected.tag; loginUrl = detected.loginUrl; console.log('🔍 自动检测结果:', detected); } // 获取数据 let data; if (CONFIG.type === 'cookie') { data = getCookieData(); } else { console.error('❌ 不支持的数据类型:', CONFIG.type); return; } // 构建元数据 const metadata = { expires_in: CONFIG.expiresIn, login_url: loginUrl, note: `自动同步 - ${new Date().toLocaleString()}` }; // 上传 uploadData(tag, CONFIG.type, data, metadata); } /** * 复制配置到剪贴板 */ function copyConfig() { let tag = CONFIG.tag; if (CONFIG.autoDetect || tag === 'auto') { const detected = autoDetectTag(); tag = detected.tag; } const config = { serverUrl: CONFIG.serverUrl, password: CONFIG.password, tag: tag, type: CONFIG.type }; const configText = JSON.stringify(config, null, 2); GM_setClipboard(configText); console.log('📋 配置已复制到剪贴板:', config); GM_notification({ title: '配置已复制', text: `Tag: ${tag}`, timeout: 2000 }); } // ==================== UI 界面 ==================== /** * 创建浮动按钮 */ function createFloatingButton() { const button = document.createElement('div'); button.id = 'data-sync-button'; button.innerHTML = '🔄'; button.style.cssText = ` position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; background: #4CAF50; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 24px; box-shadow: 0 4px 8px rgba(0,0,0,0.3); z-index: 10000; transition: all 0.3s; `; button.addEventListener('mouseenter', () => { button.style.transform = 'scale(1.1)'; }); button.addEventListener('mouseleave', () => { button.style.transform = 'scale(1)'; }); button.addEventListener('click', () => { showSyncPanel(); }); document.body.appendChild(button); } /** * 显示同步面板 */ function showSyncPanel() { const detected = autoDetectTag(); const panel = document.createElement('div'); panel.id = 'data-sync-panel'; panel.innerHTML = `

数据同步

项目: ${detected.project}
账号: ${detected.account}
Tag: ${detected.tag}
类型: ${CONFIG.type}
`; panel.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10001; `; // 添加背景遮罩 const overlay = document.createElement('div'); overlay.id = 'data-sync-overlay'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 10000; `; document.body.appendChild(overlay); document.body.appendChild(panel); // 绑定事件 document.getElementById('sync-now-btn').addEventListener('click', () => { syncData(); closePanel(); }); document.getElementById('copy-config-btn').addEventListener('click', () => { copyConfig(); }); document.getElementById('close-panel-btn').addEventListener('click', closePanel); overlay.addEventListener('click', closePanel); } /** * 关闭面板 */ function closePanel() { const panel = document.getElementById('data-sync-panel'); const overlay = document.getElementById('data-sync-overlay'); if (panel) panel.remove(); if (overlay) overlay.remove(); } // ==================== 初始化 ==================== function init() { console.log('🚀 通用数据同步脚本已加载'); // 创建浮动按钮 createFloatingButton(); // 自动同步 if (CONFIG.autoSync) { setTimeout(() => { console.log('⏰ 执行自动同步...'); syncData(); }, 3000); } // 定时同步 if (CONFIG.syncInterval > 0) { setInterval(() => { console.log('⏰ 执行定时同步...'); syncData(); }, CONFIG.syncInterval * 1000); } // 快捷键 Ctrl+Shift+S document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.shiftKey && e.key === 'S') { e.preventDefault(); syncData(); } }); // 快捷键 Ctrl+Shift+C document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.shiftKey && e.key === 'C') { e.preventDefault(); copyConfig(); } }); } // 等待 DOM 加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();