'use strict'; // ============================================ // CursorPro Account Utils - 反混淆版本 // ============================================ const vscode = require('vscode'); const path = require('path'); const fs = require('fs'); const { exec } = require('child_process'); const { promisify } = require('util'); const { sqliteSetBatch } = require('./sqlite'); const execAsync = promisify(exec); /** * 获取 Cursor 相关路径 * 返回数据库路径、存储路径和机器ID路径 */ function getCursorPaths() { const home = process.env.HOME || process.env.USERPROFILE || ''; if (process.platform === 'win32') { // Windows 路径 const appData = process.env.APPDATA || ''; return { dbPath: path.join(appData, 'Cursor', 'User', 'globalStorage', 'state.vscdb'), storagePath: path.join(appData, 'Cursor', 'User', 'globalStorage', 'storage.json'), machineidPath: path.join(appData, 'Cursor', 'machineid') }; } else if (process.platform === 'darwin') { // macOS 路径 return { dbPath: path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'state.vscdb'), storagePath: path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'storage.json'), machineidPath: path.join(home, 'Library', 'Application Support', 'Cursor', 'machineid') }; } else { // Linux 路径 return { dbPath: path.join(home, '.config', 'Cursor', 'User', 'globalStorage', 'state.vscdb'), storagePath: path.join(home, '.config', 'Cursor', 'User', 'globalStorage', 'storage.json'), machineidPath: path.join(home, '.config', 'Cursor', 'machineid') }; } } exports.getCursorPaths = getCursorPaths; /** * 将账号数据写入本地 * @param {Object} accountData - 账号数据对象 * @param {string} accountData.accessToken - 访问令牌 * @param {string} accountData.refreshToken - 刷新令牌 * @param {string} accountData.workosSessionToken - WorkOS 会话令牌 * @param {string} accountData.email - 邮箱 * @param {string} accountData.membership_type - 会员类型 * @param {string} accountData.usage_type - 使用类型 * @param {string} accountData.serviceMachineId - 服务机器ID * @param {string} accountData.machineId - 机器ID * @param {string} accountData.macMachineId - Mac机器ID * @param {string} accountData.devDeviceId - 设备ID * @param {string} accountData.sqmId - SQM ID * @param {string} accountData.machineIdFile - 机器ID文件内容 */ async function writeAccountToLocal(accountData) { try { const paths = getCursorPaths(); const { dbPath, storagePath, machineidPath } = paths; console.log('[CursorPro] 数据库路径:', dbPath); console.log('[CursorPro] 文件是否存在:', fs.existsSync(dbPath)); console.log('[CursorPro] 账号数据:', JSON.stringify({ hasAccessToken: !!accountData.accessToken, hasRefreshToken: !!accountData.refreshToken, hasWorkosToken: !!accountData.workosSessionToken, email: accountData.email })); // 写入数据库 if (fs.existsSync(dbPath)) { try { const kvPairs = []; // 添加访问令牌 if (accountData.accessToken) { kvPairs.push(['cursorAuth/accessToken', accountData.accessToken]); } // 添加刷新令牌 if (accountData.refreshToken) { kvPairs.push(['cursorAuth/refreshToken', accountData.refreshToken]); } // 添加 WorkOS 会话令牌 if (accountData.workosSessionToken) { kvPairs.push(['cursorAuth/WorkosCursorSessionToken', accountData.workosSessionToken]); } // 添加邮箱 if (accountData.email) { kvPairs.push(['cursorAuth/cachedEmail', accountData.email]); } // 添加会员类型 if (accountData.membership_type) { kvPairs.push(['cursorAuth/stripeMembershipType', accountData.membership_type]); } // 添加使用类型 if (accountData.usage_type) { kvPairs.push(['cursorAuth/stripeUsageType', accountData.usage_type || 'default']); } // 添加服务机器ID if (accountData.serviceMachineId) { kvPairs.push(['telemetry.serviceMachineId', accountData.serviceMachineId]); } console.log('[CursorPro] 待写入数据库:', kvPairs.length); // 批量写入数据库 const result = await sqliteSetBatch(dbPath, kvPairs); if (!result) { throw new Error('数据库写入失败'); } console.log('[CursorPro] 数据库已更新:', kvPairs.length, '个字段'); } catch (error) { console.error('[CursorPro] 数据库操作失败:', error); vscode.window.showErrorMessage('数据库写入失败: ' + error); return false; } } else { console.error('[CursorPro] 数据库文件不存在:', dbPath); vscode.window.showErrorMessage('[CursorPro] 数据库文件不存在'); return false; } // 更新 storage.json if (fs.existsSync(storagePath)) { const storageData = JSON.parse(fs.readFileSync(storagePath, 'utf-8')); if (accountData.machineId) { storageData['telemetry.machineId'] = accountData.machineId; } if (accountData.macMachineId) { storageData['telemetry.macMachineId'] = accountData.macMachineId; } if (accountData.devDeviceId) { storageData['telemetry.devDeviceId'] = accountData.devDeviceId; } if (accountData.sqmId) { storageData['telemetry.sqmId'] = accountData.sqmId; } fs.writeFileSync(storagePath, JSON.stringify(storageData, null, 4)); console.log('[CursorPro] storage.json 已更新'); } // 更新 machineid 文件 if (accountData.machineIdFile && machineidPath) { const dir = path.dirname(machineidPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.writeFileSync(machineidPath, accountData.machineIdFile); console.log('[CursorPro] machineid 文件已更新'); } // Windows 注册表写入 (如果有 sqmId) if (accountData.sqmId && process.platform === 'win32') { try { const regCommand = `reg add "HKCU\\Software\\Cursor" /v SQMId /t REG_SZ /d "${accountData.sqmId}" /f`; await execAsync(regCommand); console.log('[CursorPro] 注册表已更新'); } catch (error) { console.warn('[CursorPro] 注册表写入失败(可能需要管理员权限):', error); } } return true; } catch (error) { console.error('[CursorPro] writeAccountToLocal 失败:', error); return false; } } exports.writeAccountToLocal = writeAccountToLocal; /** * 关闭 Cursor 进程 */ async function closeCursor() { try { if (process.platform === 'win32') { // Windows: 使用 taskkill await execAsync('taskkill /F /IM Cursor.exe').catch(() => {}); } else { // macOS/Linux: 使用 pkill await execAsync('pkill -9 -f Cursor').catch(() => {}); } } catch (error) { console.warn('[CursorPro] 关闭 Cursor 失败:', error); } } exports.closeCursor = closeCursor; /** * 提示用户重启 Cursor */ async function promptRestartCursor(message) { const selection = await vscode.window.showInformationMessage( message, '立即重启', '稍后手动重启' ); if (selection === '立即重启') { await closeCursor(); } } exports.promptRestartCursor = promptRestartCursor;