- // ==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();
- })();