CursorPro 后台管理系统 v1.0

功能:
- 激活码管理 (Pro/Auto 两种类型)
- 账号池管理
- 设备绑定记录
- 使用日志
- 搜索/筛选功能
- 禁用/启用功能 (支持退款参考)
- 全局设置 (换号间隔、额度消耗等)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
ccdojox-crypto
2025-12-16 20:54:44 +08:00
commit 9e2333c90c
62 changed files with 9567 additions and 0 deletions

View File

@@ -0,0 +1,226 @@
'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;

View File

@@ -0,0 +1,203 @@
'use strict';
// ============================================
// CursorPro SQLite Utils - 反混淆版本
// ============================================
const { exec } = require('child_process');
const { promisify } = require('util');
const fs = require('fs');
const execAsync = promisify(exec);
/**
* 转义 SQL 字符串中的单引号
*/
function escapeSqlString(value) {
if (value === null || value === undefined) {
return '';
}
return String(value).replace(/'/g, "''");
}
/**
* 执行 SQLite 命令
* @param {string} dbPath - 数据库文件路径
* @param {string} sql - SQL 语句
* @returns {Promise<string>} - 执行结果
*/
async function execSqlite(dbPath, sql) {
const isWindows = process.platform === 'win32';
try {
if (isWindows) {
// Windows: 直接使用 sqlite3 命令
const escapedSql = sql.replace(/"/g, '\\"');
const command = `sqlite3 "${dbPath}" "${escapedSql}"`;
const { stdout, stderr } = await execAsync(command, {
encoding: 'utf-8',
maxBuffer: 10 * 1024 * 1024 // 10MB
});
if (stderr && !stderr.includes('-- Loading')) {
console.warn('[SQLite] stderr:', stderr);
}
return stdout.trim();
} else {
// macOS/Linux: 使用临时文件避免转义问题
const os = require('os');
const pathModule = require('path');
const tempFile = pathModule.join(
os.tmpdir(),
'cursor_sql_' + Date.now() + '.sql'
);
// 写入 SQL 到临时文件
fs.writeFileSync(tempFile, sql, 'utf-8');
try {
const command = `sqlite3 "${dbPath}" < "${tempFile}"`;
const { stdout, stderr } = await execAsync(command, {
encoding: 'utf-8',
maxBuffer: 10 * 1024 * 1024,
shell: '/bin/bash'
});
if (stderr && !stderr.includes('-- Loading')) {
console.warn('[SQLite] stderr:', stderr);
}
return stdout.trim();
} finally {
// 清理临时文件
try {
fs.unlinkSync(tempFile);
} catch (e) {}
}
}
} catch (error) {
// 检查是否是 sqlite3 不存在的错误
if (
error.message === 'ENOENT' ||
error.message?.includes('sqlite3') ||
error.message?.includes('not found')
) {
throw new Error('sqlite3 命令不存在,请先安装 SQLite3');
}
throw error;
}
}
/**
* 从 SQLite 数据库读取单个值
* @param {string} dbPath - 数据库路径
* @param {string} key - 键名
* @returns {Promise<string|null>} - 值或 null
*/
async function sqliteGet(dbPath, key) {
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
return null;
}
try {
const sql = `SELECT value FROM ItemTable WHERE key = '${escapeSqlString(key)}';`;
const result = await execSqlite(dbPath, sql);
return result || null;
} catch (error) {
console.error('[SQLite] 读取失败:', error);
return null;
}
}
exports.sqliteGet = sqliteGet;
/**
* 向 SQLite 数据库写入单个值
* @param {string} dbPath - 数据库路径
* @param {string} key - 键名
* @param {string} value - 值
* @returns {Promise<boolean>} - 是否成功
*/
async function sqliteSet(dbPath, key, value) {
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
return false;
}
try {
// 使用 REPLACE INTO 实现 upsert
const sql = `REPLACE INTO ItemTable (key, value) VALUES ('${escapeSqlString(key)}', '${escapeSqlString(value)}');`;
await execSqlite(dbPath, sql);
return true;
} catch (error) {
console.error('[SQLite] 写入失败:', error);
return false;
}
}
exports.sqliteSet = sqliteSet;
/**
* 批量写入 SQLite 数据库
* @param {string} dbPath - 数据库路径
* @param {Array<[string, string]>} kvPairs - 键值对数组
* @returns {Promise<boolean>} - 是否成功
*/
async function sqliteSetBatch(dbPath, kvPairs) {
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
return false;
}
if (kvPairs.length === 0) {
return true;
}
try {
// 构建批量 SQL 语句
const statements = kvPairs.map(([key, value]) =>
`REPLACE INTO ItemTable (key, value) VALUES ('${escapeSqlString(key)}', '${escapeSqlString(value)}');`
);
const sql = 'BEGIN TRANSACTION; ' + statements.join(' ') + ' COMMIT;';
await execSqlite(dbPath, sql);
return true;
} catch (error) {
console.error('[SQLite] 批量写入失败:', error);
return false;
}
}
exports.sqliteSetBatch = sqliteSetBatch;
/**
* 批量读取 SQLite 数据库
* @param {string} dbPath - 数据库路径
* @param {string[]} keys - 键名数组
* @returns {Promise<Map<string, string|null>>} - 键值 Map
*/
async function sqliteGetBatch(dbPath, keys) {
const resultMap = new Map();
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
keys.forEach(key => resultMap.set(key, null));
return resultMap;
}
try {
// 逐个读取 (SQLite CLI 批量读取输出解析较复杂)
for (const key of keys) {
const value = await sqliteGet(dbPath, key);
resultMap.set(key, value);
}
return resultMap;
} catch (error) {
console.error('[SQLite] 批量读取失败:', error);
keys.forEach(key => resultMap.set(key, null));
return resultMap;
}
}
exports.sqliteGetBatch = sqliteGetBatch;