Spaces:
Paused
Paused
| const fs = require('fs'); | |
| const path = require('path'); | |
| const readline = require('readline'); | |
| const dotenv = require('dotenv'); | |
| // 创建交互式命令行界面 | |
| const rl = readline.createInterface({ | |
| input: process.stdin, | |
| output: process.stdout | |
| }); | |
| // 配置模板 | |
| const ENV_TEMPLATE = `# 服务端口 | |
| PORT=3010 | |
| # 日志格式 (tiny, combined, common, dev, short) | |
| MORGAN_FORMAT=tiny | |
| # API Key与Cookie映射关系 (JSON格式) | |
| # 格式: {"自定义API Key": "Cookie值"} 或 {"自定义API Key": ["Cookie值1", "Cookie值2"]} | |
| API_KEYS={API_KEYS_PLACEHOLDER} | |
| # 轮询策略 (random 或 round-robin) | |
| ROTATION_STRATEGY=round-robin | |
| # Cursor校验和 (可选) | |
| # x-cursor-checksum=xxxxxxxx | |
| # 自动刷新Cookie设置 | |
| # 是否启用自动刷新Cookie (true 或 false) | |
| ENABLE_AUTO_REFRESH=true | |
| # 自动刷新Cookie的定时规则 (Cron表达式) | |
| # 默认每6小时执行一次 | |
| REFRESH_CRON=0 */6 * * * | |
| # 每个API Key最小Cookie数量 | |
| # 当Cookie数量低于此值时,会自动尝试刷新 | |
| MIN_COOKIE_COUNT=1000 | |
| # Cookie刷新模式 | |
| # replace: 每次刷新都将现有cookie全部标记为无效并替换成新cookie(默认) | |
| # append: 保留现有cookie,仅追加新cookie | |
| COOKIE_REFRESH_MODE=replace | |
| # GitHub 仓库信息 | |
| GITHUB_OWNER={GITHUB_OWNER_PLACEHOLDER} | |
| GITHUB_REPO=Cursor-Register-fix | |
| # GitHub Token (用于从GitHub Actions下载Artifact) | |
| # 需要有repo权限 | |
| GITHUB_TOKEN={GITHUB_TOKEN_PLACEHOLDER} | |
| # GitHub Actions 工作流ID | |
| # 用于触发工作流程 | |
| GITHUB_WORKFLOW_ID=cursor_register.yml | |
| # 是否自动触发工作流 | |
| # 设置为true时,会自动触发工作流而不是仅获取最新结果 | |
| TRIGGER_WORKFLOW=true | |
| # 工作流参数设置 目前只支持gmail,outlook过于复杂,暂时不支持 | |
| # 注册账号数量 | |
| REGISTER_NUMBER=1 | |
| # 最大并发工作线程数 | |
| REGISTER_MAX_WORKERS=1 | |
| # 邮箱服务器类型 (TempEmail 或 IMAP) | |
| REGISTER_EMAIL_SERVER=IMAP | |
| # 是否将账号令牌注入到OneAPI (true 或 false) | |
| REGISTER_INGEST_TO_ONEAPI=false | |
| # 是否上传账号信息到Artifact (true 或 false) | |
| REGISTER_UPLOAD_ARTIFACT=true | |
| # 是否从config.yaml读取邮箱配置 (true 或 false) | |
| REGISTER_USE_CONFIG_FILE=false | |
| # 邮箱配置JSON字符串(仅在REGISTER_USE_CONFIG_FILE=false时有效) | |
| # 格式例如[{"email":"[email protected]","imap_server":"imap.gmail.com","imap_port":993,"username":"[email protected]","password":"your_app_password"}] | |
| REGISTER_EMAIL_CONFIGS={EMAIL_CONFIGS_PLACEHOLDER} | |
| `; | |
| // 提示信息 | |
| console.log('===== Cursor-To-OpenAI 环境配置助手 ====='); | |
| console.log('这个脚本将帮助你配置必要的环境变量\n'); | |
| // 应用密码说明 | |
| function printAppPasswordInstructions() { | |
| console.log('\n===== 如何创建谷歌应用密码 ====='); | |
| console.log('1. 访问 https://myaccount.google.com/security'); | |
| console.log('2. 在"登录Google"部分,点击"两步验证"'); | |
| console.log(' (如果未启用两步验证,需要先启用)'); | |
| console.log('3. 在页面底部找到"应用密码",点击进入'); | |
| console.log('4. 在"选择应用"下拉菜单中选择"其他(自定义名称)"'); | |
| console.log('5. 输入一个名称,例如"Cursor注册"'); | |
| console.log('6. 点击"生成"'); | |
| console.log('7. 复制生成的16位应用密码(格式如:xxxx xxxx xxxx xxxx)'); | |
| console.log('8. 在下面的提示中输入这个密码'); | |
| console.log('注意: 应用密码只会显示一次,请务必保存好\n'); | |
| } | |
| // 从现有.env文件加载配置 | |
| function loadExistingConfig() { | |
| const envPath = path.join(process.cwd(), '.env'); | |
| let existingConfig = { | |
| apiKeys: {}, | |
| githubOwner: '', | |
| githubToken: '', | |
| emailConfigs: [], | |
| cookieRefreshMode: 'append' | |
| }; | |
| if (fs.existsSync(envPath)) { | |
| console.log('发现现有的.env配置文件,将加载现有设置作为默认值'); | |
| console.log('提示: 直接按回车将保留现有设置不变\n'); | |
| try { | |
| // 加载.env文件 | |
| const envConfig = dotenv.parse(fs.readFileSync(envPath)); | |
| // 提取API Keys | |
| if (envConfig.API_KEYS) { | |
| try { | |
| existingConfig.apiKeys = JSON.parse(envConfig.API_KEYS); | |
| } catch (e) { | |
| console.log('无法解析现有的API Keys配置,将使用默认设置'); | |
| } | |
| } | |
| // 提取GitHub Owner | |
| if (envConfig.GITHUB_OWNER) { | |
| existingConfig.githubOwner = envConfig.GITHUB_OWNER; | |
| } | |
| // 提取GitHub Token | |
| if (envConfig.GITHUB_TOKEN) { | |
| existingConfig.githubToken = envConfig.GITHUB_TOKEN; | |
| } | |
| // 提取Email配置 | |
| if (envConfig.REGISTER_EMAIL_CONFIGS) { | |
| try { | |
| existingConfig.emailConfigs = JSON.parse(envConfig.REGISTER_EMAIL_CONFIGS); | |
| } catch (e) { | |
| console.log('无法解析现有的Email配置,将使用默认设置'); | |
| } | |
| } | |
| // 提取Cookie刷新模式 | |
| if (envConfig.COOKIE_REFRESH_MODE) { | |
| existingConfig.cookieRefreshMode = envConfig.COOKIE_REFRESH_MODE; | |
| } | |
| console.log('成功加载现有配置'); | |
| } catch (error) { | |
| console.error('加载现有配置时出错:', error.message); | |
| console.log('将使用默认设置'); | |
| } | |
| } else { | |
| console.log('未找到现有的.env配置文件,将创建新的配置文件'); | |
| } | |
| return existingConfig; | |
| } | |
| // 提示用户输入,带有默认值 | |
| function promptWithDefault(question, defaultValue) { | |
| return new Promise((resolve) => { | |
| const defaultText = defaultValue ? ` [${defaultValue}]` : ''; | |
| rl.question(`${question}${defaultText}: `, (answer) => { | |
| // 如果用户只按了回车,使用默认值 | |
| resolve(answer.trim() || defaultValue || ''); | |
| }); | |
| }); | |
| } | |
| // 收集配置信息 | |
| async function collectConfig() { | |
| // 加载现有配置 | |
| const existingConfig = loadExistingConfig(); | |
| const config = { | |
| apiKeys: {}, | |
| githubOwner: '', | |
| githubToken: '', | |
| emailConfigs: [], | |
| cookieRefreshMode: 'replace' | |
| }; | |
| // 获取GitHub用户名 | |
| config.githubOwner = await promptWithDefault('请输入你的GitHub用户名', existingConfig.githubOwner); | |
| // 获取GitHub Token | |
| config.githubToken = await promptWithDefault('请输入你的GitHub Token (具有repo权限)', existingConfig.githubToken); | |
| // 处理API Keys | |
| const existingApiKeys = Object.keys(existingConfig.apiKeys); | |
| if (existingApiKeys.length > 0) { | |
| console.log('\n现有的API Keys:'); | |
| existingApiKeys.forEach(key => console.log(`- ${key}`)); | |
| const keepExistingApiKeys = await promptWithDefault('是否保留现有的API Keys? (y/n)', 'y'); | |
| if (keepExistingApiKeys.toLowerCase() === 'y') { | |
| config.apiKeys = { ...existingConfig.apiKeys }; | |
| } | |
| } | |
| // 询问是否添加新的API Key | |
| const addNewApiKey = await promptWithDefault('是否添加新的API Key? (y/n)', existingApiKeys.length === 0 ? 'y' : 'n'); | |
| if (addNewApiKey.toLowerCase() === 'y') { | |
| const apiKey = await promptWithDefault('请输入自定义的API Key (不含sk-前缀,将自动添加)', ''); | |
| if (apiKey) { | |
| const fullApiKey = apiKey.startsWith('sk-') ? apiKey : `sk-${apiKey}`; | |
| config.apiKeys[fullApiKey] = []; | |
| } | |
| } | |
| // 询问Cookie刷新模式 | |
| const refreshModePrompt = `选择Cookie刷新模式 [append/replace]`; | |
| const defaultRefreshMode = existingConfig.cookieRefreshMode || 'replace'; | |
| config.cookieRefreshMode = await promptWithDefault(refreshModePrompt, defaultRefreshMode); | |
| // 解释所选的刷新模式 | |
| if (config.cookieRefreshMode.toLowerCase() === 'replace') { | |
| config.cookieRefreshMode = 'replace'; | |
| console.log('已选择替换模式: 每次刷新都将现有cookie全部标记为无效并替换成新cookie'); | |
| } else { | |
| config.cookieRefreshMode = 'append'; | |
| console.log('已选择追加模式: 保留现有cookie,仅追加新cookie'); | |
| } | |
| // 处理Email配置 | |
| if (existingConfig.emailConfigs.length > 0) { | |
| console.log('\n现有的Gmail账号:'); | |
| existingConfig.emailConfigs.forEach((emailConfig, index) => { | |
| console.log(`- ${index + 1}: ${emailConfig.email}`); | |
| }); | |
| const keepExistingEmails = await promptWithDefault('是否保留现有的Gmail账号? (y/n)', 'y'); | |
| if (keepExistingEmails.toLowerCase() === 'y') { | |
| config.emailConfigs = [...existingConfig.emailConfigs]; | |
| } | |
| } | |
| // 询问是否添加新的Gmail账号 | |
| const addNewGmail = await promptWithDefault('是否添加新的Gmail账号? (y/n)', existingConfig.emailConfigs.length === 0 ? 'y' : 'n'); | |
| if (addNewGmail.toLowerCase() === 'y') { | |
| printAppPasswordInstructions(); | |
| await askForGmailAccount(config); | |
| } else if (config.emailConfigs.length === 0 && existingConfig.emailConfigs.length === 0) { | |
| console.log('\n⚠️ 警告: 未添加Gmail账号,自动刷新功能可能无法正常工作'); | |
| console.log('你可以稍后在.env文件中手动配置REGISTER_EMAIL_CONFIGS\n'); | |
| } | |
| return config; | |
| } | |
| // 询问Gmail账号 | |
| async function askForGmailAccount(config) { | |
| const addGmail = await promptWithDefault('\n是否添加Gmail账号用于注册? (y/n)', 'y'); | |
| if (addGmail.toLowerCase() === 'y') { | |
| const email = await promptWithDefault('请输入Gmail地址', ''); | |
| const password = await promptWithDefault('请输入Gmail的应用密码 (不是邮箱密码)', ''); | |
| if (email && password) { | |
| // 添加Email配置 | |
| config.emailConfigs.push({ | |
| email: email, | |
| imap_server: "imap.gmail.com", | |
| imap_port: 993, | |
| username: email, | |
| password: password | |
| }); | |
| } | |
| const continueAnswer = await promptWithDefault('是否继续添加另一个Gmail账号? (y/n)', 'n'); | |
| if (continueAnswer.toLowerCase() === 'y') { | |
| await askForGmailAccount(config); | |
| } | |
| } | |
| return config; | |
| } | |
| // 生成配置文件 | |
| function generateEnvFile(config) { | |
| try { | |
| // 准备API Keys | |
| const apiKeysJson = JSON.stringify(config.apiKeys); | |
| // 准备邮箱配置 | |
| const emailConfigsJson = JSON.stringify(config.emailConfigs); | |
| // 替换模板中的占位符 | |
| let envContent = ENV_TEMPLATE | |
| .replace('{API_KEYS_PLACEHOLDER}', apiKeysJson) | |
| .replace('{GITHUB_OWNER_PLACEHOLDER}', config.githubOwner) | |
| .replace('{GITHUB_TOKEN_PLACEHOLDER}', config.githubToken) | |
| .replace('{EMAIL_CONFIGS_PLACEHOLDER}', emailConfigsJson); | |
| // 更新Cookie刷新模式 | |
| envContent = envContent.replace('COOKIE_REFRESH_MODE=append', `COOKIE_REFRESH_MODE=${config.cookieRefreshMode}`); | |
| // 写入.env文件 | |
| const envPath = path.join(process.cwd(), '.env'); | |
| // 检查是否存在备份文件 | |
| const backupPath = path.join(process.cwd(), '.env.backup'); | |
| if (fs.existsSync(envPath)) { | |
| // 创建备份 | |
| fs.copyFileSync(envPath, backupPath); | |
| console.log(`\n✅ 已创建原配置文件备份: ${backupPath}`); | |
| } | |
| fs.writeFileSync(envPath, envContent, 'utf8'); | |
| console.log(`\n✅ 配置文件已生成: ${envPath}`); | |
| // 检查data目录 | |
| const dataDir = path.join(process.cwd(), 'data'); | |
| if (!fs.existsSync(dataDir)) { | |
| fs.mkdirSync(dataDir, { recursive: true }); | |
| console.log(`✅ 创建数据目录: ${dataDir}`); | |
| } | |
| return true; | |
| } catch (error) { | |
| console.error('\n❌ 生成配置文件时出错:', error.message); | |
| return false; | |
| } | |
| } | |
| // 主函数 | |
| async function main() { | |
| try { | |
| const config = await collectConfig(); | |
| if (generateEnvFile(config)) { | |
| console.log('\n===== 配置完成 ====='); | |
| console.log('你可以使用以下命令启动服务:'); | |
| console.log(' npm start'); | |
| console.log('\n如需手动获取cookie执行:'); | |
| console.log(' npm run refresh-cookies'); | |
| // 根据配置的刷新模式提供提示 | |
| console.log(`\n当前Cookie刷新模式为: ${config.cookieRefreshMode}`); | |
| if (config.cookieRefreshMode === 'replace') { | |
| console.log('每次刷新都会将现有cookie全部标记为无效并替换成新cookie'); | |
| } else { | |
| console.log('刷新时会保留现有cookie,仅追加新cookie'); | |
| } | |
| console.log('你可以在.env文件中修改COOKIE_REFRESH_MODE设置'); | |
| } | |
| } catch (error) { | |
| console.error('\n❌ 配置过程中出错:', error.message); | |
| } finally { | |
| rl.close(); | |
| } | |
| } | |
| // 运行主函数 | |
| main(); |