cursor2api / src /utils /keyManager.js
github-actions[bot]
Update from GitHub Actions
b51f54a
raw
history blame
12.7 kB
const config = require('../config/config');
const fs = require('fs');
const path = require('path');
// 定义无效cookie的存储文件路径
const INVALID_COOKIES_FILE = path.join(__dirname, '../../data/invalid_cookies.json');
// 定义API Keys的存储文件路径
const API_KEYS_FILE = path.join(__dirname, '../../data/api_keys.json');
// 确保data目录存在
function ensureDataDirExists() {
const dataDir = path.join(__dirname, '../../data');
if (!fs.existsSync(dataDir)) {
try {
fs.mkdirSync(dataDir, { recursive: true });
console.log('创建data目录成功');
} catch (err) {
console.error('创建data目录失败:', err);
}
}
}
// 存储API key与Cursor cookie的映射关系
let apiKeyMap = new Map();
// 存储每个API key对应的cookie轮询索引
let rotationIndexes = new Map();
// 存储被标记为无效的cookie
let invalidCookies = new Set();
// 从文件加载无效cookie
function loadInvalidCookiesFromFile() {
ensureDataDirExists();
try {
if (fs.existsSync(INVALID_COOKIES_FILE)) {
const data = fs.readFileSync(INVALID_COOKIES_FILE, 'utf8');
const cookiesArray = JSON.parse(data);
// 清空当前集合并添加从文件加载的cookie
invalidCookies.clear();
cookiesArray.forEach(cookie => invalidCookies.add(cookie));
console.log(`从文件加载了 ${cookiesArray.length} 个无效cookie`);
} else {
saveInvalidCookiesToFile(); // 如果文件不存在,创建新文件
}
} catch (err) {
console.error('加载无效cookie文件失败:', err);
saveInvalidCookiesToFile(); // 如果加载失败,尝试创建新文件
}
}
// 将无效cookie保存到文件
function saveInvalidCookiesToFile() {
ensureDataDirExists();
try {
const cookiesArray = Array.from(invalidCookies);
fs.writeFileSync(INVALID_COOKIES_FILE, JSON.stringify(cookiesArray, null, 2), 'utf8');
console.log(`已将 ${cookiesArray.length} 个无效cookie保存到文件`);
} catch (err) {
console.error('保存无效cookie文件失败:', err);
}
}
// 从文件加载API Keys
function loadApiKeysFromFile() {
ensureDataDirExists();
try {
if (fs.existsSync(API_KEYS_FILE)) {
const data = fs.readFileSync(API_KEYS_FILE, 'utf8');
const apiKeysObj = JSON.parse(data);
// 清空现有映射
apiKeyMap.clear();
rotationIndexes.clear();
// 统计总cookie数量
let totalCookies = 0;
// 添加从文件加载的API Keys
for (const [apiKey, cookies] of Object.entries(apiKeysObj)) {
if (Array.isArray(cookies)) {
apiKeyMap.set(apiKey, cookies);
rotationIndexes.set(apiKey, 0);
totalCookies += cookies.length;
} else {
console.error(`API Key ${apiKey} 的cookies不是数组,跳过`);
}
}
const apiKeyCount = Object.keys(apiKeysObj).length;
console.log(`从文件加载了 ${apiKeyCount} 个API Key,共 ${totalCookies} 个Cookie`);
return apiKeyCount > 0;
} else {
console.log('API Keys文件不存在,将使用配置中的API Keys');
return false;
}
} catch (err) {
console.error('加载API Keys文件失败:', err);
return false;
}
}
// 将API Keys保存到文件
function saveApiKeysToFile() {
ensureDataDirExists();
try {
// 将Map转换为普通对象
const apiKeysObj = {};
for (const [apiKey, cookies] of apiKeyMap.entries()) {
apiKeysObj[apiKey] = cookies;
}
// 使用JSON.stringify时避免特殊字符处理问题
const jsonString = JSON.stringify(apiKeysObj, null, 2);
fs.writeFileSync(API_KEYS_FILE, jsonString, 'utf8');
console.log(`已将 ${Object.keys(apiKeysObj).length} 个API Key保存到文件`);
// 简化验证过程
try {
const savedContent = fs.readFileSync(API_KEYS_FILE, 'utf8');
JSON.parse(savedContent); // 只验证JSON格式是否正确
console.log('验证通过: 所有cookie都被完整保存');
} catch (verifyErr) {
console.error('验证保存内容时出错:', verifyErr);
}
} catch (err) {
console.error('保存API Keys文件失败:', err);
}
}
// API Keys初始化函数
function initializeApiKeys() {
// 首先从文件加载现有的API Keys
const loadedFromFile = loadApiKeysFromFile();
// 检查环境变量中是否有API Keys配置
const configApiKeys = config.apiKeys;
const hasEnvApiKeys = Object.keys(configApiKeys).length > 0;
if (hasEnvApiKeys) {
console.log('从环境变量检测到API Keys配置,将合并到现有配置...');
// 记录合并前的Cookie数量
let beforeMergeCookies = 0;
for (const cookies of apiKeyMap.values()) {
beforeMergeCookies += cookies.length;
}
// 合并环境变量中的API Keys到现有映射
for (const [apiKey, cookieValue] of Object.entries(configApiKeys)) {
// 获取现有的cookies(如果有)
const existingCookies = apiKeyMap.get(apiKey) || [];
// 准备要添加的新cookies
let newCookies = [];
if (typeof cookieValue === 'string') {
newCookies = [cookieValue];
} else if (Array.isArray(cookieValue)) {
newCookies = cookieValue;
}
// 合并cookies,确保不重复
const mergedCookies = [...existingCookies];
for (const cookie of newCookies) {
if (!mergedCookies.includes(cookie)) {
mergedCookies.push(cookie);
}
}
// 更新映射
apiKeyMap.set(apiKey, mergedCookies);
// 确保轮询索引存在
if (!rotationIndexes.has(apiKey)) {
rotationIndexes.set(apiKey, 0);
}
}
// 记录合并后的Cookie数量
let afterMergeCookies = 0;
for (const cookies of apiKeyMap.values()) {
afterMergeCookies += cookies.length;
}
console.log(`合并前共有 ${beforeMergeCookies} 个Cookie,合并后共有 ${afterMergeCookies} 个Cookie`);
// 保存合并后的结果到文件
saveApiKeysToFile();
} else if (!loadedFromFile) {
console.log('警告: 未能从文件加载API Keys,且环境变量中也没有配置API Keys');
}
// 统计API Keys和Cookies数量
let totalCookies = 0;
for (const cookies of apiKeyMap.values()) {
totalCookies += cookies.length;
}
console.log(`API Keys初始化完成,共有 ${apiKeyMap.size} 个API Key,${totalCookies} 个Cookie`);
// 加载无效cookie
loadInvalidCookiesFromFile();
// 从API Key中移除已知的无效cookie
console.log('开始从API Keys中移除无效cookie...');
removeInvalidCookiesFromApiKeys();
}
// 从所有API Key中移除已知的无效cookie
function removeInvalidCookiesFromApiKeys() {
let totalRemoved = 0;
for (const [apiKey, cookies] of apiKeyMap.entries()) {
const initialLength = cookies.length;
// 过滤掉无效的cookie
const filteredCookies = cookies.filter(cookie => !invalidCookies.has(cookie));
// 如果有cookie被移除,更新API Key的cookie列表
if (filteredCookies.length < initialLength) {
const removedCount = initialLength - filteredCookies.length;
totalRemoved += removedCount;
apiKeyMap.set(apiKey, filteredCookies);
rotationIndexes.set(apiKey, 0);
console.log(`从API Key ${apiKey} 中移除了 ${removedCount} 个无效cookie,剩余 ${filteredCookies.length} 个`);
}
}
console.log(`总共从API Keys中移除了 ${totalRemoved} 个无效cookie`);
// 如果有cookie被移除,保存更新后的API Keys
if (totalRemoved > 0) {
saveApiKeysToFile();
}
}
// 添加或更新API key映射
function addOrUpdateApiKey(apiKey, cookieValues) {
if (!Array.isArray(cookieValues)) {
cookieValues = [cookieValues];
}
// 过滤掉已知的无效cookie
const validCookies = cookieValues.filter(cookie => !invalidCookies.has(cookie));
if (validCookies.length < cookieValues.length) {
console.log(`API Key ${apiKey} 中有 ${cookieValues.length - validCookies.length} 个无效cookie被过滤`);
}
apiKeyMap.set(apiKey, validCookies);
rotationIndexes.set(apiKey, 0);
// 保存更新后的API Keys
saveApiKeysToFile();
}
// 删除API key映射
function removeApiKey(apiKey) {
apiKeyMap.delete(apiKey);
rotationIndexes.delete(apiKey);
// 保存更新后的API Keys
saveApiKeysToFile();
}
// 获取API key对应的cookie值(根据轮询策略)
function getCookieForApiKey(apiKey, strategy = config.defaultRotationStrategy) {
// 如果API key不存在,也许是cookie本身,直接返回API key本身(向后兼容)
if (!apiKeyMap.has(apiKey)) {
return apiKey;
}
const cookies = apiKeyMap.get(apiKey);
if (!cookies || cookies.length === 0) {
return apiKey;
}
if (cookies.length === 1) {
return cookies[0];
}
// 根据策略选择cookie
if (strategy === 'random') {
// 随机策略
const randomIndex = Math.floor(Math.random() * cookies.length);
return cookies[randomIndex];
} else {
// 轮询策略(round-robin)
let currentIndex = rotationIndexes.get(apiKey) || 0;
const cookie = cookies[currentIndex];
// 更新索引
currentIndex = (currentIndex + 1) % cookies.length;
rotationIndexes.set(apiKey, currentIndex);
return cookie;
}
}
// 获取所有API key
function getAllApiKeys() {
return Array.from(apiKeyMap.keys());
}
// 获取API key对应的所有cookie
function getAllCookiesForApiKey(apiKey) {
return apiKeyMap.get(apiKey) || [];
}
// 从API key的cookie列表中移除特定cookie
function removeCookieFromApiKey(apiKey, cookieToRemove) {
if (!apiKeyMap.has(apiKey)) {
console.log(`API Key ${apiKey} 不存在,无法移除cookie`);
return false;
}
const cookies = apiKeyMap.get(apiKey);
const initialLength = cookies.length;
// 检查是否尝试移除与API Key相同的值(可能是向后兼容模式)
if (cookieToRemove === apiKey && initialLength === 0) {
console.log(`API Key ${apiKey} 中没有任何cookie,系统正在尝试以向后兼容模式使用API Key本身`);
return false;
}
// 过滤掉要移除的cookie
const filteredCookies = cookies.filter(cookie => cookie !== cookieToRemove);
// 如果长度没变,说明没有找到要移除的cookie
if (filteredCookies.length === initialLength) {
console.log(`未找到要移除的cookie: ${cookieToRemove}`);
return false;
}
// 更新cookie列表
apiKeyMap.set(apiKey, filteredCookies);
// 重置轮询索引
rotationIndexes.set(apiKey, 0);
// 将移除的cookie添加到无效cookie集合中
invalidCookies.add(cookieToRemove);
// 保存无效cookie到文件
saveInvalidCookiesToFile();
// 保存更新后的API Keys
saveApiKeysToFile();
console.log(`已从API Key ${apiKey} 中移除cookie: ${cookieToRemove}`);
console.log(`剩余cookie数量: ${filteredCookies.length}`);
return true;
}
// 获取所有被标记为无效的cookie
function getInvalidCookies() {
return invalidCookies;
}
// 清除特定的无效cookie记录
function clearInvalidCookie(cookie) {
const result = invalidCookies.delete(cookie);
if (result) {
// 保存更新后的无效cookie到文件
saveInvalidCookiesToFile();
}
return result;
}
// 清除所有无效cookie记录
function clearAllInvalidCookies() {
invalidCookies.clear();
// 保存更新后的无效cookie到文件
saveInvalidCookiesToFile();
return true;
}
module.exports = {
addOrUpdateApiKey,
removeApiKey,
getCookieForApiKey,
getAllApiKeys,
getAllCookiesForApiKey,
initializeApiKeys,
removeCookieFromApiKey,
getInvalidCookies,
clearInvalidCookie,
clearAllInvalidCookies,
loadInvalidCookiesFromFile,
saveInvalidCookiesToFile,
loadApiKeysFromFile,
saveApiKeysToFile
};