// ==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 = `
🔄 同步数据
🔄 立即同步
📋 复制配置
⚙️ 配置设置
`; document.body.appendChild(button); // 事件绑定 const btn = document.getElementById('sync-helper-btn'); const menu = document.getElementById('sync-helper-menu'); btn.addEventListener('click', () => { menu.style.display = menu.style.display === 'none' ? 'block' : 'none'; }); document.getElementById('sync-now').addEventListener('click', () => { menu.style.display = 'none'; syncData(); }); document.getElementById('copy-config').addEventListener('click', () => { menu.style.display = 'none'; copyConfig(); }); document.getElementById('open-settings').addEventListener('click', () => { menu.style.display = 'none'; showSettingsPanel(); }); // 点击外部关闭菜单 document.addEventListener('click', (e) => { if (!btn.contains(e.target) && !menu.contains(e.target)) { menu.style.display = 'none'; } }); } function showSettingsPanel() { const panel = document.createElement('div'); panel.id = 'sync-settings-panel'; panel.innerHTML = `

配置设置

`; document.body.appendChild(panel); // 绑定事件 document.getElementById('settings-save').addEventListener('click', () => { const newConfig = { serverUrl: document.getElementById('settings-serverUrl').value.trim(), password: document.getElementById('settings-password').value, autoDetect: document.getElementById('settings-autoDetect').checked }; CONFIG = newConfig; saveConfig(newConfig); showMessage('✅ 配置已保存', 'success'); panel.remove(); }); document.getElementById('settings-reset').addEventListener('click', () => { if (confirm('确定要恢复默认配置吗?')) { CONFIG = {...DEFAULT_CONFIG}; saveConfig(CONFIG); showMessage('✅ 配置已重置', 'success'); panel.remove(); } }); document.getElementById('settings-close').addEventListener('click', () => { panel.remove(); }); // 点击背景关闭 panel.addEventListener('click', (e) => { if (e.target === panel) { panel.remove(); } }); } function showMessage(text, type) { const colors = { success: '#4CAF50', error: '#f44336', warning: '#ff9800', info: '#2196F3' }; const msg = document.createElement('div'); msg.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 999999; background: ${colors[type] || colors.info}; color: white; padding: 15px 20px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.3); font-size: 14px; white-space: pre-line; max-width: 400px; animation: slideIn 0.3s ease-out; `; msg.textContent = text; const style = document.createElement('style'); style.textContent = ` @keyframes slideIn { from { transform: translateX(400px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } `; document.head.appendChild(style); document.body.appendChild(msg); setTimeout(() => { msg.style.animation = 'slideOut 0.3s ease-in'; setTimeout(() => msg.remove(), 300); }, 3000); const styleOut = document.createElement('style'); styleOut.textContent = ` @keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(400px); opacity: 0; } } `; document.head.appendChild(styleOut); } // ==================== 初始化 ==================== window.addEventListener('load', () => { setTimeout(() => { createButton(); console.log('[同步助手] 已加载'); }, 1000); }); })();