// ==UserScript==
// @name fuclaude SessionKey Switch
// @version 3.0
// @description 使用sessionKey自动登录demo.fuclaude.com
// @match https://demo.fuclaude.com/*
// @grant none
// @license GNU GPLv3
// @namespace https://greasyfork.org/users/1369183
// ==/UserScript==
(function() {
'use strict';
// 配置对象,存储token列表和本地存储键名
let CONFIG = {
tokens: [
// 预设的token列表,每个token包含名称和密钥
{name: 'Token 1', key: ''},
],
storageKey: 'fuclaude_SelectedToken', // 用于存储选中token的本地存储键名
configStorageKey: 'fuclaude_Config' // 用于存储整个配置的本地存储键名
};
// 创建HTML元素的通用函数
const createElement = (tag, styles, attributes = {}) => {
const elem = document.createElement(tag);
Object.assign(elem.style, styles);
Object.entries(attributes).forEach(([key, value]) => elem.setAttribute(key, value));
return elem;
};
// 创建下拉选择框的函数
const createSelect = (options, styles) => {
const select = createElement('select', styles);
options.forEach(({name, key}) => {
const option = createElement('option', {}, {value: key});
option.textContent = name;
select.appendChild(option);
});
return select;
};
// 创建按钮的函数
const createButton = (text, primaryColor, hoverColor) => {
const button = createElement('button', {
fontSize: '14px',
padding: '10px 15px',
backgroundColor: primaryColor,
color: '#333333',
border: '1px solid #d0d0d0',
borderRadius: '5px',
cursor: 'pointer',
transition: 'all 0.3s ease',
margin: '0 5px'
}, {
onmouseover: `this.style.backgroundColor='${hoverColor}'`,
onmouseout: `this.style.backgroundColor='${primaryColor}'`
});
button.textContent = text;
return button;
};
// 创建主UI的函数
const createUI = () => {
// 创建token选择下拉框
const tokenSelect = createSelect(CONFIG.tokens, {
fontSize: '14px',
width: '100%',
backgroundColor: '#ffffff',
color: '#333333',
height: '40px',
padding: '0 10px',
border: '1px solid #e0e0e0',
borderRadius: '5px',
appearance: 'none',
WebkitAppearance: 'none',
MozAppearance: 'none',
backgroundImage: 'url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E")',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'right 10px top 50%',
backgroundSize: '12px auto',
marginBottom: '10px',
transition: 'all 0.3s ease',
cursor: 'pointer'
});
// 创建保存和配置按钮
const saveButton = createButton('切换', '#f0f0f0', '#e0e0e0');
const configButton = createButton('配置', '#f0f0f0', '#e0e0e0');
// 创建切换按钮
const toggleButton = createElement('button', {
fontSize: '14px',
padding: '10px 15px',
backgroundColor: '#f0f0f0',
color: '#333333',
border: '1px solid #d0d0d0',
borderRadius: '5px',
cursor: 'pointer',
position: 'fixed',
top: '20px',
right: '300px',
zIndex: '10000',
transition: 'all 0.3s ease',
boxShadow: '0 2px 5px rgba(0,0,0,0.1)'
}, {
onmouseover: "this.style.backgroundColor='#e0e0e0'",
onmouseout: "this.style.backgroundColor='#f0f0f0'"
});
toggleButton.textContent = 'SessionKey切换';
// 创建主容器
const container = createElement('div', {
position: 'fixed',
zIndex: '9999',
backgroundColor: '#ffffff',
padding: '20px',
borderRadius: '10px',
boxShadow: '0 4px 10px rgba(0,0,0,0.1)',
display: 'none',
flexDirection: 'column',
alignItems: 'center',
gap: '10px',
width: '300px'
});
// 创建按钮容器
const buttonContainer = createElement('div', {
display: 'flex',
justifyContent: 'center',
width: '100%'
});
// 组装UI元素
buttonContainer.appendChild(saveButton);
buttonContainer.appendChild(configButton);
container.appendChild(tokenSelect);
container.appendChild(buttonContainer);
return { tokenSelect, saveButton, configButton, toggleButton, container };
};
// 创建配置UI的函数
const createConfigUI = () => {
// 创建配置容器
const configContainer = createElement('div', {
position: 'fixed',
zIndex: '10001',
backgroundColor: '#ffffff',
padding: '20px',
borderRadius: '10px',
boxShadow: '0 4px 10px rgba(0,0,0,0.1)',
display: 'none',
flexDirection: 'column',
alignItems: 'center',
gap: '10px',
width: '400px',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)'
});
// 创建token列表
const tokenList = createElement('ul', {
listStyleType: 'none',
padding: '0',
width: '100%'
});
// 为每个token创建列表项
CONFIG.tokens.forEach((token, index) => {
const listItem = createElement('li', {
marginBottom: '10px',
display: 'flex',
alignItems: 'center'
});
const nameInput = createElement('input', {
width: '30%',
marginRight: '10px'
}, { type: 'text', value: token.name });
const keyInput = createElement('input', {
width: '50%',
marginRight: '10px'
}, { type: 'text', value: token.key });
const deleteButton = createButton('删除', '#f0f0f0', '#e0e0e0');
deleteButton.style.padding = '5px 10px';
deleteButton.style.fontSize = '12px';
listItem.appendChild(nameInput);
listItem.appendChild(keyInput);
listItem.appendChild(deleteButton);
tokenList.appendChild(listItem);
});
// 创建添加和保存按钮
const addButton = createButton('添加Token', '#f0f0f0', '#e0e0e0');
const saveConfigButton = createButton('保存配置', '#f0f0f0', '#e0e0e0');
// 组装配置UI
configContainer.appendChild(tokenList);
configContainer.appendChild(addButton);
configContainer.appendChild(saveConfigButton);
return { configContainer, addButton, saveConfigButton, tokenList };
};
// 处理token选择的函数
const handleTokenSelection = (token) => {
if (token === '') {
console.log('Empty token selected. No action taken.');
} else {
autoLogin(token);
}
};
// 自动登录函数
const autoLogin = (token) => {
const loginUrl = `https://demo.fuclaude.com/login_token?session_key=${token}`;
window.location.href = loginUrl;
};
// 保存配置到本地存储的函数
const saveConfig = () => {
localStorage.setItem(CONFIG.configStorageKey, JSON.stringify(CONFIG));
};
// 从本地存储加载配置的函数
const loadConfig = () => {
const savedConfig = localStorage.getItem(CONFIG.configStorageKey);
if (savedConfig) {
Object.assign(CONFIG, JSON.parse(savedConfig));
}
};
// 设置事件监听器的函数
const setupEventListeners = (ui) => {
// 切换按钮点击事件
ui.toggleButton.addEventListener('click', (event) => {
event.stopPropagation();
if (ui.container.style.display === 'none') {
const buttonRect = ui.toggleButton.getBoundingClientRect();
ui.container.style.top = `${buttonRect.bottom + window.scrollY + 10}px`;
ui.container.style.left = `${buttonRect.left + window.scrollX}px`;
ui.container.style.display = 'flex';
} else {
ui.container.style.display = 'none';
}
});
// 保存按钮点击事件
ui.saveButton.addEventListener('click', () => {
const selectedToken = ui.tokenSelect.value;
localStorage.setItem(CONFIG.storageKey, selectedToken);
handleTokenSelection(selectedToken);
});
// token选择变化事件
ui.tokenSelect.addEventListener('change', () => {
localStorage.setItem(CONFIG.storageKey, ui.tokenSelect.value);
});
// 创建配置UI
const configUI = createConfigUI();
document.body.appendChild(configUI.configContainer);
// 配置按钮点击事件
ui.configButton.addEventListener('click', () => {
configUI.configContainer.style.display = 'flex';
});
// 添加token按钮点击事件
configUI.addButton.addEventListener('click', () => {
const newToken = { name: 'New Token', key: '' };
CONFIG.tokens.push(newToken);
updateConfigUI(configUI);
});
// 保存配置按钮点击事件
configUI.saveConfigButton.addEventListener('click', () => {
updateConfigFromUI(configUI);
saveConfig();
updateMainUI(ui);
configUI.configContainer.style.display = 'none';
});
// 删除token的处理函数
const handleDeleteToken = (index) => {
CONFIG.tokens.splice(index, 1);
updateConfigUI(configUI);
};
// token列表点击事件(用于删除)
configUI.tokenList.addEventListener('click', (event) => {
if (event.target.textContent === '删除') {
const listItem = event.target.closest('li');
const index = Array.from(configUI.tokenList.children).indexOf(listItem);
handleDeleteToken(index);
}
});
// 点击其他位置时收起菜单
document.addEventListener('click', (event) => {
if (!ui.container.contains(event.target) && event.target !== ui.toggleButton) {
ui.container.style.display = 'none';
}
if (!configUI.configContainer.contains(event.target)) {
configUI.configContainer.style.display = 'none';
}
});
// 阻止点击菜单内部时关闭菜单
ui.container.addEventListener('click', (event) => {
event.stopPropagation();
});
configUI.configContainer.addEventListener('click', (event) => {
event.stopPropagation();
});
};
// 更新配置UI的函数
const updateConfigUI = (configUI) => {
configUI.tokenList.innerHTML = '';
CONFIG.tokens.forEach((token, index) => {
const listItem = createElement('li', {
marginBottom: '10px',
display: 'flex',
alignItems: 'center'
});
// 创建名称输入框
const nameInput = createElement('input', {
width: '30%',
marginRight: '10px'
}, { type: 'text', value: token.name });
// 创建密钥输入框
const keyInput = createElement('input', {
width: '50%',
marginRight: '10px'
}, { type: 'text', value: token.key });
// 创建删除按钮
const deleteButton = createButton('删除', '#f0f0f0', '#e0e0e0');
deleteButton.style.padding = '5px 10px';
deleteButton.style.fontSize = '12px';
// 将元素添加到列表项中
listItem.appendChild(nameInput);
listItem.appendChild(keyInput);
listItem.appendChild(deleteButton);
configUI.tokenList.appendChild(listItem);
});
};
// 从UI更新配置的函数
const updateConfigFromUI = (configUI) => {
const tokenInputs = configUI.tokenList.querySelectorAll('li');
CONFIG.tokens = Array.from(tokenInputs).map(li => ({
name: li.querySelector('input[type="text"]:nth-child(1)').value,
key: li.querySelector('input[type="text"]:nth-child(2)').value
}));
};
// 更新主UI的函数
const updateMainUI = (ui) => {
ui.tokenSelect.innerHTML = '';
CONFIG.tokens.forEach(token => {
const option = createElement('option', {}, { value: token.key });
option.textContent = token.name;
ui.tokenSelect.appendChild(option);
});
};
// 初始化函数
const init = () => {
// 从本地存储加载配置
loadConfig();
// 创建主UI
const ui = createUI();
// 将UI添加到页面
document.body.appendChild(ui.container);
document.body.appendChild(ui.toggleButton);
// 设置事件监听器
setupEventListeners(ui);
// 从本地存储中读取之前选择的token
const storedToken = localStorage.getItem(CONFIG.storageKey);
if (storedToken) {
ui.tokenSelect.value = storedToken;
}
};
// 执行初始化
init();
})();