您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
批量化添加和管理GPT账号
// ==UserScript== // @name GPT账号批量管理助手 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 批量化添加和管理GPT账号 // @author xuming // @match https://chat.openai.com/** // @match https://auth.openai.com/* // @match https://auth0.openai.com/u/login/* // @match https://auth0.openai.com/u/login/password* // @match https://chatgpt.com/** // @icon https://t1.gstatic.cn/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&size=32&url=https://chat.rawchat.cc // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function() { 'use strict'; let accounts = JSON.parse(GM_getValue('accounts', '[]')) || []; let accountsLastUsed = JSON.parse(GM_getValue('accountsLastUsed', '{}')) || {}; let currentAccountIndex = parseInt(GM_getValue('currentAccountIndex', '0'), 10); const commonStyles = { button: { padding: '8px 15px', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer' }, closeButton: { backgroundColor: 'transparent', border: 'none', fontSize: '20px', cursor: 'pointer', padding: '5px 10px', color: '#666' }, popup: { position: 'fixed', right: '20px', bottom: '80px', padding: '20px', backgroundColor: 'white', border: '1px solid black', zIndex: 1000, boxShadow: '0 2px 10px rgba(0,0,0,0.1)' }, container: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, titleBar: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '15px', backgroundColor: 'white', padding: '10px 0' } }; function createElement(tag, styles = {}, innerText = '') { const element = document.createElement(tag); Object.assign(element.style, styles); element.innerText = innerText; return element; } function createButton(text, styles = {}, onClick) { const button = createElement('button', {...commonStyles.button, ...styles}, text); if (onClick) button.addEventListener('click', onClick); return button; } function createPopup(title, content, styles = {}) { const popup = createElement('div', {...commonStyles.popup, ...styles}); const titleBar = createElement('div', commonStyles.titleBar); titleBar.appendChild(createElement('h3', {}, title)); titleBar.appendChild(createButton('×', commonStyles.closeButton, () => document.body.removeChild(popup))); popup.appendChild(titleBar); popup.appendChild(content); document.body.appendChild(popup); return popup; } function updateAccounts(newAccounts) { accounts = newAccounts; GM_setValue('accounts', JSON.stringify(accounts)); } function showToast(message, duration = 2000) { const toast = createElement('div', { position: 'fixed', bottom: '50px', left: '50%', transform: 'translateX(-50%)', backgroundColor: 'rgba(0, 0, 0, 0.7)', color: 'white', padding: '10px 20px', borderRadius: '4px', zIndex: 10000, fontSize: '14px' }, message); document.body.appendChild(toast); setTimeout(() => { document.body.removeChild(toast); }, duration); } const accountOperations = { copy: (text, type, accountDiv) => { navigator.clipboard.writeText(text); accountsLastUsed[text] = new Date().toLocaleString(); GM_setValue('accountsLastUsed', JSON.stringify(accountsLastUsed)); accountDiv.querySelector('small:last-child').textContent = `上次使用: ${accountsLastUsed[text]}`; if (type === '账号') { const newIndex = accounts.findIndex(acc => acc.username === text); if (newIndex !== -1) { currentAccountIndex = newIndex; GM_setValue('currentAccountIndex', currentAccountIndex); const popupElement = accountDiv.closest('[style*="position: fixed"]'); if (popupElement) { document.body.removeChild(popupElement); showAccountsList(); } } } showToast(`已复制${type}:${text}`); }, delete: (index, container) => { accounts.splice(index, 1); updateAccounts(accounts); if (currentAccountIndex >= accounts.length) { currentAccountIndex = 0; GM_setValue('currentAccountIndex', currentAccountIndex); } document.body.removeChild(container); showAccountsList(); } }; const AccountManager = { export: () => { if (accounts.length === 0) { showToast('当前没有保存的账号!'); return; } const text = accounts.map(acc => `${acc.username}---${acc.password}`).join('\n'); const blob = new Blob([text], { type: 'text/plain' }); const link = createElement('a'); link.download = `GPT账号列表_${new Date().toLocaleDateString()}.txt`; link.href = URL.createObjectURL(blob); link.click(); URL.revokeObjectURL(link.href); } }; function showAddAccountForm() { const content = createElement('div'); const textArea = createElement('textarea', {width: '300px', height: '200px'}); textArea.placeholder = '请输入账号,格式如下:\[email protected]\n每行一个账号'; const buttonContainer = createElement('div', {marginTop: '10px'}); const buttons = [ { text: '批量导入', color: '#2196F3', onClick: () => { const newAccounts = textArea.value.split('\n') .filter(line => line.trim()) .map(line => { const [username, password] = line.split('---'); return username && password ? {username: username.trim(), password: password.trim()} : null; }) .filter(acc => acc); accounts.push(...newAccounts); updateAccounts(accounts); document.body.removeChild(popup); showToast(`成功添加 ${newAccounts.length} 个账号`); } }, { text: '清空所有账号', color: '#ff4444', onClick: () => { if (confirm('确定要清空所有账号吗?')) { updateAccounts([]); document.body.removeChild(popup); showToast('已清空所有账号'); } } } ]; buttons.forEach(({ text, color, onClick }) => { buttonContainer.appendChild(createButton(text, { backgroundColor: color }, onClick)); }); content.appendChild(textArea); content.appendChild(buttonContainer); const popup = createPopup('添加账号', content); } function showAccountsList() { const content = createElement('div', {overflow: 'auto'}); if (accounts.length > 0) { const currentAccount = accounts[currentAccountIndex]; const nextIndex = (currentAccountIndex + 1) % accounts.length; const nextAccount = accounts[nextIndex]; content.innerHTML = ` <div style="font-size: 0.9em; color: #666; margin-bottom: 10px;"> 当前账号: ${currentAccountIndex + 1}号 (${currentAccount.username})<br> 下一个账号: ${nextIndex + 1}号 (${nextAccount.username}) </div> `; } accounts.forEach((account, index) => { const accountDiv = createElement('div', { padding: '10px', borderBottom: '1px solid #eee', ...commonStyles.container }); accountDiv.innerHTML = ` <div style="flex: 1"> <strong>${index + 1}. ${account.username}</strong><br> <small style="color: #666;">密码: ${account.password}</small><br> <small style="color: #999; font-size: 0.8em;"> 上次使用: ${accountsLastUsed[account.username] || '从未使用'} </small> </div> `; const buttonContainer = createElement('div', {display: 'flex', gap: '5px'}); [ ['复制账号', '#4CAF50', () => accountOperations.copy(account.username, '账号', accountDiv)], ['复制密码', '#2196F3', () => accountOperations.copy(account.password, '密码', accountDiv)], ['删除', '#ff4444', () => accountOperations.delete(index, popup)] ].forEach(([text, color, onClick]) => { buttonContainer.appendChild(createButton(text, { backgroundColor: color }, onClick)); }); accountDiv.appendChild(buttonContainer); content.appendChild(accountDiv); }); const popup = createPopup( `当前账号列表 (共${accounts.length}个)`, content, { maxHeight: '80vh', width: '400px', overflowY: 'auto' } ); } window.addEventListener('load', () => { setTimeout(createAccountPool, 1000); }); function createAccountPool() { const mainButton = createButton('账号池', { position: 'fixed', right: '15px', bottom: '15px', zIndex: 1000, padding: '4px 8px', backgroundColor: 'rgba(255, 255, 255, 0.8)', color: '#666', border: '1px solid rgba(0, 0, 0, 0.1)', borderRadius: '3px', cursor: 'pointer', boxShadow: '0 1px 3px rgba(0,0,0,0.1)', fontSize: '12px', transition: 'all 0.3s ease' }); const menuContainer = createElement('div', { position: 'fixed', right: '20px', bottom: '70px', backgroundColor: 'white', borderRadius: '4px', boxShadow: '0 2px 10px rgba(0,0,0,0.1)', display: 'none', flexDirection: 'column', gap: '5px', padding: '5px', zIndex: 999 }); const menuItems = [ { text: '添加账号', color: '#2196F3', handler: showAddAccountForm }, { text: '查看账号', color: '#FF9800', handler: showAccountsList }, { text: '导出账号', color: '#9C27B0', handler: AccountManager.export } ].forEach(({ text, color, handler }) => { menuContainer.appendChild(createButton(text, { backgroundColor: color, width: '100%', minWidth: '120px' }, handler)); }); const toggleMenu = (() => { let isVisible = false; return () => { isVisible = !isVisible; menuContainer.style.display = isVisible ? 'flex' : 'none'; }; })(); mainButton.addEventListener('click', toggleMenu); document.addEventListener('click', (event) => { if (!mainButton.contains(event.target) && !menuContainer.contains(event.target)) { menuContainer.style.display = 'none'; } }); [mainButton, menuContainer].forEach(el => document.body.appendChild(el)); } })();