您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
CookieCloud的tampermonkey版本,目前仅支持上传cookie。
当前为
// ==UserScript== // @name CookieCloud // @namespace http://tampermonkey.net/ // @version 2024-09-25 // @description CookieCloud的tampermonkey版本,目前仅支持上传cookie。 // @author tomato // @icon https://store-images.s-microsoft.com/image/apps.63473.a0ccb631-d5e7-422b-bcc7-c0405274114b.be044f83-1292-4e84-a65d-e0527d895863.05fc1666-519a-4d36-8b67-8110c70b45cc?mode=scale&h=64&q=90&w=64 // @match *://*/* // @grant GM_cookie // @grant GM_xmlhttpRequest // @grant GM_notification // @connect * // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js // @run-at document-end // @license MIT // ==/UserScript== /* global $, jQuery, CryptoJS */ (function() { 'use strict'; const configStoreKey = '_cookieCloudConfig'; async function init() { const btnContainer = document.createElement('section'); const asyncBtn = document.createElement('button'); const asyncConfigBtn = document.createElement('button'); asyncBtn.innerText = '上传'; asyncConfigBtn.innerText = '配置'; const btnContainerStyles = { position: 'fixed', bottom: '200px', left: '20px', fontSize: '14px', zIndex: 1000, }; const btnStyles = { display: 'block', width: '50px', height: '50px', borderRadius: '50%', backgroundColor: '#87CEEB', border: 'none', color: '#fff', marginBottom: '10px', boxShadow: '0 4px 8px rgba(0, 0, 0, 0.3)' } Object.assign(btnContainer.style, btnContainerStyles); Object.assign(asyncBtn.style, btnStyles); Object.assign(asyncConfigBtn.style, btnStyles); btnContainer.appendChild(asyncBtn); btnContainer.appendChild(asyncConfigBtn); document.body.appendChild(btnContainer); asyncConfigBtn.onclick = function() { const modal = initConfigForm(); document.body.appendChild(modal); } // 为按钮添加点击事件 asyncBtn.onclick = async function(event) { event.stopPropagation(); const config = localStorage.getItem(configStoreKey); if (!config) { msg('请填写配置'); return; }; const {url, uuid, password, domain = location.host} = JSON.parse(config); if (!url) { msg('请填写服务器地址'); return; }; if (!uuid) { msg('请填写uuid'); return; }; if (!password) { msg('请填写密码'); return; }; const cookies = await getCookie(domain); const encryptCookies = cookie_encrypt(uuid, password, cookies); const payload = { uuid, encrypted: encryptCookies }; const res = await syncCookie(url, payload); try { const resData = JSON.parse(res.response) console.log('resData:', resData); if (resData.action === 'done') { msg('同步成功') } else { throw('错误') } } catch(e) { msg(String(e)) } }; } function msg(title) { window.confirm(title); } function initConfigForm() { // 创建遮罩层 const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; overlay.style.zIndex = '1001'; // 创建弹框(Modal)容器 const modal = document.createElement('div'); const modalStyles = { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', width: '400px', backgroundColor: '#fff', padding: '20px', boxShadow: '0 4px 10px rgba(0, 0, 0, 0.3)', zIndex: '1000', borderRadius: '8px', }; Object.assign(modal.style, modalStyles); // 创建表单 const form = document.createElement('form'); const inputStyles = { width: '100%', padding: '8px', boxSizing: 'border-box', marginBottom: '10px' }; // 创建同步域名关键词·默认当前域名 const domainEle = document.createElement('input'); domainEle.type = 'text'; domainEle.placeholder = '同步域名关键词·默认当前域名'; Object.assign(domainEle.style, inputStyles); // 创建输入框 服务器地址 const urlEle = document.createElement('input'); urlEle.type = 'text'; urlEle.placeholder = '服务器地址'; Object.assign(urlEle.style, inputStyles); // 创建输入框 端对端加密密码 const pwdEle = document.createElement('input'); pwdEle.type = 'text'; pwdEle.placeholder = '输入框 端对端加密密码'; Object.assign(pwdEle.style, inputStyles); // 创建输入框 用户KEY · UUID const uuieEle = document.createElement('input'); uuieEle.type = 'text'; uuieEle.placeholder = '用户KEY · UUID'; Object.assign(uuieEle.style, inputStyles); // 创建保存按钮 const saveButton = document.createElement('button'); saveButton.type = 'submit'; saveButton.innerText = '保存'; saveButton.style.width = '100%'; saveButton.style.padding = '10px'; saveButton.style.backgroundColor = '#87CEEB'; saveButton.style.border = 'none'; saveButton.style.color = '#fff'; saveButton.style.cursor = 'pointer'; saveButton.style.fontSize = '16px'; saveButton.style.borderRadius = '4px'; const config = localStorage.getItem(configStoreKey); if (config) { const {url, uuid, password, domain = ''} = JSON.parse(config); urlEle.value = url; pwdEle.value = password; uuieEle.value = uuid; domainEle.value = domain; }; saveButton.onclick = function () { const configStr = JSON.stringify({ url: urlEle.value, password: pwdEle.value, uuid: uuieEle.value, domain: domainEle.value }); localStorage.setItem(configStoreKey, configStr); overlay.remove(); } modal.onclick = function (event) { event.stopPropagation(); } overlay.onclick = function () { overlay.remove(); } // 将输入框和保存按钮添加到表单 form.appendChild(domainEle); form.appendChild(urlEle); form.appendChild(pwdEle); form.appendChild(uuieEle); form.appendChild(saveButton); // 将表单添加到弹框中 modal.appendChild(form); overlay.appendChild(modal); return overlay; } // 用aes对cookie进行加密 function cookie_encrypt( uuid, password, cookies ) { const the_key = CryptoJS.MD5(uuid+'-'+password).toString().substring(0,16); const data_to_encrypt = JSON.stringify({"cookie_data":cookies,"update_time":new Date()}); return CryptoJS.AES.encrypt(data_to_encrypt, the_key).toString(); } async function getCookie(domain) { return new Promise((res, rej) => { GM_cookie.list({}, function(cookies, error) { if (!error) { const ret_cookies = {}; for( const cookie of cookies ) { if( cookie.domain?.includes(domain) ) { if (!ret_cookies[domain]) { ret_cookies[domain] = [cookie]; } else { ret_cookies[domain].push(cookie); } } } res(ret_cookies); } else { console.error(error); rej(error) } }); }) } // 上传cookie async function syncCookie(url, body) { return new Promise((res, rej) => { GM_xmlhttpRequest({ method: 'POST', url: url+'/update', data: JSON.stringify(body), headers: { 'Content-Type': 'application/json', }, onload: function(response) { console.log('Response:', response.responseText); res(response); }, onerror: function(error) { console.error('Error:', error); rej(error); } }); }) } init(); })();