// ==UserScript== // @name 通用数据同步助手 // @namespace http://tampermonkey.net/ // @version 2.0.0 // @description 一键同步 Cookie/Token 到服务器(通用版),支持可视化配置管理 // @author K-hermes // @match https://tingwu.aliyun.com/* // @match https://mp.weixin.qq.com/* // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @connect 47.122.126.244 // @connect * // ==/UserScript== (function() { 'use strict'; // ==================== 配置管理 ==================== const DEFAULT_CONFIG = { serverUrl: 'http://47.122.126.244:5001', password: 'admin123123123', autoDetect: true }; // 加载配置 function loadConfig() { const saved = GM_getValue('sync_config', null); if (saved) { try { return {...DEFAULT_CONFIG, ...JSON.parse(saved)}; } catch (e) { console.error('[同步助手] 配置解析失败,使用默认配置', e); } } return {...DEFAULT_CONFIG}; } // 保存配置 function saveConfig(config) { GM_setValue('sync_config', JSON.stringify(config)); console.log('[同步助手] 配置已保存'); } // 全局配置对象 let CONFIG = loadConfig(); // ==================== 项目检测 ==================== const PROJECT_PATTERNS = { 'tingwu.aliyun.com': { project: 'tingwu', accountSelector: '.user-email, [class*="email"], [class*="account"]', loginUrl: 'https://tingwu.aliyun.com/' }, 'mp.weixin.qq.com': { project: 'wechat', accountSelector: '.account__nickname, .weui-desktop-account__name', loginUrl: 'https://mp.weixin.qq.com/' } }; function detectProject() { const host = window.location.hostname; for (const [pattern, config] of Object.entries(PROJECT_PATTERNS)) { if (host.includes(pattern)) { return config; } } return null; } function detectAccount(selector) { if (!selector) return 'auto'; const element = document.querySelector(selector); if (element) { return element.innerText.trim() || 'auto'; } // 尝试从 localStorage/sessionStorage 读取 const storageKeys = ['userEmail', 'account', 'username', 'user_id']; for (const key of storageKeys) { const value = localStorage.getItem(key) || sessionStorage.getItem(key); if (value) { return value; } } return 'auto'; } // ==================== Cookie 提取 ==================== function getAllCookies() { const cookies = document.cookie.split(';').map(cookie => { const [name, value] = cookie.trim().split('='); return { name: name, value: value || '', domain: window.location.hostname, path: '/', secure: window.location.protocol === 'https:', httpOnly: false }; }); return cookies.filter(c => c.name); } // ==================== 同步功能 ==================== function syncData() { const projectConfig = detectProject(); if (!projectConfig) { showMessage('⚠️ 当前网站不支持自动同步', 'warning'); return; } const account = detectAccount(projectConfig.accountSelector); const tag = `${projectConfig.project}:${account}`; const cookies = getAllCookies(); if (cookies.length === 0) { showMessage('⚠️ 未找到 Cookie', 'warning'); return; } const data = { password: CONFIG.password, tag: tag, type: 'cookie', data: { cookies: cookies, raw_cookie: document.cookie, user_agent: navigator.userAgent }, metadata: { expires_in: 7 * 24 * 3600, // 7天 note: `${projectConfig.project} 账号同步`, login_url: projectConfig.loginUrl } }; showMessage('🔄 正在同步...', 'info'); GM_xmlhttpRequest({ method: 'POST', url: `${CONFIG.serverUrl}/api/data`, headers: { 'Content-Type': 'application/json' }, data: JSON.stringify(data), onload: function(response) { let result; try { result = JSON.parse(response.responseText); } catch (e) { showMessage('❌ 服务器响应格式错误', 'error'); return; } // 检查是否成功:HTTP 200 且响应体包含 success: true if (response.status === 200 && result.success === true) { showMessage(`✅ 同步成功!\n\nTag: ${tag}\n时间: ${result.timestamp || '未知'}`, 'success'); } else { // 失败:可能是 HTTP 错误码,或响应包含 error 字段 const errorMsg = result.error || result.message || response.statusText || '未知错误'; showMessage(`❌ 同步失败\n\n状态码: ${response.status}\n错误: ${errorMsg}`, 'error'); } }, onerror: function(error) { showMessage(`❌ 网络错误: ${error.error || '无法连接到服务器'}`, 'error'); } }); } // ==================== 复制配置 ==================== function copyConfig() { const projectConfig = detectProject(); if (!projectConfig) { showMessage('⚠️ 当前网站不支持', 'warning'); return; } const account = detectAccount(projectConfig.accountSelector); const tag = `${projectConfig.project}:${account}`; const config = { serverUrl: CONFIG.serverUrl, password: CONFIG.password, tag: tag, type: 'cookie' }; const configText = JSON.stringify(config, null, 2); GM_setClipboard(configText); showMessage('✅ 配置已复制到剪贴板', 'success'); } // ==================== UI ==================== function createButton() { const button = document.createElement('div'); button.innerHTML = `