// ==UserScript== // @name 通用数据同步助手 // @namespace http://tampermonkey.net/ // @version 1.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 // ==/UserScript== (function() { 'use strict'; // ==================== 配置 ==================== const CONFIG = { serverUrl: 'http://47.122.126.244:5001', password: 'admin123123123', autoDetect: true // 自动检测项目名和账号 }; // ==================== 项目检测 ==================== 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) { if (response.status === 200) { const result = JSON.parse(response.responseText); showMessage(`✅ 同步成功!\n\nTag: ${tag}\n过期时间: ${result.expires_at}`, 'success'); } else { showMessage(`❌ 同步失败: ${response.statusText}`, '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.addEventListener('click', (e) => { if (!btn.contains(e.target) && !menu.contains(e.target)) { menu.style.display = 'none'; } }); } 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); }); })();