fuclaude SessionKey Switch

使用sessionKey自动登录demo.fuclaude.com

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

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