github-actions[bot] commited on
Commit
0d3f8ee
·
1 Parent(s): ed5e4c4

Update from GitHub Actions

Browse files
.cnb.yml CHANGED
@@ -16,4 +16,3 @@ main:
16
  private_key: $SERVER_PRIVATE_KEY
17
  inventory: hosts
18
  playbook: playbook.yml
19
-
 
16
  private_key: $SERVER_PRIVATE_KEY
17
  inventory: hosts
18
  playbook: playbook.yml
 
.env.example CHANGED
@@ -1,22 +1,28 @@
1
  # 服务端口
2
  PORT=3010
3
 
4
- # 日志格式 (tiny, combined, common, dev, short)
 
 
 
 
 
 
5
  MORGAN_FORMAT=tiny
6
 
7
  # API Key与Cookie映射关系 (JSON格式)
8
  # 格式: {"自定义API Key": "Cookie值"} 或 {"自定义API Key": ["Cookie值1", "Cookie值2"]}
9
  API_KEYS={"sk-cursor-123":"user_xxxxxxx","sk-cursor-456":["user_yyyyyyy","user_zzzzzzz"]}
10
 
11
- # 轮询策略 (random 或 round-robin)
12
- ROTATION_STRATEGY=round-robin
13
 
14
  # Cursor校验和 (可选)
15
  # x-cursor-checksum=xxxxxxxx
16
 
17
  # 自动刷新Cookie设置
18
  # 是否启用自动刷新Cookie (true 或 false)
19
- ENABLE_AUTO_REFRESH=true
20
 
21
  # 自动刷新Cookie的定时规则 (Cron表达式)
22
  # 默认每6小时执行一次
@@ -62,4 +68,28 @@ REGISTER_UPLOAD_ARTIFACT=true
62
  REGISTER_USE_CONFIG_FILE=false
63
  # 邮箱配置JSON字符串(仅在REGISTER_USE_CONFIG_FILE=false时有效)
64
  # 格式例如[{"email":"[email protected]","imap_server":"imap.gmail.com","imap_port":993,"username":"[email protected]","password":"your_app_password"}]
65
- REGISTER_EMAIL_CONFIGS=[]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # 服务端口
2
  PORT=3010
3
 
4
+ # HTTP请求日志格式
5
+ # 选项: tiny, combined, common, dev, short
6
+ # tiny: 最简洁的格式,包含方法、URL、状态码、响应时间
7
+ # combined: 标准的Apache组合日志格式,包含IP、时间、请求、状态码、响应大小、referrer、user-agent
8
+ # common: 标准的Apache通用日志格式,类似combined但不包含referrer和user-agent
9
+ # dev: 开发友好的彩色格式,包含方法、URL、状态码(带颜色)、响应时间
10
+ # short: 更短的格式,包含方法、URL、状态码、响应时间、响应大小
11
  MORGAN_FORMAT=tiny
12
 
13
  # API Key与Cookie映射关系 (JSON格式)
14
  # 格式: {"自定义API Key": "Cookie值"} 或 {"自定义API Key": ["Cookie值1", "Cookie值2"]}
15
  API_KEYS={"sk-cursor-123":"user_xxxxxxx","sk-cursor-456":["user_yyyyyyy","user_zzzzzzz"]}
16
 
17
+ # 轮询策略 (random 或 round-robin 或 default)
18
+ ROTATION_STRATEGY=default
19
 
20
  # Cursor校验和 (可选)
21
  # x-cursor-checksum=xxxxxxxx
22
 
23
  # 自动刷新Cookie设置
24
  # 是否启用自动刷新Cookie (true 或 false)
25
+ ENABLE_AUTO_REFRESH=false
26
 
27
  # 自动刷新Cookie的定时规则 (Cron表达式)
28
  # 默认每6小时执行一次
 
68
  REGISTER_USE_CONFIG_FILE=false
69
  # 邮箱配置JSON字符串(仅在REGISTER_USE_CONFIG_FILE=false时有效)
70
  # 格式例如[{"email":"[email protected]","imap_server":"imap.gmail.com","imap_port":993,"username":"[email protected]","password":"your_app_password"}]
71
+ REGISTER_EMAIL_CONFIGS=[]
72
+
73
+ # 日志系统配置
74
+ LOG_LEVEL=INFO # ERROR, WARN, INFO, DEBUG, TRACE
75
+ LOG_FORMAT=colored # colored, json, text
76
+ LOG_TO_FILE=false
77
+ LOG_MAX_SIZE=10 # 单位MB
78
+ LOG_MAX_FILES=10 # 保留的历史日志文件数量
79
+
80
+ # 代理服务器配置
81
+ # 是否使用TLS代理服务器 (true 或 false)
82
+ USE_TLS_PROXY=true
83
+ # 是否使用其它接口代理服务器 (true 或 false)
84
+ USE_OTHERS_PROXY=true
85
+
86
+ # 代理服务器平台
87
+ # 可选值: auto, windows_x64, linux_x64, android_arm64
88
+ # auto: 自动检测平台
89
+ # windows_x64: Windows 64位
90
+ # linux_x64: Linux 64位
91
+ # android_arm64: 安卓ARM 64位
92
+ PROXY_PLATFORM=auto
93
+
94
+ # 是否使用其它接口 (true 或 false)
95
+ USE_OTHERS=true
.gitattributes CHANGED
@@ -35,3 +35,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.png filter=lfs diff=lfs merge=lfs -text
37
  *.webp filter=lfs diff=lfs merge=lfs -text
 
 
 
 
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.png filter=lfs diff=lfs merge=lfs -text
37
  *.webp filter=lfs diff=lfs merge=lfs -text
38
+ *_arm64 filter=lfs diff=lfs merge=lfs -text
39
+ *_amd64 filter=lfs diff=lfs merge=lfs -text
40
+ *_amd64.exe filter=lfs diff=lfs merge=lfs -text
Dockerfile CHANGED
@@ -1,26 +1,13 @@
1
  FROM node:lts-alpine
2
 
3
- # 创建应用目录并设置工作目录
4
  WORKDIR /app
5
 
6
- # 复制依赖文件
7
  COPY package.json package-lock.json ./
8
 
9
- # 安装依赖
10
  RUN npm install
11
 
12
- # 复制应用代码
13
  COPY . /app
14
 
15
- # 创建数据目录并设置权限
16
- RUN mkdir -p /app/data && \
17
- chown -R node:node /app
18
 
19
- # 使用非root用户运行应用
20
- USER node
21
-
22
- # 暴露端口
23
- EXPOSE 7860
24
-
25
- # 启动应用
26
  CMD ["npm", "run", "start"]
 
1
  FROM node:lts-alpine
2
 
 
3
  WORKDIR /app
4
 
 
5
  COPY package.json package-lock.json ./
6
 
 
7
  RUN npm install
8
 
 
9
  COPY . /app
10
 
11
+ EXPOSE 3010
 
 
12
 
 
 
 
 
 
 
 
13
  CMD ["npm", "run", "start"]
README.en.md ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cursor-To-OpenAI-Nexus
2
+
3
+ [中文](README.md) | English
4
+
5
+ Forward Cursor API requests to OpenAI, with support for multiple API Keys rotation.
6
+
7
+ ## Features
8
+
9
+ - 🔑 **Multiple Keys Rotation**: Configure multiple API Keys rotation to improve availability
10
+ - 🚀 **Easy Configuration**: One-click configuration script for quick setup
11
+ - 📊 **Status Monitoring**: Monitor API Key usage status
12
+ - 🔧 **Easy Maintenance**: Convenient maintenance scripts to simplify daily operations
13
+
14
+ ## 🚀 Basic Installation
15
+ ### Clone Repository
16
+ ```
17
+ git clone https://github.com/liuw1535/cursor-to-openai-nexus.git
18
+ ```
19
+ ### Enter Project Directory
20
+ ```
21
+ cd cursor-to-openai-nexus
22
+ ```
23
+ ### Install Dependencies
24
+ ```
25
+ npm install
26
+ ```
27
+
28
+ ## ⚙️ Configure Project
29
+ ```
30
+ npm run setup
31
+ ```
32
+ - Just fill in the custom key and whether to enable TLS proxy server
33
+ - Other options can be skipped by pressing Enter or filled in randomly
34
+ - 🛡️ If you frequently encounter account blocking issues, it's recommended to enable TLS server
35
+ - If you're not satisfied with the configuration, you can re-run this command to modify it
36
+
37
+ ## 🏃 Start Service
38
+ ```
39
+ npm start
40
+ ```
41
+
42
+ ## 🔍 Usage
43
+ 1. Access the management interface: `http://127.0.0.1:3010`
44
+ 2. Use the blue button at the bottom of the page to get cookies
45
+ 3. Configure in the Tavern page:
46
+ - API address: `http://127.0.0.1:3010/v1`
47
+ - Key: `sk-text` (if "text" was entered during configuration)
48
+
49
+ ## 📧 Account Registration Recommendations
50
+ - Recommended to use domain email (subdomain email is better)
51
+ - Search for "cloudfare domain email" for configuration tutorials
52
+ - ⚠️ Register no more than 2 accounts at a time to avoid being blocked
53
+
54
+ ## 🛠️ Common Commands
55
+ ```
56
+ npm start # Start project
57
+ npm run setup # Modify configuration
58
+ ```
59
+
60
+ ## Environment Configuration
61
+
62
+ Configure the following key parameters in the `.env` file:
63
+
64
+ - `API_KEYS`: Mapping relationship between API Key and Cookie (JSON format)
65
+ - `USE_TLS_PROXY`: (true) Enable TLS server, which can avoid request blocking issues
66
+ - `PROXY_PLATFORM`: The platform corresponding to the TLS server when enabled, default is auto detection
67
+
68
+ The system will automatically merge API Keys from `.env` and `data/api_keys.json` at startup to ensure data consistency.
69
+
70
+ ## Deployment Method
71
+
72
+ ### Using Docker Compose
73
+
74
+ ```bash
75
+ # Create configuration files
76
+ cp .env.example .env
77
+ mkdir -p data
78
+ cp data/admin.example.json data/admin.json
79
+
80
+ # Create admin account
81
+ node scripts/create-admin.js
82
+
83
+ # Start service
84
+ docker compose up -d --build
85
+
86
+ # View logs
87
+ docker compose logs -f
88
+
89
+ # Stop service
90
+ docker compose down
91
+ ```
92
+
93
+ ## API Usage Example
94
+
95
+ ### Python Example
96
+
97
+ ```python
98
+ from openai import OpenAI
99
+
100
+ # Use custom API Key
101
+ client = OpenAI(api_key="your_custom_api_key",
102
+ base_url="http://localhost:3010/v1")
103
+
104
+ # Or use Cookie directly
105
+ # client = OpenAI(api_key="user_...",
106
+ # base_url="http://localhost:3010/v1")
107
+
108
+ response = client.chat.completions.create(
109
+ model="claude-3-7-sonnet",
110
+ messages=[
111
+ {"role": "user", "content": "Hello."},
112
+ ],
113
+ stream=False
114
+ )
115
+
116
+ print(response.choices)
117
+ ```
118
+
119
+ ## Notes
120
+
121
+ - Please keep your WorkosCursorSessionToken secure
122
+ - This project is for learning and research purposes only, please comply with Cursor's terms of use
123
+
124
+ ## Acknowledgements
125
+
126
+ - This project is based on [cursor-api](https://github.com/zhx47/cursor-api) (by zhx47)
127
+ - Integrated content from [cursor-api](https://github.com/lvguanjun/cursor-api) (by lvguanjun)
128
+
129
+ # Logging System
130
+
131
+ The project integrates a unified logging system, which can be configured through the following methods:
132
+
133
+ ## Log Level Configuration
134
+
135
+ 1. Set environment variables in the `.env` file
136
+ ```
137
+ LOG_LEVEL=INFO
138
+ LOG_FORMAT=colored
139
+ LOG_TO_FILE=true
140
+ LOG_MAX_SIZE=10
141
+ LOG_MAX_FILES=10
142
+ ```
143
+ 2. Specify environment variables in the startup command, for example: `LOG_LEVEL=DEBUG npm start`
144
+
145
+ Supported log levels include:
146
+ - ERROR: Only display error messages
147
+ - WARN: Display warning and error messages
148
+ - INFO: Display general information, warnings, and error messages (default)
149
+ - DEBUG: Display debug information, general information, warnings, and error messages
150
+ - TRACE: Display all log information
151
+
152
+ ## Log Format
153
+
154
+ The log format is: `[LEVEL] timestamp log content`, with different levels displayed in different colors for easy differentiation:
155
+ - ERROR: Red
156
+ - WARN: Yellow
157
+ - INFO: Green
158
+ - DEBUG: Blue
159
+ - TRACE: Cyan
160
+ - HTTP: Cyan (dedicated to HTTP request logs)
161
+
162
+ ## HTTP Request Logs
163
+
164
+ The project uses the Morgan middleware to record HTTP requests, integrated into the unified logging system:
165
+
166
+ 1. Set HTTP log format in the `.env` file:
167
+ ```
168
+ # Options: tiny, combined, common, dev, short
169
+ MORGAN_FORMAT=tiny
170
+ ```
171
+
172
+ 2. HTTP logs will be displayed with the `[HTTP]` prefix, highlighted in cyan for easy identification
173
+
174
+ 3. Morgan format options explanation:
175
+ - `tiny`: The most concise format, including only method, URL, status code, response time
176
+ - `combined`: Standard Apache combined log format, including IP, time, request, status code, response size, referrer, user-agent
177
+ - `common`: Standard Apache common log format, similar to combined but without referrer and user-agent
178
+ - `dev`: Developer-friendly colored format, including method, URL, status code (with color), response time
179
+ - `short`: Shorter format, including method, URL, status code, response time, response size
180
+
181
+ ## File Logs
182
+
183
+ The project supports outputting logs to both console and files, which can be enabled with the following configuration:
184
+
185
+ 1. Set in the `.env` file: `LOG_TO_FILE=true`
186
+ 2. Optional configuration:
187
+ - `LOG_MAX_SIZE`: Maximum size of log file, in MB, default 10MB
188
+ - `LOG_MAX_FILES`: Number of historical log files to keep, default 10
189
+
190
+ Log files are stored in the `logs` folder in the project root directory:
191
+ - Current log file: `app.log`
192
+ - Historical log file: `app-2023-05-05T12-45-30-000Z.log`
193
+
194
+ File logs will automatically rotate, creating a new log file when the log file size exceeds the set value and keeping the most recent N files.
195
+
196
+ ## Usage in Code
197
+
198
+ Different log levels can be used as needed in the code:
199
+
200
+ ```javascript
201
+ const logger = require('./utils/logger');
202
+
203
+ logger.error('This is an error message');
204
+ logger.warn('This is a warning message');
205
+ logger.info('This is a general information message');
206
+ logger.debug('This is a debug message');
207
+ logger.trace('This is a trace message');
208
+ logger.http('This is an HTTP request log');
209
+ ```
auto-refresh-cookies.js CHANGED
@@ -1,16 +1,22 @@
1
  // 加载环境变量
2
  require('dotenv').config();
3
 
 
 
 
 
 
 
 
4
  // 环境检查
5
  const envChecker = require('./src/utils/envChecker');
6
- console.log('启动前检查环境配置...');
7
  envChecker.enforceEnvCheck();
8
 
9
  // 已适配GitHub Actions工作流新参数 (use_config_file, email_configs)
10
- console.log('环境检查通过,已适配最新GitHub Actions工作流参数');
11
 
12
  const cookieRefresher = require('./src/utils/cookieRefresher');
13
- const keyManager = require('./src/utils/keyManager');
14
  const config = require('./src/config/config');
15
 
16
  // 解析命令行参数
@@ -19,23 +25,23 @@ const targetApiKey = args.length > 0 ? args[0] : null;
19
  const forceRefresh = args.includes('--force') || args.includes('-f');
20
 
21
  // 最小 Cookie 数量
22
- const MIN_COOKIE_COUNT = config.refresh.minCookieCount;
23
 
24
  // 获取Cookie刷新模式
25
  const COOKIE_REFRESH_MODE = process.env.COOKIE_REFRESH_MODE || 'append';
26
 
27
  // 主函数
28
  async function main() {
29
- console.log('===== 自动刷新 Cookie 开始 =====');
30
- console.log(`最小 Cookie 数量: ${MIN_COOKIE_COUNT}`);
31
- console.log(`Cookie 刷新模式: ${COOKIE_REFRESH_MODE} (${COOKIE_REFRESH_MODE === 'replace' ? '替换现有cookie' : '追加新cookie'})`);
32
 
33
  if (targetApiKey) {
34
- console.log(`指定刷新 API Key: ${targetApiKey}`);
35
  }
36
 
37
  if (forceRefresh) {
38
- console.log('强制刷新模式: 忽略 Cookie 数量检查');
39
  }
40
 
41
  try {
@@ -43,13 +49,13 @@ async function main() {
43
  const apiKeys = keyManager.getAllApiKeys();
44
 
45
  if (apiKeys.length === 0) {
46
- console.log('警告: 系统中没有找到任何 API Key');
47
 
48
  // 检查环境变量中是否有 API Keys
49
  const envApiKeys = Object.keys(config.apiKeys);
50
  if (envApiKeys.length > 0) {
51
- console.log(`检测到环境变量中有 ${envApiKeys.length} 个 API Key,但尚未加载到系统中`);
52
- console.log('正在重新初始化 API Keys...');
53
 
54
  // 重新初始化 API Keys
55
  keyManager.initializeApiKeys();
@@ -57,28 +63,28 @@ async function main() {
57
  // 重新获取 API Keys
58
  const refreshedApiKeys = keyManager.getAllApiKeys();
59
  if (refreshedApiKeys.length > 0) {
60
- console.log(`成功加载 ${refreshedApiKeys.length} 个 API Key,继续刷新流程`);
61
  // 继续执行后续刷新逻辑
62
  } else {
63
- console.log('初始化后仍未找到 API Key,请检查配置');
64
- console.log('===== 自动刷新 Cookie 结束 =====');
65
  return;
66
  }
67
  } else {
68
- console.log('环境变量中也没有配置 API Key,请先添加 API Key');
69
- console.log('===== 自动刷新 Cookie 结束 =====');
70
  return;
71
  }
72
  }
73
 
74
  // 重新获取最新的 API Keys(可能已经通过上面的初始化更新了)
75
  const updatedApiKeys = keyManager.getAllApiKeys();
76
- console.log(`系统中共有 ${updatedApiKeys.length} 个 API Key`);
77
 
78
  // 如果指定了特定的 API Key,检查它是否存在
79
  if (targetApiKey && !updatedApiKeys.includes(targetApiKey)) {
80
- console.error(`错误: 指定的 API Key "${targetApiKey}" 不存在`);
81
- console.log('===== 自动刷新 Cookie 异常结束 =====');
82
  return;
83
  }
84
 
@@ -98,46 +104,46 @@ async function main() {
98
 
99
  for (const apiKey of sortedKeys) {
100
  const cookies = keyManager.getAllCookiesForApiKey(apiKey);
101
- console.log(`API Key: ${apiKey}, Cookie 数量: ${cookies.length}`);
102
 
103
  // 判断是否需要刷新:强制刷新模式或 Cookie 数量低于阈值
104
  if (forceRefresh || cookies.length < MIN_COOKIE_COUNT) {
105
  needRefreshCount++;
106
  if (forceRefresh) {
107
- console.log(`强制刷新 API Key: ${apiKey}`);
108
  } else {
109
- console.log(`API Key ${apiKey} 的 Cookie 数量不足,需要刷新`);
110
  }
111
 
112
  // 执行刷新
113
- console.log(`开始自动刷新 Cookie,目标 API Key: ${apiKey},最小 Cookie 数量: ${MIN_COOKIE_COUNT},刷新模式: ${COOKIE_REFRESH_MODE}`);
114
  const result = await cookieRefresher.autoRefreshCookies(apiKey, MIN_COOKIE_COUNT);
115
 
116
  if (result.success) {
117
  refreshedCount++;
118
- console.log(`刷新结果: ${result.message}`);
119
 
120
  // 根据刷新模式输出额外的信息
121
  if (COOKIE_REFRESH_MODE === 'replace') {
122
- console.log(`使用替换模式: 现有cookie已全部标记为无效,系统现在只使用新cookie`);
123
  } else {
124
- console.log(`使用追加模式: 现有cookie已保留,新cookie已添加到系统`);
125
  }
126
  } else {
127
- console.error(`刷新失败: ${result.message}`);
128
  }
129
  } else {
130
- console.log(`API Key ${apiKey} 的 Cookie 数量足够,不需要刷新`);
131
  }
132
  }
133
 
134
- console.log('===== 自动刷新 Cookie 完成 =====');
135
- console.log(`共有 ${needRefreshCount} 个 API Key 需要刷新,成功刷新 ${refreshedCount} 个`);
136
  } catch (error) {
137
- console.error('自动刷新 Cookie 失败:', error);
138
- console.log('===== 自动刷新 Cookie 异常结束 =====');
139
  }
140
  }
141
 
142
  // 执行主函数
143
- main().catch(console.error);
 
1
  // 加载环境变量
2
  require('dotenv').config();
3
 
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const axios = require('axios');
7
+ const { spawn } = require('child_process');
8
+ const keyManager = require('./src/utils/keyManager');
9
+ const logger = require('./src/utils/logger');
10
+
11
  // 环境检查
12
  const envChecker = require('./src/utils/envChecker');
13
+ logger.info('启动前检查环境配置...');
14
  envChecker.enforceEnvCheck();
15
 
16
  // 已适配GitHub Actions工作流新参数 (use_config_file, email_configs)
17
+ logger.info('环境检查通过,已适配最新GitHub Actions工作流参数');
18
 
19
  const cookieRefresher = require('./src/utils/cookieRefresher');
 
20
  const config = require('./src/config/config');
21
 
22
  // 解析命令行参数
 
25
  const forceRefresh = args.includes('--force') || args.includes('-f');
26
 
27
  // 最小 Cookie 数量
28
+ const MIN_COOKIE_COUNT = process.env.MIN_COOKIE_COUNT || 3;
29
 
30
  // 获取Cookie刷新模式
31
  const COOKIE_REFRESH_MODE = process.env.COOKIE_REFRESH_MODE || 'append';
32
 
33
  // 主函数
34
  async function main() {
35
+ logger.info('===== 自动刷新 Cookie 开始 =====');
36
+ logger.info(`最小 Cookie 数量: ${MIN_COOKIE_COUNT}`);
37
+ logger.info(`Cookie 刷新模式: ${COOKIE_REFRESH_MODE} (${COOKIE_REFRESH_MODE === 'replace' ? '替换现有cookie' : '追加新cookie'})`);
38
 
39
  if (targetApiKey) {
40
+ logger.info(`指定刷新 API Key: ${targetApiKey}`);
41
  }
42
 
43
  if (forceRefresh) {
44
+ logger.info('强制刷新模式: 忽略 Cookie 数量检查');
45
  }
46
 
47
  try {
 
49
  const apiKeys = keyManager.getAllApiKeys();
50
 
51
  if (apiKeys.length === 0) {
52
+ logger.warn('警告: 系统中没有找到任何 API Key');
53
 
54
  // 检查环境变量中是否有 API Keys
55
  const envApiKeys = Object.keys(config.apiKeys);
56
  if (envApiKeys.length > 0) {
57
+ logger.info(`检测到环境变量中有 ${envApiKeys.length} 个 API Key,但尚未加载到系统中`);
58
+ logger.info('正在重新初始化 API Keys...');
59
 
60
  // 重新初始化 API Keys
61
  keyManager.initializeApiKeys();
 
63
  // 重新获取 API Keys
64
  const refreshedApiKeys = keyManager.getAllApiKeys();
65
  if (refreshedApiKeys.length > 0) {
66
+ logger.info(`成功加载 ${refreshedApiKeys.length} 个 API Key,继续刷新流程`);
67
  // 继续执行后续刷新逻辑
68
  } else {
69
+ logger.warn('初始化后仍未找到 API Key,请检查配置');
70
+ logger.info('===== 自动刷新 Cookie 结束 =====');
71
  return;
72
  }
73
  } else {
74
+ logger.warn('环境变量中也没有配置 API Key,请先添加 API Key');
75
+ logger.info('===== 自动刷新 Cookie 结束 =====');
76
  return;
77
  }
78
  }
79
 
80
  // 重新获取最新的 API Keys(可能已经通过上面的初始化更新了)
81
  const updatedApiKeys = keyManager.getAllApiKeys();
82
+ logger.info(`系统中共有 ${updatedApiKeys.length} 个 API Key`);
83
 
84
  // 如果指定了特定的 API Key,检查它是否存在
85
  if (targetApiKey && !updatedApiKeys.includes(targetApiKey)) {
86
+ logger.error(`错误: 指定的 API Key "${targetApiKey}" 不存在`);
87
+ logger.info('===== 自动刷新 Cookie 异常结束 =====');
88
  return;
89
  }
90
 
 
104
 
105
  for (const apiKey of sortedKeys) {
106
  const cookies = keyManager.getAllCookiesForApiKey(apiKey);
107
+ logger.info(`API Key: ${apiKey}, Cookie 数量: ${cookies.length}`);
108
 
109
  // 判断是否需要刷新:强制刷新模式或 Cookie 数量低于阈值
110
  if (forceRefresh || cookies.length < MIN_COOKIE_COUNT) {
111
  needRefreshCount++;
112
  if (forceRefresh) {
113
+ logger.info(`强制刷新 API Key: ${apiKey}`);
114
  } else {
115
+ logger.info(`API Key ${apiKey} 的 Cookie 数量不足,需要刷新`);
116
  }
117
 
118
  // 执行刷新
119
+ logger.info(`开始自动刷新 Cookie,目标 API Key: ${apiKey},最小 Cookie 数量: ${MIN_COOKIE_COUNT},刷新模式: ${COOKIE_REFRESH_MODE}`);
120
  const result = await cookieRefresher.autoRefreshCookies(apiKey, MIN_COOKIE_COUNT);
121
 
122
  if (result.success) {
123
  refreshedCount++;
124
+ logger.info(`刷新结果: ${result.message}`);
125
 
126
  // 根据刷新模式输出额外的信息
127
  if (COOKIE_REFRESH_MODE === 'replace') {
128
+ logger.info(`使用替换模式: 现有cookie已全部标记为无效,系统现在只使用新cookie`);
129
  } else {
130
+ logger.info(`使用追加模式: 现有cookie已保留,新cookie已添加到系统`);
131
  }
132
  } else {
133
+ logger.error(`刷新失败: ${result.message}`);
134
  }
135
  } else {
136
+ logger.info(`API Key ${apiKey} 的 Cookie 数量足够,不需要刷新`);
137
  }
138
  }
139
 
140
+ logger.info('===== 自动刷新 Cookie 完成 =====');
141
+ logger.info(`共有 ${needRefreshCount} 个 API Key 需要刷新,成功刷新 ${refreshedCount} 个`);
142
  } catch (error) {
143
+ logger.error('自动刷新 Cookie 失败:', error);
144
+ logger.info('===== 自动刷新 Cookie 异常结束 =====');
145
  }
146
  }
147
 
148
  // 执行主函数
149
+ main().catch(err => logger.error(err));
hosts CHANGED
@@ -3,4 +3,4 @@
3
  [hostgroup]
4
  # 这里填写部署主机的ip
5
  8.130.88.130
6
- 8.130.132.23
 
3
  [hostgroup]
4
  # 这里填写部署主机的ip
5
  8.130.88.130
6
+ 8.130.132.23
manage-invalid-cookies.js CHANGED
@@ -5,6 +5,7 @@ const fs = require('fs');
5
  const path = require('path');
6
  const readline = require('readline');
7
  const keyManager = require('./src/utils/keyManager');
 
8
 
9
  // 创建命令行交互界面
10
  const rl = readline.createInterface({
@@ -12,16 +13,19 @@ const rl = readline.createInterface({
12
  output: process.stdout
13
  });
14
 
 
 
 
15
  // 显示菜单
16
  function showMenu() {
17
- console.log('\n===== 无效Cookie管理工具 =====');
18
- console.log('1. 查看所有无效Cookie');
19
- console.log('2. 添加无效Cookie');
20
- console.log('3. 删除特定无效Cookie');
21
- console.log('4. 清空所有无效Cookie');
22
- console.log('5. 从API Keys中移除所有无效Cookie');
23
- console.log('6. 退出');
24
- console.log('============================');
25
 
26
  rl.question('请选择操作 (1-6): ', (answer) => {
27
  switch(answer) {
@@ -41,11 +45,11 @@ function showMenu() {
41
  removeInvalidCookiesFromApiKeys();
42
  break;
43
  case '6':
44
- console.log('退出程序');
45
  rl.close();
46
  break;
47
  default:
48
- console.log('无效的选择,请重新输入');
49
  showMenu();
50
  break;
51
  }
@@ -56,12 +60,12 @@ function showMenu() {
56
  function listInvalidCookies() {
57
  const invalidCookies = Array.from(keyManager.getInvalidCookies());
58
 
59
- console.log('\n===== 所有无效Cookie =====');
60
  if (invalidCookies.length === 0) {
61
- console.log('没有无效Cookie');
62
  } else {
63
  invalidCookies.forEach((cookie, index) => {
64
- console.log(`${index + 1}. ${cookie}`);
65
  });
66
  }
67
 
@@ -72,7 +76,7 @@ function listInvalidCookies() {
72
  function addInvalidCookie() {
73
  rl.question('\n请输入要添加的无效Cookie: ', (cookie) => {
74
  if (!cookie.trim()) {
75
- console.log('Cookie不能为空');
76
  showMenu();
77
  return;
78
  }
@@ -91,12 +95,12 @@ function addInvalidCookie() {
91
  }
92
 
93
  fs.writeFileSync(INVALID_COOKIES_FILE, JSON.stringify(Array.from(invalidCookies), null, 2), 'utf8');
94
- console.log('无效Cookie添加成功');
95
 
96
  // 重新加载无效cookie
97
  keyManager.loadInvalidCookiesFromFile();
98
  } catch (err) {
99
- console.error('保存无效Cookie失败:', err);
100
  }
101
 
102
  showMenu();
@@ -108,21 +112,21 @@ function removeInvalidCookie() {
108
  const invalidCookies = Array.from(keyManager.getInvalidCookies());
109
 
110
  if (invalidCookies.length === 0) {
111
- console.log('\n没有无效Cookie可删除');
112
  showMenu();
113
  return;
114
  }
115
 
116
- console.log('\n===== 所有无效Cookie =====');
117
  invalidCookies.forEach((cookie, index) => {
118
- console.log(`${index + 1}. ${cookie}`);
119
  });
120
 
121
  rl.question('\n请输入要删除的Cookie编号 (1-' + invalidCookies.length + '): ', (answer) => {
122
  const index = parseInt(answer) - 1;
123
 
124
  if (isNaN(index) || index < 0 || index >= invalidCookies.length) {
125
- console.log('无效的编号');
126
  showMenu();
127
  return;
128
  }
@@ -131,9 +135,9 @@ function removeInvalidCookie() {
131
  const result = keyManager.clearInvalidCookie(cookieToRemove);
132
 
133
  if (result) {
134
- console.log(`成功删除无效Cookie: ${cookieToRemove}`);
135
  } else {
136
- console.log('删除失败');
137
  }
138
 
139
  showMenu();
@@ -145,9 +149,9 @@ function clearAllInvalidCookies() {
145
  rl.question('\n确定要清空所有无效Cookie吗? (y/n): ', (answer) => {
146
  if (answer.toLowerCase() === 'y') {
147
  keyManager.clearAllInvalidCookies();
148
- console.log('所有无效Cookie已清空');
149
  } else {
150
- console.log('操作已取消');
151
  }
152
 
153
  showMenu();
@@ -158,12 +162,12 @@ function clearAllInvalidCookies() {
158
  function removeInvalidCookiesFromApiKeys() {
159
  // 重新初始化API Keys,这会自动移除无效cookie
160
  keyManager.initializeApiKeys();
161
- console.log('已从API Keys中移除所有无效Cookie');
162
 
163
  showMenu();
164
  }
165
 
166
  // 启动程序
167
- console.log('正在加载无效Cookie...');
168
  keyManager.loadInvalidCookiesFromFile();
169
  showMenu();
 
5
  const path = require('path');
6
  const readline = require('readline');
7
  const keyManager = require('./src/utils/keyManager');
8
+ const logger = require('./src/utils/logger');
9
 
10
  // 创建命令行交互界面
11
  const rl = readline.createInterface({
 
13
  output: process.stdout
14
  });
15
 
16
+ // 初始化API Keys
17
+ keyManager.initializeApiKeys();
18
+
19
  // 显示菜单
20
  function showMenu() {
21
+ logger.info('\n===== 无效Cookie管理工具 =====');
22
+ logger.info('1. 查看所有无效Cookie');
23
+ logger.info('2. 添加无效Cookie');
24
+ logger.info('3. 删除特定无效Cookie');
25
+ logger.info('4. 清空所有无效Cookie');
26
+ logger.info('5. 从API Keys中移除所有无效Cookie');
27
+ logger.info('6. 退出');
28
+ logger.info('============================');
29
 
30
  rl.question('请选择操作 (1-6): ', (answer) => {
31
  switch(answer) {
 
45
  removeInvalidCookiesFromApiKeys();
46
  break;
47
  case '6':
48
+ logger.info('退出程序');
49
  rl.close();
50
  break;
51
  default:
52
+ logger.warn('无效的选择,请重新输入');
53
  showMenu();
54
  break;
55
  }
 
60
  function listInvalidCookies() {
61
  const invalidCookies = Array.from(keyManager.getInvalidCookies());
62
 
63
+ logger.info('\n===== 所有无效Cookie =====');
64
  if (invalidCookies.length === 0) {
65
+ logger.info('没有无效Cookie');
66
  } else {
67
  invalidCookies.forEach((cookie, index) => {
68
+ logger.info(`${index + 1}. ${cookie}`);
69
  });
70
  }
71
 
 
76
  function addInvalidCookie() {
77
  rl.question('\n请输入要添加的无效Cookie: ', (cookie) => {
78
  if (!cookie.trim()) {
79
+ logger.warn('Cookie不能为空');
80
  showMenu();
81
  return;
82
  }
 
95
  }
96
 
97
  fs.writeFileSync(INVALID_COOKIES_FILE, JSON.stringify(Array.from(invalidCookies), null, 2), 'utf8');
98
+ logger.info('无效Cookie添加成功');
99
 
100
  // 重新加载无效cookie
101
  keyManager.loadInvalidCookiesFromFile();
102
  } catch (err) {
103
+ logger.error('保存无效Cookie失败:', err);
104
  }
105
 
106
  showMenu();
 
112
  const invalidCookies = Array.from(keyManager.getInvalidCookies());
113
 
114
  if (invalidCookies.length === 0) {
115
+ logger.warn('\n没有无效Cookie可删除');
116
  showMenu();
117
  return;
118
  }
119
 
120
+ logger.info('\n===== 所有无效Cookie =====');
121
  invalidCookies.forEach((cookie, index) => {
122
+ logger.info(`${index + 1}. ${cookie}`);
123
  });
124
 
125
  rl.question('\n请输入要删除的Cookie编号 (1-' + invalidCookies.length + '): ', (answer) => {
126
  const index = parseInt(answer) - 1;
127
 
128
  if (isNaN(index) || index < 0 || index >= invalidCookies.length) {
129
+ logger.warn('无效的编号');
130
  showMenu();
131
  return;
132
  }
 
135
  const result = keyManager.clearInvalidCookie(cookieToRemove);
136
 
137
  if (result) {
138
+ logger.info(`成功删除无效Cookie: ${cookieToRemove}`);
139
  } else {
140
+ logger.warn('删除失败');
141
  }
142
 
143
  showMenu();
 
149
  rl.question('\n确定要清空所有无效Cookie吗? (y/n): ', (answer) => {
150
  if (answer.toLowerCase() === 'y') {
151
  keyManager.clearAllInvalidCookies();
152
+ logger.info('所有无效Cookie已清空');
153
  } else {
154
+ logger.info('操作已取消');
155
  }
156
 
157
  showMenu();
 
162
  function removeInvalidCookiesFromApiKeys() {
163
  // 重新初始化API Keys,这会自动移除无效cookie
164
  keyManager.initializeApiKeys();
165
+ logger.info('已��API Keys中移除所有无效Cookie');
166
 
167
  showMenu();
168
  }
169
 
170
  // 启动程序
171
+ logger.info('正在加载无效Cookie...');
172
  keyManager.loadInvalidCookiesFromFile();
173
  showMenu();
package-lock.json CHANGED
@@ -12,18 +12,22 @@
12
  "@octokit/rest": "^20.0.2",
13
  "adm-zip": "^0.5.16",
14
  "axios": "^1.6.7",
 
15
  "csv-parser": "^3.0.0",
16
  "dotenv": "^16.4.7",
17
  "express": "4.21.2",
18
  "jsonwebtoken": "^9.0.2",
 
19
  "morgan": "^1.10.0",
20
  "node-cron": "^3.0.3",
21
  "node-fetch": "^2.7.0",
 
22
  "protobufjs": "^7.4.0",
23
  "undici": "^6.21.2",
24
  "uuid": "11.0.5"
25
  },
26
  "devDependencies": {
 
27
  "protobufjs-cli": "^1.1.3"
28
  }
29
  },
@@ -77,6 +81,35 @@
77
  "node": ">=6.9.0"
78
  }
79
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  "node_modules/@jsdoc/salty": {
81
  "version": "0.2.9",
82
  "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz",
@@ -334,6 +367,13 @@
334
  "dev": true,
335
  "license": "MIT"
336
  },
 
 
 
 
 
 
 
337
  "node_modules/@types/node": {
338
  "version": "22.10.5",
339
  "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz",
@@ -343,6 +383,13 @@
343
  "undici-types": "~6.20.0"
344
  }
345
  },
 
 
 
 
 
 
 
346
  "node_modules/accepts": {
347
  "version": "1.3.8",
348
  "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -411,18 +458,77 @@
411
  "dev": true,
412
  "license": "Python-2.0"
413
  },
 
 
 
 
 
 
 
 
 
 
414
  "node_modules/array-flatten": {
415
  "version": "1.1.1",
416
  "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
417
  "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
418
  "license": "MIT"
419
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  "node_modules/asynckit": {
421
  "version": "0.4.0",
422
  "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
423
  "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
424
  "license": "MIT"
425
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  "node_modules/axios": {
427
  "version": "1.8.3",
428
  "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
@@ -512,6 +618,28 @@
512
  "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
513
  "license": "BSD-3-Clause"
514
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
  "node_modules/bytes": {
516
  "version": "3.1.2",
517
  "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -521,10 +649,29 @@
521
  "node": ">= 0.8"
522
  }
523
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  "node_modules/call-bind-apply-helpers": {
525
- "version": "1.0.1",
526
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
527
- "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
528
  "license": "MIT",
529
  "dependencies": {
530
  "es-errors": "^1.3.0",
@@ -535,13 +682,13 @@
535
  }
536
  },
537
  "node_modules/call-bound": {
538
- "version": "1.0.3",
539
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
540
- "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
541
  "license": "MIT",
542
  "dependencies": {
543
- "call-bind-apply-helpers": "^1.0.1",
544
- "get-intrinsic": "^1.2.6"
545
  },
546
  "engines": {
547
  "node": ">= 0.4"
@@ -580,6 +727,45 @@
580
  "url": "https://github.com/chalk/chalk?sponsor=1"
581
  }
582
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  "node_modules/color-convert": {
584
  "version": "2.0.1",
585
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -612,6 +798,23 @@
612
  "node": ">= 0.8"
613
  }
614
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  "node_modules/content-disposition": {
616
  "version": "0.5.4",
617
  "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -642,12 +845,44 @@
642
  "node": ">= 0.6"
643
  }
644
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
645
  "node_modules/cookie-signature": {
646
  "version": "1.0.6",
647
  "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
648
  "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
649
  "license": "MIT"
650
  },
 
 
 
 
 
 
 
 
 
 
651
  "node_modules/csv-parser": {
652
  "version": "3.2.0",
653
  "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz",
@@ -676,6 +911,82 @@
676
  "dev": true,
677
  "license": "MIT"
678
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
  "node_modules/delayed-stream": {
680
  "version": "1.0.0",
681
  "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -792,9 +1103,9 @@
792
  }
793
  },
794
  "node_modules/es-object-atoms": {
795
- "version": "1.0.0",
796
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
797
- "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
798
  "license": "MIT",
799
  "dependencies": {
800
  "es-errors": "^1.3.0"
@@ -818,6 +1129,13 @@
818
  "node": ">= 0.4"
819
  }
820
  },
 
 
 
 
 
 
 
821
  "node_modules/escape-html": {
822
  "version": "1.0.3",
823
  "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -867,6 +1185,20 @@
867
  "node": ">=4.0"
868
  }
869
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
870
  "node_modules/eslint-visitor-keys": {
871
  "version": "3.4.3",
872
  "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
@@ -912,6 +1244,19 @@
912
  "node": ">=4"
913
  }
914
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
915
  "node_modules/estraverse": {
916
  "version": "5.3.0",
917
  "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
@@ -987,6 +1332,13 @@
987
  "url": "https://opencollective.com/express"
988
  }
989
  },
 
 
 
 
 
 
 
990
  "node_modules/fast-levenshtein": {
991
  "version": "2.0.6",
992
  "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
@@ -1032,6 +1384,22 @@
1032
  }
1033
  }
1034
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1035
  "node_modules/form-data": {
1036
  "version": "4.0.2",
1037
  "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
@@ -1082,17 +1450,17 @@
1082
  }
1083
  },
1084
  "node_modules/get-intrinsic": {
1085
- "version": "1.2.7",
1086
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
1087
- "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
1088
  "license": "MIT",
1089
  "dependencies": {
1090
- "call-bind-apply-helpers": "^1.0.1",
1091
  "es-define-property": "^1.0.1",
1092
  "es-errors": "^1.3.0",
1093
- "es-object-atoms": "^1.0.0",
1094
  "function-bind": "^1.1.2",
1095
- "get-proto": "^1.0.0",
1096
  "gopd": "^1.2.0",
1097
  "has-symbols": "^1.1.0",
1098
  "hasown": "^2.0.2",
@@ -1168,6 +1536,19 @@
1168
  "node": ">=8"
1169
  }
1170
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
1171
  "node_modules/has-symbols": {
1172
  "version": "1.1.0",
1173
  "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -1253,6 +1634,13 @@
1253
  "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1254
  "license": "ISC"
1255
  },
 
 
 
 
 
 
 
1256
  "node_modules/ipaddr.js": {
1257
  "version": "1.9.1",
1258
  "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -1262,16 +1650,264 @@
1262
  "node": ">= 0.10"
1263
  }
1264
  },
1265
- "node_modules/js2xmlparser": {
1266
- "version": "4.0.2",
1267
- "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz",
1268
- "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==",
1269
  "dev": true,
1270
- "license": "Apache-2.0",
1271
  "dependencies": {
1272
- "xmlcreate": "^2.0.4"
1273
- }
1274
- },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1275
  "node_modules/jsdoc": {
1276
  "version": "4.0.4",
1277
  "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz",
@@ -1375,6 +2011,13 @@
1375
  "node": ">= 0.8.0"
1376
  }
1377
  },
 
 
 
 
 
 
 
1378
  "node_modules/linkify-it": {
1379
  "version": "5.0.0",
1380
  "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
@@ -1434,6 +2077,14 @@
1434
  "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
1435
  "license": "MIT"
1436
  },
 
 
 
 
 
 
 
 
1437
  "node_modules/long": {
1438
  "version": "5.2.4",
1439
  "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz",
@@ -1491,6 +2142,18 @@
1491
  "node": ">= 0.4"
1492
  }
1493
  },
 
 
 
 
 
 
 
 
 
 
 
 
1494
  "node_modules/mdurl": {
1495
  "version": "2.0.0",
1496
  "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
@@ -1628,6 +2291,50 @@
1628
  "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1629
  "license": "MIT"
1630
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1631
  "node_modules/negotiator": {
1632
  "version": "0.6.3",
1633
  "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -1690,6 +2397,33 @@
1690
  "url": "https://github.com/sponsors/ljharb"
1691
  }
1692
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1693
  "node_modules/on-finished": {
1694
  "version": "2.4.1",
1695
  "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -1720,6 +2454,34 @@
1720
  "wrappy": "1"
1721
  }
1722
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1723
  "node_modules/optionator": {
1724
  "version": "0.8.3",
1725
  "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
@@ -1753,6 +2515,16 @@
1753
  "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
1754
  "license": "MIT"
1755
  },
 
 
 
 
 
 
 
 
 
 
1756
  "node_modules/prelude-ls": {
1757
  "version": "1.1.2",
1758
  "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -1762,6 +2534,16 @@
1762
  "node": ">= 0.8.0"
1763
  }
1764
  },
 
 
 
 
 
 
 
 
 
 
1765
  "node_modules/protobufjs": {
1766
  "version": "7.4.0",
1767
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
@@ -1883,6 +2665,13 @@
1883
  "node": ">= 0.8"
1884
  }
1885
  },
 
 
 
 
 
 
 
1886
  "node_modules/requizzle": {
1887
  "version": "0.2.4",
1888
  "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz",
@@ -1893,6 +2682,18 @@
1893
  "lodash": "^4.17.21"
1894
  }
1895
  },
 
 
 
 
 
 
 
 
 
 
 
 
1896
  "node_modules/safe-buffer": {
1897
  "version": "5.2.1",
1898
  "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -1913,6 +2714,24 @@
1913
  ],
1914
  "license": "MIT"
1915
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1916
  "node_modules/safer-buffer": {
1917
  "version": "2.1.2",
1918
  "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -1985,6 +2804,24 @@
1985
  "node": ">= 0.8.0"
1986
  }
1987
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1988
  "node_modules/setprototypeof": {
1989
  "version": "1.2.0",
1990
  "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -2069,11 +2906,21 @@
2069
  "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
2070
  "dev": true,
2071
  "license": "BSD-3-Clause",
2072
- "optional": true,
2073
  "engines": {
2074
  "node": ">=0.10.0"
2075
  }
2076
  },
 
 
 
 
 
 
 
 
 
 
 
2077
  "node_modules/statuses": {
2078
  "version": "2.0.1",
2079
  "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@@ -2083,6 +2930,23 @@
2083
  "node": ">= 0.8"
2084
  }
2085
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2086
  "node_modules/strip-json-comments": {
2087
  "version": "3.1.1",
2088
  "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -2134,6 +2998,13 @@
2134
  "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
2135
  "license": "MIT"
2136
  },
 
 
 
 
 
 
 
2137
  "node_modules/type-check": {
2138
  "version": "0.3.2",
2139
  "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -2217,6 +3088,20 @@
2217
  "node": ">= 0.8"
2218
  }
2219
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2220
  "node_modules/utils-merge": {
2221
  "version": "1.0.1",
2222
  "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -2239,6 +3124,16 @@
2239
  "uuid": "dist/esm/bin/uuid"
2240
  }
2241
  },
 
 
 
 
 
 
 
 
 
 
2242
  "node_modules/vary": {
2243
  "version": "1.1.2",
2244
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -2264,6 +3159,28 @@
2264
  "webidl-conversions": "^3.0.0"
2265
  }
2266
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2267
  "node_modules/word-wrap": {
2268
  "version": "1.2.5",
2269
  "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
 
12
  "@octokit/rest": "^20.0.2",
13
  "adm-zip": "^0.5.16",
14
  "axios": "^1.6.7",
15
+ "cookie-parser": "^1.4.7",
16
  "csv-parser": "^3.0.0",
17
  "dotenv": "^16.4.7",
18
  "express": "4.21.2",
19
  "jsonwebtoken": "^9.0.2",
20
+ "logger": "^0.0.1",
21
  "morgan": "^1.10.0",
22
  "node-cron": "^3.0.3",
23
  "node-fetch": "^2.7.0",
24
+ "open": "^10.1.0",
25
  "protobufjs": "^7.4.0",
26
  "undici": "^6.21.2",
27
  "uuid": "11.0.5"
28
  },
29
  "devDependencies": {
30
+ "javascript-obfuscator": "^4.1.1",
31
  "protobufjs-cli": "^1.1.3"
32
  }
33
  },
 
81
  "node": ">=6.9.0"
82
  }
83
  },
84
+ "node_modules/@javascript-obfuscator/escodegen": {
85
+ "version": "2.3.0",
86
+ "resolved": "https://registry.npmjs.org/@javascript-obfuscator/escodegen/-/escodegen-2.3.0.tgz",
87
+ "integrity": "sha512-QVXwMIKqYMl3KwtTirYIA6gOCiJ0ZDtptXqAv/8KWLG9uQU2fZqTVy7a/A5RvcoZhbDoFfveTxuGxJ5ibzQtkw==",
88
+ "dev": true,
89
+ "license": "BSD-2-Clause",
90
+ "dependencies": {
91
+ "@javascript-obfuscator/estraverse": "^5.3.0",
92
+ "esprima": "^4.0.1",
93
+ "esutils": "^2.0.2",
94
+ "optionator": "^0.8.1"
95
+ },
96
+ "engines": {
97
+ "node": ">=6.0"
98
+ },
99
+ "optionalDependencies": {
100
+ "source-map": "~0.6.1"
101
+ }
102
+ },
103
+ "node_modules/@javascript-obfuscator/estraverse": {
104
+ "version": "5.4.0",
105
+ "resolved": "https://registry.npmjs.org/@javascript-obfuscator/estraverse/-/estraverse-5.4.0.tgz",
106
+ "integrity": "sha512-CZFX7UZVN9VopGbjTx4UXaXsi9ewoM1buL0kY7j1ftYdSs7p2spv9opxFjHlQ/QGTgh4UqufYqJJ0WKLml7b6w==",
107
+ "dev": true,
108
+ "license": "BSD-2-Clause",
109
+ "engines": {
110
+ "node": ">=4.0"
111
+ }
112
+ },
113
  "node_modules/@jsdoc/salty": {
114
  "version": "0.2.9",
115
  "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz",
 
367
  "dev": true,
368
  "license": "MIT"
369
  },
370
+ "node_modules/@types/minimatch": {
371
+ "version": "3.0.5",
372
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
373
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
374
+ "dev": true,
375
+ "license": "MIT"
376
+ },
377
  "node_modules/@types/node": {
378
  "version": "22.10.5",
379
  "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz",
 
383
  "undici-types": "~6.20.0"
384
  }
385
  },
386
+ "node_modules/@types/validator": {
387
+ "version": "13.15.1",
388
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.1.tgz",
389
+ "integrity": "sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==",
390
+ "dev": true,
391
+ "license": "MIT"
392
+ },
393
  "node_modules/accepts": {
394
  "version": "1.3.8",
395
  "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
 
458
  "dev": true,
459
  "license": "Python-2.0"
460
  },
461
+ "node_modules/array-differ": {
462
+ "version": "3.0.0",
463
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
464
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
465
+ "dev": true,
466
+ "license": "MIT",
467
+ "engines": {
468
+ "node": ">=8"
469
+ }
470
+ },
471
  "node_modules/array-flatten": {
472
  "version": "1.1.1",
473
  "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
474
  "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
475
  "license": "MIT"
476
  },
477
+ "node_modules/array-union": {
478
+ "version": "2.1.0",
479
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
480
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
481
+ "dev": true,
482
+ "license": "MIT",
483
+ "engines": {
484
+ "node": ">=8"
485
+ }
486
+ },
487
+ "node_modules/arrify": {
488
+ "version": "2.0.1",
489
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
490
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
491
+ "dev": true,
492
+ "license": "MIT",
493
+ "engines": {
494
+ "node": ">=8"
495
+ }
496
+ },
497
+ "node_modules/assert": {
498
+ "version": "2.0.0",
499
+ "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz",
500
+ "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==",
501
+ "dev": true,
502
+ "license": "MIT",
503
+ "dependencies": {
504
+ "es6-object-assign": "^1.1.0",
505
+ "is-nan": "^1.2.1",
506
+ "object-is": "^1.0.1",
507
+ "util": "^0.12.0"
508
+ }
509
+ },
510
  "node_modules/asynckit": {
511
  "version": "0.4.0",
512
  "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
513
  "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
514
  "license": "MIT"
515
  },
516
+ "node_modules/available-typed-arrays": {
517
+ "version": "1.0.7",
518
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
519
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
520
+ "dev": true,
521
+ "license": "MIT",
522
+ "dependencies": {
523
+ "possible-typed-array-names": "^1.0.0"
524
+ },
525
+ "engines": {
526
+ "node": ">= 0.4"
527
+ },
528
+ "funding": {
529
+ "url": "https://github.com/sponsors/ljharb"
530
+ }
531
+ },
532
  "node_modules/axios": {
533
  "version": "1.8.3",
534
  "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
 
618
  "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
619
  "license": "BSD-3-Clause"
620
  },
621
+ "node_modules/buffer-from": {
622
+ "version": "1.1.2",
623
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
624
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
625
+ "dev": true,
626
+ "license": "MIT"
627
+ },
628
+ "node_modules/bundle-name": {
629
+ "version": "4.1.0",
630
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
631
+ "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
632
+ "license": "MIT",
633
+ "dependencies": {
634
+ "run-applescript": "^7.0.0"
635
+ },
636
+ "engines": {
637
+ "node": ">=18"
638
+ },
639
+ "funding": {
640
+ "url": "https://github.com/sponsors/sindresorhus"
641
+ }
642
+ },
643
  "node_modules/bytes": {
644
  "version": "3.1.2",
645
  "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
 
649
  "node": ">= 0.8"
650
  }
651
  },
652
+ "node_modules/call-bind": {
653
+ "version": "1.0.8",
654
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
655
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
656
+ "dev": true,
657
+ "license": "MIT",
658
+ "dependencies": {
659
+ "call-bind-apply-helpers": "^1.0.0",
660
+ "es-define-property": "^1.0.0",
661
+ "get-intrinsic": "^1.2.4",
662
+ "set-function-length": "^1.2.2"
663
+ },
664
+ "engines": {
665
+ "node": ">= 0.4"
666
+ },
667
+ "funding": {
668
+ "url": "https://github.com/sponsors/ljharb"
669
+ }
670
+ },
671
  "node_modules/call-bind-apply-helpers": {
672
+ "version": "1.0.2",
673
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
674
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
675
  "license": "MIT",
676
  "dependencies": {
677
  "es-errors": "^1.3.0",
 
682
  }
683
  },
684
  "node_modules/call-bound": {
685
+ "version": "1.0.4",
686
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
687
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
688
  "license": "MIT",
689
  "dependencies": {
690
+ "call-bind-apply-helpers": "^1.0.2",
691
+ "get-intrinsic": "^1.3.0"
692
  },
693
  "engines": {
694
  "node": ">= 0.4"
 
727
  "url": "https://github.com/chalk/chalk?sponsor=1"
728
  }
729
  },
730
+ "node_modules/chance": {
731
+ "version": "1.1.9",
732
+ "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.9.tgz",
733
+ "integrity": "sha512-TfxnA/DcZXRTA4OekA2zL9GH8qscbbl6X0ZqU4tXhGveVY/mXWvEQLt5GwZcYXTEyEFflVtj+pG8nc8EwSm1RQ==",
734
+ "dev": true,
735
+ "license": "MIT"
736
+ },
737
+ "node_modules/char-regex": {
738
+ "version": "1.0.2",
739
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
740
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
741
+ "dev": true,
742
+ "license": "MIT",
743
+ "engines": {
744
+ "node": ">=10"
745
+ }
746
+ },
747
+ "node_modules/charenc": {
748
+ "version": "0.0.2",
749
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
750
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
751
+ "dev": true,
752
+ "license": "BSD-3-Clause",
753
+ "engines": {
754
+ "node": "*"
755
+ }
756
+ },
757
+ "node_modules/class-validator": {
758
+ "version": "0.14.1",
759
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
760
+ "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
761
+ "dev": true,
762
+ "license": "MIT",
763
+ "dependencies": {
764
+ "@types/validator": "^13.11.8",
765
+ "libphonenumber-js": "^1.10.53",
766
+ "validator": "^13.9.0"
767
+ }
768
+ },
769
  "node_modules/color-convert": {
770
  "version": "2.0.1",
771
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 
798
  "node": ">= 0.8"
799
  }
800
  },
801
+ "node_modules/commander": {
802
+ "version": "10.0.0",
803
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz",
804
+ "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==",
805
+ "dev": true,
806
+ "license": "MIT",
807
+ "engines": {
808
+ "node": ">=14"
809
+ }
810
+ },
811
+ "node_modules/concat-map": {
812
+ "version": "0.0.1",
813
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
814
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
815
+ "dev": true,
816
+ "license": "MIT"
817
+ },
818
  "node_modules/content-disposition": {
819
  "version": "0.5.4",
820
  "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
 
845
  "node": ">= 0.6"
846
  }
847
  },
848
+ "node_modules/cookie-parser": {
849
+ "version": "1.4.7",
850
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
851
+ "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
852
+ "license": "MIT",
853
+ "dependencies": {
854
+ "cookie": "0.7.2",
855
+ "cookie-signature": "1.0.6"
856
+ },
857
+ "engines": {
858
+ "node": ">= 0.8.0"
859
+ }
860
+ },
861
+ "node_modules/cookie-parser/node_modules/cookie": {
862
+ "version": "0.7.2",
863
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
864
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
865
+ "license": "MIT",
866
+ "engines": {
867
+ "node": ">= 0.6"
868
+ }
869
+ },
870
  "node_modules/cookie-signature": {
871
  "version": "1.0.6",
872
  "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
873
  "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
874
  "license": "MIT"
875
  },
876
+ "node_modules/crypt": {
877
+ "version": "0.0.2",
878
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
879
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
880
+ "dev": true,
881
+ "license": "BSD-3-Clause",
882
+ "engines": {
883
+ "node": "*"
884
+ }
885
+ },
886
  "node_modules/csv-parser": {
887
  "version": "3.2.0",
888
  "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz",
 
911
  "dev": true,
912
  "license": "MIT"
913
  },
914
+ "node_modules/default-browser": {
915
+ "version": "5.2.1",
916
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
917
+ "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
918
+ "license": "MIT",
919
+ "dependencies": {
920
+ "bundle-name": "^4.1.0",
921
+ "default-browser-id": "^5.0.0"
922
+ },
923
+ "engines": {
924
+ "node": ">=18"
925
+ },
926
+ "funding": {
927
+ "url": "https://github.com/sponsors/sindresorhus"
928
+ }
929
+ },
930
+ "node_modules/default-browser-id": {
931
+ "version": "5.0.0",
932
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz",
933
+ "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
934
+ "license": "MIT",
935
+ "engines": {
936
+ "node": ">=18"
937
+ },
938
+ "funding": {
939
+ "url": "https://github.com/sponsors/sindresorhus"
940
+ }
941
+ },
942
+ "node_modules/define-data-property": {
943
+ "version": "1.1.4",
944
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
945
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
946
+ "dev": true,
947
+ "license": "MIT",
948
+ "dependencies": {
949
+ "es-define-property": "^1.0.0",
950
+ "es-errors": "^1.3.0",
951
+ "gopd": "^1.0.1"
952
+ },
953
+ "engines": {
954
+ "node": ">= 0.4"
955
+ },
956
+ "funding": {
957
+ "url": "https://github.com/sponsors/ljharb"
958
+ }
959
+ },
960
+ "node_modules/define-lazy-prop": {
961
+ "version": "3.0.0",
962
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
963
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
964
+ "license": "MIT",
965
+ "engines": {
966
+ "node": ">=12"
967
+ },
968
+ "funding": {
969
+ "url": "https://github.com/sponsors/sindresorhus"
970
+ }
971
+ },
972
+ "node_modules/define-properties": {
973
+ "version": "1.2.1",
974
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
975
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
976
+ "dev": true,
977
+ "license": "MIT",
978
+ "dependencies": {
979
+ "define-data-property": "^1.0.1",
980
+ "has-property-descriptors": "^1.0.0",
981
+ "object-keys": "^1.1.1"
982
+ },
983
+ "engines": {
984
+ "node": ">= 0.4"
985
+ },
986
+ "funding": {
987
+ "url": "https://github.com/sponsors/ljharb"
988
+ }
989
+ },
990
  "node_modules/delayed-stream": {
991
  "version": "1.0.0",
992
  "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 
1103
  }
1104
  },
1105
  "node_modules/es-object-atoms": {
1106
+ "version": "1.1.1",
1107
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
1108
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
1109
  "license": "MIT",
1110
  "dependencies": {
1111
  "es-errors": "^1.3.0"
 
1129
  "node": ">= 0.4"
1130
  }
1131
  },
1132
+ "node_modules/es6-object-assign": {
1133
+ "version": "1.1.0",
1134
+ "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
1135
+ "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==",
1136
+ "dev": true,
1137
+ "license": "MIT"
1138
+ },
1139
  "node_modules/escape-html": {
1140
  "version": "1.0.3",
1141
  "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 
1185
  "node": ">=4.0"
1186
  }
1187
  },
1188
+ "node_modules/eslint-scope": {
1189
+ "version": "7.1.1",
1190
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
1191
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
1192
+ "dev": true,
1193
+ "license": "BSD-2-Clause",
1194
+ "dependencies": {
1195
+ "esrecurse": "^4.3.0",
1196
+ "estraverse": "^5.2.0"
1197
+ },
1198
+ "engines": {
1199
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1200
+ }
1201
+ },
1202
  "node_modules/eslint-visitor-keys": {
1203
  "version": "3.4.3",
1204
  "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
 
1244
  "node": ">=4"
1245
  }
1246
  },
1247
+ "node_modules/esrecurse": {
1248
+ "version": "4.3.0",
1249
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
1250
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
1251
+ "dev": true,
1252
+ "license": "BSD-2-Clause",
1253
+ "dependencies": {
1254
+ "estraverse": "^5.2.0"
1255
+ },
1256
+ "engines": {
1257
+ "node": ">=4.0"
1258
+ }
1259
+ },
1260
  "node_modules/estraverse": {
1261
  "version": "5.3.0",
1262
  "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
 
1332
  "url": "https://opencollective.com/express"
1333
  }
1334
  },
1335
+ "node_modules/fast-deep-equal": {
1336
+ "version": "3.1.3",
1337
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1338
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1339
+ "dev": true,
1340
+ "license": "MIT"
1341
+ },
1342
  "node_modules/fast-levenshtein": {
1343
  "version": "2.0.6",
1344
  "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
 
1384
  }
1385
  }
1386
  },
1387
+ "node_modules/for-each": {
1388
+ "version": "0.3.5",
1389
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
1390
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
1391
+ "dev": true,
1392
+ "license": "MIT",
1393
+ "dependencies": {
1394
+ "is-callable": "^1.2.7"
1395
+ },
1396
+ "engines": {
1397
+ "node": ">= 0.4"
1398
+ },
1399
+ "funding": {
1400
+ "url": "https://github.com/sponsors/ljharb"
1401
+ }
1402
+ },
1403
  "node_modules/form-data": {
1404
  "version": "4.0.2",
1405
  "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
 
1450
  }
1451
  },
1452
  "node_modules/get-intrinsic": {
1453
+ "version": "1.3.0",
1454
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
1455
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
1456
  "license": "MIT",
1457
  "dependencies": {
1458
+ "call-bind-apply-helpers": "^1.0.2",
1459
  "es-define-property": "^1.0.1",
1460
  "es-errors": "^1.3.0",
1461
+ "es-object-atoms": "^1.1.1",
1462
  "function-bind": "^1.1.2",
1463
+ "get-proto": "^1.0.1",
1464
  "gopd": "^1.2.0",
1465
  "has-symbols": "^1.1.0",
1466
  "hasown": "^2.0.2",
 
1536
  "node": ">=8"
1537
  }
1538
  },
1539
+ "node_modules/has-property-descriptors": {
1540
+ "version": "1.0.2",
1541
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
1542
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
1543
+ "dev": true,
1544
+ "license": "MIT",
1545
+ "dependencies": {
1546
+ "es-define-property": "^1.0.0"
1547
+ },
1548
+ "funding": {
1549
+ "url": "https://github.com/sponsors/ljharb"
1550
+ }
1551
+ },
1552
  "node_modules/has-symbols": {
1553
  "version": "1.1.0",
1554
  "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
 
1634
  "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1635
  "license": "ISC"
1636
  },
1637
+ "node_modules/inversify": {
1638
+ "version": "6.0.1",
1639
+ "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.1.tgz",
1640
+ "integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==",
1641
+ "dev": true,
1642
+ "license": "MIT"
1643
+ },
1644
  "node_modules/ipaddr.js": {
1645
  "version": "1.9.1",
1646
  "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
 
1650
  "node": ">= 0.10"
1651
  }
1652
  },
1653
+ "node_modules/is-arguments": {
1654
+ "version": "1.2.0",
1655
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
1656
+ "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
1657
  "dev": true,
1658
+ "license": "MIT",
1659
  "dependencies": {
1660
+ "call-bound": "^1.0.2",
1661
+ "has-tostringtag": "^1.0.2"
1662
+ },
1663
+ "engines": {
1664
+ "node": ">= 0.4"
1665
+ },
1666
+ "funding": {
1667
+ "url": "https://github.com/sponsors/ljharb"
1668
+ }
1669
+ },
1670
+ "node_modules/is-buffer": {
1671
+ "version": "1.1.6",
1672
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
1673
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
1674
+ "dev": true,
1675
+ "license": "MIT"
1676
+ },
1677
+ "node_modules/is-callable": {
1678
+ "version": "1.2.7",
1679
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
1680
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
1681
+ "dev": true,
1682
+ "license": "MIT",
1683
+ "engines": {
1684
+ "node": ">= 0.4"
1685
+ },
1686
+ "funding": {
1687
+ "url": "https://github.com/sponsors/ljharb"
1688
+ }
1689
+ },
1690
+ "node_modules/is-docker": {
1691
+ "version": "3.0.0",
1692
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
1693
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
1694
+ "license": "MIT",
1695
+ "bin": {
1696
+ "is-docker": "cli.js"
1697
+ },
1698
+ "engines": {
1699
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
1700
+ },
1701
+ "funding": {
1702
+ "url": "https://github.com/sponsors/sindresorhus"
1703
+ }
1704
+ },
1705
+ "node_modules/is-generator-function": {
1706
+ "version": "1.1.0",
1707
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
1708
+ "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
1709
+ "dev": true,
1710
+ "license": "MIT",
1711
+ "dependencies": {
1712
+ "call-bound": "^1.0.3",
1713
+ "get-proto": "^1.0.0",
1714
+ "has-tostringtag": "^1.0.2",
1715
+ "safe-regex-test": "^1.1.0"
1716
+ },
1717
+ "engines": {
1718
+ "node": ">= 0.4"
1719
+ },
1720
+ "funding": {
1721
+ "url": "https://github.com/sponsors/ljharb"
1722
+ }
1723
+ },
1724
+ "node_modules/is-inside-container": {
1725
+ "version": "1.0.0",
1726
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
1727
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
1728
+ "license": "MIT",
1729
+ "dependencies": {
1730
+ "is-docker": "^3.0.0"
1731
+ },
1732
+ "bin": {
1733
+ "is-inside-container": "cli.js"
1734
+ },
1735
+ "engines": {
1736
+ "node": ">=14.16"
1737
+ },
1738
+ "funding": {
1739
+ "url": "https://github.com/sponsors/sindresorhus"
1740
+ }
1741
+ },
1742
+ "node_modules/is-nan": {
1743
+ "version": "1.3.2",
1744
+ "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
1745
+ "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
1746
+ "dev": true,
1747
+ "license": "MIT",
1748
+ "dependencies": {
1749
+ "call-bind": "^1.0.0",
1750
+ "define-properties": "^1.1.3"
1751
+ },
1752
+ "engines": {
1753
+ "node": ">= 0.4"
1754
+ },
1755
+ "funding": {
1756
+ "url": "https://github.com/sponsors/ljharb"
1757
+ }
1758
+ },
1759
+ "node_modules/is-regex": {
1760
+ "version": "1.2.1",
1761
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
1762
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
1763
+ "dev": true,
1764
+ "license": "MIT",
1765
+ "dependencies": {
1766
+ "call-bound": "^1.0.2",
1767
+ "gopd": "^1.2.0",
1768
+ "has-tostringtag": "^1.0.2",
1769
+ "hasown": "^2.0.2"
1770
+ },
1771
+ "engines": {
1772
+ "node": ">= 0.4"
1773
+ },
1774
+ "funding": {
1775
+ "url": "https://github.com/sponsors/ljharb"
1776
+ }
1777
+ },
1778
+ "node_modules/is-typed-array": {
1779
+ "version": "1.1.15",
1780
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
1781
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
1782
+ "dev": true,
1783
+ "license": "MIT",
1784
+ "dependencies": {
1785
+ "which-typed-array": "^1.1.16"
1786
+ },
1787
+ "engines": {
1788
+ "node": ">= 0.4"
1789
+ },
1790
+ "funding": {
1791
+ "url": "https://github.com/sponsors/ljharb"
1792
+ }
1793
+ },
1794
+ "node_modules/is-wsl": {
1795
+ "version": "3.1.0",
1796
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
1797
+ "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
1798
+ "license": "MIT",
1799
+ "dependencies": {
1800
+ "is-inside-container": "^1.0.0"
1801
+ },
1802
+ "engines": {
1803
+ "node": ">=16"
1804
+ },
1805
+ "funding": {
1806
+ "url": "https://github.com/sponsors/sindresorhus"
1807
+ }
1808
+ },
1809
+ "node_modules/javascript-obfuscator": {
1810
+ "version": "4.1.1",
1811
+ "resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-4.1.1.tgz",
1812
+ "integrity": "sha512-gt+KZpIIrrxXHEQGD8xZrL8mTRwRY0U76/xz/YX0gZdPrSqQhT/c7dYLASlLlecT3r+FxE7je/+C0oLnTDCx4A==",
1813
+ "dev": true,
1814
+ "hasInstallScript": true,
1815
+ "license": "BSD-2-Clause",
1816
+ "dependencies": {
1817
+ "@javascript-obfuscator/escodegen": "2.3.0",
1818
+ "@javascript-obfuscator/estraverse": "5.4.0",
1819
+ "acorn": "8.8.2",
1820
+ "assert": "2.0.0",
1821
+ "chalk": "4.1.2",
1822
+ "chance": "1.1.9",
1823
+ "class-validator": "0.14.1",
1824
+ "commander": "10.0.0",
1825
+ "eslint-scope": "7.1.1",
1826
+ "eslint-visitor-keys": "3.3.0",
1827
+ "fast-deep-equal": "3.1.3",
1828
+ "inversify": "6.0.1",
1829
+ "js-string-escape": "1.0.1",
1830
+ "md5": "2.3.0",
1831
+ "mkdirp": "2.1.3",
1832
+ "multimatch": "5.0.0",
1833
+ "opencollective-postinstall": "2.0.3",
1834
+ "process": "0.11.10",
1835
+ "reflect-metadata": "0.1.13",
1836
+ "source-map-support": "0.5.21",
1837
+ "string-template": "1.0.0",
1838
+ "stringz": "2.1.0",
1839
+ "tslib": "2.5.0"
1840
+ },
1841
+ "bin": {
1842
+ "javascript-obfuscator": "bin/javascript-obfuscator"
1843
+ },
1844
+ "engines": {
1845
+ "node": ">=12.22.0"
1846
+ },
1847
+ "funding": {
1848
+ "type": "opencollective",
1849
+ "url": "https://opencollective.com/javascript-obfuscator"
1850
+ }
1851
+ },
1852
+ "node_modules/javascript-obfuscator/node_modules/acorn": {
1853
+ "version": "8.8.2",
1854
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
1855
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
1856
+ "dev": true,
1857
+ "license": "MIT",
1858
+ "bin": {
1859
+ "acorn": "bin/acorn"
1860
+ },
1861
+ "engines": {
1862
+ "node": ">=0.4.0"
1863
+ }
1864
+ },
1865
+ "node_modules/javascript-obfuscator/node_modules/eslint-visitor-keys": {
1866
+ "version": "3.3.0",
1867
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
1868
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
1869
+ "dev": true,
1870
+ "license": "Apache-2.0",
1871
+ "engines": {
1872
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1873
+ }
1874
+ },
1875
+ "node_modules/javascript-obfuscator/node_modules/mkdirp": {
1876
+ "version": "2.1.3",
1877
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz",
1878
+ "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==",
1879
+ "dev": true,
1880
+ "license": "MIT",
1881
+ "bin": {
1882
+ "mkdirp": "dist/cjs/src/bin.js"
1883
+ },
1884
+ "engines": {
1885
+ "node": ">=10"
1886
+ },
1887
+ "funding": {
1888
+ "url": "https://github.com/sponsors/isaacs"
1889
+ }
1890
+ },
1891
+ "node_modules/js-string-escape": {
1892
+ "version": "1.0.1",
1893
+ "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
1894
+ "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==",
1895
+ "dev": true,
1896
+ "license": "MIT",
1897
+ "engines": {
1898
+ "node": ">= 0.8"
1899
+ }
1900
+ },
1901
+ "node_modules/js2xmlparser": {
1902
+ "version": "4.0.2",
1903
+ "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz",
1904
+ "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==",
1905
+ "dev": true,
1906
+ "license": "Apache-2.0",
1907
+ "dependencies": {
1908
+ "xmlcreate": "^2.0.4"
1909
+ }
1910
+ },
1911
  "node_modules/jsdoc": {
1912
  "version": "4.0.4",
1913
  "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz",
 
2011
  "node": ">= 0.8.0"
2012
  }
2013
  },
2014
+ "node_modules/libphonenumber-js": {
2015
+ "version": "1.12.8",
2016
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.8.tgz",
2017
+ "integrity": "sha512-f1KakiQJa9tdc7w1phC2ST+DyxWimy9c3g3yeF+84QtEanJr2K77wAmBPP22riU05xldniHsvXuflnLZ4oysqA==",
2018
+ "dev": true,
2019
+ "license": "MIT"
2020
+ },
2021
  "node_modules/linkify-it": {
2022
  "version": "5.0.0",
2023
  "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
 
2077
  "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
2078
  "license": "MIT"
2079
  },
2080
+ "node_modules/logger": {
2081
+ "version": "0.0.1",
2082
+ "resolved": "https://registry.npmjs.org/logger/-/logger-0.0.1.tgz",
2083
+ "integrity": "sha512-UD45f4iZrsj6dQKt5QBN7K+R0hmFwGS8G+Pv8WtHjrnhrMQftIclma8b86mNtg1LKB6HDIOW/ZtjnXELBhr89w==",
2084
+ "engines": {
2085
+ "node": ">=0.1.90"
2086
+ }
2087
+ },
2088
  "node_modules/long": {
2089
  "version": "5.2.4",
2090
  "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz",
 
2142
  "node": ">= 0.4"
2143
  }
2144
  },
2145
+ "node_modules/md5": {
2146
+ "version": "2.3.0",
2147
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
2148
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
2149
+ "dev": true,
2150
+ "license": "BSD-3-Clause",
2151
+ "dependencies": {
2152
+ "charenc": "0.0.2",
2153
+ "crypt": "0.0.2",
2154
+ "is-buffer": "~1.1.6"
2155
+ }
2156
+ },
2157
  "node_modules/mdurl": {
2158
  "version": "2.0.0",
2159
  "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
 
2291
  "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
2292
  "license": "MIT"
2293
  },
2294
+ "node_modules/multimatch": {
2295
+ "version": "5.0.0",
2296
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
2297
+ "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==",
2298
+ "dev": true,
2299
+ "license": "MIT",
2300
+ "dependencies": {
2301
+ "@types/minimatch": "^3.0.3",
2302
+ "array-differ": "^3.0.0",
2303
+ "array-union": "^2.1.0",
2304
+ "arrify": "^2.0.1",
2305
+ "minimatch": "^3.0.4"
2306
+ },
2307
+ "engines": {
2308
+ "node": ">=10"
2309
+ },
2310
+ "funding": {
2311
+ "url": "https://github.com/sponsors/sindresorhus"
2312
+ }
2313
+ },
2314
+ "node_modules/multimatch/node_modules/brace-expansion": {
2315
+ "version": "1.1.11",
2316
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
2317
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
2318
+ "dev": true,
2319
+ "license": "MIT",
2320
+ "dependencies": {
2321
+ "balanced-match": "^1.0.0",
2322
+ "concat-map": "0.0.1"
2323
+ }
2324
+ },
2325
+ "node_modules/multimatch/node_modules/minimatch": {
2326
+ "version": "3.1.2",
2327
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
2328
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
2329
+ "dev": true,
2330
+ "license": "ISC",
2331
+ "dependencies": {
2332
+ "brace-expansion": "^1.1.7"
2333
+ },
2334
+ "engines": {
2335
+ "node": "*"
2336
+ }
2337
+ },
2338
  "node_modules/negotiator": {
2339
  "version": "0.6.3",
2340
  "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
 
2397
  "url": "https://github.com/sponsors/ljharb"
2398
  }
2399
  },
2400
+ "node_modules/object-is": {
2401
+ "version": "1.1.6",
2402
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
2403
+ "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
2404
+ "dev": true,
2405
+ "license": "MIT",
2406
+ "dependencies": {
2407
+ "call-bind": "^1.0.7",
2408
+ "define-properties": "^1.2.1"
2409
+ },
2410
+ "engines": {
2411
+ "node": ">= 0.4"
2412
+ },
2413
+ "funding": {
2414
+ "url": "https://github.com/sponsors/ljharb"
2415
+ }
2416
+ },
2417
+ "node_modules/object-keys": {
2418
+ "version": "1.1.1",
2419
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
2420
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
2421
+ "dev": true,
2422
+ "license": "MIT",
2423
+ "engines": {
2424
+ "node": ">= 0.4"
2425
+ }
2426
+ },
2427
  "node_modules/on-finished": {
2428
  "version": "2.4.1",
2429
  "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
 
2454
  "wrappy": "1"
2455
  }
2456
  },
2457
+ "node_modules/open": {
2458
+ "version": "10.1.0",
2459
+ "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz",
2460
+ "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
2461
+ "license": "MIT",
2462
+ "dependencies": {
2463
+ "default-browser": "^5.2.1",
2464
+ "define-lazy-prop": "^3.0.0",
2465
+ "is-inside-container": "^1.0.0",
2466
+ "is-wsl": "^3.1.0"
2467
+ },
2468
+ "engines": {
2469
+ "node": ">=18"
2470
+ },
2471
+ "funding": {
2472
+ "url": "https://github.com/sponsors/sindresorhus"
2473
+ }
2474
+ },
2475
+ "node_modules/opencollective-postinstall": {
2476
+ "version": "2.0.3",
2477
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
2478
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
2479
+ "dev": true,
2480
+ "license": "MIT",
2481
+ "bin": {
2482
+ "opencollective-postinstall": "index.js"
2483
+ }
2484
+ },
2485
  "node_modules/optionator": {
2486
  "version": "0.8.3",
2487
  "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
 
2515
  "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
2516
  "license": "MIT"
2517
  },
2518
+ "node_modules/possible-typed-array-names": {
2519
+ "version": "1.1.0",
2520
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
2521
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
2522
+ "dev": true,
2523
+ "license": "MIT",
2524
+ "engines": {
2525
+ "node": ">= 0.4"
2526
+ }
2527
+ },
2528
  "node_modules/prelude-ls": {
2529
  "version": "1.1.2",
2530
  "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
 
2534
  "node": ">= 0.8.0"
2535
  }
2536
  },
2537
+ "node_modules/process": {
2538
+ "version": "0.11.10",
2539
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
2540
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
2541
+ "dev": true,
2542
+ "license": "MIT",
2543
+ "engines": {
2544
+ "node": ">= 0.6.0"
2545
+ }
2546
+ },
2547
  "node_modules/protobufjs": {
2548
  "version": "7.4.0",
2549
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
 
2665
  "node": ">= 0.8"
2666
  }
2667
  },
2668
+ "node_modules/reflect-metadata": {
2669
+ "version": "0.1.13",
2670
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
2671
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
2672
+ "dev": true,
2673
+ "license": "Apache-2.0"
2674
+ },
2675
  "node_modules/requizzle": {
2676
  "version": "0.2.4",
2677
  "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz",
 
2682
  "lodash": "^4.17.21"
2683
  }
2684
  },
2685
+ "node_modules/run-applescript": {
2686
+ "version": "7.0.0",
2687
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
2688
+ "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
2689
+ "license": "MIT",
2690
+ "engines": {
2691
+ "node": ">=18"
2692
+ },
2693
+ "funding": {
2694
+ "url": "https://github.com/sponsors/sindresorhus"
2695
+ }
2696
+ },
2697
  "node_modules/safe-buffer": {
2698
  "version": "5.2.1",
2699
  "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 
2714
  ],
2715
  "license": "MIT"
2716
  },
2717
+ "node_modules/safe-regex-test": {
2718
+ "version": "1.1.0",
2719
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
2720
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
2721
+ "dev": true,
2722
+ "license": "MIT",
2723
+ "dependencies": {
2724
+ "call-bound": "^1.0.2",
2725
+ "es-errors": "^1.3.0",
2726
+ "is-regex": "^1.2.1"
2727
+ },
2728
+ "engines": {
2729
+ "node": ">= 0.4"
2730
+ },
2731
+ "funding": {
2732
+ "url": "https://github.com/sponsors/ljharb"
2733
+ }
2734
+ },
2735
  "node_modules/safer-buffer": {
2736
  "version": "2.1.2",
2737
  "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 
2804
  "node": ">= 0.8.0"
2805
  }
2806
  },
2807
+ "node_modules/set-function-length": {
2808
+ "version": "1.2.2",
2809
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
2810
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
2811
+ "dev": true,
2812
+ "license": "MIT",
2813
+ "dependencies": {
2814
+ "define-data-property": "^1.1.4",
2815
+ "es-errors": "^1.3.0",
2816
+ "function-bind": "^1.1.2",
2817
+ "get-intrinsic": "^1.2.4",
2818
+ "gopd": "^1.0.1",
2819
+ "has-property-descriptors": "^1.0.2"
2820
+ },
2821
+ "engines": {
2822
+ "node": ">= 0.4"
2823
+ }
2824
+ },
2825
  "node_modules/setprototypeof": {
2826
  "version": "1.2.0",
2827
  "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
 
2906
  "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
2907
  "dev": true,
2908
  "license": "BSD-3-Clause",
 
2909
  "engines": {
2910
  "node": ">=0.10.0"
2911
  }
2912
  },
2913
+ "node_modules/source-map-support": {
2914
+ "version": "0.5.21",
2915
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
2916
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
2917
+ "dev": true,
2918
+ "license": "MIT",
2919
+ "dependencies": {
2920
+ "buffer-from": "^1.0.0",
2921
+ "source-map": "^0.6.0"
2922
+ }
2923
+ },
2924
  "node_modules/statuses": {
2925
  "version": "2.0.1",
2926
  "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
 
2930
  "node": ">= 0.8"
2931
  }
2932
  },
2933
+ "node_modules/string-template": {
2934
+ "version": "1.0.0",
2935
+ "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz",
2936
+ "integrity": "sha512-SLqR3GBUXuoPP5MmYtD7ompvXiG87QjT6lzOszyXjTM86Uu7At7vNnt2xgyTLq5o9T4IxTYFyGxcULqpsmsfdg==",
2937
+ "dev": true,
2938
+ "license": "MIT"
2939
+ },
2940
+ "node_modules/stringz": {
2941
+ "version": "2.1.0",
2942
+ "resolved": "https://registry.npmjs.org/stringz/-/stringz-2.1.0.tgz",
2943
+ "integrity": "sha512-KlywLT+MZ+v0IRepfMxRtnSvDCMc3nR1qqCs3m/qIbSOWkNZYT8XHQA31rS3TnKp0c5xjZu3M4GY/2aRKSi/6A==",
2944
+ "dev": true,
2945
+ "license": "MIT",
2946
+ "dependencies": {
2947
+ "char-regex": "^1.0.2"
2948
+ }
2949
+ },
2950
  "node_modules/strip-json-comments": {
2951
  "version": "3.1.1",
2952
  "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
 
2998
  "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
2999
  "license": "MIT"
3000
  },
3001
+ "node_modules/tslib": {
3002
+ "version": "2.5.0",
3003
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
3004
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
3005
+ "dev": true,
3006
+ "license": "0BSD"
3007
+ },
3008
  "node_modules/type-check": {
3009
  "version": "0.3.2",
3010
  "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
 
3088
  "node": ">= 0.8"
3089
  }
3090
  },
3091
+ "node_modules/util": {
3092
+ "version": "0.12.5",
3093
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
3094
+ "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
3095
+ "dev": true,
3096
+ "license": "MIT",
3097
+ "dependencies": {
3098
+ "inherits": "^2.0.3",
3099
+ "is-arguments": "^1.0.4",
3100
+ "is-generator-function": "^1.0.7",
3101
+ "is-typed-array": "^1.1.3",
3102
+ "which-typed-array": "^1.1.2"
3103
+ }
3104
+ },
3105
  "node_modules/utils-merge": {
3106
  "version": "1.0.1",
3107
  "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
 
3124
  "uuid": "dist/esm/bin/uuid"
3125
  }
3126
  },
3127
+ "node_modules/validator": {
3128
+ "version": "13.15.0",
3129
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz",
3130
+ "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==",
3131
+ "dev": true,
3132
+ "license": "MIT",
3133
+ "engines": {
3134
+ "node": ">= 0.10"
3135
+ }
3136
+ },
3137
  "node_modules/vary": {
3138
  "version": "1.1.2",
3139
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
 
3159
  "webidl-conversions": "^3.0.0"
3160
  }
3161
  },
3162
+ "node_modules/which-typed-array": {
3163
+ "version": "1.1.19",
3164
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
3165
+ "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
3166
+ "dev": true,
3167
+ "license": "MIT",
3168
+ "dependencies": {
3169
+ "available-typed-arrays": "^1.0.7",
3170
+ "call-bind": "^1.0.8",
3171
+ "call-bound": "^1.0.4",
3172
+ "for-each": "^0.3.5",
3173
+ "get-proto": "^1.0.1",
3174
+ "gopd": "^1.2.0",
3175
+ "has-tostringtag": "^1.0.2"
3176
+ },
3177
+ "engines": {
3178
+ "node": ">= 0.4"
3179
+ },
3180
+ "funding": {
3181
+ "url": "https://github.com/sponsors/ljharb"
3182
+ }
3183
+ },
3184
  "node_modules/word-wrap": {
3185
  "version": "1.2.5",
3186
  "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
package.json CHANGED
@@ -11,13 +11,16 @@
11
  "@octokit/rest": "^20.0.2",
12
  "adm-zip": "^0.5.16",
13
  "axios": "^1.6.7",
 
14
  "csv-parser": "^3.0.0",
15
  "dotenv": "^16.4.7",
16
  "express": "4.21.2",
17
  "jsonwebtoken": "^9.0.2",
 
18
  "morgan": "^1.10.0",
19
  "node-cron": "^3.0.3",
20
  "node-fetch": "^2.7.0",
 
21
  "protobufjs": "^7.4.0",
22
  "undici": "^6.21.2",
23
  "uuid": "11.0.5"
@@ -33,6 +36,7 @@
33
  "manage-cookies": "node manage-invalid-cookies.js"
34
  },
35
  "devDependencies": {
 
36
  "protobufjs-cli": "^1.1.3"
37
  }
38
  }
 
11
  "@octokit/rest": "^20.0.2",
12
  "adm-zip": "^0.5.16",
13
  "axios": "^1.6.7",
14
+ "cookie-parser": "^1.4.7",
15
  "csv-parser": "^3.0.0",
16
  "dotenv": "^16.4.7",
17
  "express": "4.21.2",
18
  "jsonwebtoken": "^9.0.2",
19
+ "logger": "^0.0.1",
20
  "morgan": "^1.10.0",
21
  "node-cron": "^3.0.3",
22
  "node-fetch": "^2.7.0",
23
+ "open": "^10.1.0",
24
  "protobufjs": "^7.4.0",
25
  "undici": "^6.21.2",
26
  "uuid": "11.0.5"
 
36
  "manage-cookies": "node manage-invalid-cookies.js"
37
  },
38
  "devDependencies": {
39
+ "javascript-obfuscator": "^4.1.1",
40
  "protobufjs-cli": "^1.1.3"
41
  }
42
  }
playbook.yml CHANGED
@@ -56,13 +56,13 @@
56
  test -f $HOME/.nvm/nvm.sh && source $HOME/.nvm/nvm.sh
57
  npm install
58
  npm run start -- --host 0.0.0.0 --port {{ app_port }}
59
- ' > {{ deploy_path }}/start.sh
60
- chmod +x {{ deploy_path }}/start.sh
61
- nohup {{ deploy_path }}/start.sh > {{ deploy_path }}/nohup.log 2>&1 &
62
  args:
63
  executable: /bin/bash
64
 
65
  - name: 等待服务启动
66
  wait_for:
67
  port: "{{ app_port }}"
68
- timeout: 30
 
56
  test -f $HOME/.nvm/nvm.sh && source $HOME/.nvm/nvm.sh
57
  npm install
58
  npm run start -- --host 0.0.0.0 --port {{ app_port }}
59
+ ' > {{ deploy_path }}/start_app.sh
60
+ chmod +x {{ deploy_path }}/start_app.sh
61
+ nohup {{ deploy_path }}/start_app.sh > {{ deploy_path }}/nohup.log 2>&1 &
62
  args:
63
  executable: /bin/bash
64
 
65
  - name: 等待服务启动
66
  wait_for:
67
  port: "{{ app_port }}"
68
+ timeout: 30
setup.js CHANGED
@@ -22,91 +22,41 @@ MORGAN_FORMAT=tiny
22
  # 格式: {"自定义API Key": "Cookie值"} 或 {"自定义API Key": ["Cookie值1", "Cookie值2"]}
23
  API_KEYS={API_KEYS_PLACEHOLDER}
24
 
25
- # 轮询策略 (random 或 round-robin)
26
- ROTATION_STRATEGY=round-robin
27
 
28
- # Cursor校验和 (可选)
29
- # x-cursor-checksum=xxxxxxxx
30
 
31
- # 自动刷新Cookie设置
32
- # 是否启用自动刷新Cookie (true 或 false)
33
- ENABLE_AUTO_REFRESH=true
34
 
35
- # 自动刷新Cookie的定时规则 (Cron表达式)
36
- # 默认每6小时执行一次
37
- REFRESH_CRON=0 */6 * * *
 
 
 
 
38
 
39
- # 每个API Key最小Cookie数量
40
- # 当Cookie数量低于此值时,会自动尝试刷新
41
- MIN_COOKIE_COUNT=1000
42
-
43
- # Cookie刷新模式
44
- # replace: 每次刷新都将现有cookie全部标记为无效并替换成新cookie(默认)
45
- # append: 保留现有cookie,仅追加新cookie
46
- COOKIE_REFRESH_MODE=replace
47
-
48
- # GitHub 仓库信息
49
- GITHUB_OWNER={GITHUB_OWNER_PLACEHOLDER}
50
- GITHUB_REPO=Cursor-Register-fix
51
-
52
- # GitHub Token (用于从GitHub Actions下载Artifact)
53
- # 需要有repo权限
54
- GITHUB_TOKEN={GITHUB_TOKEN_PLACEHOLDER}
55
-
56
- # GitHub Actions 工作流ID
57
- # 用于触发工作流程
58
- GITHUB_WORKFLOW_ID=cursor_register.yml
59
-
60
- # 是否自动触发工作流
61
- # 设置为true时,会自动触发工作流而不是仅获取最新结果
62
- TRIGGER_WORKFLOW=true
63
-
64
- # 工作流参数设置 目前只支持gmail,outlook过于复杂,暂时不支持
65
- # 注册账号数量
66
- REGISTER_NUMBER=1
67
- # 最大并发工作线程数
68
- REGISTER_MAX_WORKERS=1
69
- # 邮箱服务器类型 (TempEmail 或 IMAP)
70
- REGISTER_EMAIL_SERVER=IMAP
71
- # 是否将账号令牌注入到OneAPI (true 或 false)
72
- REGISTER_INGEST_TO_ONEAPI=false
73
- # 是否上传账号信息到Artifact (true 或 false)
74
- REGISTER_UPLOAD_ARTIFACT=true
75
- # 是否从config.yaml读取邮箱配置 (true 或 false)
76
- REGISTER_USE_CONFIG_FILE=false
77
- # 邮箱配置JSON字符串(仅在REGISTER_USE_CONFIG_FILE=false时有效)
78
- # 格式例如[{"email":"[email protected]","imap_server":"imap.gmail.com","imap_port":993,"username":"[email protected]","password":"your_app_password"}]
79
- REGISTER_EMAIL_CONFIGS={EMAIL_CONFIGS_PLACEHOLDER}
80
  `;
81
 
82
  // 提示信息
83
  console.log('===== Cursor-To-OpenAI 环境配置助手 =====');
84
  console.log('这个脚本将帮助你配置必要的环境变量\n');
85
 
86
- // 应用密码说明
87
- function printAppPasswordInstructions() {
88
- console.log('\n===== 如何创建谷歌应用密码 =====');
89
- console.log('1. 访问 https://myaccount.google.com/security');
90
- console.log('2. 在"登录Google"部分,点击"两步验证"');
91
- console.log(' (如果未启用两步验证,需要先启用)');
92
- console.log('3. 在页面底部找到"应用密码",点击进入');
93
- console.log('4. 在"选择应用"下拉菜单中选择"其他(自定义名称)"');
94
- console.log('5. 输入一个名称,例如"Cursor注册"');
95
- console.log('6. 点击"生成"');
96
- console.log('7. 复制生成的16位应用密码(格式如:xxxx xxxx xxxx xxxx)');
97
- console.log('8. 在下面的提示中输入这个密码');
98
- console.log('注意: 应用密码只会显示一次,请务必保存好\n');
99
- }
100
-
101
  // 从现有.env文件加载配置
102
  function loadExistingConfig() {
103
  const envPath = path.join(process.cwd(), '.env');
104
  let existingConfig = {
105
  apiKeys: {},
106
- githubOwner: '',
107
- githubToken: '',
108
- emailConfigs: [],
109
- cookieRefreshMode: 'append'
 
110
  };
111
 
112
  if (fs.existsSync(envPath)) {
@@ -126,28 +76,29 @@ function loadExistingConfig() {
126
  }
127
  }
128
 
129
- // 提取GitHub Owner
130
- if (envConfig.GITHUB_OWNER) {
131
- existingConfig.githubOwner = envConfig.GITHUB_OWNER;
132
  }
133
 
134
- // 提取GitHub Token
135
- if (envConfig.GITHUB_TOKEN) {
136
- existingConfig.githubToken = envConfig.GITHUB_TOKEN;
137
  }
138
 
139
- // 提取Email配置
140
- if (envConfig.REGISTER_EMAIL_CONFIGS) {
141
- try {
142
- existingConfig.emailConfigs = JSON.parse(envConfig.REGISTER_EMAIL_CONFIGS);
143
- } catch (e) {
144
- console.log('无法解析现有的Email配置,将使用默认设置');
145
- }
 
146
  }
147
 
148
- // 提取Cookie刷新模式
149
- if (envConfig.COOKIE_REFRESH_MODE) {
150
- existingConfig.cookieRefreshMode = envConfig.COOKIE_REFRESH_MODE;
151
  }
152
 
153
  console.log('成功加载现有配置');
@@ -180,17 +131,53 @@ async function collectConfig() {
180
 
181
  const config = {
182
  apiKeys: {},
183
- githubOwner: '',
184
- githubToken: '',
185
- emailConfigs: [],
186
- cookieRefreshMode: 'replace'
 
187
  };
188
 
189
- // 获取GitHub用户名
190
- config.githubOwner = await promptWithDefault('请输入你的GitHub用户名', existingConfig.githubOwner);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
- // 获取GitHub Token
193
- config.githubToken = await promptWithDefault('请输入你的GitHub Token (具有repo权限)', existingConfig.githubToken);
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
  // 处理API Keys
196
  const existingApiKeys = Object.keys(existingConfig.apiKeys);
@@ -211,74 +198,17 @@ async function collectConfig() {
211
  if (apiKey) {
212
  const fullApiKey = apiKey.startsWith('sk-') ? apiKey : `sk-${apiKey}`;
213
  config.apiKeys[fullApiKey] = [];
 
 
 
 
214
  }
 
 
 
 
215
  }
216
 
217
- // 询问Cookie刷新模式
218
- const refreshModePrompt = `选择Cookie刷新模式 [append/replace]`;
219
- const defaultRefreshMode = existingConfig.cookieRefreshMode || 'replace';
220
- config.cookieRefreshMode = await promptWithDefault(refreshModePrompt, defaultRefreshMode);
221
-
222
- // 解释所选的刷新模式
223
- if (config.cookieRefreshMode.toLowerCase() === 'replace') {
224
- config.cookieRefreshMode = 'replace';
225
- console.log('已选择替换模式: 每次刷新都将现有cookie全部标记为无效并替换成新cookie');
226
- } else {
227
- config.cookieRefreshMode = 'append';
228
- console.log('已选择追加模式: 保留现有cookie,仅追加新cookie');
229
- }
230
-
231
- // 处理Email配置
232
- if (existingConfig.emailConfigs.length > 0) {
233
- console.log('\n现有的Gmail账号:');
234
- existingConfig.emailConfigs.forEach((emailConfig, index) => {
235
- console.log(`- ${index + 1}: ${emailConfig.email}`);
236
- });
237
-
238
- const keepExistingEmails = await promptWithDefault('是否保留现有的Gmail账号? (y/n)', 'y');
239
- if (keepExistingEmails.toLowerCase() === 'y') {
240
- config.emailConfigs = [...existingConfig.emailConfigs];
241
- }
242
- }
243
-
244
- // 询问是否添加新的Gmail账号
245
- const addNewGmail = await promptWithDefault('是否添加新的Gmail账号? (y/n)', existingConfig.emailConfigs.length === 0 ? 'y' : 'n');
246
- if (addNewGmail.toLowerCase() === 'y') {
247
- printAppPasswordInstructions();
248
- await askForGmailAccount(config);
249
- } else if (config.emailConfigs.length === 0 && existingConfig.emailConfigs.length === 0) {
250
- console.log('\n⚠️ 警告: 未添加Gmail账号,自动刷新功能可能无法正常工作');
251
- console.log('你可以稍后在.env文件中手动配置REGISTER_EMAIL_CONFIGS\n');
252
- }
253
-
254
- return config;
255
- }
256
-
257
- // 询问Gmail账号
258
- async function askForGmailAccount(config) {
259
- const addGmail = await promptWithDefault('\n是否添加Gmail账号用于注册? (y/n)', 'y');
260
-
261
- if (addGmail.toLowerCase() === 'y') {
262
- const email = await promptWithDefault('请输入Gmail地址', '');
263
- const password = await promptWithDefault('请输入Gmail的应用密码 (不是邮箱密码)', '');
264
-
265
- if (email && password) {
266
- // 添加Email配置
267
- config.emailConfigs.push({
268
- email: email,
269
- imap_server: "imap.gmail.com",
270
- imap_port: 993,
271
- username: email,
272
- password: password
273
- });
274
- }
275
-
276
- const continueAnswer = await promptWithDefault('是否继续添加另一个Gmail账号? (y/n)', 'n');
277
- if (continueAnswer.toLowerCase() === 'y') {
278
- await askForGmailAccount(config);
279
- }
280
- }
281
-
282
  return config;
283
  }
284
 
@@ -288,18 +218,16 @@ function generateEnvFile(config) {
288
  // 准备API Keys
289
  const apiKeysJson = JSON.stringify(config.apiKeys);
290
 
291
- // 准备邮箱配置
292
- const emailConfigsJson = JSON.stringify(config.emailConfigs);
293
-
294
  // 替换模板中的占位符
295
  let envContent = ENV_TEMPLATE
296
  .replace('{API_KEYS_PLACEHOLDER}', apiKeysJson)
297
- .replace('{GITHUB_OWNER_PLACEHOLDER}', config.githubOwner)
298
- .replace('{GITHUB_TOKEN_PLACEHOLDER}', config.githubToken)
299
- .replace('{EMAIL_CONFIGS_PLACEHOLDER}', emailConfigsJson);
300
-
301
- // 更新Cookie刷新模式
302
- envContent = envContent.replace('COOKIE_REFRESH_MODE=append', `COOKIE_REFRESH_MODE=${config.cookieRefreshMode}`);
 
303
 
304
  // 写入.env文件
305
  const envPath = path.join(process.cwd(), '.env');
@@ -338,17 +266,24 @@ async function main() {
338
  console.log('\n===== 配置完成 =====');
339
  console.log('你可以使用以下命令启动服务:');
340
  console.log(' npm start');
341
- console.log('\n如需手动获取cookie执行:');
342
- console.log(' npm run refresh-cookies');
343
 
344
- // 根据配置的刷新模式提供提示
345
- console.log(`\n当前Cookie刷新模式为: ${config.cookieRefreshMode}`);
346
- if (config.cookieRefreshMode === 'replace') {
347
- console.log('每次刷新都会将现有cookie全部标记为无效并替换成新cookie');
348
- } else {
349
- console.log('刷新时会保留现有cookie,仅追加新cookie');
350
  }
351
- console.log('你可以在.env文件中修改COOKIE_REFRESH_MODE设置');
 
 
 
 
 
 
 
 
 
352
  }
353
  } catch (error) {
354
  console.error('\n❌ 配置过程中出错:', error.message);
 
22
  # 格式: {"自定义API Key": "Cookie值"} 或 {"自定义API Key": ["Cookie值1", "Cookie值2"]}
23
  API_KEYS={API_KEYS_PLACEHOLDER}
24
 
25
+ # 轮询策略 (random 或 round-robin 或 default)
26
+ ROTATION_STRATEGY=default
27
 
28
+ # 是否使用TLS代理 (true 或 false)
29
+ USE_TLS_PROXY={USE_TLS_PROXY_PLACEHOLDER}
30
 
31
+ # 是否使用辅助代理服务器 (true 或 false)
32
+ USE_OTHERS_PROXY={USE_OTHERS_PROXY_PLACEHOLDER}
 
33
 
34
+ # 代理服务器平台
35
+ # 可选值: auto, windows_x64, linux_x64, android_arm64
36
+ # auto: 自动检测平台
37
+ # windows_x64: Windows 64位
38
+ # linux_x64: Linux 64位
39
+ # android_arm64: 安卓ARM 64位
40
+ PROXY_PLATFORM={PROXY_PLATFORM_PLACEHOLDER}
41
 
42
+ # 是否使用其它接口 (true 或 false)
43
+ USE_OTHERS={USE_OTHERS_PLACEHOLDER}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  `;
45
 
46
  // 提示信息
47
  console.log('===== Cursor-To-OpenAI 环境配置助手 =====');
48
  console.log('这个脚本将帮助你配置必要的环境变量\n');
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  // 从现有.env文件加载配置
51
  function loadExistingConfig() {
52
  const envPath = path.join(process.cwd(), '.env');
53
  let existingConfig = {
54
  apiKeys: {},
55
+ useTlsProxy: true,
56
+ useOthersProxy: true,
57
+ proxyPlatform: 'auto',
58
+ useOthers: true,
59
+ rotationStrategy: 'default'
60
  };
61
 
62
  if (fs.existsSync(envPath)) {
 
76
  }
77
  }
78
 
79
+ // 提取TLS代理配置
80
+ if (envConfig.USE_TLS_PROXY !== undefined) {
81
+ existingConfig.useTlsProxy = envConfig.USE_TLS_PROXY === 'true';
82
  }
83
 
84
+ // 提取辅助代理服务器配置
85
+ if (envConfig.USE_OTHERS_PROXY !== undefined) {
86
+ existingConfig.useOthersProxy = envConfig.USE_OTHERS_PROXY === 'true';
87
  }
88
 
89
+ // 提取代理服务器平台
90
+ if (envConfig.PROXY_PLATFORM) {
91
+ existingConfig.proxyPlatform = envConfig.PROXY_PLATFORM;
92
+ }
93
+
94
+ // 提取是否使用其它接口
95
+ if (envConfig.USE_OTHERS !== undefined) {
96
+ existingConfig.useOthers = envConfig.USE_OTHERS === 'true';
97
  }
98
 
99
+ // 提取轮询策略
100
+ if (envConfig.ROTATION_STRATEGY) {
101
+ existingConfig.rotationStrategy = envConfig.ROTATION_STRATEGY;
102
  }
103
 
104
  console.log('成功加载现有配置');
 
131
 
132
  const config = {
133
  apiKeys: {},
134
+ useTlsProxy: existingConfig.useTlsProxy,
135
+ useOthersProxy: existingConfig.useOthersProxy,
136
+ proxyPlatform: existingConfig.proxyPlatform,
137
+ useOthers: existingConfig.useOthers,
138
+ rotationStrategy: existingConfig.rotationStrategy
139
  };
140
 
141
+ // 询问是否使用TLS代理
142
+ const useTlsProxyPrompt = `是否使用TLS代理服务器? (y/n)`;
143
+ const defaultUseTlsProxy = existingConfig.useTlsProxy ? 'y' : 'n';
144
+ const useTlsProxyAnswer = await promptWithDefault(useTlsProxyPrompt, defaultUseTlsProxy);
145
+ config.useTlsProxy = useTlsProxyAnswer.toLowerCase() === 'y';
146
+
147
+ if (config.useTlsProxy) {
148
+ // 询问是否使用辅助代理服务器
149
+ const useOthersProxyPrompt = `是否使用辅助代理服务器(port 10654)? (y/n)`;
150
+ const defaultUseOthersProxy = existingConfig.useOthersProxy ? 'y' : 'n';
151
+ const useOthersProxyAnswer = await promptWithDefault(useOthersProxyPrompt, defaultUseOthersProxy);
152
+ config.useOthersProxy = useOthersProxyAnswer.toLowerCase() === 'y';
153
+
154
+ // 询问代理服务器平台
155
+ console.log('\n代理服务器平台选项:');
156
+ console.log('- auto: 自动检测当前系统平台');
157
+ console.log('- windows_x64: Windows 64位');
158
+ console.log('- linux_x64: Linux 64位');
159
+ console.log('- android_arm64: 安卓ARM 64位');
160
+
161
+ const proxyPlatformPrompt = `选择代理服务器平台`;
162
+ const defaultProxyPlatform = existingConfig.proxyPlatform || 'auto';
163
+ config.proxyPlatform = await promptWithDefault(proxyPlatformPrompt, defaultProxyPlatform);
164
+ }
165
 
166
+ // 询问是否使用其它接口
167
+ const useOthersPrompt = `是否使用其它接口? (y/n)`;
168
+ const defaultUseOthers = existingConfig.useOthers ? 'y' : 'n';
169
+ const useOthersAnswer = await promptWithDefault(useOthersPrompt, defaultUseOthers);
170
+ config.useOthers = useOthersAnswer.toLowerCase() === 'y';
171
+
172
+ // 询问轮询策略
173
+ console.log('\n轮询策略选项:');
174
+ console.log('- default: 默认策略');
175
+ console.log('- random: 随机策略');
176
+ console.log('- round-robin: 轮询策略');
177
+
178
+ const rotationStrategyPrompt = `选择轮询策略`;
179
+ const defaultRotationStrategy = existingConfig.rotationStrategy || 'default';
180
+ config.rotationStrategy = await promptWithDefault(rotationStrategyPrompt, defaultRotationStrategy);
181
 
182
  // 处理API Keys
183
  const existingApiKeys = Object.keys(existingConfig.apiKeys);
 
198
  if (apiKey) {
199
  const fullApiKey = apiKey.startsWith('sk-') ? apiKey : `sk-${apiKey}`;
200
  config.apiKeys[fullApiKey] = [];
201
+ } else {
202
+ // 如果用户直接回车跳过,默认添加 sk-text
203
+ config.apiKeys['sk-text'] = [];
204
+ console.log('已默认添加API Key: sk-text');
205
  }
206
+ } else if (Object.keys(config.apiKeys).length === 0) {
207
+ // 如果没有任何API Key,默认添加 sk-text
208
+ config.apiKeys['sk-text'] = [];
209
+ console.log('已默认添加API Key: sk-text');
210
  }
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  return config;
213
  }
214
 
 
218
  // 准备API Keys
219
  const apiKeysJson = JSON.stringify(config.apiKeys);
220
 
 
 
 
221
  // 替换模板中的占位符
222
  let envContent = ENV_TEMPLATE
223
  .replace('{API_KEYS_PLACEHOLDER}', apiKeysJson)
224
+ .replace('{USE_TLS_PROXY_PLACEHOLDER}', config.useTlsProxy)
225
+ .replace('{USE_OTHERS_PROXY_PLACEHOLDER}', config.useOthersProxy)
226
+ .replace('{PROXY_PLATFORM_PLACEHOLDER}', config.proxyPlatform)
227
+ .replace('{USE_OTHERS_PLACEHOLDER}', config.useOthers);
228
+
229
+ // 更新轮询策略
230
+ envContent = envContent.replace('ROTATION_STRATEGY=default', `ROTATION_STRATEGY=${config.rotationStrategy}`);
231
 
232
  // 写入.env文件
233
  const envPath = path.join(process.cwd(), '.env');
 
266
  console.log('\n===== 配置完成 =====');
267
  console.log('你可以使用以下命令启动服务:');
268
  console.log(' npm start');
 
 
269
 
270
+ // 显示TLS代理配置信息
271
+ console.log(`\n当前TLS代理配置:`);
272
+ console.log(`- 是否启用TLS代理: ${config.useTlsProxy ? '' : '否'}`);
273
+ if (config.useTlsProxy) {
274
+ console.log(`- 是否启用辅助代理服务器: ${config.useOthersProxy ? '是' : '否'}`);
275
+ console.log(`- 代理服务器平台: ${config.proxyPlatform}`);
276
  }
277
+
278
+ // 显示是否使用其它接口配置信息
279
+ console.log(`\n当前是否使用其它接口: ${config.useOthers ? '是' : '否'}`);
280
+
281
+ // 显示轮询策略
282
+ console.log(`\n当前轮询策略: ${config.rotationStrategy}`);
283
+
284
+ // 显示API Keys
285
+ console.log('\n当前配置的API Keys:');
286
+ Object.keys(config.apiKeys).forEach(key => console.log(`- ${key}`));
287
  }
288
  } catch (error) {
289
  console.error('\n❌ 配置过程中出错:', error.message);
src/app.js CHANGED
@@ -1,154 +1 @@
1
- // 加载环境变量
2
- require('dotenv').config();
3
-
4
- // 环境检查
5
- const envChecker = require('./utils/envChecker');
6
- console.log('启动前检查环境配置...');
7
- envChecker.enforceEnvCheck();
8
-
9
- const express = require('express');
10
- const morgan = require('morgan');
11
- const path = require('path');
12
- const cron = require('node-cron');
13
- const app = express();
14
-
15
- const config = require('./config/config');
16
- const routes = require('./routes');
17
- const keyManager = require('./utils/keyManager');
18
- const cookieRefresher = require('./utils/cookieRefresher');
19
- const authMiddleware = require('./middleware/auth');
20
-
21
- // 初始化API Keys
22
- console.log('初始化API Keys...');
23
- keyManager.initializeApiKeys();
24
-
25
- // 输出最终的API Keys配置
26
- console.log('最终API Keys配置:', JSON.stringify(keyManager.getAllApiKeys().reduce((obj, key) => {
27
- obj[key] = keyManager.getAllCookiesForApiKey(key);
28
- return obj;
29
- }, {}), null, 2));
30
-
31
- // 添加CORS支持
32
- app.use((req, res, next) => {
33
- res.header('Access-Control-Allow-Origin', '*');
34
- res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
35
- res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
36
-
37
- if (req.method === 'OPTIONS') {
38
- return res.status(200).end();
39
- }
40
-
41
- next();
42
- });
43
-
44
- app.use(express.json({ limit: '50mb' }));
45
- app.use(express.urlencoded({ extended: true, limit: '50mb' }));
46
-
47
- app.use(morgan(process.env.MORGAN_FORMAT ?? 'tiny'));
48
-
49
- // 添加静态文件支持
50
- app.use(express.static(path.join(__dirname, 'public')));
51
-
52
- // 添加根路由,重定向到登录页面
53
- app.get('/', (req, res) => {
54
- res.redirect('/login.html');
55
- });
56
-
57
- // 添加认证中间件
58
- app.use(authMiddleware);
59
-
60
- app.use("/", routes)
61
-
62
- // 设置定时任务,自动刷新 Cookie
63
- if (config.refresh.enabled) {
64
- const cronSchedule = config.refresh.cron;
65
- const minCookieCount = config.refresh.minCookieCount;
66
-
67
- console.log(`启用自动刷新 Cookie,定时规则: ${cronSchedule},最小 Cookie 数量: ${minCookieCount}`);
68
-
69
- cron.schedule(cronSchedule, async () => {
70
- console.log('===== 自动刷新 Cookie 开始 =====');
71
- console.log(`最小 Cookie 数量: ${minCookieCount}`);
72
-
73
- try {
74
- // 获取所有 API Key
75
- const apiKeys = keyManager.getAllApiKeys();
76
-
77
- if (apiKeys.length === 0) {
78
- console.log('警告: 系统中没有找到任何 API Key');
79
-
80
- // 检查环境变量中是否有 API Keys
81
- const envApiKeys = Object.keys(config.apiKeys);
82
- if (envApiKeys.length > 0) {
83
- console.log(`检测到环境变量中有 ${envApiKeys.length} 个 API Key,但尚未加载到系统中`);
84
- console.log('正在重新初始化 API Keys...');
85
-
86
- // 重新获取 API Keys
87
- const refreshedApiKeys = keyManager.getAllApiKeys();
88
- if (refreshedApiKeys.length > 0) {
89
- console.log(`成功加载 ${refreshedApiKeys.length} 个 API Key,继续刷新流程`);
90
- // 继续执行后续刷新逻辑
91
- } else {
92
- console.log('初始化后仍未找到 API Key,请检查配置');
93
- console.log('===== 自动刷新 Cookie 结束 =====');
94
- return;
95
- }
96
- } else {
97
- console.log('环境变量中也没有配置 API Key,请先添加 API Key');
98
- console.log('===== 自动刷新 Cookie 结束 =====');
99
- return;
100
- }
101
- }
102
-
103
- // 重新获取最新的 API Keys(可能已经通过上面的初始化更新了)
104
- const updatedApiKeys = keyManager.getAllApiKeys();
105
- console.log(`系统中共有 ${updatedApiKeys.length} 个 API Key`);
106
-
107
- // 按 Cookie 数量排序,优先处理 Cookie 数量少的 API Key
108
- const sortedKeys = updatedApiKeys.sort((a, b) => {
109
- const aCount = keyManager.getAllCookiesForApiKey(a).length;
110
- const bCount = keyManager.getAllCookiesForApiKey(b).length;
111
- return aCount - bCount; // 升序排列,Cookie 数量少的排在前面
112
- });
113
-
114
- // 检查每个 API Key 是否需要刷新
115
- let refreshedCount = 0;
116
- let needRefreshCount = 0;
117
-
118
- for (const apiKey of sortedKeys) {
119
- const cookies = keyManager.getAllCookiesForApiKey(apiKey);
120
- console.log(`API Key: ${apiKey}, Cookie 数量: ${cookies.length}`);
121
-
122
- if (cookies.length < minCookieCount) {
123
- needRefreshCount++;
124
- console.log(`API Key ${apiKey} 的 Cookie 数量不足,需要刷新`);
125
-
126
- // 执行刷新
127
- console.log(`开始自动刷新 Cookie,目标 API Key: ${apiKey},最小 Cookie 数量: ${minCookieCount}`);
128
- const result = await cookieRefresher.autoRefreshCookies(apiKey, minCookieCount);
129
-
130
- if (result.success) {
131
- refreshedCount++;
132
- console.log(`刷新结果: ${result.message}`);
133
- } else {
134
- console.error(`刷新失败: ${result.message}`);
135
- }
136
- } else {
137
- console.log(`API Key ${apiKey} 的 Cookie 数量足够,不需要刷新`);
138
- }
139
- }
140
-
141
- console.log('===== 自动刷新 Cookie 完成 =====');
142
- console.log(`共有 ${needRefreshCount} 个 API Key 需要刷新,成功刷新 ${refreshedCount} 个`);
143
- } catch (error) {
144
- console.error('自动刷新 Cookie 任务执行失败:', error);
145
- console.log('===== 自动刷新 Cookie 异常结束 =====');
146
- }
147
- });
148
- } else {
149
- console.log('未启用自动刷新 Cookie,如需启用请设置环境变量 ENABLE_AUTO_REFRESH=true');
150
- }
151
-
152
- app.listen(config.port, () => {
153
- console.log(`The server listens port: ${config.port}`);
154
- });
 
1
+ const a0_0xe54be6=a0_0x429a;(function(_0x3ed962,_0x3c2d0a){const _0x29ddc6=a0_0x429a,_0x4935fa=_0x3ed962();while(!![]){try{const _0x5a9ec6=-parseInt(_0x29ddc6(0x112))/0x1+parseInt(_0x29ddc6(0x109))/0x2*(parseInt(_0x29ddc6(0xdc))/0x3)+parseInt(_0x29ddc6(0xe1))/0x4*(-parseInt(_0x29ddc6(0xf3))/0x5)+parseInt(_0x29ddc6(0xff))/0x6+parseInt(_0x29ddc6(0xf6))/0x7+parseInt(_0x29ddc6(0xf9))/0x8*(parseInt(_0x29ddc6(0xfd))/0x9)+-parseInt(_0x29ddc6(0x10f))/0xa*(parseInt(_0x29ddc6(0x13a))/0xb);if(_0x5a9ec6===_0x3c2d0a)break;else _0x4935fa['push'](_0x4935fa['shift']());}catch(_0x3da7d6){_0x4935fa['push'](_0x4935fa['shift']());}}}(a0_0x2781,0xbb2f4),require(a0_0xe54be6(0x11b))[a0_0xe54be6(0xed)]());function tempLog(_0x5b1422,_0x57598c){const _0x468849=a0_0xe54be6,_0x1ae502=(function(){let _0x48e219=!![];return function(_0x1b9e66,_0x3dd3d9){const _0x43d28e=_0x48e219?function(){const _0x41ff21=a0_0x429a;if(_0x3dd3d9){const _0x140190=_0x3dd3d9[_0x41ff21(0xfb)](_0x1b9e66,arguments);return _0x3dd3d9=null,_0x140190;}}:function(){};return _0x48e219=![],_0x43d28e;};}()),_0x3a1cfb=_0x1ae502(this,function(){const _0x4fa2d6=a0_0x429a;return _0x3a1cfb[_0x4fa2d6(0xf5)]()[_0x4fa2d6(0xef)]('(((.+)+)+)+$')['toString']()[_0x4fa2d6(0xe7)](_0x3a1cfb)[_0x4fa2d6(0xef)](_0x4fa2d6(0x11a));});_0x3a1cfb();const _0x148236=new Date()['toISOString']();if(_0x5b1422===_0x468849(0x11e))console['error'](_0x468849(0x132)+_0x148236+'\x20'+_0x57598c);else _0x5b1422==='WARN'?console['warn'](_0x468849(0xfe)+_0x148236+'\x20'+_0x57598c):console['log']('[INFO]\x20'+_0x148236+'\x20'+_0x57598c);}function a0_0x429a(_0x1bca4e,_0x4a81cd){const _0x4cde13=a0_0x2781();return a0_0x429a=function(_0xe5ebfc,_0x195ad9){_0xe5ebfc=_0xe5ebfc-0xd9;let _0x278172=_0x4cde13[_0xe5ebfc];if(a0_0x429a['ahOtuW']===undefined){var _0x429a89=function(_0x2bd5b9){const _0x2a0b8a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5846bb='',_0x5b1422='',_0x57598c=_0x5846bb+_0x429a89;for(let _0x1ae502=0x0,_0x3a1cfb,_0x148236,_0x48e219=0x0;_0x148236=_0x2bd5b9['charAt'](_0x48e219++);~_0x148236&&(_0x3a1cfb=_0x1ae502%0x4?_0x3a1cfb*0x40+_0x148236:_0x148236,_0x1ae502++%0x4)?_0x5846bb+=_0x57598c['charCodeAt'](_0x48e219+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x3a1cfb>>(-0x2*_0x1ae502&0x6)):_0x1ae502:0x0){_0x148236=_0x2a0b8a['indexOf'](_0x148236);}for(let _0x1b9e66=0x0,_0x3dd3d9=_0x5846bb['length'];_0x1b9e66<_0x3dd3d9;_0x1b9e66++){_0x5b1422+='%'+('00'+_0x5846bb['charCodeAt'](_0x1b9e66)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5b1422);};a0_0x429a['zUuVsb']=_0x429a89,_0x1bca4e=arguments,a0_0x429a['ahOtuW']=!![];}const _0x5cd562=_0x4cde13[0x0],_0x232831=_0xe5ebfc+_0x5cd562,_0x23b2ae=_0x1bca4e[_0x232831];if(!_0x23b2ae){const _0x43d28e=function(_0x140190){this['XCsqlA']=_0x140190,this['rzZwRH']=[0x1,0x0,0x0],this['IPQwTz']=function(){return'newState';},this['FUoqKC']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['CTaWwp']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x43d28e['prototype']['jkehlG']=function(){const _0x33b97e=new RegExp(this['FUoqKC']+this['CTaWwp']),_0x4f63ac=_0x33b97e['test'](this['IPQwTz']['toString']())?--this['rzZwRH'][0x1]:--this['rzZwRH'][0x0];return this['dOXcVD'](_0x4f63ac);},_0x43d28e['prototype']['dOXcVD']=function(_0x2f7807){if(!Boolean(~_0x2f7807))return _0x2f7807;return this['nzYNJv'](this['XCsqlA']);},_0x43d28e['prototype']['nzYNJv']=function(_0x591577){for(let _0x5adb07=0x0,_0x32f2f9=this['rzZwRH']['length'];_0x5adb07<_0x32f2f9;_0x5adb07++){this['rzZwRH']['push'](Math['round'](Math['random']())),_0x32f2f9=this['rzZwRH']['length'];}return _0x591577(this['rzZwRH'][0x0]);},new _0x43d28e(a0_0x429a)['jkehlG'](),_0x278172=a0_0x429a['zUuVsb'](_0x278172),_0x1bca4e[_0x232831]=_0x278172;}else _0x278172=_0x23b2ae;return _0x278172;},a0_0x429a(_0x1bca4e,_0x4a81cd);}tempLog(a0_0xe54be6(0xfa),a0_0xe54be6(0x12d));const envChecker=require('./utils/envChecker');envChecker[a0_0xe54be6(0xdb)]();const express=require(a0_0xe54be6(0xde)),morgan=require(a0_0xe54be6(0x13c)),path=require('path'),cron=require(a0_0xe54be6(0x136)),app=express(),cookieParser=require(a0_0xe54be6(0x111)),{spawn}=require(a0_0xe54be6(0xe8)),config=require('./config/config'),logger=require(a0_0xe54be6(0x12a)),routes=require('./routes'),keyManager=require('./utils/keyManager'),cookieRefresher=require('./utils/cookieRefresher'),authMiddleware=require('./middleware/auth'),proxyLauncher=require(a0_0xe54be6(0x12f));process['env'][a0_0xe54be6(0x134)]===a0_0xe54be6(0x120)?(logger[a0_0xe54be6(0x123)](a0_0xe54be6(0x12c)),proxyLauncher[a0_0xe54be6(0x11c)]()):logger['info'](a0_0xe54be6(0x118));const v1Router=require(a0_0xe54be6(0xec));logger[a0_0xe54be6(0x123)](a0_0xe54be6(0xf0)),keyManager['initializeApiKeys'](),logger['debug'](a0_0xe54be6(0x133),JSON[a0_0xe54be6(0xda)](keyManager[a0_0xe54be6(0xfc)]()[a0_0xe54be6(0x116)]((_0x33b97e,_0x4f63ac)=>{const _0x122e55=a0_0xe54be6;return _0x33b97e[_0x4f63ac]=keyManager[_0x122e55(0xe3)](_0x4f63ac),_0x33b97e;},{}),null,0x2));const apiKeys=keyManager[a0_0xe54be6(0xfc)](),keySummary=apiKeys['map'](_0x2f7807=>{const _0x148792=a0_0xe54be6,_0x591577=keyManager['getAllCookiesForApiKey'](_0x2f7807);return _0x2f7807+':\x20'+_0x591577['length']+_0x148792(0x125);})['join'](',\x20');function a0_0x2781(){const _0x4d39c9=['5BEY5zcV55sO6iEQ5yQO5yI35PAWienVB2TPzE+8JowUMUAxTUs7U+wkOEwWHUwCQoAVJYa','Dhj1zq','BgvUz3rO','5yI35PAW6l+B56Il6l6t5yE6oIa','Aw5MBW','BgLZDgvU','5lIQq29VA2LL','lI4Vyxv0BY1YzwzYzxnOlwnVB2TPzxmUANm','zw5K','qwnJzxnZlunVBNrYB2WTqwXSB3CTtwv0Ag9KCW','C3rKzxjY','lI91DgLSCY9SB2DNzxi','zgf0yq','5Q2J5zYO5zcV5yQOveXt5lUJ55cg5PYn5yQH5zMOlI4U','5zcV5yQO5yMn5Qoa5P+L546V5Akd6ywn572UlI4U','5PYn5yQH5zMO6zsz6k+VoG','lI91DgLSCY9WCM94EuXHDw5JAgvY','zw5HyMXLza','y2XVC2u','w0vsuK9sxsa','5PYa57UiqvbjieTLExpPHy3NVA46','vvnfx1rmu19quK9ywq','5yI35PAW6l+B56Il6zsz6k+VoIa','BM9Kzs1JCM9U','u0Lhvevstq','l2zHDMLJB24UAwnV','5OMt5BYa566H55cg55wm6z2IoIbODhrWoI8VBg9JywXOB3n0oG','mtqZzNHgr1vX','5PYn5yQH5zMO5BEY5zcV5yQO77Ym55Ur5zcS56UV5y+JoIa','Bw9Yz2fU','Aw50zxj2ywW','C3rYAw5NAwz5','zw5MB3jJzuvUDKnOzwnR','otq5ofrPD09sta','ANnVBG','zxHWCMvZCW','sw50zxjUywWGC2vYDMvYigvYCM9Y','t1busu9ouW','mte1mZe2ofDJvNPIrG','C29JA2v0','z2v0qwXSq29VA2LLC0zVCKfWAuTLEq','CMvMCMvZAa','Ec1MB3j3yxjKzwqTzM9Y','CMvTB3rLlwfKzhi','y29UC3rYDwn0B3i','y2HPBgrFChjVy2vZCW','C3rHDhvZ','BwvZC2fNzq','CgLWzq','lI9YB3v0zxmVDJe','y29UzMLN','ntbTyG','C2vHCMnO','5yID5AEl5yYwqvbjieTLExmUlI4','DxnL','Dg9Rzw4','nwH0ChD5BW','AgvHzgvY','Dg9tDhjPBMC','ntK5odq0n1Hmsfzswq','BM9Kzq','l2XVz2LUlMH0BwW','mZy4vMnAEM9v','su5gtW','yxbWBhK','z2v0qwXSqxbPs2v5CW','mtiXmZGZq2Luq05r','w1DbuK5Dia','ntyWmtKZnMHPzxPJwa','tM90igzVDw5K','6iEQ5yQO5yI35PAWienVB2TPzsdLRPRML7BKU7VLIQhLVilLUlJPGidLH7RVViZKU6pNOie6ia','l2HLywX0Aa','D2fYBG','Bwv0Ag9K','zxHPDa','zxHWB3j0CW','C2nOzwr1Bgu','DxjS','nZK0tfz6zfzn','CMvZB2X2zq','z2v0','Cg9YDa','u0Lhsu5u','zw52','mteYmtKXmeTgDvzfBG','DhjPBq','y29VA2LLlxbHCNnLCG','mte1ndm5oeHts3bjsq','5PYQ5zcV55sO6iEQ5yQO5yI35PAWienVB2TPzE+8JowMGUMCGowqR+EuQoIVT+IUVUE9RUEoR+wIG+wpMoMhJYbftKfctevFqvvut19sruzsrvnipxrYDwu','6k+35Rgc55Qe6lwe5RQq5lIn5A2y5zYO','5Q2J5zYO5ygC5Q2IveXt5lUJ55cg5PYn5yQH5zMOlI4U','CMvKDwnL','ChvIBgLJ','veXt5lUJ55cg5PYn5yQH5zMO5PYQ5zcV55sO77Ym6lEZ6l+h5zcV5yQO5lUJ55cg','Cgf0Aa','kcGOlISPkYKRksSK','zg90zw52','C3rHCNrqCM94EvnLCNzLCG','zxjYB3i','rvjst1i'];a0_0x2781=function(){return _0x4d39c9;};return a0_0x2781();}logger[a0_0xe54be6(0x123)]('当前已加载\x20'+apiKeys[a0_0xe54be6(0x121)]+'\x20个API\x20Key,详情:\x20'+keySummary),app[a0_0xe54be6(0xf1)]((_0x5adb07,_0x32f2f9,_0x3ddc4c)=>{const _0x496035=a0_0xe54be6;_0x32f2f9[_0x496035(0xf4)]('Access-Control-Allow-Origin','*'),_0x32f2f9[_0x496035(0xf4)]('Access-Control-Allow-Headers','Origin,\x20X-Requested-With,\x20Content-Type,\x20Accept,\x20Authorization'),_0x32f2f9['header'](_0x496035(0x128),'GET,\x20POST,\x20PUT,\x20DELETE,\x20OPTIONS');if(_0x5adb07[_0x496035(0x104)]===_0x496035(0xe0))return _0x32f2f9[_0x496035(0xe9)](0xc8)[_0x496035(0x127)]();_0x3ddc4c();}),app[a0_0xe54be6(0xf1)](express[a0_0xe54be6(0xdd)]({'limit':a0_0xe54be6(0xee)})),app[a0_0xe54be6(0xf1)](express['urlencoded']({'extended':!![],'limit':a0_0xe54be6(0xee)})),app[a0_0xe54be6(0xf1)](cookieParser()),morgan[a0_0xe54be6(0xf2)](a0_0xe54be6(0xe6),_0x47a605=>{const _0x16881c=a0_0xe54be6;return _0x47a605['headers'][_0x16881c(0xe5)]||_0x47a605[_0x16881c(0xe2)]['remoteAddress'];});const morganLoggerStream={'write':_0x48b022=>{const _0x182149=a0_0xe54be6,_0xd6562=_0x48b022[_0x182149(0x110)]();_0xd6562&&logger['http'](_0xd6562);}};app['use'](morgan(process[a0_0xe54be6(0x10e)]['MORGAN_FORMAT']||'combined',{'stream':morganLoggerStream,'skip':(_0x1ab4c5,_0x1983e8)=>{const _0x350117=a0_0xe54be6;return _0x1ab4c5['path']===_0x350117(0x102)||_0x1ab4c5[_0x350117(0x119)]===_0x350117(0x138);}})),app[a0_0xe54be6(0xf1)](express['static'](path['join'](__dirname,a0_0xe54be6(0x117)))),app[a0_0xe54be6(0x10b)]('/',(_0x4741ee,_0x43cac1)=>{const _0x290993=a0_0xe54be6;_0x43cac1['redirect'](_0x290993(0xf8));}),app[a0_0xe54be6(0xf1)](authMiddleware),app[a0_0xe54be6(0xf1)]('/v1',v1Router),app[a0_0xe54be6(0xf1)]('/',routes);config[a0_0xe54be6(0xe4)][a0_0xe54be6(0x130)]?(logger[a0_0xe54be6(0x123)](a0_0xe54be6(0x11f)+config[a0_0xe54be6(0xe4)][a0_0xe54be6(0xd9)]+'\x20运行'),cron[a0_0xe54be6(0x107)](config[a0_0xe54be6(0xe4)][a0_0xe54be6(0xd9)],()=>{const _0x14f12f=a0_0xe54be6;logger['info']('开始定时自动刷新\x20Cookie...');const _0x1db8e0=path[_0x14f12f(0x10a)](__dirname,_0x14f12f(0x126)),_0xe61971=spawn(_0x14f12f(0xf7),[_0x1db8e0],{'stdio':['ignore',_0x14f12f(0xeb),_0x14f12f(0xeb)]});_0xe61971['stdout']['on']('data',_0x3aa57d=>{const _0x1612db=_0x14f12f;logger[_0x1612db(0x123)](_0x1612db(0x122)+_0x3aa57d[_0x1612db(0xf5)]()[_0x1612db(0x110)]());}),_0xe61971[_0x14f12f(0x129)]['on'](_0x14f12f(0x12b),_0x1e0a43=>{const _0xe6a29f=_0x14f12f;logger[_0xe6a29f(0x11d)](_0xe6a29f(0x135)+_0x1e0a43[_0xe6a29f(0xf5)]()['trim']());}),_0xe61971['on'](_0x14f12f(0x131),_0x570b94=>{const _0x2b2df2=_0x14f12f;_0x570b94===0x0?logger[_0x2b2df2(0x123)]('自动刷新\x20Cookie\x20定时任务完成'):logger[_0x2b2df2(0x11d)](_0x2b2df2(0x101)+_0x570b94);});})):logger[a0_0xe54be6(0x123)](a0_0xe54be6(0x113));app[a0_0xe54be6(0xf1)]((_0x2dd2bc,_0x50914a,_0x161173,_0x52e480)=>{const _0x94858=a0_0xe54be6;logger[_0x94858(0x11d)](_0x94858(0x12e),_0x2dd2bc),_0x161173[_0x94858(0xe9)](0x1f4)[_0x94858(0xdd)]({'error':_0x94858(0xdf),'message':_0x2dd2bc[_0x94858(0xea)]});}),app['use']((_0x26588b,_0x5b924c)=>{const _0xb5f230=a0_0xe54be6;logger[_0xb5f230(0x103)]('未找到路由:\x20'+_0x26588b[_0xb5f230(0x104)]+'\x20'+_0x26588b[_0xb5f230(0x108)]),_0x5b924c[_0xb5f230(0xe9)](0x194)['json']({'error':_0xb5f230(0x100),'message':_0xb5f230(0x114)});}),app[a0_0xe54be6(0x124)](config['port'],()=>{const _0x2c2450=a0_0xe54be6;logger[_0x2c2450(0x123)](_0x2c2450(0x13b)+config[_0x2c2450(0x10c)]),logger['info'](_0x2c2450(0x139)+config['port']);}),process['on'](a0_0xe54be6(0x10d),()=>{const _0x1bd5d8=a0_0xe54be6;logger[_0x1bd5d8(0x123)]('接收到SIGINT信号,正在优雅关闭服务...'),process[_0x1bd5d8(0x10e)][_0x1bd5d8(0x134)]==='true'&&(logger['info'](_0x1bd5d8(0x115)),proxyLauncher['stopProxyServer']()),process[_0x1bd5d8(0x105)](0x0);}),process['on'](a0_0xe54be6(0x137),()=>{const _0x51ead7=a0_0xe54be6;logger[_0x51ead7(0x123)]('接收到SIGTERM信号,正在优雅关闭服务...'),process['env'][_0x51ead7(0x134)]==='true'&&(logger['info'](_0x51ead7(0x115)),proxyLauncher['stopProxyServer']()),process[_0x51ead7(0x105)](0x0);}),module[a0_0xe54be6(0x106)]=app;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/config/config.js CHANGED
@@ -1,56 +1 @@
1
- // 读取并解析API_KEYS环境变量
2
- // 解析API Keys配置
3
- let apiKeysConfig = {};
4
- try {
5
- if (process.env.API_KEYS) {
6
- // 解析API Keys字符串为对象
7
- apiKeysConfig = JSON.parse(process.env.API_KEYS);
8
- console.log('正在从环境变量加载API Keys...');
9
- console.log(`成功解析API Keys,包含 ${Object.keys(apiKeysConfig).length} 个键`);
10
- } else {
11
- console.log('警告: 环境变量API_KEYS未设置,系统将无法正常工作');
12
- }
13
- } catch (error) {
14
- console.error('解析API_KEYS环境变量失败:', error.message);
15
- console.error('请确保API_KEYS是有效的JSON格式');
16
- }
17
-
18
- // 导出配置
19
- module.exports = {
20
- port: process.env.PORT || 3010,
21
- apiKeys: apiKeysConfig,
22
- defaultRotationStrategy: process.env.ROTATION_STRATEGY || 'round-robin',
23
-
24
- // 添加代理配置
25
- proxy: {
26
- enabled: process.env.PROXY_ENABLED === 'true' || false,
27
- url: process.env.PROXY_URL || 'http://127.0.0.1:7890',
28
- },
29
-
30
- // GitHub相关配置
31
- github: {
32
- token: process.env.GITHUB_TOKEN,
33
- owner: process.env.GITHUB_OWNER,
34
- repo: process.env.GITHUB_REPO,
35
- workflowId: process.env.GITHUB_WORKFLOW_ID,
36
- triggerWorkflow: process.env.TRIGGER_WORKFLOW === 'true'
37
- },
38
-
39
- // 工作流参数
40
- workflowParams: {
41
- number: parseInt(process.env.REGISTER_NUMBER || '2', 10),
42
- maxWorkers: parseInt(process.env.REGISTER_MAX_WORKERS || '1', 10),
43
- emailServer: process.env.REGISTER_EMAIL_SERVER || 'TempEmail',
44
- ingestToOneapi: process.env.REGISTER_INGEST_TO_ONEAPI === 'true',
45
- uploadArtifact: process.env.REGISTER_UPLOAD_ARTIFACT === 'true',
46
- useConfigFile: process.env.REGISTER_USE_CONFIG_FILE !== 'false',
47
- emailConfigs: process.env.REGISTER_EMAIL_CONFIGS || '[]'
48
- },
49
-
50
- // 刷新配置
51
- refresh: {
52
- cron: process.env.REFRESH_CRON || '0 */6 * * *',
53
- minCookieCount: parseInt(process.env.MIN_COOKIE_COUNT || '2', 10),
54
- enabled: process.env.ENABLE_AUTO_REFRESH === 'true'
55
- }
56
- };
 
1
+ const a0_0x3b0fd7=a0_0x41f8;(function(_0x20f95b,_0x302eab){const _0x477034=a0_0x41f8,_0x44e7b8=_0x20f95b();while(!![]){try{const _0x597163=-parseInt(_0x477034(0x9a))/0x1*(parseInt(_0x477034(0xb5))/0x2)+parseInt(_0x477034(0x94))/0x3*(-parseInt(_0x477034(0xbc))/0x4)+parseInt(_0x477034(0x88))/0x5*(-parseInt(_0x477034(0x83))/0x6)+-parseInt(_0x477034(0xb3))/0x7*(parseInt(_0x477034(0xaf))/0x8)+-parseInt(_0x477034(0x90))/0x9*(parseInt(_0x477034(0x9d))/0xa)+-parseInt(_0x477034(0xb7))/0xb*(parseInt(_0x477034(0xb1))/0xc)+-parseInt(_0x477034(0x80))/0xd*(-parseInt(_0x477034(0xc3))/0xe);if(_0x597163===_0x302eab)break;else _0x44e7b8['push'](_0x44e7b8['shift']());}catch(_0x108f85){_0x44e7b8['push'](_0x44e7b8['shift']());}}}(a0_0x26e1,0xa4bab));function a0_0x41f8(_0x4a013d,_0x49938b){const _0x3ec17a=a0_0x26e1();return a0_0x41f8=function(_0x2aad8c,_0x5766c5){_0x2aad8c=_0x2aad8c-0x7d;let _0x26e177=_0x3ec17a[_0x2aad8c];if(a0_0x41f8['nFMZxT']===undefined){var _0x41f87f=function(_0x347e2f){const _0x414a89='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2496ec='',_0x168038='',_0x114740=_0x2496ec+_0x41f87f;for(let _0x305e89=0x0,_0x4c47c4,_0x59e96a,_0x131fa3=0x0;_0x59e96a=_0x347e2f['charAt'](_0x131fa3++);~_0x59e96a&&(_0x4c47c4=_0x305e89%0x4?_0x4c47c4*0x40+_0x59e96a:_0x59e96a,_0x305e89++%0x4)?_0x2496ec+=_0x114740['charCodeAt'](_0x131fa3+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x4c47c4>>(-0x2*_0x305e89&0x6)):_0x305e89:0x0){_0x59e96a=_0x414a89['indexOf'](_0x59e96a);}for(let _0x4905dc=0x0,_0x1699dc=_0x2496ec['length'];_0x4905dc<_0x1699dc;_0x4905dc++){_0x168038+='%'+('00'+_0x2496ec['charCodeAt'](_0x4905dc)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x168038);};a0_0x41f8['DmCpRk']=_0x41f87f,_0x4a013d=arguments,a0_0x41f8['nFMZxT']=!![];}const _0x464e5e=_0x3ec17a[0x0],_0x4eaca7=_0x2aad8c+_0x464e5e,_0x158fb2=_0x4a013d[_0x4eaca7];if(!_0x158fb2){const _0x174027=function(_0x5ca010){this['MLZFzN']=_0x5ca010,this['ngeiww']=[0x1,0x0,0x0],this['raHvFW']=function(){return'newState';},this['hKimDl']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['qsHmBl']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x174027['prototype']['jqMWaX']=function(){const _0x4f732c=new RegExp(this['hKimDl']+this['qsHmBl']),_0xe7b6d3=_0x4f732c['test'](this['raHvFW']['toString']())?--this['ngeiww'][0x1]:--this['ngeiww'][0x0];return this['LvqfZj'](_0xe7b6d3);},_0x174027['prototype']['LvqfZj']=function(_0x32edaf){if(!Boolean(~_0x32edaf))return _0x32edaf;return this['LvfmRt'](this['MLZFzN']);},_0x174027['prototype']['LvfmRt']=function(_0x1d2d2b){for(let _0x8226a=0x0,_0x24100b=this['ngeiww']['length'];_0x8226a<_0x24100b;_0x8226a++){this['ngeiww']['push'](Math['round'](Math['random']())),_0x24100b=this['ngeiww']['length'];}return _0x1d2d2b(this['ngeiww'][0x0]);},new _0x174027(a0_0x41f8)['jqMWaX'](),_0x26e177=a0_0x41f8['DmCpRk'](_0x26e177),_0x4a013d[_0x4eaca7]=_0x26e177;}else _0x26e177=_0x158fb2;return _0x26e177;},a0_0x41f8(_0x4a013d,_0x49938b);}function log(_0x168038,_0x114740){const _0x51edd6=a0_0x41f8,_0x305e89=(function(){let _0x131fa3=!![];return function(_0x4905dc,_0x1699dc){const _0x174027=_0x131fa3?function(){const _0x135dfb=a0_0x41f8;if(_0x1699dc){const _0x5ca010=_0x1699dc[_0x135dfb(0xa5)](_0x4905dc,arguments);return _0x1699dc=null,_0x5ca010;}}:function(){};return _0x131fa3=![],_0x174027;};}()),_0x4c47c4=_0x305e89(this,function(){const _0xb3ddc0=a0_0x41f8;return _0x4c47c4[_0xb3ddc0(0xa4)]()['search'](_0xb3ddc0(0xa8))[_0xb3ddc0(0xa4)]()['constructor'](_0x4c47c4)['search'](_0xb3ddc0(0xa8));});_0x4c47c4();const _0x59e96a=new Date()[_0x51edd6(0x8f)]();if(_0x168038===_0x51edd6(0x9c))console[_0x51edd6(0x8b)](_0x51edd6(0xac)+_0x59e96a+'\x20'+_0x114740);else _0x168038===_0x51edd6(0xae)?console[_0x51edd6(0xa3)](_0x51edd6(0xb0)+_0x59e96a+'\x20'+_0x114740):console[_0x51edd6(0x84)]('[INFO]\x20'+_0x59e96a+'\x20'+_0x114740);}let apiKeysConfig={};function a0_0x26e1(){const _0x112bec=['CgfYC2u','r0Lusfvcx09xtKvs','Dg9ju09tDhjPBMC','mty5mJC4m2HNqNvPqW','ios4QUMuRG','te9hx01bwf9gsuXfuW','te9hx1rpx0zjteu','ntaXndj6wNLkt1m','vfjjr0DfuL9xt1jlrKXpvW','5OIq5yQF6kEJ5P6qqvbjieTLExpVViZLJixLKkSG','ufjpwfLFvvjm','zw50CMLLCW','su5gtW','nZKXne5Uze5vCq','qvbjx0Tfwv8','rvjst1i','mJb2CgzQqLC','Dhj1zq','r0Lusfvcx1DpuKTgte9xx0Le','C3rHCNrZv2L0Aa','A2v5CW','uKvhsvnurvjFvvnfx0nptKzjr19gsuXf','D2fYBG','Dg9tDhjPBMC','yxbWBhK','ufjpwfLFru5bqKXfra','6k+356gU5l+Dqvbjx0TfwvpMMk/MNiNMLyJNMOrku09o5Qc85BYp','kcGOlISPkYKRksSK','uKvguKvtsf9duK9o','y29SB3jLza','uKvhsvnurvjFsu5hrvnux1rpx09orufqsq','w0vsuK9sxsa','mcaQlZyGkIaQicO','v0fstG','mta5nJG4v3PnDvrT','w1DbuK5Dia','mtu0mdy3odHyDMnlDvm','zxHWB3j0CW','mJeWB0PVvM9Q','uKvhsvnurvjFru1bsuXFq09orKLhuW','ntHOyNPpu0K','BgvUz3rO','mtfLs1HMzxi','5Q2J5zYO5lUo546V5Akd5y+y6yEp5yQG6l29qvbjieTLExmUlI4','ru5bqKXfx0fvve9FuKvguKvtsa','6kEJ5P6qqvbjx0TfwvpNJQ/LOOpLJ5JPH4/LPlhOTku6','te9hx0zpuK1bva','mJm2AhHPr1Dp','te9hx01bwf9tsvPf','vgvTCevTywLS','uKvhsvnurvjFtLvnqKvs','BwfW','uKvhsvnurvjFvvbmt0fex0fsveLgqunu','zMLSDgvY','mtm5ndqYnJziD2nosxC','C2ST','Ahr0CdOVlZeYnY4WlJaUmtO3odKW','zNjVBuvUDhjPzxm','nJvgrLfTEeW','zMfSC2u','r0Lusfvcx1rps0vo','mJm0r0LwBe1l','Bg9N','tuLox0npt0Tjrv9dt1vova','uKvhsvnurvjFru1bsuXFu0vsvKvs','CMvWBgfJzq','mtmWntu1vxjQqKXU','uKvhsvnurvjFtufyx1DpuKTfuLm','qvbjx0Tfwvm','zxjYB3i','zw52'];a0_0x26e1=function(){return _0x112bec;};return a0_0x26e1();}try{process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x8a)]&&(apiKeysConfig=JSON[a0_0x3b0fd7(0x8d)](process['env'][a0_0x3b0fd7(0x8a)]),log(a0_0x3b0fd7(0x99),a0_0x3b0fd7(0xb8)),log(a0_0x3b0fd7(0x99),a0_0x3b0fd7(0x96)+Object[a0_0x3b0fd7(0xa1)](apiKeysConfig)[a0_0x3b0fd7(0xb6)]+a0_0x3b0fd7(0x91)));}catch(a0_0x4f732c){log('ERROR',a0_0x3b0fd7(0xba)+a0_0x4f732c['message']),log(a0_0x3b0fd7(0x9c),a0_0x3b0fd7(0xa7));}module[a0_0x3b0fd7(0xb2)]={'port':process[a0_0x3b0fd7(0x8c)]['PORT']||0xbb8,'log':{'level':process[a0_0x3b0fd7(0x8c)]['LOG_LEVEL']||'INFO','format':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xbb)]||a0_0x3b0fd7(0xaa),'toFile':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x93)]==='true'||![],'maxSize':parseInt(process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xbd)]||'10',0xa)*0x400*0x400,'maxFiles':parseInt(process['env'][a0_0x3b0fd7(0x92)]||'10',0xa)},'apiKeys':{...apiKeysConfig,...Object[a0_0x3b0fd7(0x7f)](Object[a0_0x3b0fd7(0x98)](process[a0_0x3b0fd7(0x8c)])[a0_0x3b0fd7(0xc2)](([_0xe7b6d3])=>_0xe7b6d3[a0_0x3b0fd7(0xa0)](a0_0x3b0fd7(0x9b)))[a0_0x3b0fd7(0xc0)](([_0x32edaf,_0x1d2d2b])=>{const _0x1481ac=a0_0x3b0fd7,_0x8226a=_0x32edaf[_0x1481ac(0x87)](_0x1481ac(0x9b),_0x1481ac(0x7d));try{const _0x24100b=JSON[_0x1481ac(0x8d)](_0x1d2d2b);return[_0x8226a,_0x24100b];}catch(_0x164a51){return[_0x8226a,_0x1d2d2b];}}))},'defaultRotationStrategy':process['env']['ROTATION_STRATEGY']||'round-robin','proxy':{'enabled':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xa6)]===a0_0x3b0fd7(0x9e)||![],'url':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x97)]||a0_0x3b0fd7(0x7e)},'github':{'token':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x82)],'owner':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x8e)],'repo':process['env']['GITHUB_REPO'],'workflowId':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x9f)],'triggerWorkflow':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x95)]==='true'},'workflowParams':{'number':parseInt(process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xbf)]||'2',0xa),'maxWorkers':parseInt(process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x89)]||'1',0xa),'emailServer':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x86)]||a0_0x3b0fd7(0xbe),'ingestToOneapi':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xab)]==='true','uploadArtifact':process['env'][a0_0x3b0fd7(0xc1)]===a0_0x3b0fd7(0x9e),'useConfigFile':process['env'][a0_0x3b0fd7(0xa2)]!==a0_0x3b0fd7(0x81),'emailConfigs':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xb4)]||'[]'},'refresh':{'cron':process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0xa9)]||a0_0x3b0fd7(0xad),'minCookieCount':parseInt(process[a0_0x3b0fd7(0x8c)][a0_0x3b0fd7(0x85)]||'2',0xa),'enabled':process['env'][a0_0x3b0fd7(0xb9)]==='true'}};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/middleware/auth.js CHANGED
@@ -1,44 +1 @@
1
- const admin = require('../models/admin');
2
-
3
- // 验证管理员权限的中间件
4
- function authMiddleware(req, res, next) {
5
- // 跳过登录相关的路由
6
- if (req.path.startsWith('/v1/admin/')) {
7
- return next();
8
- }
9
-
10
- // 修改为:只对管理相关的API进行认证
11
- if (req.path.startsWith('/v1/api-keys') ||
12
- req.path.startsWith('/v1/invalid-cookies') ||
13
- req.path.startsWith('/v1/refresh-cookies')) {
14
- // 获取Authorization头
15
- const authHeader = req.headers.authorization;
16
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
17
- return res.status(401).json({
18
- success: false,
19
- message: '未提供认证token'
20
- });
21
- }
22
-
23
- // 提取token
24
- const token = authHeader.split(' ')[1];
25
-
26
- // 验证token
27
- const result = admin.verifyToken(token);
28
- if (!result.success) {
29
- return res.status(401).json({
30
- success: false,
31
- message: '无效的token'
32
- });
33
- }
34
-
35
- // 将用户信息添加到请求对象
36
- req.admin = {
37
- username: result.username
38
- };
39
- }
40
-
41
- next();
42
- }
43
-
44
- module.exports = authMiddleware;
 
1
+ const a0_0x37d6bd=a0_0x2585;function a0_0x2585(_0xac6f56,_0x351fd2){const _0x584dd8=a0_0xd434();return a0_0x2585=function(_0x1e04cd,_0x4ba2f5){_0x1e04cd=_0x1e04cd-0x15b;let _0xd434a9=_0x584dd8[_0x1e04cd];if(a0_0x2585['ovLFQy']===undefined){var _0x25853d=function(_0x512a55){const _0x53b645='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x118b70='',_0x1450bf='',_0x3565a9=_0x118b70+_0x25853d;for(let _0x39637e=0x0,_0x279e7c,_0x430fba,_0x4f51b7=0x0;_0x430fba=_0x512a55['charAt'](_0x4f51b7++);~_0x430fba&&(_0x279e7c=_0x39637e%0x4?_0x279e7c*0x40+_0x430fba:_0x430fba,_0x39637e++%0x4)?_0x118b70+=_0x3565a9['charCodeAt'](_0x4f51b7+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x279e7c>>(-0x2*_0x39637e&0x6)):_0x39637e:0x0){_0x430fba=_0x53b645['indexOf'](_0x430fba);}for(let _0x491049=0x0,_0x3aaaad=_0x118b70['length'];_0x491049<_0x3aaaad;_0x491049++){_0x1450bf+='%'+('00'+_0x118b70['charCodeAt'](_0x491049)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1450bf);};a0_0x2585['ehPUBm']=_0x25853d,_0xac6f56=arguments,a0_0x2585['ovLFQy']=!![];}const _0x3b782e=_0x584dd8[0x0],_0x184160=_0x1e04cd+_0x3b782e,_0x2144c5=_0xac6f56[_0x184160];if(!_0x2144c5){const _0x198abd=function(_0x310ad3){this['jsZcKK']=_0x310ad3,this['fNGjxy']=[0x1,0x0,0x0],this['UFwRRg']=function(){return'newState';},this['uMOXJx']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['nqODHS']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x198abd['prototype']['OnnmMX']=function(){const _0x581145=new RegExp(this['uMOXJx']+this['nqODHS']),_0x39b366=_0x581145['test'](this['UFwRRg']['toString']())?--this['fNGjxy'][0x1]:--this['fNGjxy'][0x0];return this['jYvytj'](_0x39b366);},_0x198abd['prototype']['jYvytj']=function(_0x1966d3){if(!Boolean(~_0x1966d3))return _0x1966d3;return this['PzssbX'](this['jsZcKK']);},_0x198abd['prototype']['PzssbX']=function(_0xe4cb61){for(let _0x400723=0x0,_0x5079d8=this['fNGjxy']['length'];_0x400723<_0x5079d8;_0x400723++){this['fNGjxy']['push'](Math['round'](Math['random']())),_0x5079d8=this['fNGjxy']['length'];}return _0xe4cb61(this['fNGjxy'][0x0]);},new _0x198abd(a0_0x2585)['OnnmMX'](),_0xd434a9=a0_0x2585['ehPUBm'](_0xd434a9),_0xac6f56[_0x184160]=_0xd434a9;}else _0xd434a9=_0x2144c5;return _0xd434a9;},a0_0x2585(_0xac6f56,_0x351fd2);}(function(_0x589232,_0x24c5ba){const _0x3428e1=a0_0x2585,_0x2b0a82=_0x589232();while(!![]){try{const _0x4fa58d=-parseInt(_0x3428e1(0x161))/0x1*(parseInt(_0x3428e1(0x16b))/0x2)+-parseInt(_0x3428e1(0x174))/0x3*(parseInt(_0x3428e1(0x15b))/0x4)+parseInt(_0x3428e1(0x177))/0x5*(parseInt(_0x3428e1(0x165))/0x6)+parseInt(_0x3428e1(0x175))/0x7*(parseInt(_0x3428e1(0x17a))/0x8)+-parseInt(_0x3428e1(0x166))/0x9+parseInt(_0x3428e1(0x171))/0xa+parseInt(_0x3428e1(0x176))/0xb;if(_0x4fa58d===_0x24c5ba)break;else _0x2b0a82['push'](_0x2b0a82['shift']());}catch(_0x11399b){_0x2b0a82['push'](_0x2b0a82['shift']());}}}(a0_0xd434,0x9d592));const a0_0x4ba2f5=(function(){let _0x1450bf=!![];return function(_0x3565a9,_0x39637e){const _0x279e7c=_0x1450bf?function(){const _0x5da303=a0_0x2585;if(_0x39637e){const _0x430fba=_0x39637e[_0x5da303(0x15e)](_0x3565a9,arguments);return _0x39637e=null,_0x430fba;}}:function(){};return _0x1450bf=![],_0x279e7c;};}()),a0_0x1e04cd=a0_0x4ba2f5(this,function(){const _0x3c2c85=a0_0x2585;return a0_0x1e04cd[_0x3c2c85(0x173)]()[_0x3c2c85(0x164)](_0x3c2c85(0x167))[_0x3c2c85(0x173)]()[_0x3c2c85(0x162)](a0_0x1e04cd)[_0x3c2c85(0x164)](_0x3c2c85(0x167));});a0_0x1e04cd();const admin=require(a0_0x37d6bd(0x16f));function a0_0xd434(){const _0xbd892a=['l3yXl2fWAs1RzxLZ','qMvHCMvYia','yxbWBhK','l3yXl2fKBwLUlW','5PEG5Pwi55QeDg9Rzw4','odm4u0nPChLk','y29UC3rYDwn0B3i','Cgf0Aa','C2vHCMnO','mZiZmJjsqwnurKG','otiZntyXmvHIBKTxza','kcGOlISPkYKRksSK','l3yXl2XVz3m','ANnVBG','C3rHDhvZ','mtqZog1Ly3HkrW','DMvYAwz5vg9Rzw4','C3bSAxq','zxHWB3j0CW','lI4VBw9KzwXZl2fKBwLU','C3vJy2vZCW','mte0mJa5ntbuyvLXqwu','C3rHCNrZv2L0Aa','Dg9tDhjPBMC','nde3ou1KrgX3sW','nJiWndG0ovrlwMnHsW','nZC2mtG5n0PwA25TEa','ndeWwMXKvuTS','yxv0Ag9YAxPHDgLVBG','5PYQ5O+q5l6B6k6K6k+bDg9Rzw4','ogX3qwfPyW','l2XVz3mUAhrTBa','mJu5mMvRtNzODW'];a0_0xd434=function(){return _0xbd892a;};return a0_0xd434();}function authMiddleware(_0x4f51b7,_0x491049,_0x3aaaad){const _0x530e8a=a0_0x37d6bd;if(_0x4f51b7['path'][_0x530e8a(0x172)](_0x530e8a(0x15f)))return _0x3aaaad();if(_0x4f51b7[_0x530e8a(0x163)]===_0x530e8a(0x17b))return _0x3aaaad();if(_0x4f51b7['path'][_0x530e8a(0x172)](_0x530e8a(0x15c))||_0x4f51b7[_0x530e8a(0x163)][_0x530e8a(0x172)]('/v1/invalid-cookies')||_0x4f51b7[_0x530e8a(0x163)][_0x530e8a(0x172)]('/v1/refresh-cookies')||_0x4f51b7[_0x530e8a(0x163)][_0x530e8a(0x172)](_0x530e8a(0x168))){const _0x198abd=_0x4f51b7['headers'][_0x530e8a(0x178)];if(!_0x198abd||!_0x198abd['startsWith'](_0x530e8a(0x15d)))return _0x491049[_0x530e8a(0x16a)](0x191)['json']({'success':![],'message':_0x530e8a(0x179)});const _0x310ad3=_0x198abd[_0x530e8a(0x16d)]('\x20')[0x1],_0x581145=admin[_0x530e8a(0x16c)](_0x310ad3);if(!_0x581145[_0x530e8a(0x170)])return _0x491049['status'](0x191)[_0x530e8a(0x169)]({'success':![],'message':_0x530e8a(0x160)});_0x4f51b7['admin']={'username':_0x581145['username']};}_0x3aaaad();}module[a0_0x37d6bd(0x16e)]=authMiddleware;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/models/admin.js CHANGED
@@ -1,114 +1 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const crypto = require('crypto');
4
- const jwt = require('jsonwebtoken');
5
-
6
- // 管理员数据文件路径
7
- const ADMIN_FILE = path.join(__dirname, '../../data/admin.json');
8
- const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
9
-
10
- // 确保data目录存在
11
- const dataDir = path.dirname(ADMIN_FILE);
12
- if (!fs.existsSync(dataDir)) {
13
- fs.mkdirSync(dataDir, { recursive: true });
14
- }
15
-
16
- // 确保admin.json文件存在
17
- if (!fs.existsSync(ADMIN_FILE)) {
18
- fs.writeFileSync(ADMIN_FILE, JSON.stringify({ admin: null }), 'utf8');
19
- }
20
-
21
- class Admin {
22
- constructor() {
23
- this.loadAdmin();
24
- }
25
-
26
- // 加载管理员数据
27
- loadAdmin() {
28
- try {
29
- const data = fs.readFileSync(ADMIN_FILE, 'utf8');
30
- this.admin = JSON.parse(data).admin;
31
- } catch (error) {
32
- console.error('加载管理员数据失败:', error);
33
- this.admin = null;
34
- }
35
- }
36
-
37
- // 保存管理员数据
38
- saveAdmin() {
39
- try {
40
- fs.writeFileSync(ADMIN_FILE, JSON.stringify({ admin: this.admin }), 'utf8');
41
- } catch (error) {
42
- console.error('保存管理员数据失败:', error);
43
- throw error;
44
- }
45
- }
46
-
47
- // 检查是否已有管理员
48
- hasAdmin() {
49
- return !!this.admin;
50
- }
51
-
52
- // 注册管理员
53
- register(username, password) {
54
- if (this.hasAdmin()) {
55
- throw new Error('已存在管理员账号');
56
- }
57
-
58
- // 生成盐值
59
- const salt = crypto.randomBytes(16).toString('hex');
60
- // 使用盐值加密密码
61
- const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex');
62
-
63
- this.admin = {
64
- username,
65
- salt,
66
- hash
67
- };
68
-
69
- this.saveAdmin();
70
- return this.generateToken(username);
71
- }
72
-
73
- // 验证密码
74
- verifyPassword(password, salt, hash) {
75
- const testHash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex');
76
- return testHash === hash;
77
- }
78
-
79
- // 登录验证
80
- login(username, password) {
81
- if (!this.admin || username !== this.admin.username) {
82
- throw new Error('用户名或密码错误');
83
- }
84
-
85
- if (!this.verifyPassword(password, this.admin.salt, this.admin.hash)) {
86
- throw new Error('用户名或密码错误');
87
- }
88
-
89
- return this.generateToken(username);
90
- }
91
-
92
- // 生成JWT token
93
- generateToken(username) {
94
- return jwt.sign({ username }, JWT_SECRET, { expiresIn: '24h' });
95
- }
96
-
97
- // 验证JWT token
98
- verifyToken(token) {
99
- try {
100
- const decoded = jwt.verify(token, JWT_SECRET);
101
- return {
102
- success: true,
103
- username: decoded.username
104
- };
105
- } catch (error) {
106
- return {
107
- success: false,
108
- error: 'Invalid token'
109
- };
110
- }
111
- }
112
- }
113
-
114
- module.exports = new Admin();
 
1
+ function a0_0x4957(_0x1524ff,_0x5c2e08){const _0x3721e8=a0_0x1351();return a0_0x4957=function(_0x1490fa,_0xc85c98){_0x1490fa=_0x1490fa-0x132;let _0x13515d=_0x3721e8[_0x1490fa];if(a0_0x4957['XmysvE']===undefined){var _0x4957be=function(_0x3fa810){const _0x3578c4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x15eaa0='',_0xb5af9d='',_0x595b70=_0x15eaa0+_0x4957be;for(let _0x8915ac=0x0,_0x2ae885,_0x5b9d9c,_0x416075=0x0;_0x5b9d9c=_0x3fa810['charAt'](_0x416075++);~_0x5b9d9c&&(_0x2ae885=_0x8915ac%0x4?_0x2ae885*0x40+_0x5b9d9c:_0x5b9d9c,_0x8915ac++%0x4)?_0x15eaa0+=_0x595b70['charCodeAt'](_0x416075+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x2ae885>>(-0x2*_0x8915ac&0x6)):_0x8915ac:0x0){_0x5b9d9c=_0x3578c4['indexOf'](_0x5b9d9c);}for(let _0x182f20=0x0,_0x24a866=_0x15eaa0['length'];_0x182f20<_0x24a866;_0x182f20++){_0xb5af9d+='%'+('00'+_0x15eaa0['charCodeAt'](_0x182f20)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0xb5af9d);};a0_0x4957['zMfmvr']=_0x4957be,_0x1524ff=arguments,a0_0x4957['XmysvE']=!![];}const _0x3a92b5=_0x3721e8[0x0],_0x21f447=_0x1490fa+_0x3a92b5,_0xd8cc17=_0x1524ff[_0x21f447];if(!_0xd8cc17){const _0x20484c=function(_0x4ead62){this['cEyclV']=_0x4ead62,this['MhThOi']=[0x1,0x0,0x0],this['Ljvydh']=function(){return'newState';},this['piHNWt']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['wHUTgT']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x20484c['prototype']['Kddjri']=function(){const _0x2c3d21=new RegExp(this['piHNWt']+this['wHUTgT']),_0xfc25ea=_0x2c3d21['test'](this['Ljvydh']['toString']())?--this['MhThOi'][0x1]:--this['MhThOi'][0x0];return this['kFNXxU'](_0xfc25ea);},_0x20484c['prototype']['kFNXxU']=function(_0x35899e){if(!Boolean(~_0x35899e))return _0x35899e;return this['FzpAes'](this['cEyclV']);},_0x20484c['prototype']['FzpAes']=function(_0x4f8b31){for(let _0x303ae0=0x0,_0x1b3c39=this['MhThOi']['length'];_0x303ae0<_0x1b3c39;_0x303ae0++){this['MhThOi']['push'](Math['round'](Math['random']())),_0x1b3c39=this['MhThOi']['length'];}return _0x4f8b31(this['MhThOi'][0x0]);},new _0x20484c(a0_0x4957)['Kddjri'](),_0x13515d=a0_0x4957['zMfmvr'](_0x13515d),_0x1524ff[_0x21f447]=_0x13515d;}else _0x13515d=_0xd8cc17;return _0x13515d;},a0_0x4957(_0x1524ff,_0x5c2e08);}const a0_0x482d97=a0_0x4957;(function(_0x3919cb,_0x871992){const _0x25926f=a0_0x4957,_0x28ea77=_0x3919cb();while(!![]){try{const _0x345715=parseInt(_0x25926f(0x147))/0x1+parseInt(_0x25926f(0x159))/0x2*(-parseInt(_0x25926f(0x146))/0x3)+-parseInt(_0x25926f(0x135))/0x4+parseInt(_0x25926f(0x155))/0x5+-parseInt(_0x25926f(0x137))/0x6+-parseInt(_0x25926f(0x141))/0x7+parseInt(_0x25926f(0x157))/0x8;if(_0x345715===_0x871992)break;else _0x28ea77['push'](_0x28ea77['shift']());}catch(_0x13630f){_0x28ea77['push'](_0x28ea77['shift']());}}}(a0_0x1351,0x35e8d));const a0_0xc85c98=(function(){let _0xb5af9d=!![];return function(_0x595b70,_0x8915ac){const _0x2ae885=_0xb5af9d?function(){const _0x1f6c2f=a0_0x4957;if(_0x8915ac){const _0x5b9d9c=_0x8915ac[_0x1f6c2f(0x15b)](_0x595b70,arguments);return _0x8915ac=null,_0x5b9d9c;}}:function(){};return _0xb5af9d=![],_0x2ae885;};}()),a0_0x1490fa=a0_0xc85c98(this,function(){const _0x5b768b=a0_0x4957;return a0_0x1490fa[_0x5b768b(0x149)]()[_0x5b768b(0x144)]('(((.+)+)+)+$')['toString']()[_0x5b768b(0x15c)](a0_0x1490fa)[_0x5b768b(0x144)](_0x5b768b(0x132));});a0_0x1490fa();const fs=require('fs'),path=require(a0_0x482d97(0x160)),crypto=require(a0_0x482d97(0x148)),jwt=require(a0_0x482d97(0x152)),ADMIN_FILE=path[a0_0x482d97(0x156)](__dirname,a0_0x482d97(0x158)),JWT_SECRET=process['env'][a0_0x482d97(0x13f)]||a0_0x482d97(0x139),dataDir=path[a0_0x482d97(0x142)](ADMIN_FILE);function a0_0x1351(){const _0x32dbc7=['DMvYAwz5','zxHPC3rZu3LUyW','CMvHzezPBgvtEw5J','DMvYAwz5vg9Rzw4','sLDux1nfq1jfva','DxrMoa','mJK0ntC5nM9zrg9Rra','zgLYBMfTzq','5BEY5A2y5zYO566H55cg5zgy6lsM5y+3','C2vHCMnO','Bg9HzefKBwLU','mZmYota0sNbVsef2','nZi5mdfbwwDbCvu','y3j5ChrV','Dg9tDhjPBMC','zxHWB3j0CW','D3jPDgvgAwXLu3LUyW','DxnLCM5HBwu','C2HHnteY','zxjYB3i','AgfZqwrTAw4','C2fSDa','C2f2zufKBwLU','ANnVBNDLyNrVA2vU','z2vUzxjHDgvuB2TLBG','DMvYAwz5ugfZC3DVCMq','odC1ndvyDhLjBxq','AM9PBG','nZa2odaWmfv3zLjrrW','lI4VlI4Vzgf0ys9Hzg1PBI5QC29U','ngXKBuLzEq','CgfYC2u','yxbWBhK','y29UC3rYDwn0B3i','Agv4','CgjRzgyYu3LUyW','C3rYAw5NAwz5','Cgf0Aa','5l+D5A2y566H55cg5zgy5PwW5O2U5AsX6lsLoG','kcGOlISPkYKRksSK','55sO5OI35zcn5OIw5A+g56cb6zsz6k+V','CMvNAxn0zxi','odm2ndbfEufguu8','mJrO','ntm2ntm4swfbDLDP','ywrTAw4','Ew91CI1ZzwnYzxqTA2v5','C2LNBG'];a0_0x1351=function(){return _0x32dbc7;};return a0_0x1351();}!fs[a0_0x482d97(0x13c)](dataDir)&&fs['mkdirSync'](dataDir,{'recursive':!![]});!fs[a0_0x482d97(0x13c)](ADMIN_FILE)&&fs[a0_0x482d97(0x14b)](ADMIN_FILE,JSON[a0_0x482d97(0x15f)]({'admin':null}),'utf8');class Admin{constructor(){const _0x50c2a5=a0_0x482d97;this[_0x50c2a5(0x145)]();}[a0_0x482d97(0x145)](){const _0x1b945a=a0_0x482d97;try{const _0x416075=fs[_0x1b945a(0x13d)](ADMIN_FILE,_0x1b945a(0x140));this[_0x1b945a(0x138)]=JSON[_0x1b945a(0x15a)](_0x416075)[_0x1b945a(0x138)];}catch(_0x182f20){console['error']('加载管理员数据失败:',_0x182f20),this['admin']=null;}}[a0_0x482d97(0x151)](){const _0x4dc316=a0_0x482d97;try{fs[_0x4dc316(0x14b)](ADMIN_FILE,JSON[_0x4dc316(0x15f)]({'admin':this[_0x4dc316(0x138)]}),_0x4dc316(0x140));}catch(_0x24a866){console[_0x4dc316(0x14e)](_0x4dc316(0x161),_0x24a866);throw _0x24a866;}}[a0_0x482d97(0x14f)](){return!!this['admin'];}[a0_0x482d97(0x134)](_0x20484c,_0x4ead62){const _0x405f8f=a0_0x482d97;if(this[_0x405f8f(0x14f)]())throw new Error(_0x405f8f(0x143));const _0x2c3d21=crypto['randomBytes'](0x10)[_0x405f8f(0x149)](_0x405f8f(0x15d)),_0xfc25ea=crypto[_0x405f8f(0x15e)](_0x4ead62,_0x2c3d21,0x3e8,0x40,_0x405f8f(0x14d))[_0x405f8f(0x149)]('hex');return this[_0x405f8f(0x138)]={'username':_0x20484c,'salt':_0x2c3d21,'hash':_0xfc25ea},this[_0x405f8f(0x151)](),this[_0x405f8f(0x153)](_0x20484c);}[a0_0x482d97(0x154)](_0x35899e,_0x4f8b31,_0x303ae0){const _0x203d35=a0_0x482d97,_0x1b3c39=crypto[_0x203d35(0x15e)](_0x35899e,_0x4f8b31,0x3e8,0x40,'sha512')[_0x203d35(0x149)](_0x203d35(0x15d));return _0x1b3c39===_0x303ae0;}['login'](_0x1d2a3c,_0x365487){const _0x1820e2=a0_0x482d97;if(!this['admin']||_0x1d2a3c!==this['admin']['username'])throw new Error(_0x1820e2(0x133));if(!this[_0x1820e2(0x154)](_0x365487,this[_0x1820e2(0x138)][_0x1820e2(0x150)],this[_0x1820e2(0x138)]['hash']))throw new Error(_0x1820e2(0x133));return this[_0x1820e2(0x153)](_0x1d2a3c);}[a0_0x482d97(0x153)](_0x3c6304){const _0xb9125c=a0_0x482d97;return jwt[_0xb9125c(0x13a)]({'username':_0x3c6304},JWT_SECRET,{'expiresIn':_0xb9125c(0x136)});}[a0_0x482d97(0x13e)](_0x1a6316){const _0xc3f972=a0_0x482d97;try{const _0x3fd5f2=jwt[_0xc3f972(0x13b)](_0x1a6316,JWT_SECRET);return{'success':!![],'username':_0x3fd5f2[_0xc3f972(0x14c)]};}catch(_0x39e217){return{'success':![],'error':'Invalid\x20token'};}}}module[a0_0x482d97(0x14a)]=new Admin();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/proxy/cursor_proxy_server_android_arm64 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d39053422463f1cfeacdeb1a5f9ac7bfd22182cd8d5d22249b53d4dc6dadc0d0
3
+ size 12786243
src/proxy/cursor_proxy_server_linux_amd64 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:985fa643f2a5b793102a4e97b058f14fc1e58cfd280c0bcc70e8a8455e932a4e
3
+ size 12790492
src/proxy/cursor_proxy_server_windows_amd64.exe ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aef2c8f8ed22dbae376c9e709bce39eb774b2b747b65fa073d97933dddc8c4c6
3
+ size 12910080
src/proxy/others/cursor_proxy_server_android_arm64 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:38fde335e14480e7d4e99058e69a476a9a1dec3e7338a0c57707cfc73565adae
3
+ size 12780368
src/proxy/others/cursor_proxy_server_linux_amd64 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6fe0a95e158d753f3f179b88690d5e76cdb4a5b6408ca024bc544d2a84c6a919
3
+ size 12780345
src/proxy/others/cursor_proxy_server_windows_amd64.exe ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5c9704b115604ffde6b34d84a8e02a32c9184e7f9097506c641ed00388855ee2
3
+ size 12896768
src/public/index.html CHANGED
@@ -2,920 +2,325 @@
2
  <html lang="zh-CN">
3
  <head>
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Cursor To OpenAI - API Key 管理</title>
7
- <style>
8
- body {
9
- font-family: 'Arial', sans-serif;
10
- line-height: 1.6;
11
- margin: 0;
12
- padding: 20px;
13
- color: #333;
14
- max-width: 1200px;
15
- margin: 0 auto;
16
- }
17
- h1, h2 {
18
- color: #2c3e50;
19
- }
20
- .container {
21
- display: flex;
22
- flex-direction: column;
23
- gap: 20px;
24
- }
25
- .card {
26
- background: #fff;
27
- border-radius: 8px;
28
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
29
- padding: 20px;
30
- }
31
- .form-group {
32
- margin-bottom: 15px;
33
- }
34
- label {
35
- display: block;
36
- margin-bottom: 5px;
37
- font-weight: bold;
38
- }
39
- input, textarea {
40
- width: 100%;
41
- padding: 8px;
42
- border: 1px solid #ddd;
43
- border-radius: 4px;
44
- font-size: 16px;
45
- }
46
- textarea {
47
- min-height: 100px;
48
- font-family: monospace;
49
- }
50
- button {
51
- background: #3498db;
52
- color: white;
53
- border: none;
54
- padding: 10px 15px;
55
- border-radius: 4px;
56
- cursor: pointer;
57
- font-size: 16px;
58
- }
59
- button:hover {
60
- background: #2980b9;
61
- }
62
- table {
63
- width: 100%;
64
- border-collapse: collapse;
65
- }
66
- th, td {
67
- padding: 12px;
68
- text-align: left;
69
- border-bottom: 1px solid #ddd;
70
- }
71
- th {
72
- background-color: #f2f2f2;
73
- }
74
- .action-btn {
75
- background: #e74c3c;
76
- margin-right: 5px;
77
- }
78
- .action-btn:hover {
79
- background: #c0392b;
80
- }
81
- .edit-btn {
82
- background: #f39c12;
83
- margin-right: 5px;
84
- }
85
- .edit-btn:hover {
86
- background: #d35400;
87
- }
88
- .info {
89
- background-color: #d4edda;
90
- color: #155724;
91
- padding: 10px;
92
- border-radius: 4px;
93
- margin-bottom: 15px;
94
- }
95
- .error {
96
- background-color: #f8d7da;
97
- color: #721c24;
98
- padding: 10px;
99
- border-radius: 4px;
100
- margin-bottom: 15px;
101
- }
102
- .modal {
103
- display: none;
104
- position: fixed;
105
- z-index: 1;
106
- left: 0;
107
- top: 0;
108
- width: 100%;
109
- height: 100%;
110
- overflow: auto;
111
- background-color: rgba(0,0,0,0.4);
112
- }
113
- .modal-content {
114
- background-color: #fefefe;
115
- margin: 15% auto;
116
- padding: 20px;
117
- border: 1px solid #888;
118
- width: 80%;
119
- max-width: 600px;
120
- border-radius: 8px;
121
- }
122
- .close {
123
- color: #aaa;
124
- float: right;
125
- font-size: 28px;
126
- font-weight: bold;
127
- cursor: pointer;
128
- }
129
- .close:hover,
130
- .close:focus {
131
- color: black;
132
- text-decoration: none;
133
- }
134
- /* 无效Cookie样式 */
135
- .cookie-text {
136
- max-width: 80%;
137
- word-break: break-all;
138
- }
139
- </style>
140
  </head>
141
  <body>
142
  <div class="container">
143
- <div class="card">
144
- <h1>Cursor To OpenAI - API Key 管理</h1>
145
- <p>在此页面上,您可以管理自定义 API Key Cursor Cookie 的映射关系。</p>
146
- <div style="margin-top: 10px; display: flex; justify-content: space-between; align-items: center;">
147
- <div>
148
- <button id="testApiBtn" style="margin-right: 10px;">测试API连接</button>
149
- <button id="clearCacheBtn">清除缓存并刷新</button>
 
 
 
 
 
 
 
150
  </div>
151
  <div>
152
- <span id="adminUsername" style="margin-right: 10px;"></span>
153
- <button id="logoutBtn" style="background: #e74c3c;">退出登录</button>
 
 
 
 
154
  </div>
155
  </div>
156
- <div id="testApiResult" style="margin-top: 10px;"></div>
157
  </div>
158
 
159
  <div class="card">
160
- <h2>添加/更新 API Key</h2>
 
 
 
161
  <div id="addKeyMessage"></div>
162
  <form id="addKeyForm">
163
  <div class="form-group">
164
- <label for="apiKey">API Key(自定义)</label>
 
 
165
  <input type="text" id="apiKey" name="apiKey" placeholder="输入您想使用的自定义 API Key" required>
166
  </div>
167
  <div class="form-group">
168
- <label for="cookieValues">Cursor Cookie 值(多个值请用逗号分隔)</label>
169
- <textarea id="cookieValues" name="cookieValues" placeholder="输入 WorkosCursorSessionToken 值,多个值请用逗号分隔" required></textarea>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  </div>
171
- <button type="submit">保存</button>
 
 
172
  </form>
173
  </div>
174
 
175
  <div class="card">
176
- <h2>现有 API Key</h2>
 
 
 
177
  <div id="keyListMessage"></div>
178
- <table id="keyTable">
179
- <thead>
180
- <tr>
181
- <th>API Key</th>
182
- <th>Cookie 数量</th>
183
- <th>操作</th>
184
- </tr>
185
- </thead>
186
- <tbody id="keyList">
187
- <!-- 数据将通过 JavaScript 动态加载 -->
188
- </tbody>
189
- </table>
 
 
190
  </div>
191
 
192
  <div class="card">
193
- <h2>使用说明</h2>
194
- <ol>
 
 
 
195
  <li>添加自定义 API Key 和对应的 Cursor Cookie 值。</li>
 
196
  <li>使用自定义 API Key 作为 OpenAI API 的认证凭证。</li>
197
- <li>系统将自动在多个 Cookie 之间进行轮询。</li>
198
- <li>API 端点:
199
- <ul>
200
- <li>模型列表:<code>/v1/models</code></li>
201
- <li>聊天补全:<code>/v1/chat/completions</code></li>
202
  </ul>
203
  </li>
204
  </ol>
205
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  </div>
207
 
208
  <!-- 修改 Cookie 的模态框 -->
209
  <div id="editModal" class="modal">
210
  <div class="modal-content">
211
  <span class="close">&times;</span>
212
- <h2>修改 API Key Cookie</h2>
 
 
 
213
  <div id="editModalMessage"></div>
214
  <form id="editCookieForm">
215
  <input type="hidden" id="editApiKey" name="editApiKey">
216
  <div class="form-group">
217
- <label for="editCookieValues">Cursor Cookie 值(多个值请用逗号分隔)</label>
218
- <textarea id="editCookieValues" name="editCookieValues" placeholder="输入 WorkosCursorSessionToken 值,多个值请用逗号分隔" required></textarea>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  </div>
220
- <button type="submit">保存修改</button>
 
 
221
  </form>
222
  </div>
223
  </div>
224
 
225
- <div class="card">
226
- <h2>无效Cookie管理</h2>
227
- <div class="form-group">
228
- <div class="info">
229
- 以下是系统自动检测到的无效Cookie列表。这些Cookie在请求过程中被发现无效,已被自动从API Key中移除。
230
- </div>
231
- <div id="invalidCookiesContainer">
232
- <div style="text-align: center; padding: 20px;">
233
- <div>加载中...</div>
234
- </div>
235
- </div>
236
- <button id="clearAllInvalidCookies" style="background: #e74c3c;">清除所有无效Cookie</button>
237
- </div>
238
- </div>
239
-
240
- <!-- 新增:Cookie刷新功能 -->
241
- <div class="card">
242
- <h2>Cookie自动刷新</h2>
243
- <div class="form-group">
244
- <div class="info">
245
- 系统支持自动刷新Cookie,确保API Key始终有足够的可用Cookie。您可以在此手动触发刷新操作。
246
  </div>
247
- <div id="refreshCookieMessage"></div>
248
- <div style="margin-top: 15px;">
249
  <div class="form-group">
250
- <label for="refreshApiKey">选择要刷新的API Key(不选则刷新所有)</label>
251
- <select id="refreshApiKey" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px;">
252
- <option value="">所有API Key</option>
253
- <!-- 选项将通过JavaScript动态加载 -->
254
- </select>
255
- </div>
256
- <button id="refreshCookieBtn" style="background: #27ae60;">刷新Cookie</button>
257
- </div>
258
- <div id="refreshStatusContainer" style="margin-top: 15px; display: none;">
259
- <div class="info">
260
- <div>刷新状态:<span id="refreshStatus">准备中...</span></div>
261
- <div style="margin-top: 10px;">
262
- <progress id="refreshProgress" value="0" max="100" style="width: 100%;"></progress>
 
 
 
263
  </div>
 
264
  </div>
265
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  </div>
267
  </div>
268
 
269
- <script>
270
- // 获取模态框元素
271
- const modal = document.getElementById('editModal');
272
- const closeBtn = document.getElementsByClassName('close')[0];
273
-
274
- // 关闭模态框
275
- closeBtn.onclick = function() {
276
- modal.style.display = 'none';
277
- }
278
-
279
- // 点击模态框外部关闭
280
- window.onclick = function(event) {
281
- if (event.target == modal) {
282
- modal.style.display = 'none';
283
- }
284
- }
285
-
286
- // 加载现有 API Key
287
- async function loadApiKeys() {
288
- try {
289
- console.log('开始加载API Keys...');
290
- const response = await fetch('/v1/api-keys', {
291
- method: 'GET',
292
- headers: {
293
- 'Content-Type': 'application/json',
294
- 'Cache-Control': 'no-cache'
295
- }
296
- });
297
-
298
- if (!response.ok) {
299
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
300
- }
301
-
302
- console.log('API响应状态:', response.status);
303
- const data = await response.json();
304
- console.log('获取到的数据:', data);
305
-
306
- const keyList = document.getElementById('keyList');
307
- keyList.innerHTML = '';
308
-
309
- if (data.success && data.apiKeys.length > 0) {
310
- data.apiKeys.forEach(key => {
311
- const row = document.createElement('tr');
312
- row.innerHTML = `
313
- <td>${key.key}</td>
314
- <td>${key.cookieCount}</td>
315
- <td>
316
- <button class="edit-btn" onclick="editApiKey('${key.key}')">修改</button>
317
- <button class="action-btn" onclick="deleteApiKey('${key.key}')">删除</button>
318
- </td>
319
- `;
320
- keyList.appendChild(row);
321
- });
322
- } else {
323
- keyList.innerHTML = '<tr><td colspan="3">暂无 API Key</td></tr>';
324
- }
325
- } catch (error) {
326
- console.error('加载 API Key 失败:', error);
327
- document.getElementById('keyListMessage').innerHTML = `
328
- <div class="error">加载 API Key 失败: ${error.message}</div>
329
- `;
330
- }
331
- }
332
-
333
- // 添加/更新 API Key
334
- document.getElementById('addKeyForm').addEventListener('submit', async function(e) {
335
- e.preventDefault();
336
-
337
- const apiKey = document.getElementById('apiKey').value.trim();
338
- const cookieValuesText = document.getElementById('cookieValues').value.trim();
339
-
340
- if (!apiKey || !cookieValuesText) {
341
- document.getElementById('addKeyMessage').innerHTML = `
342
- <div class="error">API Key 和 Cookie 值不能为空</div>
343
- `;
344
- return;
345
- }
346
-
347
- // 将逗号分隔的 Cookie 值转换为数组
348
- const cookieValues = cookieValuesText.split(',').map(cookie => cookie.trim()).filter(cookie => cookie);
349
-
350
- try {
351
- const response = await fetch('/v1/api-keys', {
352
- method: 'POST',
353
- headers: {
354
- 'Content-Type': 'application/json',
355
- },
356
- body: JSON.stringify({
357
- apiKey,
358
- cookieValues,
359
- }),
360
- });
361
-
362
- const data = await response.json();
363
-
364
- if (data.success) {
365
- document.getElementById('addKeyMessage').innerHTML = `
366
- <div class="info">API Key 添加/更新成功</div>
367
- `;
368
- document.getElementById('apiKey').value = '';
369
- document.getElementById('cookieValues').value = '';
370
- loadApiKeys();
371
- } else {
372
- document.getElementById('addKeyMessage').innerHTML = `
373
- <div class="error">API Key 添加/更新失败: ${data.error}</div>
374
- `;
375
- }
376
- } catch (error) {
377
- console.error('添加/更新 API Key 失败:', error);
378
- document.getElementById('addKeyMessage').innerHTML = `
379
- <div class="error">添加/更新 API Key 失败: ${error.message}</div>
380
- `;
381
- }
382
- });
383
-
384
- // 删除 API Key
385
- async function deleteApiKey(apiKey) {
386
- if (!confirm(`确定要删除 API Key "${apiKey}" 吗?`)) {
387
- return;
388
- }
389
-
390
- try {
391
- const response = await fetch(`/v1/api-keys/${encodeURIComponent(apiKey)}`, {
392
- method: 'DELETE',
393
- });
394
-
395
- const data = await response.json();
396
-
397
- if (data.success) {
398
- document.getElementById('keyListMessage').innerHTML = `
399
- <div class="info">API Key 删除成功</div>
400
- `;
401
- loadApiKeys();
402
- } else {
403
- document.getElementById('keyListMessage').innerHTML = `
404
- <div class="error">API Key 删除失败: ${data.error}</div>
405
- `;
406
- }
407
- } catch (error) {
408
- console.error('删除 API Key 失败:', error);
409
- document.getElementById('keyListMessage').innerHTML = `
410
- <div class="error">删除 API Key 失败: ${error.message}</div>
411
- `;
412
- }
413
- }
414
-
415
- // 获取API Key的Cookie值
416
- async function getCookiesForApiKey(apiKey) {
417
- try {
418
- const response = await fetch(`/v1/api-keys/${encodeURIComponent(apiKey)}/cookies`, {
419
- method: 'GET',
420
- headers: {
421
- 'Content-Type': 'application/json',
422
- 'Cache-Control': 'no-cache'
423
- }
424
- });
425
-
426
- if (!response.ok) {
427
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
428
- }
429
-
430
- const data = await response.json();
431
- return data.cookies;
432
- } catch (error) {
433
- console.error(`获取 ${apiKey} 的Cookie值失败:`, error);
434
- throw error;
435
- }
436
- }
437
-
438
- // 修改 API Key
439
- async function editApiKey(apiKey) {
440
- try {
441
- document.getElementById('editModalMessage').innerHTML = '';
442
- document.getElementById('editApiKey').value = apiKey;
443
-
444
- // 获取当前Cookie值
445
- const cookies = await getCookiesForApiKey(apiKey);
446
- document.getElementById('editCookieValues').value = cookies.join(',');
447
-
448
- // 显示模态框
449
- modal.style.display = 'block';
450
- } catch (error) {
451
- alert(`获取 ${apiKey} 的Cookie值失败: ${error.message}`);
452
- }
453
- }
454
-
455
- // 提交修改表单
456
- document.getElementById('editCookieForm').addEventListener('submit', async function(e) {
457
- e.preventDefault();
458
-
459
- const apiKey = document.getElementById('editApiKey').value.trim();
460
- const cookieValuesText = document.getElementById('editCookieValues').value.trim();
461
-
462
- if (!apiKey || !cookieValuesText) {
463
- document.getElementById('editModalMessage').innerHTML = `
464
- <div class="error">API Key 和 Cookie 值不能为空</div>
465
- `;
466
- return;
467
- }
468
-
469
- // 将逗号分隔的 Cookie 值转换为数组
470
- const cookieValues = cookieValuesText.split(',').map(cookie => cookie.trim()).filter(cookie => cookie);
471
-
472
- try {
473
- const response = await fetch('/v1/api-keys', {
474
- method: 'POST',
475
- headers: {
476
- 'Content-Type': 'application/json',
477
- },
478
- body: JSON.stringify({
479
- apiKey,
480
- cookieValues,
481
- }),
482
- });
483
-
484
- const data = await response.json();
485
-
486
- if (data.success) {
487
- document.getElementById('editModalMessage').innerHTML = `
488
- <div class="info">Cookie 修改成功</div>
489
- `;
490
- setTimeout(() => {
491
- modal.style.display = 'none';
492
- loadApiKeys();
493
- }, 1500);
494
- } else {
495
- document.getElementById('editModalMessage').innerHTML = `
496
- <div class="error">Cookie 修改失败: ${data.error}</div>
497
- `;
498
- }
499
- } catch (error) {
500
- console.error('修改 Cookie 失败:', error);
501
- document.getElementById('editModalMessage').innerHTML = `
502
- <div class="error">修改 Cookie 失败: ${error.message}</div>
503
- `;
504
- }
505
- });
506
-
507
- // 测试API连接
508
- document.getElementById('testApiBtn').addEventListener('click', async function() {
509
- const resultDiv = document.getElementById('testApiResult');
510
- resultDiv.innerHTML = '<div class="info">正在测试API连接...</div>';
511
-
512
- try {
513
- const response = await fetch('/v1/api-keys', {
514
- method: 'GET',
515
- headers: {
516
- 'Content-Type': 'application/json',
517
- 'Cache-Control': 'no-cache'
518
- }
519
- });
520
-
521
- resultDiv.innerHTML = `<div class="info">API响应状态: ${response.status}</div>`;
522
-
523
- if (!response.ok) {
524
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
525
- }
526
-
527
- const data = await response.json();
528
- resultDiv.innerHTML += `<div class="info">获取到的数据: ${JSON.stringify(data)}</div>`;
529
- } catch (error) {
530
- console.error('测试API失败:', error);
531
- resultDiv.innerHTML = `<div class="error">测试API失败: ${error.message}</div>`;
532
- }
533
- });
534
-
535
- // 清除缓存并刷新
536
- document.getElementById('clearCacheBtn').addEventListener('click', function() {
537
- // 清除缓存
538
- if ('caches' in window) {
539
- caches.keys().then(function(names) {
540
- for (let name of names) {
541
- caches.delete(name);
542
- }
543
- });
544
- }
545
-
546
- // 强制刷新页面(绕过缓存)
547
- window.location.reload(true);
548
- });
549
-
550
- // 获取无效Cookie列表
551
- async function getInvalidCookies() {
552
- try {
553
- const response = await fetch('/v1/invalid-cookies', {
554
- method: 'GET',
555
- headers: {
556
- 'Content-Type': 'application/json',
557
- 'Cache-Control': 'no-cache'
558
- }
559
- });
560
-
561
- if (!response.ok) {
562
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
563
- }
564
-
565
- const data = await response.json();
566
- return data.invalidCookies;
567
- } catch (error) {
568
- console.error('获取无效Cookie失败:', error);
569
- throw error;
570
- }
571
- }
572
-
573
- // 清除特定无效Cookie
574
- async function clearInvalidCookie(cookie) {
575
- try {
576
- const response = await fetch(`/v1/invalid-cookies/${encodeURIComponent(cookie)}`, {
577
- method: 'DELETE',
578
- headers: {
579
- 'Content-Type': 'application/json',
580
- 'Cache-Control': 'no-cache'
581
- }
582
- });
583
-
584
- if (!response.ok) {
585
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
586
- }
587
-
588
- const data = await response.json();
589
- return data.success;
590
- } catch (error) {
591
- console.error(`清除无效Cookie失败:`, error);
592
- throw error;
593
- }
594
- }
595
-
596
- // 清除所有无效Cookie
597
- async function clearAllInvalidCookies() {
598
- try {
599
- const response = await fetch('/v1/invalid-cookies', {
600
- method: 'DELETE',
601
- headers: {
602
- 'Content-Type': 'application/json',
603
- 'Cache-Control': 'no-cache'
604
- }
605
- });
606
-
607
- if (!response.ok) {
608
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
609
- }
610
-
611
- const data = await response.json();
612
- return data.success;
613
- } catch (error) {
614
- console.error('清除所有无效Cookie失败:', error);
615
- throw error;
616
- }
617
- }
618
-
619
- // 渲染无效Cookie列表
620
- async function renderInvalidCookies() {
621
- const container = document.getElementById('invalidCookiesContainer');
622
-
623
- try {
624
- const invalidCookies = await getInvalidCookies();
625
-
626
- if (invalidCookies.length === 0) {
627
- container.innerHTML = '<div class="info">没有检测到无效Cookie</div>';
628
- return;
629
- }
630
-
631
- let html = '<table><thead><tr><th>无效Cookie</th><th>操作</th></tr></thead><tbody>';
632
-
633
- invalidCookies.forEach(cookie => {
634
- // 截断显示cookie,避免页面过长
635
- const displayCookie = cookie.length > 50 ? cookie.substring(0, 50) + '...' : cookie;
636
-
637
- html += `
638
- <tr>
639
- <td class="cookie-text" title="${cookie}">${displayCookie}</td>
640
- <td>
641
- <button class="action-btn clear-invalid-cookie" data-cookie="${cookie}">
642
- 清除
643
- </button>
644
- </td>
645
- </tr>
646
- `;
647
- });
648
-
649
- html += '</tbody></table>';
650
- container.innerHTML = html;
651
-
652
- // 添加清除按钮事件监听
653
- document.querySelectorAll('.clear-invalid-cookie').forEach(button => {
654
- button.addEventListener('click', async function() {
655
- const cookie = this.getAttribute('data-cookie');
656
-
657
- try {
658
- await clearInvalidCookie(cookie);
659
- showMessage('invalidCookiesContainer', '无效Cookie已清除', 'info');
660
- renderInvalidCookies(); // 重新渲染列表
661
- } catch (error) {
662
- showMessage('invalidCookiesContainer', `清除失败: ${error.message}`, 'error');
663
- }
664
- });
665
- });
666
-
667
- } catch (error) {
668
- container.innerHTML = `<div class="error">加载失败: ${error.message}</div>`;
669
- }
670
- }
671
-
672
- // 清除所有无效Cookie按钮事件
673
- document.getElementById('clearAllInvalidCookies').addEventListener('click', async function() {
674
- try {
675
- await clearAllInvalidCookies();
676
- showMessage('invalidCookiesContainer', '所有无效Cookie已清除', 'info');
677
- renderInvalidCookies(); // 重新渲染列表
678
- } catch (error) {
679
- showMessage('invalidCookiesContainer', `清除失败: ${error.message}`, 'error');
680
- }
681
- });
682
-
683
- // 页面加载时获取 API Key 列表和无效Cookie列表
684
- document.addEventListener('DOMContentLoaded', function() {
685
- checkAuth();
686
- loadApiKeys();
687
- renderInvalidCookies();
688
- populateRefreshApiKeySelect();
689
- });
690
-
691
- // 显示消息的通用函数
692
- function showMessage(containerId, message, type) {
693
- const container = document.getElementById(containerId);
694
- container.innerHTML = `<div class="${type}">${message}</div>`;
695
- }
696
-
697
- // 填充刷新API Key的下拉选择框
698
- async function populateRefreshApiKeySelect() {
699
- try {
700
- const apiKeys = await getApiKeys();
701
- const select = document.getElementById('refreshApiKey');
702
-
703
- // 清空现有选项(保留"所有API Key"选项)
704
- while (select.options.length > 1) {
705
- select.remove(1);
706
- }
707
-
708
- // 添加API Key选项
709
- apiKeys.forEach(key => {
710
- const option = document.createElement('option');
711
- option.value = key.key;
712
- option.textContent = `${key.key} (${key.cookieCount} 个Cookie)`;
713
- select.appendChild(option);
714
- });
715
- } catch (error) {
716
- console.error('加载API Key选项失败:', error);
717
- }
718
- }
719
-
720
- // 获取API Keys的辅助函数
721
- async function getApiKeys() {
722
- const response = await fetch('/v1/api-keys', {
723
- method: 'GET',
724
- headers: {
725
- 'Content-Type': 'application/json',
726
- 'Cache-Control': 'no-cache'
727
- }
728
- });
729
-
730
- if (!response.ok) {
731
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
732
- }
733
-
734
- const data = await response.json();
735
- return data.success ? data.apiKeys : [];
736
- }
737
-
738
- // 刷新Cookie按钮事件
739
- document.getElementById('refreshCookieBtn').addEventListener('click', async function() {
740
- const refreshBtn = this;
741
- const apiKey = document.getElementById('refreshApiKey').value;
742
- const statusContainer = document.getElementById('refreshStatusContainer');
743
- const statusText = document.getElementById('refreshStatus');
744
- const progressBar = document.getElementById('refreshProgress');
745
-
746
- // 禁用按钮,显示状态容器
747
- refreshBtn.disabled = true;
748
- statusContainer.style.display = 'block';
749
- statusText.textContent = '正在发送刷新请求...';
750
- progressBar.value = 10;
751
-
752
- try {
753
- // 构建请求URL
754
- let url = '/v1/refresh-cookies';
755
- if (apiKey) {
756
- url += `?apiKey=${encodeURIComponent(apiKey)}`;
757
- }
758
-
759
- // 发送刷新请求
760
- statusText.textContent = '正在发送刷新请求...';
761
- progressBar.value = 20;
762
-
763
- const response = await fetch(url, {
764
- method: 'POST',
765
- headers: {
766
- 'Content-Type': 'application/json',
767
- 'Cache-Control': 'no-cache'
768
- }
769
- });
770
-
771
- if (!response.ok) {
772
- throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
773
- }
774
-
775
- // 显示长时间等待提示
776
- statusText.textContent = '刷新请求已发送,请耐心等待2-12分钟...';
777
- progressBar.value = 50;
778
- showMessage('refreshCookieMessage', '刷新请求已发送,由于需要访问Cursor官网获取新Cookie,整个过程可能需要2-12分钟,请耐心等待。您可以关闭此页面,稍后再来查看结果。', 'info');
779
-
780
- // 启动定时检查刷新状态
781
- let checkInterval = setInterval(async () => {
782
- try {
783
- const statusResponse = await fetch('/v1/refresh-status', {
784
- method: 'GET',
785
- headers: {
786
- 'Cache-Control': 'no-cache'
787
- }
788
- });
789
-
790
- if (!statusResponse.ok) {
791
- throw new Error(`HTTP错误: ${statusResponse.status} ${statusResponse.statusText}`);
792
- }
793
-
794
- const statusData = await statusResponse.json();
795
- const refreshData = statusData.data;
796
-
797
- // 更新状态信息
798
- statusText.textContent = refreshData.message || '正在刷新...';
799
-
800
- // 根据状态更新进度条和UI
801
- if (refreshData.status === 'completed') {
802
- // 刷新完成
803
- progressBar.value = 100;
804
- statusText.textContent = `刷新完成: ${refreshData.message}`;
805
- clearInterval(checkInterval);
806
-
807
- // 重新加载API Key列表
808
- await loadApiKeys();
809
- await populateRefreshApiKeySelect();
810
-
811
- // 显示成功消息
812
- showMessage('refreshCookieMessage', `刷新完成: ${refreshData.message}`, 'success');
813
-
814
- // 启用按钮
815
- refreshBtn.disabled = false;
816
-
817
- // 3秒后隐藏状态容器
818
- setTimeout(() => {
819
- statusContainer.style.display = 'none';
820
- }, 3000);
821
- } else if (refreshData.status === 'failed') {
822
- // 刷新失败
823
- progressBar.value = 0;
824
- statusText.textContent = `刷新失败: ${refreshData.message}`;
825
- clearInterval(checkInterval);
826
-
827
- // 显示错误消息
828
- showMessage('refreshCookieMessage', `刷新失败: ${refreshData.message}`, 'error');
829
-
830
- // 启用按钮
831
- refreshBtn.disabled = false;
832
- } else if (refreshData.status === 'running') {
833
- // 正在刷新
834
- progressBar.value = 75;
835
- } else if (!refreshData.isRunning) {
836
- // 未知状态但不在运行
837
- clearInterval(checkInterval);
838
- refreshBtn.disabled = false;
839
- }
840
- } catch (error) {
841
- console.error('检查刷新状态失败:', error);
842
- }
843
- }, 5000); // 每5秒检查一次
844
-
845
- // 设置超时检查,12分钟后如果还没完成就停止检查
846
- setTimeout(() => {
847
- if (checkInterval) {
848
- clearInterval(checkInterval);
849
- refreshBtn.disabled = false;
850
- statusContainer.style.display = 'none';
851
- }
852
- }, 720000);
853
- } catch (error) {
854
- console.error('刷新Cookie失败:', error);
855
- statusText.textContent = '刷新请求发送失败';
856
- progressBar.value = 0;
857
- showMessage('refreshCookieMessage', `刷新请求发送失败: ${error.message}`, 'error');
858
- refreshBtn.disabled = false;
859
- }
860
- });
861
-
862
- // 检查登录状态
863
- function checkAuth() {
864
- const token = localStorage.getItem('adminToken');
865
- if (!token) {
866
- window.location.href = '/login.html';
867
- return;
868
- }
869
-
870
- // 验证token
871
- fetch('/v1/admin/verify', {
872
- headers: {
873
- 'Authorization': `Bearer ${token}`
874
- }
875
- })
876
- .then(response => response.json())
877
- .then(data => {
878
- if (!data.success) {
879
- localStorage.removeItem('adminToken');
880
- window.location.href = '/login.html';
881
- } else {
882
- // 显示管理员用户名
883
- document.getElementById('adminUsername').textContent = `管理员:${data.username}`;
884
- }
885
- })
886
- .catch(error => {
887
- console.error('验证失败:', error);
888
- localStorage.removeItem('adminToken');
889
- window.location.href = '/login.html';
890
- });
891
- }
892
-
893
- // 退出登录
894
- document.getElementById('logoutBtn').addEventListener('click', () => {
895
- localStorage.removeItem('adminToken');
896
- window.location.href = '/login.html';
897
- });
898
-
899
- // 添加token到所有API请求
900
- function addAuthHeader(headers = {}) {
901
- const token = localStorage.getItem('adminToken');
902
- return {
903
- ...headers,
904
- 'Authorization': `Bearer ${token}`
905
- };
906
- }
907
-
908
- // 修改所有fetch请求,添加token
909
- const originalFetch = window.fetch;
910
- window.fetch = function(url, options = {}) {
911
- // 只对管理页面的API请求添加token
912
- if (url.includes('/v1/api-keys') ||
913
- url.includes('/v1/invalid-cookies') ||
914
- url.includes('/v1/refresh-cookies')) {
915
- options.headers = addAuthHeader(options.headers);
916
- }
917
- return originalFetch(url, options);
918
- };
919
- </script>
920
  </body>
921
  </html>
 
2
  <html lang="zh-CN">
3
  <head>
4
  <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
  <title>Cursor To OpenAI - API Key 管理</title>
7
+ <link rel="stylesheet" href="styles.css">
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <meta name="apple-mobile-web-app-capable" content="yes">
10
+ <meta name="apple-mobile-web-app-status-bar-style" content="default">
11
+ <meta name="theme-color" content="#007aff">
12
+ <script src="theme.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  </head>
14
  <body>
15
  <div class="container">
16
+ <div class="card header-card">
17
+ <div style="display: flex; align-items: center; margin-bottom: 8px;">
18
+ <i class="fas fa-link" style="font-size: 24px; margin-right: 12px;"></i>
19
+ <h1>Cursor To OpenAI</h1>
20
+ </div>
21
+ <p>管理自定义 API Key 与 Cursor Cookie 映射关系的高效工具</p>
22
+ <div style="margin-top: 20px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap;">
23
+ <div style="display: flex; flex-wrap: wrap; gap: 10px;">
24
+ <button id="clearCacheBtn" style="background-color: rgba(255,255,255,0.15); backdrop-filter: blur(5px);">
25
+ <i class="fas fa-sync-alt" style="margin-right: 6px;"></i>清除缓存
26
+ </button>
27
+ <button id="logsBtn" style="background-color: rgba(255,255,255,0.15); backdrop-filter: blur(5px);">
28
+ <i class="fas fa-list-ul" style="margin-right: 6px;"></i>系统日志
29
+ </button>
30
  </div>
31
  <div>
32
+ <span id="adminUsername" style="margin-right: 10px; color: white; font-weight: 500; display: inline-flex; align-items: center;">
33
+ <i class="fas fa-user-circle" style="margin-right: 6px;"></i><span id="usernameText"></span>
34
+ </span>
35
+ <button id="logoutBtn" style="background: rgba(255, 59, 48, 0.8); backdrop-filter: blur(5px);">
36
+ <i class="fas fa-sign-out-alt" style="margin-right: 6px;"></i>退出
37
+ </button>
38
  </div>
39
  </div>
40
+ <div id="testApiResult" style="margin-top: 15px; display: none;"></div>
41
  </div>
42
 
43
  <div class="card">
44
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
45
+ <i class="fas fa-key" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
46
+ <h2 style="margin: 0;">添加/更新 API Key</h2>
47
+ </div>
48
  <div id="addKeyMessage"></div>
49
  <form id="addKeyForm">
50
  <div class="form-group">
51
+ <label for="apiKey">
52
+ <i class="fas fa-fingerprint" style="margin-right: 6px; color: var(--ios-gray);"></i>API Key(自定义)
53
+ </label>
54
  <input type="text" id="apiKey" name="apiKey" placeholder="输入您想使用的自定义 API Key" required>
55
  </div>
56
  <div class="form-group">
57
+ <label for="cookieValues">
58
+ <i class="fas fa-cookie-bite" style="margin-right: 6px; color: var(--ios-gray);"></i>Cursor Cookie 值列表
59
+ </label>
60
+ <div class="cookies-container" id="addCookieTagsContainer">
61
+ <!-- Cookie标签将在这里动态显示 -->
62
+ </div>
63
+ <div class="form-group">
64
+ <label for="addNewCookie">
65
+ <i class="fas fa-plus-circle" style="margin-right: 6px; color: var(--ios-gray);"></i>添加新Cookie
66
+ </label>
67
+ <div style="display: flex; gap: 10px;">
68
+ <input type="text" id="addNewCookie" placeholder="输入新的WorkosCursorSessionToken值">
69
+ <button type="button" id="addNewCookieBtn" class="add-cookie-btn">
70
+ <i class="fas fa-plus"></i>
71
+ </button>
72
+ </div>
73
+ </div>
74
+ <textarea id="cookieValues" name="cookieValues" style="display: none;"></textarea>
75
  </div>
76
+ <button type="submit">
77
+ <i class="fas fa-save" style="margin-right: 6px;"></i>保存
78
+ </button>
79
  </form>
80
  </div>
81
 
82
  <div class="card">
83
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
84
+ <i class="fas fa-list" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
85
+ <h2 style="margin: 0;">现有 API Key</h2>
86
+ </div>
87
  <div id="keyListMessage"></div>
88
+ <div class="table-responsive">
89
+ <table id="keyTable">
90
+ <thead>
91
+ <tr>
92
+ <th>API KEY</th>
93
+ <th>COOKIE 数量</th>
94
+ <th>操作</th>
95
+ </tr>
96
+ </thead>
97
+ <tbody id="keyList">
98
+ <!-- 数据将通过 JavaScript 动态加载 -->
99
+ </tbody>
100
+ </table>
101
+ </div>
102
  </div>
103
 
104
  <div class="card">
105
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
106
+ <i class="fas fa-book" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
107
+ <h2 style="margin: 0;">使用说明</h2>
108
+ </div>
109
+ <ol style="padding-left: 20px; margin-top: 0;">
110
  <li>添加自定义 API Key 和对应的 Cursor Cookie 值。</li>
111
+ <li>API Key 可以不添加 Cookie,但不会有任何功能,可以后续再添加 Cookie。</li>
112
  <li>使用自定义 API Key 作为 OpenAI API 的认证凭证。</li>
113
+ <li>系统将自动在多个 Cookie 之间进行轮询。
114
+ <ul style="margin-top: 8px;">
115
+ <li><code style="background: rgba(0, 122, 255, 0.1); padding: 2px 6px; border-radius: 4px; font-family: monospace;">/v1/models</code> - 模型列表</li>
116
+ <li><code style="background: rgba(0, 122, 255, 0.1); padding: 2px 6px; border-radius: 4px; font-family: monospace;">/v1/chat/completions</code> - 聊天补全</li>
 
117
  </ul>
118
  </li>
119
  </ol>
120
  </div>
121
+
122
+ <div class="card">
123
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
124
+ <i class="fas fa-exclamation-triangle" style="color: var(--ios-red); font-size: 18px; margin-right: 10px;"></i>
125
+ <h2 style="margin: 0;">无效Cookie管理</h2>
126
+ </div>
127
+ <div class="form-group">
128
+ <div class="info">
129
+ <i class="fas fa-info-circle" style="margin-right: 8px;"></i>
130
+ 以下是系统自动检测到的无效Cookie列表。这些Cookie在请求过程中被发现无效,已被自动从API Key中移除。
131
+ </div>
132
+ <div id="invalidCookiesContainer">
133
+ <div style="text-align: center; padding: 20px;">
134
+ <i class="fas fa-spinner fa-spin" style="margin-right: 8px;"></i>
135
+ <span>正在加载...</span>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </div>
140
+
141
+ <!-- 新增:Cookie刷新功能 -->
142
+ <div class="card" style="border: 1px solid rgba(255, 59, 48, 0.3); position: relative; background: linear-gradient(to right, rgba(255, 59, 48, 0.05), rgba(255, 255, 255, 0));">
143
+ <div style="position: absolute; top: -10px; right: -10px; background: var(--ios-red); color: white; padding: 5px 10px; border-radius: 8px; font-weight: 500; font-size: 13px; box-shadow: 0 2px 6px rgba(255, 59, 48, 0.3);">不建议使用</div>
144
+
145
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
146
+ <i class="fas fa-sync-alt" style="color: var(--ios-red); font-size: 18px; margin-right: 10px;"></i>
147
+ <h2 style="margin: 0;">Cookie自动刷新 <span style="color: var(--ios-red); font-size: 0.8em; font-weight: 400;">(不建议使用)</span></h2>
148
+ </div>
149
+
150
+ <div class="form-group">
151
+ <div class="error">
152
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
153
+ <strong>警告:</strong>此功能已标记为不建议使用,可能会导致账号风险。除非必要,请避免使用此功能。
154
+ </div>
155
+ <div class="info" style="margin-top: 10px;">
156
+ <i class="fas fa-info-circle" style="margin-right: 8px;"></i>
157
+ 系统支持自动刷新Cookie,确保API Key始终有足够的可用Cookie。您可以在此手动触发刷新操作。
158
+ </div>
159
+ <div id="refreshCookieMessage"></div>
160
+ <div style="margin-top: 15px;">
161
+ <div class="form-group">
162
+ <label for="refreshApiKey">
163
+ <i class="fas fa-filter" style="margin-right: 6px; color: var(--ios-gray);"></i>选择要刷新的API Key
164
+ </label>
165
+ <select id="refreshApiKey">
166
+ <option value="">所有API Key</option>
167
+ <!-- 选项将通过JavaScript动态加载 -->
168
+ </select>
169
+ </div>
170
+ <button id="refreshCookieBtn" style="background: var(--ios-green);">
171
+ <i class="fas fa-sync-alt" style="margin-right: 6px;"></i>刷新Cookie
172
+ </button>
173
+ </div>
174
+ <div id="refreshStatusContainer" style="margin-top: 15px; display: none;">
175
+ <div class="info">
176
+ <div>
177
+ <i class="fas fa-spinner fa-spin" style="margin-right: 8px;"></i>
178
+ 刷新状态:<span id="refreshStatus">准备中...</span>
179
+ </div>
180
+ <div style="margin-top: 10px;">
181
+ <progress id="refreshProgress" value="0" max="100"></progress>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+ <!-- 新增:获取Cursor Cookie功能 -->
189
+ <div class="card">
190
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
191
+ <i class="fas fa-plus-circle" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
192
+ <h2 style="margin: 0;">获取Cursor Cookie</h2>
193
+ </div>
194
+ <div class="form-group">
195
+ <div class="info">
196
+ <i class="fas fa-info-circle" style="margin-right: 8px;"></i>
197
+ 通过此功能可以快速获取新的Cursor Cookie并添加到系统中。点击按钮生成链接,完成登录后自动添加Cookie。系统将等待最多5分钟获取Cookie。
198
+ </div>
199
+ <div id="getCookieMessage"></div>
200
+ <div style="margin-top: 15px;">
201
+ <div class="form-group">
202
+ <label for="targetApiKey">
203
+ <i class="fas fa-tag" style="margin-right: 6px; color: var(--ios-gray);"></i>选择要添加Cookie的API Key
204
+ </label>
205
+ <select id="targetApiKey">
206
+ <option value="">所有API Key</option>
207
+ <!-- 选项将通过JavaScript动态加载 -->
208
+ </select>
209
+ </div>
210
+ <button id="generateLinkBtn" style="background: var(--ios-blue);">
211
+ <i class="fas fa-link" style="margin-right: 6px;"></i>生成登录链接
212
+ </button>
213
+ </div>
214
+ <div id="loginLinkContainer" style="margin-top: 15px; display: none;">
215
+ <div class="info">
216
+ <p><i class="fas fa-info-circle" style="margin-right: 8px;"></i>请点击下面的链接或复制到浏览器打开,然后登录Cursor账号并授权:</p>
217
+ <div style="margin: 10px 0; word-break: break-all; background: rgba(0, 122, 255, 0.08); padding: 12px; border-radius: 8px; border: 1px solid rgba(0, 122, 255, 0.15);">
218
+ <a id="loginLink" href="#" target="_blank" style="color: var(--ios-blue); text-decoration: none; display: flex; align-items: center;">
219
+ <i class="fas fa-external-link-alt" style="margin-right: 8px;"></i>
220
+ <span id="loginLinkText"></span>
221
+ </a>
222
+ </div>
223
+ <p><i class="fas fa-clock" style="margin-right: 8px;"></i>登录完成后系统将自动获取Cookie并添加到API Key中。请等待最多5分钟,期间请勿关闭此页面。</p>
224
+ </div>
225
+ <div id="pollStatus" style="margin-top: 10px;">
226
+ <div style="display: flex; align-items: center; margin-bottom: 8px;">
227
+ <i class="fas fa-spinner fa-spin" style="margin-right: 8px; color: var(--ios-blue);"></i>
228
+ 状态:<span id="pollStatusText" style="margin-left: 4px;">等待用户登录...</span>
229
+ </div>
230
+ <div>
231
+ <progress id="pollProgress" value="0" max="100"></progress>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </div>
236
+ </div>
237
  </div>
238
 
239
  <!-- 修改 Cookie 的模态框 -->
240
  <div id="editModal" class="modal">
241
  <div class="modal-content">
242
  <span class="close">&times;</span>
243
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
244
+ <i class="fas fa-edit" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
245
+ <h2 style="margin: 0;">修改 API Key 的 Cookie</h2>
246
+ </div>
247
  <div id="editModalMessage"></div>
248
  <form id="editCookieForm">
249
  <input type="hidden" id="editApiKey" name="editApiKey">
250
  <div class="form-group">
251
+ <label for="editCookieValues">
252
+ <i class="fas fa-cookie-bite" style="margin-right: 6px; color: var(--ios-gray);"></i>Cursor Cookie 值列表
253
+ </label>
254
+ <div class="cookies-container" id="cookieTagsContainer">
255
+ <!-- Cookie标签将在这里动态显示 -->
256
+ </div>
257
+ <div class="form-group">
258
+ <label for="newCookie">
259
+ <i class="fas fa-plus-circle" style="margin-right: 6px; color: var(--ios-gray);"></i>添加新Cookie
260
+ </label>
261
+ <div style="display: flex; gap: 10px;">
262
+ <input type="text" id="newCookie" placeholder="输入新的WorkosCursorSessionToken值">
263
+ <button type="button" id="addCookieBtn" class="add-cookie-btn">
264
+ <i class="fas fa-plus"></i>
265
+ </button>
266
+ </div>
267
+ </div>
268
+ <textarea id="editCookieValues" name="editCookieValues" style="display: none;"></textarea>
269
  </div>
270
+ <button type="submit">
271
+ <i class="fas fa-save" style="margin-right: 6px;"></i>保存修改
272
+ </button>
273
  </form>
274
  </div>
275
  </div>
276
 
277
+ <!-- 无效Cookie编辑模态框 -->
278
+ <div id="invalidCookieModal" class="modal">
279
+ <div class="modal-content">
280
+ <span class="close" id="closeInvalidCookieModal">&times;</span>
281
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
282
+ <i class="fas fa-ban" style="color: var(--ios-red); font-size: 18px; margin-right: 10px;"></i>
283
+ <h2 style="margin: 0;">管理无效Cookie</h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  </div>
285
+ <div id="invalidCookieModalMessage"></div>
286
+ <form id="invalidCookieForm">
287
  <div class="form-group">
288
+ <label for="invalidCookiesValues">
289
+ <i class="fas fa-cookie-bite" style="margin-right: 6px; color: var(--ios-gray);"></i>无效Cookie列表
290
+ </label>
291
+ <div class="cookies-container" id="invalidCookieTagsContainer">
292
+ <!-- Cookie标签将在这里动态显示 -->
293
+ </div>
294
+ <div class="form-group">
295
+ <label for="newInvalidCookie">
296
+ <i class="fas fa-plus-circle" style="margin-right: 6px; color: var(--ios-gray);"></i>添加Cookie
297
+ </label>
298
+ <div style="display: flex; gap: 10px;">
299
+ <input type="text" id="newInvalidCookie" placeholder="输入Cookie值">
300
+ <button type="button" id="addInvalidCookieBtn" class="add-cookie-btn">
301
+ <i class="fas fa-plus"></i>
302
+ </button>
303
+ </div>
304
  </div>
305
+ <textarea id="invalidCookiesValues" name="invalidCookiesValues" style="display: none;"></textarea>
306
  </div>
307
+ <button type="submit">
308
+ <i class="fas fa-save" style="margin-right: 6px;"></i>保存修改
309
+ </button>
310
+ </form>
311
+ </div>
312
+ </div>
313
+
314
+ <!-- 侧边目录导航 -->
315
+ <div class="side-nav-trigger">
316
+ <div class="trigger-dot"></div>
317
+ </div>
318
+ <div class="side-nav-menu">
319
+ <div class="side-nav-content">
320
+ <!-- 目录项将通过JS动态生成 -->
321
  </div>
322
  </div>
323
 
324
+ <script src="scripts.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  </body>
326
  </html>
src/public/login.html CHANGED
@@ -2,146 +2,122 @@
2
  <html lang="zh-CN">
3
  <head>
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Cursor To OpenAI - 管理员登录</title>
7
- <style>
8
- body {
9
- font-family: 'Arial', sans-serif;
10
- line-height: 1.6;
11
- margin: 0;
12
- padding: 20px;
13
- color: #333;
14
- background-color: #f5f5f5;
15
- display: flex;
16
- justify-content: center;
17
- align-items: center;
18
- min-height: 100vh;
19
- }
20
- .container {
21
- background: #fff;
22
- padding: 30px;
23
- border-radius: 8px;
24
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
25
- width: 100%;
26
- max-width: 400px;
27
- }
28
- h1 {
29
- color: #2c3e50;
30
- text-align: center;
31
- margin-bottom: 30px;
32
- }
33
- .form-group {
34
- margin-bottom: 20px;
35
- }
36
- label {
37
- display: block;
38
- margin-bottom: 5px;
39
- font-weight: bold;
40
- }
41
- input {
42
- width: 100%;
43
- padding: 10px;
44
- border: 1px solid #ddd;
45
- border-radius: 4px;
46
- font-size: 16px;
47
- box-sizing: border-box;
48
- }
49
- button {
50
- background: #3498db;
51
- color: white;
52
- border: none;
53
- padding: 12px 20px;
54
- border-radius: 4px;
55
- cursor: pointer;
56
- font-size: 16px;
57
- width: 100%;
58
- margin-top: 10px;
59
- }
60
- button:hover {
61
- background: #2980b9;
62
- }
63
- .message {
64
- margin-top: 20px;
65
- padding: 10px;
66
- border-radius: 4px;
67
- text-align: center;
68
- }
69
- .error {
70
- background-color: #f8d7da;
71
- color: #721c24;
72
- }
73
- .info {
74
- background-color: #d4edda;
75
- color: #155724;
76
- }
77
- .toggle-form {
78
- text-align: center;
79
- margin-top: 20px;
80
- color: #3498db;
81
- cursor: pointer;
82
- }
83
- #registerForm {
84
- display: none;
85
- }
86
- </style>
87
  </head>
88
  <body>
89
  <div class="container">
90
- <h1>管理员登录</h1>
91
-
92
- <!-- 登录表单 -->
93
- <form id="loginForm">
94
- <div class="form-group">
95
- <label for="loginUsername">用户名</label>
96
- <input type="text" id="loginUsername" required>
97
  </div>
98
- <div class="form-group">
99
- <label for="loginPassword">密码</label>
100
- <input type="password" id="loginPassword" required>
 
 
 
 
 
101
  </div>
102
- <button type="submit">登录</button>
103
  <div id="loginMessage" class="message"></div>
104
- </form>
105
-
106
- <!-- 注册表单 -->
107
- <form id="registerForm">
108
- <div class="form-group">
109
- <label for="registerUsername">用户名</label>
110
- <input type="text" id="registerUsername" required>
 
 
 
 
 
 
 
 
 
 
 
 
111
  </div>
112
- <div class="form-group">
113
- <label for="registerPassword">密码</label>
114
- <input type="password" id="registerPassword" required>
115
- </div>
116
- <div class="form-group">
117
- <label for="confirmPassword">确认密码</label>
118
- <input type="password" id="confirmPassword" required>
119
  </div>
120
- <button type="submit">注册</button>
121
  <div id="registerMessage" class="message"></div>
122
- </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- <div class="toggle-form" id="toggleForm">
125
- 还没有账号?点击注册
 
 
 
 
 
 
 
126
  </div>
127
  </div>
128
 
129
  <script>
130
  // 获取元素
131
- const loginForm = document.getElementById('loginForm');
132
- const registerForm = document.getElementById('registerForm');
133
  const toggleForm = document.getElementById('toggleForm');
 
134
  const loginMessage = document.getElementById('loginMessage');
135
  const registerMessage = document.getElementById('registerMessage');
 
 
136
 
137
  // 切换表单显示
138
- let isLoginForm = true;
139
  toggleForm.addEventListener('click', () => {
140
- isLoginForm = !isLoginForm;
141
- loginForm.style.display = isLoginForm ? 'block' : 'none';
142
- registerForm.style.display = isLoginForm ? 'none' : 'block';
143
- toggleForm.textContent = isLoginForm ? '还没有账号?点击注册' : '已有账号?点击登录';
144
  loginMessage.textContent = '';
 
 
 
 
 
145
  registerMessage.textContent = '';
146
  });
147
 
@@ -153,18 +129,29 @@
153
 
154
  if (data.exists) {
155
  // 如果已有管理员,显示登录表单
156
- loginForm.style.display = 'block';
157
- registerForm.style.display = 'none';
158
  toggleForm.style.display = 'none';
159
  } else {
160
  // 如果没有管理员,显示注册表单
161
- loginForm.style.display = 'none';
162
- registerForm.style.display = 'block';
163
- toggleForm.style.display = 'none';
164
- registerMessage.innerHTML = '<div class="info">首次使用,请注册管理员账号</div>';
 
 
 
 
 
 
165
  }
166
  } catch (error) {
167
  console.error('检查管理员账号失败:', error);
 
 
 
 
 
168
  }
169
  }
170
 
@@ -175,6 +162,13 @@
175
  const username = document.getElementById('loginUsername').value;
176
  const password = document.getElementById('loginPassword').value;
177
 
 
 
 
 
 
 
 
178
  try {
179
  const response = await fetch('/v1/admin/login', {
180
  method: 'POST',
@@ -189,13 +183,30 @@
189
  if (data.success) {
190
  // 登录成功,保存token并跳转
191
  localStorage.setItem('adminToken', data.token);
192
- window.location.href = '/index.html';
 
 
 
 
 
 
 
 
 
193
  } else {
194
- loginMessage.innerHTML = `<div class="error">${data.message}</div>`;
 
 
 
 
195
  }
196
  } catch (error) {
197
  console.error('登录失败:', error);
198
- loginMessage.innerHTML = '<div class="error">登录失败,请稍后重试</div>';
 
 
 
 
199
  }
200
  });
201
 
@@ -208,10 +219,21 @@
208
  const confirmPassword = document.getElementById('confirmPassword').value;
209
 
210
  if (password !== confirmPassword) {
211
- registerMessage.innerHTML = '<div class="error">两次输入的密码不一致</div>';
 
 
 
 
212
  return;
213
  }
214
 
 
 
 
 
 
 
 
215
  try {
216
  const response = await fetch('/v1/admin/register', {
217
  method: 'POST',
@@ -226,13 +248,30 @@
226
  if (data.success) {
227
  // 注册成功,保存token并跳转
228
  localStorage.setItem('adminToken', data.token);
229
- window.location.href = '/index.html';
 
 
 
 
 
 
 
 
 
230
  } else {
231
- registerMessage.innerHTML = `<div class="error">${data.message}</div>`;
 
 
 
 
232
  }
233
  } catch (error) {
234
  console.error('注册失败:', error);
235
- registerMessage.innerHTML = '<div class="error">注册失败,请稍后重试</div>';
 
 
 
 
236
  }
237
  });
238
 
 
2
  <html lang="zh-CN">
3
  <head>
4
  <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
  <title>Cursor To OpenAI - 管理员登录</title>
7
+ <link rel="stylesheet" href="styles.css">
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <meta name="apple-mobile-web-app-capable" content="yes">
10
+ <meta name="apple-mobile-web-app-status-bar-style" content="default">
11
+ <meta name="theme-color" content="#007aff">
12
+ <script src="theme.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  </head>
14
  <body>
15
  <div class="container">
16
+ <div class="card header-card">
17
+ <div style="display: flex; align-items: center; margin-bottom: 8px;">
18
+ <i class="fas fa-link" style="font-size: 24px; margin-right: 12px;"></i>
19
+ <h1>Cursor To OpenAI</h1>
 
 
 
20
  </div>
21
+ <p>管理员登录系统 - 安全访问后台管理界面</p>
22
+ </div>
23
+
24
+ <!-- 登录表单卡片 -->
25
+ <div class="card" id="loginCard">
26
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
27
+ <i class="fas fa-sign-in-alt" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
28
+ <h2 style="margin: 0;">管理员登录</h2>
29
  </div>
 
30
  <div id="loginMessage" class="message"></div>
31
+ <form id="loginForm">
32
+ <div class="form-group">
33
+ <label for="loginUsername">
34
+ <i class="fas fa-user" style="margin-right: 6px; color: var(--ios-gray);"></i>用户名
35
+ </label>
36
+ <input type="text" id="loginUsername" placeholder="请输入管理员用户名" required>
37
+ </div>
38
+ <div class="form-group">
39
+ <label for="loginPassword">
40
+ <i class="fas fa-lock" style="margin-right: 6px; color: var(--ios-gray);"></i>密码
41
+ </label>
42
+ <input type="password" id="loginPassword" placeholder="请输入密码" required>
43
+ </div>
44
+ <button type="submit">
45
+ <i class="fas fa-sign-in-alt" style="margin-right: 6px;"></i>登录
46
+ </button>
47
+ </form>
48
+ <div class="toggle-form" id="toggleForm">
49
+ <i class="fas fa-user-plus" style="margin-right: 6px; color: var(--ios-blue);"></i>还没有账号?点击注册
50
  </div>
51
+ </div>
52
+
53
+ <!-- 注册表单卡片 -->
54
+ <div class="card" id="registerCard" style="display: none;">
55
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
56
+ <i class="fas fa-user-plus" style="color: var(--ios-green); font-size: 18px; margin-right: 10px;"></i>
57
+ <h2 style="margin: 0;">注册管理员账号</h2>
58
  </div>
 
59
  <div id="registerMessage" class="message"></div>
60
+ <form id="registerForm">
61
+ <div class="form-group">
62
+ <label for="registerUsername">
63
+ <i class="fas fa-user" style="margin-right: 6px; color: var(--ios-gray);"></i>用户名
64
+ </label>
65
+ <input type="text" id="registerUsername" placeholder="请设置管理员用户名" required>
66
+ </div>
67
+ <div class="form-group">
68
+ <label for="registerPassword">
69
+ <i class="fas fa-lock" style="margin-right: 6px; color: var(--ios-gray);"></i>密码
70
+ </label>
71
+ <input type="password" id="registerPassword" placeholder="请设置密码" required>
72
+ </div>
73
+ <div class="form-group">
74
+ <label for="confirmPassword">
75
+ <i class="fas fa-check-circle" style="margin-right: 6px; color: var(--ios-gray);"></i>确认密码
76
+ </label>
77
+ <input type="password" id="confirmPassword" placeholder="请再次输入密码" required>
78
+ </div>
79
+ <button type="submit">
80
+ <i class="fas fa-user-plus" style="margin-right: 6px;"></i>注册
81
+ </button>
82
+ </form>
83
+ <div class="toggle-form" id="toggleLoginForm">
84
+ <i class="fas fa-sign-in-alt" style="margin-right: 6px; color: var(--ios-blue);"></i>已有账号?点击登录
85
+ </div>
86
+ </div>
87
 
88
+ <div class="card">
89
+ <div style="display: flex; align-items: center; margin-bottom: 16px;">
90
+ <i class="fas fa-info-circle" style="color: var(--ios-blue); font-size: 18px; margin-right: 10px;"></i>
91
+ <h2 style="margin: 0;">系统信息</h2>
92
+ </div>
93
+ <div class="info">
94
+ <i class="fas fa-shield-alt" style="margin-right: 8px;"></i>
95
+ Cursor To OpenAI 是一个管理自定义 API Key 与 Cursor Cookie 映射关系的高效工具。登录后可以进行API Key的管理和配置。
96
+ </div>
97
  </div>
98
  </div>
99
 
100
  <script>
101
  // 获取元素
102
+ const loginCard = document.getElementById('loginCard');
103
+ const registerCard = document.getElementById('registerCard');
104
  const toggleForm = document.getElementById('toggleForm');
105
+ const toggleLoginForm = document.getElementById('toggleLoginForm');
106
  const loginMessage = document.getElementById('loginMessage');
107
  const registerMessage = document.getElementById('registerMessage');
108
+ const loginForm = document.getElementById('loginForm');
109
+ const registerForm = document.getElementById('registerForm');
110
 
111
  // 切换表单显示
 
112
  toggleForm.addEventListener('click', () => {
113
+ loginCard.style.display = 'none';
114
+ registerCard.style.display = 'block';
 
 
115
  loginMessage.textContent = '';
116
+ });
117
+
118
+ toggleLoginForm.addEventListener('click', () => {
119
+ registerCard.style.display = 'none';
120
+ loginCard.style.display = 'block';
121
  registerMessage.textContent = '';
122
  });
123
 
 
129
 
130
  if (data.exists) {
131
  // 如果已有管理员,显示登录表单
132
+ loginCard.style.display = 'block';
133
+ registerCard.style.display = 'none';
134
  toggleForm.style.display = 'none';
135
  } else {
136
  // 如果没有管理员,显示注册表单
137
+ loginCard.style.display = 'none';
138
+ registerCard.style.display = 'block';
139
+ toggleLoginForm.style.display = 'none';
140
+
141
+ // 添加首次使用的信息提示
142
+ registerMessage.innerHTML = `
143
+ <div class="info">
144
+ <i class="fas fa-info-circle" style="margin-right: 8px;"></i>
145
+ 首次使用,请注册管理员账号
146
+ </div>`;
147
  }
148
  } catch (error) {
149
  console.error('检查管理员账号失败:', error);
150
+ loginMessage.innerHTML = `
151
+ <div class="error">
152
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
153
+ 连接服务器失败,请检查网络连接
154
+ </div>`;
155
  }
156
  }
157
 
 
162
  const username = document.getElementById('loginUsername').value;
163
  const password = document.getElementById('loginPassword').value;
164
 
165
+ // 添加登录中的状态提示
166
+ loginMessage.innerHTML = `
167
+ <div class="info">
168
+ <i class="fas fa-spinner fa-spin" style="margin-right: 8px;"></i>
169
+ 登录中,请稍候...
170
+ </div>`;
171
+
172
  try {
173
  const response = await fetch('/v1/admin/login', {
174
  method: 'POST',
 
183
  if (data.success) {
184
  // 登录成功,保存token并跳转
185
  localStorage.setItem('adminToken', data.token);
186
+
187
+ loginMessage.innerHTML = `
188
+ <div class="info" style="background-color: rgba(52, 199, 89, 0.1); border-left: 3px solid var(--ios-green);">
189
+ <i class="fas fa-check-circle" style="margin-right: 8px;"></i>
190
+ 登录成功,正在跳转...
191
+ </div>`;
192
+
193
+ setTimeout(() => {
194
+ window.location.href = '/index.html';
195
+ }, 1000);
196
  } else {
197
+ loginMessage.innerHTML = `
198
+ <div class="error">
199
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
200
+ ${data.message}
201
+ </div>`;
202
  }
203
  } catch (error) {
204
  console.error('登录失败:', error);
205
+ loginMessage.innerHTML = `
206
+ <div class="error">
207
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
208
+ 登录失败,请稍后重试
209
+ </div>`;
210
  }
211
  });
212
 
 
219
  const confirmPassword = document.getElementById('confirmPassword').value;
220
 
221
  if (password !== confirmPassword) {
222
+ registerMessage.innerHTML = `
223
+ <div class="error">
224
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
225
+ 两次输入的密码不一致
226
+ </div>`;
227
  return;
228
  }
229
 
230
+ // 添加注册中的状态提示
231
+ registerMessage.innerHTML = `
232
+ <div class="info">
233
+ <i class="fas fa-spinner fa-spin" style="margin-right: 8px;"></i>
234
+ 注册中,请稍候...
235
+ </div>`;
236
+
237
  try {
238
  const response = await fetch('/v1/admin/register', {
239
  method: 'POST',
 
248
  if (data.success) {
249
  // 注册成功,保存token并跳转
250
  localStorage.setItem('adminToken', data.token);
251
+
252
+ registerMessage.innerHTML = `
253
+ <div class="info" style="background-color: rgba(52, 199, 89, 0.1); border-left: 3px solid var(--ios-green);">
254
+ <i class="fas fa-check-circle" style="margin-right: 8px;"></i>
255
+ 注册成功,正在跳转...
256
+ </div>`;
257
+
258
+ setTimeout(() => {
259
+ window.location.href = '/index.html';
260
+ }, 1000);
261
  } else {
262
+ registerMessage.innerHTML = `
263
+ <div class="error">
264
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
265
+ ${data.message}
266
+ </div>`;
267
  }
268
  } catch (error) {
269
  console.error('注册失败:', error);
270
+ registerMessage.innerHTML = `
271
+ <div class="error">
272
+ <i class="fas fa-exclamation-circle" style="margin-right: 8px;"></i>
273
+ 注册失败,请稍后重试
274
+ </div>`;
275
  }
276
  });
277
 
src/public/logs.html ADDED
@@ -0,0 +1,714 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>Cursor To OpenAI - 日志查看</title>
7
+ <link rel="stylesheet" href="styles.css">
8
+ <style>
9
+ .log-table {
10
+ width: 100%;
11
+ border-collapse: collapse;
12
+ }
13
+ .log-table th, .log-table td {
14
+ padding: 8px;
15
+ text-align: left;
16
+ border-bottom: 1px solid #ddd;
17
+ }
18
+ .log-table tr:hover {
19
+ background-color: rgba(0,0,0,0.05);
20
+ }
21
+ .log-level {
22
+ padding: 3px 6px;
23
+ border-radius: 4px;
24
+ font-weight: bold;
25
+ }
26
+ .log-level-ERROR {
27
+ background-color: #e74c3c;
28
+ color: white;
29
+ }
30
+ .log-level-WARN {
31
+ background-color: #f39c12;
32
+ color: white;
33
+ }
34
+ .log-level-INFO {
35
+ background-color: #27ae60;
36
+ color: white;
37
+ }
38
+ .log-level-DEBUG {
39
+ background-color: #3498db;
40
+ color: white;
41
+ }
42
+ .log-level-TRACE {
43
+ background-color: #9b59b6;
44
+ color: white;
45
+ }
46
+ .log-level-HTTP {
47
+ background-color: #1abc9c;
48
+ color: white;
49
+ }
50
+ .filter-container {
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ gap: 10px;
54
+ margin-bottom: 15px;
55
+ }
56
+ .filter-group {
57
+ flex: 1;
58
+ min-width: 150px;
59
+ }
60
+ /* 移动端优化 */
61
+ @media (max-width: 768px) {
62
+ .filter-group {
63
+ flex-basis: 100%;
64
+ min-width: auto;
65
+ }
66
+
67
+ .table-responsive {
68
+ overflow-x: auto;
69
+ -webkit-overflow-scrolling: touch;
70
+ }
71
+ }
72
+ .pagination {
73
+ display: flex;
74
+ justify-content: center;
75
+ gap: 10px;
76
+ margin-top: 20px;
77
+ flex-wrap: wrap;
78
+ }
79
+ .pagination button {
80
+ padding: 5px 10px;
81
+ background-color: #3498db;
82
+ color: white;
83
+ border: none;
84
+ border-radius: 4px;
85
+ cursor: pointer;
86
+ min-width: 80px;
87
+ min-height: 36px; /* 增加触摸区域 */
88
+ }
89
+ .pagination button:disabled {
90
+ background-color: #bdc3c7;
91
+ cursor: not-allowed;
92
+ }
93
+ .pagination-info {
94
+ margin-right: 15px;
95
+ align-self: center;
96
+ width: 100%;
97
+ text-align: center;
98
+ margin-bottom: 10px;
99
+ }
100
+ @media (min-width: 768px) {
101
+ .pagination-info {
102
+ width: auto;
103
+ margin-bottom: 0;
104
+ text-align: left;
105
+ }
106
+ }
107
+ .level-filter {
108
+ display: flex;
109
+ flex-wrap: wrap;
110
+ gap: 8px;
111
+ margin-top: 8px;
112
+ }
113
+ .level-checkbox {
114
+ display: none;
115
+ }
116
+ .level-label {
117
+ padding: 5px 10px;
118
+ border-radius: 4px;
119
+ cursor: pointer;
120
+ opacity: 0.4;
121
+ transition: opacity 0.2s;
122
+ /* 增加触摸区域 */
123
+ min-height: 28px;
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ }
128
+ .level-checkbox:checked + .level-label {
129
+ opacity: 1;
130
+ outline: 2px solid white;
131
+ }
132
+ .search-box {
133
+ position: relative;
134
+ }
135
+ .search-box input {
136
+ width: 100%;
137
+ padding: 8px;
138
+ padding-right: 40px; /* 增加右侧空间给搜索按钮 */
139
+ border: 1px solid #ddd;
140
+ border-radius: 4px;
141
+ font-size: 16px; /* 避免iOS自动缩放 */
142
+ min-height: 44px; /* 增加触摸区域 */
143
+ -webkit-appearance: none; /* 移除iOS默认样式 */
144
+ appearance: none;
145
+ }
146
+ .search-box button {
147
+ position: absolute;
148
+ right: 5px;
149
+ top: 50%;
150
+ transform: translateY(-50%);
151
+ background: none;
152
+ border: none;
153
+ cursor: pointer;
154
+ color: #555;
155
+ padding: 10px; /* 增加触摸区域 */
156
+ font-size: 18px; /* 增大搜索图标 */
157
+ }
158
+ .date-picker {
159
+ width: 100%;
160
+ padding: 8px;
161
+ border: 1px solid #ddd;
162
+ border-radius: 4px;
163
+ font-size: 16px; /* 避免iOS自动缩放 */
164
+ min-height: 44px; /* 增加触摸区域 */
165
+ -webkit-appearance: none; /* 移除iOS默认样式 */
166
+ appearance: none;
167
+ }
168
+ /* 为安卓设备特殊优化日期选择器 */
169
+ input[type="datetime-local"]::-webkit-calendar-picker-indicator {
170
+ width: 20px;
171
+ height: 20px;
172
+ padding: 5px;
173
+ }
174
+ /* 按钮样式优化 */
175
+ button {
176
+ min-height: 44px; /* 增加触摸区域 */
177
+ font-size: 16px; /* 移动端更容易点击的字体大小 */
178
+ }
179
+ /* 表格在移动端的特殊处理 */
180
+ @media (max-width: 480px) {
181
+ .log-table th:nth-child(1),
182
+ .log-table td:nth-child(1) {
183
+ min-width: 120px;
184
+ }
185
+ .log-table th:nth-child(2),
186
+ .log-table td:nth-child(2) {
187
+ min-width: 80px;
188
+ }
189
+ }
190
+ /* 开关样式 */
191
+ .switch {
192
+ position: relative;
193
+ display: inline-block;
194
+ width: 50px;
195
+ height: 24px;
196
+ }
197
+
198
+ .switch input {
199
+ opacity: 0;
200
+ width: 0;
201
+ height: 0;
202
+ }
203
+
204
+ .slider {
205
+ position: absolute;
206
+ cursor: pointer;
207
+ top: 0;
208
+ left: 0;
209
+ right: 0;
210
+ bottom: 0;
211
+ background-color: #ccc;
212
+ transition: .4s;
213
+ }
214
+
215
+ .slider:before {
216
+ position: absolute;
217
+ content: "";
218
+ height: 16px;
219
+ width: 16px;
220
+ left: 4px;
221
+ bottom: 4px;
222
+ background-color: white;
223
+ transition: .4s;
224
+ }
225
+
226
+ input:checked + .slider {
227
+ background-color: #27ae60;
228
+ }
229
+
230
+ input:focus + .slider {
231
+ box-shadow: 0 0 1px #27ae60;
232
+ }
233
+
234
+ input:checked + .slider:before {
235
+ transform: translateX(26px);
236
+ }
237
+
238
+ .slider.round {
239
+ border-radius: 24px;
240
+ }
241
+
242
+ .slider.round:before {
243
+ border-radius: 50%;
244
+ }
245
+ </style>
246
+ </head>
247
+ <body>
248
+ <div class="container">
249
+ <div class="card header-card">
250
+ <h1>Cursor To OpenAI - 日志查看</h1>
251
+ <p>在此页面上,您可以查看和筛选系统日志。</p>
252
+ <div style="margin-top: 15px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
253
+ <div style="display: flex; flex-wrap: wrap; gap: 10px;">
254
+ <button id="clearCacheBtn" style="background-color: rgba(255,255,255,0.2);">清除缓存并刷新</button>
255
+ <button id="backBtn" style="background-color: rgba(255,255,255,0.2);">返回主页</button>
256
+ </div>
257
+ <div>
258
+ <span id="adminUsername" style="margin-right: 10px; color: white;"></span>
259
+ <button id="logoutBtn" style="background: rgba(231, 76, 60, 0.8);">退出登录</button>
260
+ </div>
261
+ </div>
262
+ </div>
263
+
264
+ <div class="card">
265
+ <h2>日志筛选</h2>
266
+ <div class="filter-container">
267
+ <div class="filter-group">
268
+ <label>日志级别</label>
269
+ <div class="level-filter">
270
+ <input type="radio" name="level-filter" id="level-all" class="level-checkbox" value="ALL" checked>
271
+ <label for="level-all" class="level-label" style="background-color: #7f8c8d; color: white;">全部</label>
272
+
273
+ <input type="radio" name="level-filter" id="level-error" class="level-checkbox" value="ERROR">
274
+ <label for="level-error" class="level-label log-level-ERROR">错误</label>
275
+
276
+ <input type="radio" name="level-filter" id="level-warn" class="level-checkbox" value="WARN">
277
+ <label for="level-warn" class="level-label log-level-WARN">警告</label>
278
+
279
+ <input type="radio" name="level-filter" id="level-info" class="level-checkbox" value="INFO">
280
+ <label for="level-info" class="level-label log-level-INFO">信息</label>
281
+
282
+ <input type="radio" name="level-filter" id="level-http" class="level-checkbox" value="HTTP">
283
+ <label for="level-http" class="level-label log-level-HTTP">HTTP</label>
284
+
285
+ <input type="radio" name="level-filter" id="level-debug" class="level-checkbox" value="DEBUG">
286
+ <label for="level-debug" class="level-label log-level-DEBUG">调试</label>
287
+
288
+ <input type="radio" name="level-filter" id="level-trace" class="level-checkbox" value="TRACE">
289
+ <label for="level-trace" class="level-label log-level-TRACE">跟踪</label>
290
+ </div>
291
+ </div>
292
+ <div class="filter-group">
293
+ <label for="search">搜索</label>
294
+ <div class="search-box">
295
+ <input type="text" id="search" placeholder="搜索日志内容..." autocomplete="off">
296
+ <button id="searchBtn" aria-label="搜索">🔍</button>
297
+ </div>
298
+ </div>
299
+ <div class="filter-group">
300
+ <label for="startTime">开始时间</label>
301
+ <input type="datetime-local" id="startTime" class="date-picker" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}">
302
+ </div>
303
+ <div class="filter-group">
304
+ <label for="endTime">结束时间</label>
305
+ <input type="datetime-local" id="endTime" class="date-picker" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}">
306
+ </div>
307
+ <div class="filter-group" style="display: flex; align-items: flex-end;">
308
+ <button id="filterBtn" style="flex: 1; padding: 8px; background-color: #3498db;">应用筛选</button>
309
+ </div>
310
+ <div class="filter-group" style="display: flex; align-items: flex-end;">
311
+ <button id="clearLogsBtn" style="flex: 1; padding: 8px; background-color: #e74c3c;">清空日志</button>
312
+ </div>
313
+ <div class="filter-group">
314
+ <label for="hideCommonLogs">屏蔽常见请求</label>
315
+ <div style="display: flex; align-items: center; margin-top: 8px;">
316
+ <label class="switch" style="margin-right: 10px;">
317
+ <input type="checkbox" id="hideCommonLogs" checked>
318
+ <span class="slider round"></span>
319
+ </label>
320
+ <span id="hideStatus">已开启</span>
321
+ </div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+
326
+ <div class="card">
327
+ <h2>日志列表</h2>
328
+ <div id="logsContainer">
329
+ <div class="table-responsive">
330
+ <table class="log-table">
331
+ <thead>
332
+ <tr>
333
+ <th style="width: 200px;">时间</th>
334
+ <th style="width: 100px;">级别</th>
335
+ <th>内容</th>
336
+ </tr>
337
+ </thead>
338
+ <tbody id="logsList">
339
+ <!-- 日志数据将通过JavaScript动态加载 -->
340
+ </tbody>
341
+ </table>
342
+ </div>
343
+ <div class="pagination">
344
+ <span class="pagination-info">显示 <span id="currentRange">0-0</span> / <span id="totalLogs">0</span> 条日志</span>
345
+ <button id="prevPage" disabled>上一页</button>
346
+ <button id="nextPage" disabled>下一页</button>
347
+ </div>
348
+ </div>
349
+ </div>
350
+ </div>
351
+
352
+ <script>
353
+ // 全局变量
354
+ let currentPage = 1;
355
+ const pageSize = 12;
356
+ let totalLogs = 0;
357
+ let token = localStorage.getItem('adminToken');
358
+ let selectedLevels = []; // 默认为空数组,表示不筛选日志级别
359
+ let hideCommonLogs = true; // 默认屏蔽常见请求日志
360
+
361
+ // 页面加载完成后执行
362
+ document.addEventListener('DOMContentLoaded', function() {
363
+ // 检查登录状态
364
+ checkAuthStatus();
365
+
366
+ // 加载日志数据
367
+ loadLogs();
368
+
369
+ // 屏蔽常见请求开关
370
+ const hideCommonLogsCheckbox = document.getElementById('hideCommonLogs');
371
+ const hideStatus = document.getElementById('hideStatus');
372
+
373
+ hideCommonLogsCheckbox.addEventListener('change', function() {
374
+ hideCommonLogs = this.checked;
375
+ hideStatus.textContent = hideCommonLogs ? '已开启' : '已关闭';
376
+ loadLogs();
377
+ });
378
+
379
+ // 返回主页
380
+ document.getElementById('backBtn').addEventListener('click', function() {
381
+ window.location.href = '/';
382
+ });
383
+
384
+ // 清除缓存并刷新
385
+ document.getElementById('clearCacheBtn').addEventListener('click', function() {
386
+ localStorage.removeItem('logs');
387
+ window.location.reload();
388
+ });
389
+
390
+ // 退出登录
391
+ document.getElementById('logoutBtn').addEventListener('click', function() {
392
+ localStorage.removeItem('adminToken');
393
+ window.location.href = '/login.html';
394
+ });
395
+
396
+ // 筛选按钮
397
+ document.getElementById('filterBtn').addEventListener('click', function() {
398
+ currentPage = 1;
399
+ loadLogs();
400
+ });
401
+
402
+ // 清空日志按钮
403
+ document.getElementById('clearLogsBtn').addEventListener('click', function() {
404
+ if (confirm('确定要清空所有日志吗?此操作不可撤销。')) {
405
+ clearLogs();
406
+ }
407
+ });
408
+
409
+ // 上一页
410
+ document.getElementById('prevPage').addEventListener('click', function() {
411
+ if (currentPage > 1) {
412
+ currentPage--;
413
+ loadLogs();
414
+ }
415
+ });
416
+
417
+ // 下一页
418
+ document.getElementById('nextPage').addEventListener('click', function() {
419
+ if (currentPage * pageSize < totalLogs) {
420
+ currentPage++;
421
+ loadLogs();
422
+ }
423
+ });
424
+
425
+ // 搜索按钮
426
+ document.getElementById('searchBtn').addEventListener('click', function() {
427
+ currentPage = 1;
428
+ loadLogs();
429
+ });
430
+
431
+ // 搜索框回车
432
+ document.getElementById('search').addEventListener('keypress', function(e) {
433
+ if (e.key === 'Enter') {
434
+ currentPage = 1;
435
+ loadLogs();
436
+ }
437
+ });
438
+
439
+ // 日志级别筛选
440
+ document.querySelectorAll('.level-checkbox').forEach(radio => {
441
+ radio.addEventListener('change', function() {
442
+ // 更新选中的日志级别
443
+ if (this.value === 'ALL') {
444
+ selectedLevels = [];
445
+ } else {
446
+ selectedLevels = [this.value];
447
+ }
448
+ });
449
+ });
450
+
451
+ // 修复Android日期选择器问题
452
+ const isAndroid = /Android/i.test(navigator.userAgent);
453
+ if (isAndroid) {
454
+ // 为Android设备添加特殊处理
455
+ const dateInputs = document.querySelectorAll('input[type="datetime-local"]');
456
+ dateInputs.forEach(input => {
457
+ // 监听焦点事件,确保日期选择器在Android上正常工作
458
+ input.addEventListener('focus', function() {
459
+ this.click(); // 确保日期选择器弹出
460
+ });
461
+
462
+ // 监听输入变化,处理可能的格式问题
463
+ input.addEventListener('change', function() {
464
+ if (this.value) {
465
+ // 确保日期格式有效
466
+ try {
467
+ const date = new Date(this.value);
468
+ if (!isNaN(date.getTime())) {
469
+ // 格式有效,无需处理
470
+ } else {
471
+ // 格式无效,清空输入
472
+ this.value = '';
473
+ }
474
+ } catch (e) {
475
+ // 出错时清空输入
476
+ this.value = '';
477
+ }
478
+ }
479
+ });
480
+ });
481
+ }
482
+ });
483
+
484
+ // 检查登录状态
485
+ function checkAuthStatus() {
486
+ const token = localStorage.getItem('adminToken');
487
+
488
+ if (!token) {
489
+ window.location.href = '/login.html';
490
+ return;
491
+ }
492
+
493
+ // 验证token
494
+ fetch('/v1/admin/verify', {
495
+ headers: {
496
+ 'Authorization': `Bearer ${token}`
497
+ }
498
+ })
499
+ .then(response => response.json())
500
+ .then(data => {
501
+ if (!data.success) {
502
+ localStorage.removeItem('adminToken');
503
+ window.location.href = '/login.html';
504
+ } else {
505
+ // 显示管理员用户名
506
+ document.getElementById('adminUsername').textContent = `管理员:${data.username}`;
507
+ }
508
+ })
509
+ .catch(error => {
510
+ console.error('验证失败:', error);
511
+ localStorage.removeItem('adminToken');
512
+ window.location.href = '/login.html';
513
+ });
514
+ }
515
+
516
+ // 加载日志数据
517
+ function loadLogs() {
518
+ const search = document.getElementById('search').value;
519
+ const startTime = document.getElementById('startTime').value;
520
+ const endTime = document.getElementById('endTime').value;
521
+
522
+ // 构建查询参数
523
+ const params = new URLSearchParams({
524
+ page: currentPage,
525
+ pageSize: pageSize
526
+ });
527
+
528
+ // 添加日志级别筛选
529
+ if (selectedLevels.length === 1) {
530
+ params.append('level', selectedLevels[0]);
531
+ }
532
+
533
+ if (search) {
534
+ params.append('search', search);
535
+ }
536
+
537
+ if (startTime) {
538
+ try {
539
+ params.append('startTime', new Date(startTime).toISOString());
540
+ } catch (e) {
541
+ console.error('开始时间格式错误', e);
542
+ }
543
+ }
544
+
545
+ if (endTime) {
546
+ try {
547
+ params.append('endTime', new Date(endTime).toISOString());
548
+ } catch (e) {
549
+ console.error('结束时间格式错误', e);
550
+ }
551
+ }
552
+
553
+ // 输出请求URL便于调试
554
+ console.log(`请求URL: /v1/logs?${params.toString()}`);
555
+
556
+ // 发起请求
557
+ fetch(`/v1/logs?${params.toString()}`, {
558
+ method: 'GET',
559
+ headers: {
560
+ 'Authorization': `Bearer ${token}`
561
+ }
562
+ })
563
+ .then(response => {
564
+ if (!response.ok) {
565
+ throw new Error('加载日志失败');
566
+ }
567
+ return response.json();
568
+ })
569
+ .then(data => {
570
+ if (data.success) {
571
+ renderLogs(data.data);
572
+ } else {
573
+ showMessage('加载日志失败:' + data.message);
574
+ }
575
+ })
576
+ .catch(error => {
577
+ console.error('加载日志错误:', error);
578
+ showMessage('加载日志错误:' + error.message);
579
+ });
580
+ }
581
+
582
+ // 清空日志
583
+ function clearLogs() {
584
+ fetch('/v1/logs', {
585
+ method: 'DELETE',
586
+ headers: {
587
+ 'Authorization': `Bearer ${token}`
588
+ }
589
+ })
590
+ .then(response => {
591
+ if (!response.ok) {
592
+ throw new Error('清空日志失败');
593
+ }
594
+ return response.json();
595
+ })
596
+ .then(data => {
597
+ if (data.success) {
598
+ loadLogs();
599
+ showMessage('日志已清空');
600
+ } else {
601
+ showMessage('清空日志失败:' + data.message);
602
+ }
603
+ })
604
+ .catch(error => {
605
+ console.error('清空日志错误:', error);
606
+ showMessage('清空日志错误:' + error.message);
607
+ });
608
+ }
609
+
610
+ // 渲染日志数据
611
+ function renderLogs(data) {
612
+ const logsList = document.getElementById('logsList');
613
+ logsList.innerHTML = '';
614
+
615
+ if (!data.logs || data.logs.length === 0) {
616
+ logsList.innerHTML = '<tr><td colspan="3" style="text-align: center;">没有符合条件的日志</td></tr>';
617
+ document.getElementById('prevPage').disabled = true;
618
+ document.getElementById('nextPage').disabled = true;
619
+ document.getElementById('currentRange').textContent = '0-0';
620
+ document.getElementById('totalLogs').textContent = '0';
621
+ return;
622
+ }
623
+
624
+ // 要屏蔽的请求路径
625
+ const excludePaths = [
626
+ 'GET /styles.css',
627
+ 'GET /v1/logs',
628
+ 'GET /logs.html'
629
+ ];
630
+
631
+ // 根据用户设置决定是否过滤日志
632
+ let logsToRender = data.logs;
633
+ let totalToShow = data.total;
634
+
635
+ if (hideCommonLogs) {
636
+ // 过滤掉不需要显示的日志
637
+ logsToRender = data.logs.filter(log => {
638
+ if (log.level === 'HTTP') {
639
+ // 检查是否为要屏蔽的请求路径
640
+ for (const path of excludePaths) {
641
+ if (log.message.includes(path)) {
642
+ return false;
643
+ }
644
+ }
645
+ }
646
+ return true;
647
+ });
648
+
649
+ // 如果过滤后没有日志
650
+ if (logsToRender.length === 0) {
651
+ logsList.innerHTML = '<tr><td colspan="3" style="text-align: center;">没有符合条件的日志</td></tr>';
652
+ document.getElementById('prevPage').disabled = true;
653
+ document.getElementById('nextPage').disabled = true;
654
+ document.getElementById('currentRange').textContent = '0-0';
655
+ document.getElementById('totalLogs').textContent = '0';
656
+ return;
657
+ }
658
+
659
+ // 更新总数
660
+ totalToShow = data.total - (data.logs.length - logsToRender.length);
661
+ }
662
+
663
+ // 更新总数和分页信息
664
+ totalLogs = totalToShow;
665
+ const start = (currentPage - 1) * pageSize + 1;
666
+ const end = Math.min(currentPage * pageSize, totalToShow);
667
+ document.getElementById('currentRange').textContent = `${start}-${end}`;
668
+ document.getElementById('totalLogs').textContent = totalToShow;
669
+
670
+ // 更新分页按钮状态
671
+ document.getElementById('prevPage').disabled = currentPage <= 1;
672
+ document.getElementById('nextPage').disabled = end >= totalToShow;
673
+
674
+ // 渲染日志列表
675
+ logsToRender.forEach(log => {
676
+ const row = document.createElement('tr');
677
+
678
+ // 格式化时间
679
+ const timestamp = new Date(log.timestamp);
680
+ const formattedTime = timestamp.toLocaleString('zh-CN');
681
+
682
+ row.innerHTML = `
683
+ <td>${formattedTime}</td>
684
+ <td><span class="log-level log-level-${log.level}">${log.level}</span></td>
685
+ <td>${log.message}</td>
686
+ `;
687
+
688
+ logsList.appendChild(row);
689
+ });
690
+ }
691
+
692
+ // 显示消息
693
+ function showMessage(message) {
694
+ alert(message);
695
+ }
696
+
697
+ // 添加token到所有日志API请求
698
+ (function() {
699
+ const originalFetch = window.fetch;
700
+ window.fetch = function(url, options = {}) {
701
+ // 如果是日志API请求,添加token
702
+ if (url.includes('/v1/logs') && !url.includes('/v1/admin/')) {
703
+ const token = localStorage.getItem('adminToken');
704
+ options.headers = {
705
+ ...options.headers,
706
+ 'Authorization': `Bearer ${token}`
707
+ };
708
+ }
709
+ return originalFetch(url, options);
710
+ };
711
+ })();
712
+ </script>
713
+ </body>
714
+ </html>
src/public/scripts.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const a0_0x2e920c=a0_0x9c1d;(function(_0x50c06,_0x324f3f){const _0x1ebe51=a0_0x9c1d,_0x1f1cdc=_0x50c06();while(!![]){try{const _0x4ec3f1=-parseInt(_0x1ebe51(0xd8))/0x1+-parseInt(_0x1ebe51(0x1c8))/0x2+-parseInt(_0x1ebe51(0xfa))/0x3*(-parseInt(_0x1ebe51(0x183))/0x4)+-parseInt(_0x1ebe51(0x138))/0x5+-parseInt(_0x1ebe51(0x105))/0x6*(parseInt(_0x1ebe51(0x118))/0x7)+parseInt(_0x1ebe51(0x18c))/0x8+parseInt(_0x1ebe51(0x13d))/0x9;if(_0x4ec3f1===_0x324f3f)break;else _0x1f1cdc['push'](_0x1f1cdc['shift']());}catch(_0x5805b8){_0x1f1cdc['push'](_0x1f1cdc['shift']());}}}(a0_0xba5c,0x3f750));const a0_0x3d41df=(function(){let _0x23c0c3=!![];return function(_0x55d6ea,_0x3bee2a){const _0x16f743=_0x23c0c3?function(){const _0x23db8a=a0_0x9c1d;if(_0x3bee2a){const _0x5cc1d6=_0x3bee2a[_0x23db8a(0x15b)](_0x55d6ea,arguments);return _0x3bee2a=null,_0x5cc1d6;}}:function(){};return _0x23c0c3=![],_0x16f743;};}()),a0_0x22c531=a0_0x3d41df(this,function(){const _0x1feea9=a0_0x9c1d;return a0_0x22c531[_0x1feea9(0xe7)]()[_0x1feea9(0xe4)](_0x1feea9(0xdc))[_0x1feea9(0xe7)]()[_0x1feea9(0x16d)](a0_0x22c531)[_0x1feea9(0xe4)](_0x1feea9(0xdc));});a0_0x22c531(),document[a0_0x2e920c(0x190)](a0_0x2e920c(0x18d),function(){const _0xc639c7=a0_0x2e920c,_0x47f003=document[_0xc639c7(0x17d)]('.modal'),_0x27409b=document[_0xc639c7(0x17d)](_0xc639c7(0xd3));function _0x479e7d(){const _0x48c3e4=_0xc639c7;_0x47f003['forEach'](_0x38ed25=>{const _0x24f79e=a0_0x9c1d;_0x38ed25[_0x24f79e(0x164)]['display']=_0x24f79e(0x11b);}),document['body'][_0x48c3e4(0x195)][_0x48c3e4(0x100)](_0x48c3e4(0x178));}_0x27409b[_0xc639c7(0xed)](_0x156e15=>{const _0x5abfcd=_0xc639c7;_0x156e15[_0x5abfcd(0x1b9)]=_0x479e7d;}),window[_0xc639c7(0x1b9)]=function(_0x1db810){const _0x2bae4d=_0xc639c7;_0x47f003[_0x2bae4d(0xed)](_0xfcb760=>{const _0x5ab2b0=_0x2bae4d;_0x1db810[_0x5ab2b0(0xdd)]==_0xfcb760&&_0x479e7d();});},checkAuth(),loadApiKeys(),renderInvalidCookies(),populateRefreshApiKeySelect(),populateCookieApiKeySelect(),renderAddCookieTags([]),bindEventListeners(),document['getElementById']('logsBtn')?.[_0xc639c7(0x190)](_0xc639c7(0x12e),function(){const _0x3bf994=_0xc639c7;window['location'][_0x3bf994(0xd4)]=_0x3bf994(0x167);});});function bindEventListeners(){const _0x52c375=a0_0x2e920c;document['getElementById'](_0x52c375(0xf3))[_0x52c375(0x190)](_0x52c375(0x1b5),handleAddKeyForm),document['getElementById'](_0x52c375(0x107))[_0x52c375(0x190)](_0x52c375(0x1b5),handleEditCookieForm),document[_0x52c375(0x137)](_0x52c375(0x1d9))[_0x52c375(0x190)](_0x52c375(0x1b5),handleInvalidCookieForm);const _0x114f2e=document[_0x52c375(0x17d)](_0x52c375(0x142));_0x114f2e[_0x52c375(0xed)](_0x528537=>{const _0x9f6ae=_0x52c375;if(_0x528537)_0x528537[_0x9f6ae(0x190)](_0x9f6ae(0x12e),testApiConnection);});const _0x3133ce=document[_0x52c375(0x17d)](_0x52c375(0x1d8));_0x3133ce['forEach'](_0x35dbe3=>{const _0x2278b7=_0x52c375;if(_0x35dbe3)_0x35dbe3[_0x2278b7(0x190)](_0x2278b7(0x12e),clearCacheAndRefresh);});if(document[_0x52c375(0x137)](_0x52c375(0x19e)))document['getElementById']('addNewCookieBtn')[_0x52c375(0x190)](_0x52c375(0x12e),handleAddNewCookie);if(document[_0x52c375(0x137)](_0x52c375(0x109)))document[_0x52c375(0x137)](_0x52c375(0x109))['addEventListener']('click',handleAddCookie);if(document[_0x52c375(0x137)](_0x52c375(0x185)))document[_0x52c375(0x137)]('addInvalidCookieBtn')['addEventListener'](_0x52c375(0x12e),handleAddInvalidCookie);if(document['getElementById'](_0x52c375(0x140)))document[_0x52c375(0x137)]('closeInvalidCookieModal')[_0x52c375(0x190)](_0x52c375(0x12e),closeInvalidCookieModal);const _0x3f2642=document['getElementById'](_0x52c375(0x1de));_0x3f2642&&(console[_0x52c375(0x120)](_0x52c375(0x14f)),_0x3f2642['addEventListener'](_0x52c375(0x12e),handleRefreshCookie));const _0x5a6695=document[_0x52c375(0x137)](_0x52c375(0x1d0));_0x5a6695&&(console[_0x52c375(0x120)](_0x52c375(0x186)),_0x5a6695[_0x52c375(0x190)](_0x52c375(0x12e),handleGenerateLink));if(document[_0x52c375(0x137)]('logoutBtn'))document[_0x52c375(0x137)](_0x52c375(0x114))[_0x52c375(0x190)](_0x52c375(0x12e),handleLogout);}async function loadApiKeys(){const _0x24fd43=a0_0x2e920c;try{console[_0x24fd43(0x120)]('开始加载API\x20Keys...');const _0x505248=await fetch(_0x24fd43(0x171),{'method':'GET','headers':{'Content-Type':'application/json','Cache-Control':_0x24fd43(0x11f)}});if(!_0x505248['ok'])throw new Error('HTTP错误:\x20'+_0x505248[_0x24fd43(0x19c)]+'\x20'+_0x505248[_0x24fd43(0x1c9)]);console[_0x24fd43(0x120)](_0x24fd43(0x1af),_0x505248['status']);const _0x504684=await _0x505248['json']();console['log'](_0x24fd43(0x1a0),_0x504684);const _0x543316=document[_0x24fd43(0x137)](_0x24fd43(0x1bd));_0x543316[_0x24fd43(0x1e2)]='',_0x504684['success']&&_0x504684[_0x24fd43(0x196)][_0x24fd43(0xe8)]>0x0?_0x504684[_0x24fd43(0x196)][_0x24fd43(0xed)](_0x278f2a=>{const _0x14b19f=_0x24fd43,_0x22b28f=document[_0x14b19f(0x1d7)]('tr');_0x22b28f[_0x14b19f(0x1e2)]=_0x14b19f(0x177)+_0x278f2a[_0x14b19f(0xdb)]+_0x14b19f(0x18f)+_0x278f2a[_0x14b19f(0x12d)]+_0x14b19f(0x175)+_0x278f2a[_0x14b19f(0xdb)]+_0x14b19f(0x12c)+_0x278f2a[_0x14b19f(0xdb)]+'\x27)\x22>删除</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20',_0x543316['appendChild'](_0x22b28f);}):_0x543316['innerHTML']=_0x24fd43(0xf2);}catch(_0x6786c4){console[_0x24fd43(0x1dd)](_0x24fd43(0x17b),_0x6786c4),document[_0x24fd43(0x137)](_0x24fd43(0xf1))[_0x24fd43(0x1e2)]=_0x24fd43(0xda)+_0x6786c4[_0x24fd43(0xe1)]+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20';}}async function handleAddKeyForm(_0x49ddcb){const _0x62bf78=a0_0x2e920c;_0x49ddcb[_0x62bf78(0x1d2)]();const _0xbfcee9=document['getElementById'](_0x62bf78(0x1ab))['value'][_0x62bf78(0x1cb)](),_0x553c86=document[_0x62bf78(0x137)]('cookieValues')[_0x62bf78(0x1ca)][_0x62bf78(0x1cb)]();if(!_0xbfcee9){document[_0x62bf78(0x137)](_0x62bf78(0x1a7))['innerHTML']=_0x62bf78(0x146);return;}const _0x3b7ca3=_0x553c86?_0x553c86[_0x62bf78(0x1d4)](',')[_0x62bf78(0x1a6)](_0x2783dd=>_0x2783dd[_0x62bf78(0x1cb)]())['filter'](_0x5cac7a=>_0x5cac7a):[];try{const _0xe35209=await fetch(_0x62bf78(0x171),{'method':_0x62bf78(0x17c),'headers':{'Content-Type':_0x62bf78(0x1a3)},'body':JSON[_0x62bf78(0x155)]({'apiKey':_0xbfcee9,'cookieValues':_0x3b7ca3})}),_0x312cd3=await _0xe35209[_0x62bf78(0x174)]();_0x312cd3['success']?(document[_0x62bf78(0x137)](_0x62bf78(0x1a7))[_0x62bf78(0x1e2)]='\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22info\x22>API\x20Key\x20添加/更新成功</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20',setTimeout(()=>{const _0x430dc3=_0x62bf78;window[_0x430dc3(0x119)][_0x430dc3(0x134)]();},0xbb8)):document[_0x62bf78(0x137)](_0x62bf78(0x1a7))[_0x62bf78(0x1e2)]=_0x62bf78(0x18b)+_0x312cd3[_0x62bf78(0x1dd)]+_0x62bf78(0x15d);}catch(_0x900bd7){console[_0x62bf78(0x1dd)](_0x62bf78(0x16e),_0x900bd7),document['getElementById'](_0x62bf78(0x1a7))[_0x62bf78(0x1e2)]=_0x62bf78(0x188)+_0x900bd7[_0x62bf78(0xe1)]+_0x62bf78(0xf8);}}async function deleteApiKey(_0x53a985){const _0x2e4bf3=a0_0x2e920c;if(!confirm(_0x2e4bf3(0x151)+_0x53a985+_0x2e4bf3(0x117)))return;try{const _0x4a7092=await fetch(_0x2e4bf3(0x15f)+encodeURIComponent(_0x53a985),{'method':_0x2e4bf3(0x1a9)}),_0x286b15=await _0x4a7092[_0x2e4bf3(0x174)]();_0x286b15['success']?(document[_0x2e4bf3(0x137)](_0x2e4bf3(0xf1))[_0x2e4bf3(0x1e2)]=_0x2e4bf3(0xe5),loadApiKeys()):document[_0x2e4bf3(0x137)](_0x2e4bf3(0xf1))['innerHTML']=_0x2e4bf3(0x1b1)+_0x286b15['error']+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20';}catch(_0xf8e181){console[_0x2e4bf3(0x1dd)](_0x2e4bf3(0x1d1),_0xf8e181),document[_0x2e4bf3(0x137)](_0x2e4bf3(0xf1))[_0x2e4bf3(0x1e2)]=_0x2e4bf3(0x141)+_0xf8e181[_0x2e4bf3(0xe1)]+_0x2e4bf3(0xf8);}}async function getCookiesForApiKey(_0x5c23e1){const _0x26aff1=a0_0x2e920c;try{const _0x668084=await fetch(_0x26aff1(0x15f)+encodeURIComponent(_0x5c23e1)+_0x26aff1(0xd7),{'method':_0x26aff1(0x1be),'headers':{'Content-Type':'application/json','Cache-Control':'no-cache'}});if(!_0x668084['ok'])throw new Error(_0x26aff1(0xd5)+_0x668084['status']+'\x20'+_0x668084[_0x26aff1(0x1c9)]);const _0x22527d=await _0x668084[_0x26aff1(0x174)]();return _0x22527d[_0x26aff1(0xd2)];}catch(_0x1b7c3a){console[_0x26aff1(0x1dd)](_0x26aff1(0x16c)+_0x5c23e1+_0x26aff1(0x135),_0x1b7c3a);throw _0x1b7c3a;}}async function editApiKey(_0x45a72a){const _0x25b58f=a0_0x2e920c;try{document[_0x25b58f(0x137)](_0x25b58f(0x103))[_0x25b58f(0x1e2)]='',document[_0x25b58f(0x137)](_0x25b58f(0x170))['value']=_0x45a72a;const _0x1cb873=await getCookiesForApiKey(_0x45a72a);document['getElementById']('editCookieValues')[_0x25b58f(0x1ca)]=_0x1cb873[_0x25b58f(0x16f)](','),renderCookieTags(_0x1cb873),document[_0x25b58f(0x137)](_0x25b58f(0x179))['value']='';const _0x1252ae=document['getElementById']('editModal');_0x1252ae['style'][_0x25b58f(0x144)]=_0x25b58f(0x160),document[_0x25b58f(0x192)]['classList']['add']('modal-open');}catch(_0x5eb66c){console[_0x25b58f(0x1dd)](_0x25b58f(0x139),_0x5eb66c),document[_0x25b58f(0x137)]('editModalMessage')[_0x25b58f(0x1e2)]='\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22error\x22>无法加载Cookie数据:\x20'+_0x5eb66c[_0x25b58f(0xe1)]+_0x25b58f(0xf8);const _0x527ce5=document['getElementById'](_0x25b58f(0x112));_0x527ce5[_0x25b58f(0x164)][_0x25b58f(0x144)]=_0x25b58f(0x160),document[_0x25b58f(0x192)][_0x25b58f(0x195)][_0x25b58f(0x194)](_0x25b58f(0x178));}}async function getApiKeys(){const _0x1387e2=a0_0x2e920c,_0xef71e8=await fetch(_0x1387e2(0x171),{'method':'GET','headers':{'Content-Type':_0x1387e2(0x1a3),'Cache-Control':_0x1387e2(0x11f)}});if(!_0xef71e8['ok'])throw new Error(_0x1387e2(0xd5)+_0xef71e8['status']+'\x20'+_0xef71e8[_0x1387e2(0x1c9)]);const _0x53268a=await _0xef71e8['json']();return _0x53268a[_0x1387e2(0x126)]?_0x53268a['apiKeys']:[];}async function copyTextToClipboard(_0x2573db){const _0x4b1c00=a0_0x2e920c;try{return await navigator['clipboard'][_0x4b1c00(0x1ce)](_0x2573db),!![];}catch(_0x120c5b){console[_0x4b1c00(0x1dd)](_0x4b1c00(0x127),_0x120c5b);try{const _0x51f944=document[_0x4b1c00(0x1d7)]('textarea');_0x51f944['value']=_0x2573db,_0x51f944[_0x4b1c00(0x164)]['position']='fixed',_0x51f944[_0x4b1c00(0x164)]['top']='0',_0x51f944[_0x4b1c00(0x164)][_0x4b1c00(0xf6)]='0',_0x51f944[_0x4b1c00(0x164)][_0x4b1c00(0x108)]=_0x4b1c00(0x115),_0x51f944[_0x4b1c00(0x164)][_0x4b1c00(0xdf)]=_0x4b1c00(0x115),_0x51f944[_0x4b1c00(0x164)]['padding']='0',_0x51f944['style'][_0x4b1c00(0x13b)]=_0x4b1c00(0x11b),_0x51f944[_0x4b1c00(0x164)][_0x4b1c00(0xfb)]='none',_0x51f944[_0x4b1c00(0x164)][_0x4b1c00(0xd6)]='none',_0x51f944[_0x4b1c00(0x164)][_0x4b1c00(0x162)]='transparent',document[_0x4b1c00(0x192)]['appendChild'](_0x51f944),_0x51f944['focus'](),_0x51f944[_0x4b1c00(0x10e)]();const _0x25413d=document[_0x4b1c00(0x191)](_0x4b1c00(0xd0));return document[_0x4b1c00(0x192)][_0x4b1c00(0x11a)](_0x51f944),_0x25413d;}catch(_0x507ce0){return console['error'](_0x4b1c00(0xfc),_0x507ce0),![];}}}function showCopyToast(_0x44fb2b){const _0x34fc74=a0_0x2e920c,_0x4ec55f=document['createElement'](_0x34fc74(0x101));_0x4ec55f[_0x34fc74(0x164)][_0x34fc74(0x189)]='fixed',_0x4ec55f[_0x34fc74(0x164)][_0x34fc74(0xe0)]=_0x34fc74(0x1d5),_0x4ec55f['style'][_0x34fc74(0xf6)]='50%',_0x4ec55f['style']['transform']=_0x34fc74(0x15e),_0x4ec55f[_0x34fc74(0x164)]['padding']=_0x34fc74(0xec),_0x4ec55f['style']['borderRadius']=_0x34fc74(0xeb),_0x4ec55f[_0x34fc74(0x164)][_0x34fc74(0x1e4)]=_0x34fc74(0x166),_0x4ec55f[_0x34fc74(0x164)][_0x34fc74(0xde)]=_0x34fc74(0x173),_0x44fb2b?(_0x4ec55f[_0x34fc74(0x164)][_0x34fc74(0x1e0)]=_0x34fc74(0x18e),_0x4ec55f[_0x34fc74(0x164)]['color']=_0x34fc74(0xe9),_0x4ec55f[_0x34fc74(0x1c0)]=_0x34fc74(0x128)):(_0x4ec55f['style']['backgroundColor']=_0x34fc74(0x1ae),_0x4ec55f[_0x34fc74(0x164)][_0x34fc74(0x14a)]=_0x34fc74(0xe9),_0x4ec55f['textContent']=_0x34fc74(0x181)),document['body'][_0x34fc74(0x1ac)](_0x4ec55f),setTimeout(()=>{const _0x49378e=_0x34fc74;_0x4ec55f[_0x49378e(0x164)][_0x49378e(0x176)]='0',_0x4ec55f[_0x49378e(0x164)][_0x49378e(0x129)]=_0x49378e(0xef),setTimeout(()=>{const _0x538760=_0x49378e;document[_0x538760(0x192)]['removeChild'](_0x4ec55f);},0x1f4);},0x7d0);}async function handleCopyCookie(_0x1e3686){const _0x245d51=await copyTextToClipboard(_0x1e3686);showCopyToast(_0x245d51);}function renderCookieTags(_0x3d4432){const _0x1d51b8=a0_0x2e920c,_0x3b3471=document[_0x1d51b8(0x137)]('cookieTagsContainer');_0x3b3471[_0x1d51b8(0x1e2)]='';if(_0x3d4432[_0x1d51b8(0xe8)]===0x0){_0x3b3471[_0x1d51b8(0x1e2)]='<div\x20style=\x22padding:\x2010px;\x20color:\x20#666;\x22>暂无Cookie,请添加</div>';return;}_0x3d4432[_0x1d51b8(0xed)]((_0xa957b1,_0x226583)=>{const _0x4bc1ad=_0x1d51b8,_0x3c1871=document[_0x4bc1ad(0x1d7)](_0x4bc1ad(0x13a));_0x3c1871[_0x4bc1ad(0x13e)]=_0x4bc1ad(0x168);_0xa957b1[_0x4bc1ad(0xe8)]<0x5&&_0x3c1871[_0x4bc1ad(0x195)][_0x4bc1ad(0x194)](_0x4bc1ad(0x16a));const _0x98a54d=_0xa957b1[_0x4bc1ad(0xe8)]>0x14?_0xa957b1[_0x4bc1ad(0x182)](0x0,0x8)+_0x4bc1ad(0xf9)+_0xa957b1[_0x4bc1ad(0x182)](_0xa957b1[_0x4bc1ad(0xe8)]-0x8):_0xa957b1;_0x3c1871[_0x4bc1ad(0xf7)]=_0xa957b1,_0x3c1871['innerHTML']=_0x4bc1ad(0xf0)+_0x98a54d+_0x4bc1ad(0xcf)+_0xa957b1+_0x4bc1ad(0x150)+_0x226583+_0x4bc1ad(0xee),_0x3b3471[_0x4bc1ad(0x1ac)](_0x3c1871);}),document[_0x1d51b8(0x17d)](_0x1d51b8(0x149))['forEach'](_0x51c210=>{const _0x2cac10=_0x1d51b8;_0x51c210[_0x2cac10(0x190)](_0x2cac10(0x12e),function(){const _0x4ccc48=_0x2cac10,_0x23da9e=parseInt(this[_0x4ccc48(0x1df)](_0x4ccc48(0x13c)));deleteCookieTag(_0x23da9e);});}),document[_0x1d51b8(0x17d)](_0x1d51b8(0xd1))[_0x1d51b8(0xed)](_0x3e47ae=>{const _0x12c960=_0x1d51b8;_0x3e47ae['addEventListener'](_0x12c960(0x12e),function(){const _0x543a5d=_0x12c960,_0x2e6cfe=this[_0x543a5d(0x1df)]('data-cookie');handleCopyCookie(_0x2e6cfe);});});}function deleteCookieTag(_0x471ff4){const _0xc29776=a0_0x2e920c,_0x2cdc59=document[_0xc29776(0x137)](_0xc29776(0x14b));let _0x1247f9=_0x2cdc59[_0xc29776(0x1ca)][_0xc29776(0x1d4)](',')[_0xc29776(0x1a6)](_0x405210=>_0x405210[_0xc29776(0x1cb)]())[_0xc29776(0x11c)](_0x487525=>_0x487525);_0x1247f9[_0xc29776(0x15c)](_0x471ff4,0x1),_0x2cdc59[_0xc29776(0x1ca)]=_0x1247f9[_0xc29776(0x16f)](','),renderCookieTags(_0x1247f9);}function handleAddCookie(){const _0x2d87a5=a0_0x2e920c,_0x3734c9=document[_0x2d87a5(0x137)](_0x2d87a5(0x179)),_0x302829=_0x3734c9[_0x2d87a5(0x1ca)][_0x2d87a5(0x1cb)]();if(!_0x302829)return;const _0x1c2d46=document[_0x2d87a5(0x137)](_0x2d87a5(0x14b));let _0x1e69f0=_0x1c2d46['value']?_0x1c2d46[_0x2d87a5(0x1ca)][_0x2d87a5(0x1d4)](',')[_0x2d87a5(0x1a6)](_0x1c16b6=>_0x1c16b6[_0x2d87a5(0x1cb)]())[_0x2d87a5(0x11c)](_0x860bd2=>_0x860bd2):[];_0x1e69f0[_0x2d87a5(0x1cd)](_0x302829),_0x1c2d46[_0x2d87a5(0x1ca)]=_0x1e69f0[_0x2d87a5(0x16f)](','),renderCookieTags(_0x1e69f0),_0x3734c9[_0x2d87a5(0x1ca)]='';}async function handleEditCookieForm(_0xa4875b){const _0x116576=a0_0x2e920c;_0xa4875b['preventDefault']();const _0x4702d6=document['getElementById'](_0x116576(0x170))[_0x116576(0x1ca)]['trim'](),_0x5498e2=document[_0x116576(0x137)](_0x116576(0x14b))[_0x116576(0x1ca)][_0x116576(0x1cb)]();if(!_0x4702d6){document[_0x116576(0x137)](_0x116576(0x103))[_0x116576(0x1e2)]=_0x116576(0x1ba);return;}const _0xdfee10=_0x5498e2?_0x5498e2[_0x116576(0x1d4)](',')[_0x116576(0x1a6)](_0x4a82a0=>_0x4a82a0[_0x116576(0x1cb)]())[_0x116576(0x11c)](_0x59734d=>_0x59734d):[];try{const _0x3b3aa3=await fetch(_0x116576(0x171),{'method':_0x116576(0x17c),'headers':{'Content-Type':_0x116576(0x1a3)},'body':JSON['stringify']({'apiKey':_0x4702d6,'cookieValues':_0xdfee10})}),_0x541404=await _0x3b3aa3[_0x116576(0x174)]();_0x541404[_0x116576(0x126)]?(document[_0x116576(0x137)](_0x116576(0x103))[_0x116576(0x1e2)]=_0x116576(0x1a2),setTimeout(()=>{const _0x4c419e=_0x116576;document['getElementById'](_0x4c419e(0x112))[_0x4c419e(0x164)][_0x4c419e(0x144)]=_0x4c419e(0x11b),loadApiKeys();},0x5dc)):document[_0x116576(0x137)]('editModalMessage')['innerHTML']=_0x116576(0x1ad)+_0x541404[_0x116576(0x1dd)]+_0x116576(0x15d);}catch(_0x4ac201){console['error'](_0x116576(0x11e),_0x4ac201),document['getElementById'](_0x116576(0x103))[_0x116576(0x1e2)]=_0x116576(0x19b)+_0x4ac201['message']+_0x116576(0xf8);}}function renderAddCookieTags(_0x501891){const _0x5d9c6a=a0_0x2e920c,_0x38237b=document[_0x5d9c6a(0x137)](_0x5d9c6a(0x122));_0x38237b[_0x5d9c6a(0x1e2)]='';if(_0x501891[_0x5d9c6a(0xe8)]===0x0){_0x38237b[_0x5d9c6a(0x1e2)]=_0x5d9c6a(0x1bf);return;}_0x501891[_0x5d9c6a(0xed)]((_0x32a4fe,_0x4f27df)=>{const _0x1fe46c=_0x5d9c6a,_0x527114=document[_0x1fe46c(0x1d7)](_0x1fe46c(0x13a));_0x527114[_0x1fe46c(0x13e)]=_0x1fe46c(0x168);_0x32a4fe[_0x1fe46c(0xe8)]<0x5&&_0x527114[_0x1fe46c(0x195)][_0x1fe46c(0x194)]('short-cookie');const _0x48680b=_0x32a4fe[_0x1fe46c(0xe8)]>0x14?_0x32a4fe['substring'](0x0,0x8)+'...'+_0x32a4fe[_0x1fe46c(0x182)](_0x32a4fe[_0x1fe46c(0xe8)]-0x8):_0x32a4fe;_0x527114['title']=_0x32a4fe,_0x527114['innerHTML']=_0x1fe46c(0xf0)+_0x48680b+_0x1fe46c(0xcf)+_0x32a4fe+'\x22\x20aria-label=\x22复制\x22>C</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20type=\x22button\x22\x20class=\x22delete-add-cookie\x22\x20data-index=\x22'+_0x4f27df+_0x1fe46c(0xee),_0x38237b['appendChild'](_0x527114);}),document['querySelectorAll'](_0x5d9c6a(0x193))[_0x5d9c6a(0xed)](_0x1a5af0=>{const _0xaf2a11=_0x5d9c6a;_0x1a5af0['addEventListener'](_0xaf2a11(0x12e),function(){const _0x1f5a69=parseInt(this['getAttribute']('data-index'));deleteAddCookieTag(_0x1f5a69);});}),document[_0x5d9c6a(0x17d)](_0x5d9c6a(0xd1))[_0x5d9c6a(0xed)](_0xeaa932=>{const _0x1574c7=_0x5d9c6a;_0xeaa932[_0x1574c7(0x190)](_0x1574c7(0x12e),function(){const _0x184d76=_0x1574c7,_0x430ffc=this[_0x184d76(0x1df)](_0x184d76(0x136));handleCopyCookie(_0x430ffc);});});}function deleteAddCookieTag(_0x3c7855){const _0x2727bc=a0_0x2e920c,_0x19921f=document[_0x2727bc(0x137)](_0x2727bc(0x172));let _0x5024ae=_0x19921f[_0x2727bc(0x1ca)]?_0x19921f[_0x2727bc(0x1ca)][_0x2727bc(0x1d4)](',')[_0x2727bc(0x1a6)](_0xe00e81=>_0xe00e81[_0x2727bc(0x1cb)]())[_0x2727bc(0x11c)](_0x2e391c=>_0x2e391c):[];_0x5024ae[_0x2727bc(0x15c)](_0x3c7855,0x1),_0x19921f[_0x2727bc(0x1ca)]=_0x5024ae[_0x2727bc(0x16f)](','),renderAddCookieTags(_0x5024ae);}function handleAddNewCookie(){const _0x3db5f9=a0_0x2e920c,_0x5c16b0=document[_0x3db5f9(0x137)](_0x3db5f9(0x12f)),_0x10cdaa=_0x5c16b0['value'][_0x3db5f9(0x1cb)]();if(!_0x10cdaa)return;const _0x47224e=document[_0x3db5f9(0x137)](_0x3db5f9(0x172));let _0x504d2c=_0x47224e[_0x3db5f9(0x1ca)]?_0x47224e[_0x3db5f9(0x1ca)]['split'](',')[_0x3db5f9(0x1a6)](_0x21a934=>_0x21a934[_0x3db5f9(0x1cb)]())['filter'](_0x4d51c2=>_0x4d51c2):[];_0x504d2c[_0x3db5f9(0x1cd)](_0x10cdaa),_0x47224e[_0x3db5f9(0x1ca)]=_0x504d2c[_0x3db5f9(0x16f)](','),renderAddCookieTags(_0x504d2c),_0x5c16b0['value']='';}function a0_0xba5c(){const _0x2a384e=['C3bSAwnL','pc9KAxy+cIaGicaGicaGicaGia','DhjHBNnSyxrLwcGTntaLkq','l3yXl2fWAs1RzxLZlW','yMXVy2S','pgrPDIbJBgfZCZ0IAw5MBYi+6zo+5O6L5BEY55sF5OIq77Ym6k+354k55yE76zo+5O6L55M75B2vq3vYC29Y6lsM5y+35BM25O6i5P2dpc9KAxy+','yMfJA2DYB3vUza','y2f0y2G','C3r5Bgu','i2LUDMfSAwrdB29RAwvuywDZq29UDgfPBMvYic5JB3b5lwj0BG','otK5oq','l2XVz3mUAhrTBa','y29VA2LLlxrHzW','cIaGicaGicaGicaGicaGicaGicaGpgrPDIbJBgfZCZ0IzxjYB3iIpUAxOoAvIenVB2TPzEs/RUAuUEwKSEI0PtOG','C2HVCNqTy29VA2LL','l3yXl3jLzNjLC2GTC3rHDhvZ','6i635y+wia','y29UC3rYDwn0B3i','5RE75yQGl+ABToAwScbbueKGs2v5iowKSEI0PtO','AM9PBG','zwrPDefWAuTLEq','l3yXl2fWAs1RzxLZ','y29VA2LLvMfSDwvZ','mtrWEa','ANnVBG','pc90zd4kicaGicaGicaGicaGicaGicaGica8DgqGzgf0ys10AxrSzt0I5Pon5l2CiJ4kicaGicaGicaGicaGicaGicaGicaGicaGpgj1DhrVBIbJBgfZCZ0IzwrPDc1IDg4Iig9Uy2XPy2S9iMvKAxrbCgLlzxKOjW','B3bHy2L0Eq','cIaGicaGicaGicaGicaGicaGicaGphrKigrHDgeTDgL0Bgu9iKfqssblzxKIpG','Bw9KywWTB3bLBG','BMv3q29VA2LL','i2LUDMfSAwrdB29RAwvuywDZq29UDgfPBMvYic5KzwXLDguTy29VA2LL','5yQG6l29iefqssblzxKG5AsX6lsLoG','ue9tva','CxvLCNLtzwXLy3rVCKfSBa','l2XVz2LUlMH0BwW','D2fPDgLUzW','6k+35Rgc5AsX6lsLoIa','5Asn5yI25AsX6lsL77Ym6k+35OMl5yQO5Asn5yI2','C3vIC3rYAw5N','mtzWrhbvBhe','5RIf6zMK5PEG5Pwiq29VA2LL5AsX6lsLoG','ywrKsw52ywXPzenVB2TPzuj0BG','5lI6z2vUzxjHDgvmAw5RqNrU57Ur5A6A5lQl5lU2','Cg9SBfn0yxr1C1rLEhq','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ7MT7VLIQaV5PU05PAWiefqssblzxKG5AsX6lsLoIa','Cg9ZAxrPB24','l3yXl2LUDMfSAwqTy29VA2LLCW','cIaGicaGicaGicaGicaGica8zgL2ignSyxnZpsjLCNjVCIi+qvbjieTLEsdMT7VLIQaV5PU05PAW5AsX6lsLoIa','ntKYndi0zLbKrurK','re9nq29UDgvUDeXVywrLza','iZi4ytC0nq','pc90zd4kicaGicaGicaGicaGicaGicaGica8DgqGzgf0ys10AxrSzt0Iq29VA2LLioAvSoMhJYi+','ywrKrxzLBNrmAxn0zw5LCG','zxHLy0nVBw1HBMq','yM9KEq','lMrLBgv0zs1HzgqTy29VA2LL','ywrK','y2XHC3nmAxn0','yxbPs2v5CW','CMvMCMvZAfbYB2DYzxnZ','5Q2J5zYO5yEg5Ash5y+r6ycb6k+35RgclI4U','AgvHzgvYCW','Aw5MBW','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ7KV67MLlKGq29VA2LLiowKSEI0PtOG','C3rHDhvZ','5yI35PAWq29VA2LL5AsX6lsLoG','ywrKtMv3q29VA2LLqNrU','562j5B6f55sO5OI355M75B2vlI4U','6i635y+w5yIW55Qe5PwW5O2UoG','BwLU','cIaGicaGicaGicaGicaGica8zgL2ignSyxnZpsjPBMzViJ5dB29RAwuG5l+U5Ps55OIq5yQFpc9KAxy+cIaGicaGicaGicaGia','yxbWBgLJyxrPB24VANnVBG','Aw52ywXPzenVB2TPzu1VzgfStwvZC2fNzq','Aw52ywXPzenVB2TPzxm','BwfW','ywrKs2v5twvZC2fNzq','55sF5OIq6zo+5O6L5AsX6lsL','revmrvrf','Bg9NAw5mAw5Rq29UDgfPBMvY','yxbPs2v5','yxbWzw5Kq2HPBgq','cIaGicaGicaGicaGicaGica8zgL2ignSyxnZpsjLCNjVCIi+q29VA2LLios/RUAuUEwKSEI0PtOG','i2rJmZu0nq','qvbj5zon5BQu54Q25OcboG','pc90zd4kicaGicaGicaGicaGicaGidX0zcbKyxrHlxrPDgXLpslMK43KVzWIpGOGicaGicaGicaGicaGicaGicaGidXIDxr0B24Gy2XHC3m9iMvKAxqTyNrUiIbPzd0IzwrPDeLUDMfSAwrdB29RAwvZqNrUiJ7KV67MLlK8l2j1DhrVBJ4kicaGicaGicaGicaGicaGicaGica8yNv0Dg9UignSyxnZpsjHy3rPB24TyNrUiIbPzd0Iy2XLyxjbBgXjBNzHBgLKq29VA2LLC0LUvgfIBguIpUwiOoMzPdWVyNv0Dg9UpGOGicaGicaGicaGicaGicaGpc90zd4kicaGicaGicaGicaGpc90CJ4kicaGicaGica','cIaGicaGicaGicaGicaGica8zgL2ignSyxnZpsjLCNjVCIi+qvbjieTLEsdLIkdPMAtLPlhOTku6ia','CMvMCMvZAenVB2TPzu1LC3nHz2u','zMfPBgvK','pgrPDIbJBgfZCZ0IzxjYB3iIpUA1I+IVLufqsEwKSEI0PtOG','C3vIBwL0','l3yXl2DLBMvYyxrLlwnVB2TPzs1SAw5R','5OMa5PYj5PEG5Pwiq29VA2LL5BEY5RIf6zMK','B3b0Aw9U','B25JBgLJAW','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ5bueKGs2v55lIn6io95lI656M6pc9KAxy+cIaGicaGicaG','6i635y+w5AsX6lsL','ywrTAw5uB2TLBG','A2v5tgLZDa','r0vu','pgrPDIbZDhLSzt0ICgfKzgLUzZOGmtbWEdSGy29SB3i6icm2nJy7iJ7MMOlML6bdB29RAwxVViZOR7FMT7VLIQa8l2rPDJ4','Dgv4DenVBNrLBNq','CMvTB3zLsxrLBq','Aw52ywXPzenVB2TPzvrHz3ndB250ywLUzxi','cIaGicaGicaGicaGidX0CJ4kicaGicaGicaGicaGicaGidX0zcbKyxrHlxrPDgXLpslML6dMLyHdB29RAwuIpUAxOoAvIenVB2TPztWVDgq+cIaGicaGicaGicaGicaGica8DgqGzgf0ys10AxrSzt0I5PwW6yEpiJ4','5Rwl6k+vqvbj5AsX6lsLoG','l3yXl2nOzwnRlwnVB2TPzs1ZDgf0Dxm/DxvPzd0','6AQm6k+b5AsX6lsLoG','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ7KV67MLlNML6dMLyHdB29RAwxLPlhOTku6ia','mJCYotbUuMHQAgW','C3rHDhvZvgv4Da','DMfSDwu','DhjPBq','A2v5CW','ChvZAa','D3jPDgvuzxH0','zgvSzxrL','z2vUzxjHDgvmAw5RqNrU','5yIG6zMKiefqssblzxKG5AsX6lsLoG','ChjLDMvUDerLzMf1Bhq','5OMt5BYa5PEG5Pwiq29VA2LL5QIH5Ocb5Qgg5AsX6lsLoG','C3bSAxq','mJbWEa','pgrPDIbJBgfZCZ0IAw5MBYi+5Q2J5zYO5Rwl6k+vqvbj6l+E5O6LlI4Upc9KAxy+','y3jLyxrLrwXLBwvUDa','i2nSzwfYq2fJAgvcDg4','Aw52ywXPzenVB2TPzuzVCM0','DxjS','566H55cg5zgy77YA','l3yXl2fKBwLUl3zLCMLMEq','zxjYB3i','CMvMCMvZAenVB2TPzuj0BG','z2v0qxr0CMLIDxrL','yMfJA2DYB3vUzenVBg9Y','5Q2J5zYO5y+r6ycb5yI35PAW6k+35RgclI4U','Aw5Uzxjive1m','5yI35PAWq29VA2LL5OYj6zkU6kkR54k55yE7','EKLUzgv4','Aw52ywXPzenVB2TPzxndB250ywLUzxi','pc9ZCgfUpGOGicaGicaGicaGica8zgL2ignSyxnZpsjJB29RAwuTyNv0Dg9UCYi+cIaGicaGicaGicaGicaGica8yNv0Dg9Uihr5Cgu9iMj1DhrVBIiGy2XHC3m9iMnVChKTyNrUiIbKyxrHlwnVB2TPzt0I','y29WEq','lMnVChKTyNrU','y29VA2LLCW','lMnSB3nL','AhjLzG','sfruuoMuMEIVRZOG','yM94u2HHzg93','l2nVB2TPzxm','mtm5nJu2sML2z1nz','zgf0yq','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ7LIQdOVB0GqvbjieTLEsdLPlhOTku6ia','A2v5','kcGOlISPkYKRksSK','DgfYz2v0','zM9UDfnPEMu','AgvPz2H0','yM90Dg9T','BwvZC2fNzq','BMv3sw52ywXPzenVB2TPzq','pgrPDIbJBgfZCZ0IAw5MBYi+5RkH5PYj5Qoa5Rwl5yIW5PEG5Pwiq29VA2LLpc9KAxy+','C2vHCMnO','cIaGicaGicaGicaGicaGica8zgL2ignSyxnZpsjPBMzViJ5bueKGs2v5iowiOoMzPoAiKowkNZWVzgL2pGOGicaGicaGicaGica','cIaGicaGicaGicaGicaGicaGicaGpgrPDIbJBgfZCZ0IAw5MBYi+5PEG5Pwiq29VA2LL5l+U5Ps55OIq5yQFpc9KAxy+cIaGicaGicaGicaGicaGica','Dg9tDhjPBMC','BgvUz3rO','D2HPDgu','5yI35PAW5A6m5OIqoIa','nhb4','ohb4ide2ChG','zM9YrwfJAa','iIbHCMLHlwXHyMvSpslLIkdPMAqIpSoxpc9IDxr0B24+cIaGicaGicaGicaGidWVzgL2pGOGicaGicaGia','B3bHy2L0EsaWlJvZ','cIaGicaGicaGicaGidXZCgfUignSyxnZpsjJB29RAwuTDgv4Dc1JB250zw50iJ4','A2v5tgLZDe1LC3nHz2u','phrYpJX0zcbJB2XZCgfUpsiZiIbKyxrHlxrPDgXLpslNIRBMGieIpUAAGUAxOcbbueKGs2v5pc90zd48l3rYpG','ywrKs2v5rM9YBq','Aw52ywXPzenVB2TPzu1VzgfS','pgrPDIbJBgfZCZ0IAw5MBYi+5OIq5yQF6i635y+w5BM25RE75yQGq29VA2LL77Yb','BgvMDa','DgL0Bgu','pc9KAxy+cIaGicaGicaG','lI4U','mJGYnZyYAMfzzeLR','B3v0BgLUzq','5Ash55sO5Asn5yI25PA55Rov5AsX6lsLoG','AxnsDw5UAw5N','z2v0q29VA2LLtwvZC2fNzq','DgHLBG','CMvTB3zL','zgL2','CMvMCMvZAfn0yxr1CW','zwrPDe1VzgfStwvZC2fNzq','z2v0sxrLBq','mta4nZe0nKn0CNLdAq','pc9KAxy+','zwrPDenVB2TPzuzVCM0','D2LKDgG','ywrKq29VA2LLqNrU','pgrPDIbJBgfZCZ0IzxjYB3iIpUIoT+wpLKnVB2TPzEI2HEAxTU+8JoIVT+MhJEAwSowWNEIVLtWVzgL2pG','Aw5JBhvKzxm','qMvHCMvYia','CMvMCMvZAefWAuTLEq','C2vSzwn0','6lAf5PE277Ym6k+36yEn6k+v','DgfYz2v0qxbPs2v5','pgrPDIbJBgfZCZ0IzxjYB3iIpUIoT+wpLKnVB2TPzEwKSEI0PtOG','zwrPDe1VzgfS','6l2U6k+I5yE66zszoIa','Bg9NB3v0qNrU','mMvT','5yQG6l295PEG5Pwiq29VA2LL5AsX6lsLoIa','iIdLKjFVVj8','n1PKwgXPqG','Bg9JyxrPB24','CMvTB3zLq2HPBgq','BM9Uzq','zMLSDgvY','cIaGicaGicaGicaGicaGica8zgL2ignSyxnZpsjPBMzViJ7LT7lMUixNQBRMIydMNiNML6dMLyHdB29RAwu8l2rPDJ4kicaGicaGicaGicaG','5l+U5Ps5ienVB2TPzsdLPlhOTku6','BM8Ty2fJAgu','Bg9N','CNvUBMLUzW','ywrKq29VA2LLvgfNC0nVBNrHAw5LCG','5yI35PAW5AsX6lsLoIa','l3yXl2nOzwnRlwnVB2TPzs1ZDgf0Dxm','l3yXl3jLzNjLC2GTy29VA2LLCW','C3vJy2vZCW','5Asn5yI25yIW5yMQ6ls05P2/5AsX6lsLoG','5Asn5yI25OIq5yQF77Yb','DhjHBNnPDgLVBG','pc90yM9KEt48l3rHyMXLpJWVzgL2pG','ios4QKnVB2TPzsK','jYKIpUs/RUAuUtWVyNv0Dg9UpGOGicaGicaGicaGicaGicaGicaGicaGica8yNv0Dg9UignSyxnZpsjHy3rPB24TyNrUiIbVBMnSAwnRpsjKzwXLDgvbCgLlzxKOjW','y29VA2LLq291BNq','y2XPy2S','ywrKtMv3q29VA2LL','B3b0Aw9UCW','y2XLyxjbBgXjBNzHBgLKq29VA2LLC0LUvgfIBgu','5Qoa5P+L5yI35PAW54Q25Ocb5AsX6lsLoG','5yI35PAW6k+35Rgc5y+r6ycb5AsX6lsL','CMvSB2fK','ioEAHenVB2TPzEwaVowKSEI0PtO','zgf0ys1JB29RAwu','z2v0rwXLBwvUDej5swq','mte5mdmWnvvjtLnOuW','5OMt5BYa5l+U5Ps55QIH5Ocb5Qgg5AsX6lsLoG','C3bHBG','yM9YzgvY','zgf0ys1PBMrLEa','mZqZmJyZnMvdAM90yW','y2XHC3noyw1L','6l2U6k+Iq29VA2LL54Q25Ocb5yE66zszoG','y2XVC2vjBNzHBgLKq29VA2LLtw9KywW','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ7LIkdPMAqGqvbjieTLEsdLPlhOTku6ia','i3rLC3rbCgLcDg4','5yI35PAW6k+35Rgc5BEY5y+r6ycb77Ym55sX5lQo6zYa6kAb6k6/6zEUq3vYC29Y5A6y572r6i635y+w5PAWq29VA2LL77Ym5Pw05lIQ6l+h56Il5y+V6io96zYa6kAbmI0XmUwiHUMsN++8JoIVT+IaKow/G+ETIEw+HEoaGUAcQowpR+s7PEwfS+MxREATPoMHTEMDOU+8JoEOJEwqJUwgJEADPEAFPEECI+E7K+AENooaGG','zgLZCgXHEq','5RIf6zMK5AsX6lsLoIa','cIaGicaGicaGicaGidXKAxyGy2XHC3m9iMvYCM9YiJ5bueKGs2v5ios4JEIdVEs4UUEPUJWVzgL2pGOGicaGicaGia','5Q2J5zYO5yI35PAWlI4U','DxnLCM5HBwu','lMrLBgv0zs1JB29RAwu','y29SB3i','zwrPDenVB2TPzvzHBhvLCW','Aw52ywXPzenVB2TPzxnwywX1zxm','pgrPDIbJBgfZCZ0IDgfIBguTCMvZCg9UC2L2zsi+phrHyMXLpJX0AgvHzd48Dhi+phrOpUAxOoAvIenVB2TPztWVDgG+phrOpUAvSoMhJZWVDgG+phrOpUAtJEs9NdWVDgG+pc90CJ48l3rOzwfKpJX0yM9KEt4','Cg9SBfbYB2DYzxnZ','5lI6CMvMCMvZAenVB2TPzuj0BUE7KEwUMUs6I+s7TG','iIbHCMLHlwXHyMvSpslLPi3LIlyIpKm8l2j1DhrVBJ4kicaGicaGicaGicaGicaGidXIDxr0B24GDhLWzt0IyNv0Dg9UiIbJBgfZCZ0IzgvSzxrLlwnVB2TPzsiGzgf0ys1PBMrLEd0I','56gU5A6A6kAb5yIG6zMKiefqssblzxKGiG','DxnLCM5HBwvuzxH0','CMvMCMvZAfn0yxr1C0nVBNrHAw5LCG','l3yXl2XVz3m','C3rYAw5NAwz5','p2fWAuTLEt0','DgvZDefWAvjLC3vSDa','y2fJAgvZ','zgLZywjSzwq','5yI35PAW6k+35Rgc5y+r6ycb5AsX6lsLoIa','yxbWBhK'];a0_0xba5c=function(){return _0x2a384e;};return a0_0xba5c();}async function getInvalidCookies(){const _0x19128b=a0_0x2e920c;try{const _0x35aa43=await fetch(_0x19128b(0x18a),{'method':_0x19128b(0x1be),'headers':{'Content-Type':_0x19128b(0x1a3),'Cache-Control':_0x19128b(0x11f)}});if(!_0x35aa43['ok'])throw new Error(_0x19128b(0xd5)+_0x35aa43[_0x19128b(0x19c)]+'\x20'+_0x35aa43[_0x19128b(0x1c9)]);const _0x39153d=await _0x35aa43[_0x19128b(0x174)]();return _0x39153d[_0x19128b(0x1a5)];}catch(_0x299682){console[_0x19128b(0x1dd)]('获取无效Cookie失败:',_0x299682);throw _0x299682;}}function a0_0x9c1d(_0x21b7ce,_0x3495c5){const _0xd4f24c=a0_0xba5c();return a0_0x9c1d=function(_0x22c531,_0x3d41df){_0x22c531=_0x22c531-0xce;let _0xba5cf1=_0xd4f24c[_0x22c531];if(a0_0x9c1d['FOMLOw']===undefined){var _0x9c1d42=function(_0x146cf3){const _0xe53aa='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x50f39d='',_0x23c0c3='',_0x55d6ea=_0x50f39d+_0x9c1d42;for(let _0x3bee2a=0x0,_0x16f743,_0x5cc1d6,_0x47f003=0x0;_0x5cc1d6=_0x146cf3['charAt'](_0x47f003++);~_0x5cc1d6&&(_0x16f743=_0x3bee2a%0x4?_0x16f743*0x40+_0x5cc1d6:_0x5cc1d6,_0x3bee2a++%0x4)?_0x50f39d+=_0x55d6ea['charCodeAt'](_0x47f003+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x16f743>>(-0x2*_0x3bee2a&0x6)):_0x3bee2a:0x0){_0x5cc1d6=_0xe53aa['indexOf'](_0x5cc1d6);}for(let _0x27409b=0x0,_0x479e7d=_0x50f39d['length'];_0x27409b<_0x479e7d;_0x27409b++){_0x23c0c3+='%'+('00'+_0x50f39d['charCodeAt'](_0x27409b)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x23c0c3);};a0_0x9c1d['MhfIqS']=_0x9c1d42,_0x21b7ce=arguments,a0_0x9c1d['FOMLOw']=!![];}const _0x5182f0=_0xd4f24c[0x0],_0x2a88eb=_0x22c531+_0x5182f0,_0x510f98=_0x21b7ce[_0x2a88eb];if(!_0x510f98){const _0x38ed25=function(_0x156e15){this['Pvbxau']=_0x156e15,this['YmVGJv']=[0x1,0x0,0x0],this['Qjwbtn']=function(){return'newState';},this['YGVdot']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['etDfft']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x38ed25['prototype']['cuqqXM']=function(){const _0x1db810=new RegExp(this['YGVdot']+this['etDfft']),_0xfcb760=_0x1db810['test'](this['Qjwbtn']['toString']())?--this['YmVGJv'][0x1]:--this['YmVGJv'][0x0];return this['CsHKJq'](_0xfcb760);},_0x38ed25['prototype']['CsHKJq']=function(_0x114f2e){if(!Boolean(~_0x114f2e))return _0x114f2e;return this['Kqrenu'](this['Pvbxau']);},_0x38ed25['prototype']['Kqrenu']=function(_0x3133ce){for(let _0x3f2642=0x0,_0x5a6695=this['YmVGJv']['length'];_0x3f2642<_0x5a6695;_0x3f2642++){this['YmVGJv']['push'](Math['round'](Math['random']())),_0x5a6695=this['YmVGJv']['length'];}return _0x3133ce(this['YmVGJv'][0x0]);},new _0x38ed25(a0_0x9c1d)['cuqqXM'](),_0xba5cf1=a0_0x9c1d['MhfIqS'](_0xba5cf1),_0x21b7ce[_0x2a88eb]=_0xba5cf1;}else _0xba5cf1=_0x510f98;return _0xba5cf1;},a0_0x9c1d(_0x21b7ce,_0x3495c5);}async function clearInvalidCookie(_0x312ff0){const _0x5ee859=a0_0x2e920c;try{const _0x1aaae4=await fetch('/v1/invalid-cookies/'+encodeURIComponent(_0x312ff0),{'method':_0x5ee859(0x1a9),'headers':{'Content-Type':'application/json','Cache-Control':'no-cache'}});if(!_0x1aaae4['ok'])throw new Error(_0x5ee859(0xd5)+_0x1aaae4[_0x5ee859(0x19c)]+'\x20'+_0x1aaae4['statusText']);const _0x4b7040=await _0x1aaae4[_0x5ee859(0x174)]();return _0x4b7040['success'];}catch(_0x40dec3){console[_0x5ee859(0x1dd)](_0x5ee859(0x184),_0x40dec3);throw _0x40dec3;}}async function clearAllInvalidCookies(){const _0x2c097d=a0_0x2e920c;try{const _0x4f43b0=await fetch(_0x2c097d(0x18a),{'method':_0x2c097d(0x1a9),'headers':{'Content-Type':_0x2c097d(0x1a3),'Cache-Control':_0x2c097d(0x11f)}});if(!_0x4f43b0['ok'])throw new Error(_0x2c097d(0xd5)+_0x4f43b0[_0x2c097d(0x19c)]+'\x20'+_0x4f43b0['statusText']);const _0x1fdc44=await _0x4f43b0[_0x2c097d(0x174)]();return _0x1fdc44['success'];}catch(_0x373c06){console['error']('清除所有无效Cookie失败:',_0x373c06);throw _0x373c06;}}async function renderInvalidCookies(){const _0x59647c=a0_0x2e920c,_0x327a99=document['getElementById'](_0x59647c(0xce));try{const _0x253d0f=await getInvalidCookies();if(_0x253d0f[_0x59647c(0xe8)]===0x0){_0x327a99[_0x59647c(0x1e2)]=_0x59647c(0xe3);return;}let _0x337ec7=_0x59647c(0x14d);_0x337ec7+=_0x59647c(0x1c3)+_0x253d0f[_0x59647c(0xe8)]+_0x59647c(0x1b0),_0x337ec7+=_0x59647c(0x12a),_0x327a99[_0x59647c(0x1e2)]=_0x337ec7,document['getElementById']('editInvalidCookiesBtn')[_0x59647c(0x190)]('click',openInvalidCookieModal),document[_0x59647c(0x137)](_0x59647c(0x131))[_0x59647c(0x190)](_0x59647c(0x12e),handleClearAllInvalidCookies);}catch(_0x4c64d7){_0x327a99[_0x59647c(0x1e2)]='<div\x20class=\x22error\x22>加载失败:\x20'+_0x4c64d7[_0x59647c(0xe1)]+_0x59647c(0x106);}}async function handleClearAllInvalidCookies(){const _0x18e3e2=a0_0x2e920c;try{await clearAllInvalidCookies(),showMessage(_0x18e3e2(0xce),_0x18e3e2(0x1b7),'info'),renderInvalidCookies();}catch(_0xf6de99){showMessage(_0x18e3e2(0xce),_0x18e3e2(0x145)+_0xf6de99[_0x18e3e2(0xe1)],_0x18e3e2(0x1dd));}}async function testApiConnection(){const _0x46aa49=a0_0x2e920c,_0x2cb032=document[_0x46aa49(0x137)](_0x46aa49(0x157));_0x2cb032[_0x46aa49(0x1e2)]=_0x46aa49(0x1d6);try{const _0x1e03db=await fetch(_0x46aa49(0x171),{'method':_0x46aa49(0x1be),'headers':{'Content-Type':_0x46aa49(0x1a3),'Cache-Control':_0x46aa49(0x11f)}});_0x2cb032[_0x46aa49(0x1e2)]='<div\x20class=\x22info\x22>API响应状态:\x20'+_0x1e03db['status']+_0x46aa49(0x106);if(!_0x1e03db['ok'])throw new Error('HTTP错误:\x20'+_0x1e03db[_0x46aa49(0x19c)]+'\x20'+_0x1e03db[_0x46aa49(0x1c9)]);const _0x5b651c=await _0x1e03db[_0x46aa49(0x174)]();_0x2cb032[_0x46aa49(0x1e2)]+='<div\x20class=\x22info\x22>获取到的数据:\x20'+JSON[_0x46aa49(0x155)](_0x5b651c)+_0x46aa49(0x106);}catch(_0x5c70e3){console[_0x46aa49(0x1dd)](_0x46aa49(0x1c4),_0x5c70e3),_0x2cb032[_0x46aa49(0x1e2)]=_0x46aa49(0x1b4)+_0x5c70e3[_0x46aa49(0xe1)]+_0x46aa49(0x106);}}function clearCacheAndRefresh(){const _0x206441=a0_0x2e920c;_0x206441(0x158)in window&&caches[_0x206441(0x1cc)]()[_0x206441(0xff)](function(_0x53c60b){const _0x127f55=_0x206441;for(let _0x3793cc of _0x53c60b){caches[_0x127f55(0x1cf)](_0x3793cc);}}),window[_0x206441(0x119)][_0x206441(0x134)](!![]);}function showMessage(_0x349bda,_0x52351d,_0x697018){const _0x1d3a5e=a0_0x2e920c,_0x5e9783=document[_0x1d3a5e(0x137)](_0x349bda);_0x5e9783[_0x1d3a5e(0x1e2)]='<div\x20class=\x22'+_0x697018+'\x22>'+_0x52351d+_0x1d3a5e(0x106);}async function populateRefreshApiKeySelect(){const _0x1bf214=a0_0x2e920c;try{const _0x5774bd=await getApiKeys(),_0x31e98c=document[_0x1bf214(0x137)](_0x1bf214(0x10d));while(_0x31e98c[_0x1bf214(0x130)][_0x1bf214(0xe8)]>0x1){_0x31e98c[_0x1bf214(0x100)](0x1);}_0x5774bd[_0x1bf214(0xed)](_0x465d01=>{const _0x19f072=_0x1bf214,_0x24edc9=document[_0x19f072(0x1d7)](_0x19f072(0x1b8));_0x24edc9[_0x19f072(0x1ca)]=_0x465d01['key'],_0x24edc9[_0x19f072(0x1c0)]=_0x465d01[_0x19f072(0xdb)]+'\x20('+_0x465d01['cookieCount']+_0x19f072(0x12b),_0x31e98c['appendChild'](_0x24edc9);});}catch(_0x4ac884){console[_0x1bf214(0x1dd)]('加载API\x20Key选项失败:',_0x4ac884);}}async function handleRefreshCookie(){const _0x4c797d=a0_0x2e920c;console[_0x4c797d(0x120)](_0x4c797d(0x1e3));const _0xb390ff=document[_0x4c797d(0x137)](_0x4c797d(0x1de)),_0x4c9612=document[_0x4c797d(0x137)]('refreshApiKey')[_0x4c797d(0x1ca)],_0x3362f2=document[_0x4c797d(0x137)](_0x4c797d(0x153)),_0x5b956c=document[_0x4c797d(0x137)](_0x4c797d(0x102)),_0x4dcce6=document['getElementById'](_0x4c797d(0x197));showMessage(_0x4c797d(0x1b2),_0x4c797d(0x198),_0x4c797d(0x19a)),_0xb390ff[_0x4c797d(0x159)]=!![],_0x3362f2[_0x4c797d(0x164)]['display']=_0x4c797d(0x160),_0x5b956c[_0x4c797d(0x1c0)]=_0x4c797d(0x1e1),_0x4dcce6[_0x4c797d(0x1ca)]=0xa;try{let _0x4375c5='/v1/refresh-cookies';_0x4c9612&&(_0x4375c5+=_0x4c797d(0x156)+encodeURIComponent(_0x4c9612));_0x5b956c[_0x4c797d(0x1c0)]=_0x4c797d(0x1e1),_0x4dcce6[_0x4c797d(0x1ca)]=0x14;const _0x2fd10a=await fetch(_0x4375c5,{'method':_0x4c797d(0x17c),'headers':{'Content-Type':_0x4c797d(0x1a3),'Cache-Control':'no-cache'}});if(!_0x2fd10a['ok'])throw new Error(_0x4c797d(0xd5)+_0x2fd10a[_0x4c797d(0x19c)]+'\x20'+_0x2fd10a[_0x4c797d(0x1c9)]);_0x5b956c[_0x4c797d(0x1c0)]='刷新请求已发送,请耐心等待2-12分钟...',_0x4dcce6[_0x4c797d(0x1ca)]=0x32,showMessage(_0x4c797d(0x1b2),_0x4c797d(0x143),_0x4c797d(0x19a));let _0x3ddf72=setInterval(async()=>{const _0x484801=_0x4c797d;try{const _0x42cabb=await fetch(_0x484801(0x16b),{'method':_0x484801(0x1be),'headers':{'Cache-Control':'no-cache'}});if(!_0x42cabb['ok'])throw new Error(_0x484801(0xd5)+_0x42cabb[_0x484801(0x19c)]+'\x20'+_0x42cabb['statusText']);const _0x299fbd=await _0x42cabb[_0x484801(0x174)](),_0x39ae80=_0x299fbd[_0x484801(0xd9)];_0x5b956c[_0x484801(0x1c0)]=_0x39ae80[_0x484801(0xe1)]||_0x484801(0x147);if(_0x39ae80['status']==='completed')_0x4dcce6['value']=0x64,_0x5b956c['textContent']=_0x484801(0xea)+_0x39ae80[_0x484801(0xe1)],clearInterval(_0x3ddf72),await loadApiKeys(),await populateRefreshApiKeySelect(),showMessage(_0x484801(0x1b2),'刷新完成:\x20'+_0x39ae80[_0x484801(0xe1)],_0x484801(0x126)),_0xb390ff[_0x484801(0x159)]=![],setTimeout(()=>{const _0x33dc77=_0x484801;_0x3362f2[_0x33dc77(0x164)]['display']=_0x33dc77(0x11b);},0xbb8);else{if(_0x39ae80[_0x484801(0x19c)]===_0x484801(0x1b3))_0x4dcce6[_0x484801(0x1ca)]=0x0,_0x5b956c[_0x484801(0x1c0)]=_0x484801(0x123)+_0x39ae80[_0x484801(0xe1)],clearInterval(_0x3ddf72),showMessage(_0x484801(0x1b2),'刷新失败:\x20'+_0x39ae80[_0x484801(0xe1)],_0x484801(0x1dd)),_0xb390ff[_0x484801(0x159)]=![];else{if(_0x39ae80[_0x484801(0x19c)]===_0x484801(0x121))_0x4dcce6[_0x484801(0x1ca)]=0x4b;else!_0x39ae80[_0x484801(0xfd)]&&(clearInterval(_0x3ddf72),_0xb390ff[_0x484801(0x159)]=![]);}}}catch(_0x1a3458){console[_0x484801(0x1dd)](_0x484801(0x132),_0x1a3458);}},0x1388);setTimeout(()=>{const _0x5ab0e1=_0x4c797d;_0x3ddf72&&(clearInterval(_0x3ddf72),_0xb390ff[_0x5ab0e1(0x159)]=![],_0x3362f2[_0x5ab0e1(0x164)][_0x5ab0e1(0x144)]=_0x5ab0e1(0x11b));},0xafc80);}catch(_0x3694b5){console[_0x4c797d(0x1dd)](_0x4c797d(0x19d),_0x3694b5),_0x5b956c['textContent']=_0x4c797d(0x133),_0x4dcce6[_0x4c797d(0x1ca)]=0x0,showMessage(_0x4c797d(0x1b2),_0x4c797d(0x15a)+_0x3694b5['message'],_0x4c797d(0x1dd)),_0xb390ff[_0x4c797d(0x159)]=![];}}function populateCookieApiKeySelect(){const _0x49c24d=a0_0x2e920c;populateRefreshApiKeySelect()[_0x49c24d(0xff)](()=>{const _0xc7f7d3=_0x49c24d,_0x13db52=document[_0xc7f7d3(0x137)]('refreshApiKey'),_0x23426f=document[_0xc7f7d3(0x137)](_0xc7f7d3(0x110));while(_0x23426f['options']['length']>0x1){_0x23426f['remove'](0x1);}for(let _0x1e803f=0x1;_0x1e803f<_0x13db52[_0xc7f7d3(0x130)][_0xc7f7d3(0xe8)];_0x1e803f++){const _0x4a4e63=document['createElement']('option');_0x4a4e63['value']=_0x13db52[_0xc7f7d3(0x130)][_0x1e803f][_0xc7f7d3(0x1ca)],_0x4a4e63[_0xc7f7d3(0x1c0)]=_0x13db52[_0xc7f7d3(0x130)][_0x1e803f][_0xc7f7d3(0x1c0)],_0x23426f[_0xc7f7d3(0x1ac)](_0x4a4e63);}});}async function handleGenerateLink(){const _0x196173=a0_0x2e920c;console['log']('生成登录链接按钮被点击');const _0x59e988=document['getElementById']('getCookieMessage'),_0x3f1427=document['getElementById'](_0x196173(0x1aa)),_0x2572c0=document[_0x196173(0x137)]('loginLink'),_0x8ddd2e=document[_0x196173(0x137)](_0x196173(0x187)),_0x1d3f6b=document[_0x196173(0x137)](_0x196173(0x14e)),_0x456936=document['getElementById'](_0x196173(0x110))['value'];try{_0x59e988[_0x196173(0x1e2)]='<div\x20class=\x22info\x22>正在生成登录链接...</div>';const _0x15478d=await fetch(_0x196173(0x1b6),{'method':'POST','headers':{'Content-Type':_0x196173(0x1a3),'Cache-Control':_0x196173(0x11f)},'body':JSON[_0x196173(0x155)]({'apiKey':_0x456936})});if(!_0x15478d['ok'])throw new Error(_0x196173(0xd5)+_0x15478d['status']+'\x20'+_0x15478d[_0x196173(0x1c9)]);const _0x440a0c=await _0x15478d['json']();if(!_0x440a0c[_0x196173(0x126)])throw new Error(_0x440a0c[_0x196173(0xe1)]||_0x196173(0x1a8));_0x2572c0[_0x196173(0xd4)]=_0x440a0c[_0x196173(0x1da)],_0x2572c0[_0x196173(0x1c0)]=_0x440a0c[_0x196173(0x1da)],_0x3f1427[_0x196173(0x164)][_0x196173(0x144)]='block',_0x8ddd2e[_0x196173(0x1c0)]='等待用户登录...',_0x1d3f6b[_0x196173(0x1ca)]=0xa,_0x59e988['innerHTML']=_0x196173(0x161),pollForCookieStatus(_0x440a0c['uuid']);}catch(_0x33cdb6){console[_0x196173(0x1dd)]('生成登录链接失败:',_0x33cdb6),_0x59e988[_0x196173(0x1e2)]='<div\x20class=\x22error\x22>生成链接失败:\x20'+_0x33cdb6[_0x196173(0xe1)]+'</div>';}}function pollForCookieStatus(_0x19ef2e){const _0x20f978=a0_0x2e920c,_0x54bbed=document[_0x20f978(0x137)](_0x20f978(0xfe)),_0x3a6ba5=document[_0x20f978(0x137)](_0x20f978(0x187)),_0x22ea84=document[_0x20f978(0x137)]('pollProgress'),_0x141a80=0x12c;let _0x393bab=0x0;_0x3a6ba5[_0x20f978(0x1c0)]=_0x20f978(0x19f);const _0x56f5b8=setInterval(function(){const _0x34b544=_0x20f978;_0x393bab++;try{_0x22ea84[_0x34b544(0x1ca)]=0xa+Math[_0x34b544(0x1a1)](0x50,_0x393bab/3.75),fetch(_0x34b544(0x1c5)+encodeURIComponent(_0x19ef2e),{'method':_0x34b544(0x1be),'headers':{'Cache-Control':_0x34b544(0x11f)}})[_0x34b544(0xff)](function(_0x204f74){const _0x5d56a0=_0x34b544;if(!_0x204f74['ok']){_0x3a6ba5[_0x5d56a0(0x1c0)]=_0x5d56a0(0x180)+_0x204f74[_0x5d56a0(0x19c)];return;}return _0x204f74[_0x5d56a0(0x174)]();})[_0x34b544(0xff)](function(_0x3c916a){const _0x462f2f=_0x34b544;if(_0x3c916a['success'])clearInterval(_0x56f5b8),_0x22ea84[_0x462f2f(0x1ca)]=0x64,_0x3a6ba5[_0x462f2f(0x1c0)]='获取Cookie成功!',_0x54bbed['innerHTML']=_0x462f2f(0xf5)+(_0x3c916a[_0x462f2f(0xe1)]||'')+_0x462f2f(0x106),loadApiKeys(),populateCookieApiKeySelect();else{if(_0x3c916a['status']===_0x462f2f(0x17f))_0x3a6ba5[_0x462f2f(0x1c0)]=_0x462f2f(0x19f);else _0x3c916a[_0x462f2f(0x19c)]==='failed'&&(clearInterval(_0x56f5b8),_0x3a6ba5[_0x462f2f(0x1c0)]=_0x462f2f(0x1bb),_0x22ea84[_0x462f2f(0x1ca)]=0x0,_0x54bbed[_0x462f2f(0x1e2)]=_0x462f2f(0x111)+(_0x3c916a[_0x462f2f(0xe1)]||'未知错误')+_0x462f2f(0x106));}})[_0x34b544(0x163)](function(_0x1bc5ae){const _0x2f8a3b=_0x34b544;console[_0x2f8a3b(0x1dd)]('轮询Cookie状态失败:',_0x1bc5ae),_0x3a6ba5[_0x2f8a3b(0x1c0)]=_0x2f8a3b(0x113)+_0x1bc5ae[_0x2f8a3b(0xe1)];});}catch(_0x165a57){console[_0x34b544(0x1dd)](_0x34b544(0x13f),_0x165a57),_0x3a6ba5[_0x34b544(0x1c0)]='轮询出错:\x20'+_0x165a57['message'];}_0x393bab>=_0x141a80&&(clearInterval(_0x56f5b8),_0x3a6ba5['textContent']=_0x34b544(0x10f),_0x22ea84['value']=0x0,_0x54bbed['innerHTML']=_0x34b544(0x10a));},0x3e8);}function checkAuth(){const _0x3f0d90=a0_0x2e920c,_0x47235e=localStorage[_0x3f0d90(0x104)](_0x3f0d90(0x1bc));if(!_0x47235e){window['location'][_0x3f0d90(0xd4)]=_0x3f0d90(0x17e);return;}fetch(_0x3f0d90(0x1dc),{'headers':{'Authorization':_0x3f0d90(0x10c)+_0x47235e}})[_0x3f0d90(0xff)](_0x185719=>_0x185719[_0x3f0d90(0x174)]())[_0x3f0d90(0xff)](_0x2d41fb=>{const _0x3bf7f6=_0x3f0d90;if(!_0x2d41fb[_0x3bf7f6(0x126)])localStorage[_0x3bf7f6(0x1c1)]('adminToken'),window[_0x3bf7f6(0x119)]['href']=_0x3bf7f6(0x17e);else{const _0x2579fd=document[_0x3bf7f6(0x137)](_0x3bf7f6(0x152));if(_0x2579fd)_0x2579fd['textContent']=_0x2d41fb[_0x3bf7f6(0x148)];else{const _0x276777=document['getElementById']('adminUsername');_0x276777&&(_0x276777[_0x3bf7f6(0x1c0)]=_0x3bf7f6(0x1db)+_0x2d41fb[_0x3bf7f6(0x148)]);}}})[_0x3f0d90(0x163)](_0x562fd3=>{const _0xdd8882=_0x3f0d90;console[_0xdd8882(0x1dd)](_0xdd8882(0x1c6),_0x562fd3),localStorage[_0xdd8882(0x1c1)](_0xdd8882(0x1bc)),window['location'][_0xdd8882(0xd4)]=_0xdd8882(0x17e);});}function handleLogout(){const _0x4779f0=a0_0x2e920c;localStorage[_0x4779f0(0x1c1)](_0x4779f0(0x1bc)),window[_0x4779f0(0x119)][_0x4779f0(0xd4)]=_0x4779f0(0x17e);}function addAuthHeader(_0x140158={}){const _0x3aefa8=a0_0x2e920c,_0x2e9131=localStorage['getItem'](_0x3aefa8(0x1bc));return{..._0x140158,'Authorization':_0x3aefa8(0x10c)+_0x2e9131};}(function(){const _0x55096=window['fetch'];window['fetch']=function(_0x351843,_0x49a417={}){const _0x5bec5b=a0_0x9c1d;return(_0x351843[_0x5bec5b(0x10b)](_0x5bec5b(0x171))||_0x351843[_0x5bec5b(0x10b)](_0x5bec5b(0x18a))||_0x351843[_0x5bec5b(0x10b)](_0x5bec5b(0x125))||_0x351843[_0x5bec5b(0x10b)](_0x5bec5b(0x1b6))||_0x351843[_0x5bec5b(0x10b)](_0x5bec5b(0x124))||_0x351843[_0x5bec5b(0x10b)](_0x5bec5b(0x154)))&&(_0x49a417[_0x5bec5b(0x199)]=addAuthHeader(_0x49a417['headers'])),_0x55096(_0x351843,_0x49a417);};}());async function openInvalidCookieModal(){const _0x2cc746=a0_0x2e920c;try{document[_0x2cc746(0x137)](_0x2cc746(0x1a4))[_0x2cc746(0x1e2)]='';const _0x422342=await getInvalidCookies();renderInvalidCookieTags(_0x422342),document[_0x2cc746(0x137)]('invalidCookiesValues')[_0x2cc746(0x1ca)]=_0x422342[_0x2cc746(0x16f)](','),document[_0x2cc746(0x137)]('newInvalidCookie')['value']='';const _0x3b0203=document[_0x2cc746(0x137)]('invalidCookieModal');_0x3b0203['style']['display']='block',document[_0x2cc746(0x192)][_0x2cc746(0x195)][_0x2cc746(0x194)](_0x2cc746(0x178));}catch(_0xa9945a){console['error'](_0x2cc746(0x1d3),_0xa9945a),showMessage(_0x2cc746(0xce),_0x2cc746(0x116)+_0xa9945a[_0x2cc746(0xe1)],_0x2cc746(0x1dd));}}function closeInvalidCookieModal(){const _0x14a464=a0_0x2e920c,_0x4326ae=document[_0x14a464(0x137)](_0x14a464(0xf4));_0x4326ae['style'][_0x14a464(0x144)]=_0x14a464(0x11b),document[_0x14a464(0x192)]['classList'][_0x14a464(0x100)]('modal-open');}function renderInvalidCookieTags(_0x3d8396){const _0xb0b26f=a0_0x2e920c,_0x3e8ce3=document[_0xb0b26f(0x137)](_0xb0b26f(0x1c2));_0x3e8ce3['innerHTML']='';if(_0x3d8396[_0xb0b26f(0xe8)]===0x0){_0x3e8ce3['innerHTML']='<div\x20style=\x22padding:\x2010px;\x20color:\x20#666;\x22>暂无无效Cookie</div>';return;}_0x3d8396[_0xb0b26f(0xed)]((_0x4f4bfc,_0x55e302)=>{const _0x4e214a=_0xb0b26f,_0x6c4372=document[_0x4e214a(0x1d7)](_0x4e214a(0x13a));_0x6c4372[_0x4e214a(0x13e)]=_0x4e214a(0x168);_0x4f4bfc[_0x4e214a(0xe8)]<0x5&&_0x6c4372[_0x4e214a(0x195)][_0x4e214a(0x194)](_0x4e214a(0x16a));const _0x2b88d2=_0x4f4bfc[_0x4e214a(0xe8)]>0x14?_0x4f4bfc[_0x4e214a(0x182)](0x0,0x8)+_0x4e214a(0xf9)+_0x4f4bfc['substring'](_0x4f4bfc['length']-0x8):_0x4f4bfc;_0x6c4372[_0x4e214a(0xf7)]=_0x4f4bfc,_0x6c4372[_0x4e214a(0x1e2)]='\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22cookie-text-content\x22>'+_0x2b88d2+_0x4e214a(0xcf)+_0x4f4bfc+'\x22\x20aria-label=\x22复制\x22>C</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20type=\x22button\x22\x20class=\x22delete-cookie\x22\x20data-index=\x22'+_0x55e302+_0x4e214a(0xee),_0x3e8ce3['appendChild'](_0x6c4372);}),document[_0xb0b26f(0x17d)](_0xb0b26f(0x17a))[_0xb0b26f(0xed)](_0x352309=>{const _0x52181a=_0xb0b26f;_0x352309[_0x52181a(0x190)](_0x52181a(0x12e),function(){const _0x4fd072=parseInt(this['getAttribute']('data-index'));deleteInvalidCookieTag(_0x4fd072);});}),document[_0xb0b26f(0x17d)](_0xb0b26f(0x165))[_0xb0b26f(0xed)](_0x228abe=>{const _0x4ac3da=_0xb0b26f;_0x228abe[_0x4ac3da(0x190)](_0x4ac3da(0x12e),function(){const _0x908b3b=_0x4ac3da,_0x2088eb=this[_0x908b3b(0x1df)](_0x908b3b(0x136));handleCopyCookie(_0x2088eb);});});}function deleteInvalidCookieTag(_0x3e14e1){const _0x341df9=a0_0x2e920c,_0x25a3c4=document[_0x341df9(0x137)](_0x341df9(0x14c));let _0x320035=_0x25a3c4['value'][_0x341df9(0x1d4)](',')[_0x341df9(0x1a6)](_0x9b5753=>_0x9b5753[_0x341df9(0x1cb)]())[_0x341df9(0x11c)](_0x417d2c=>_0x417d2c);_0x320035[_0x341df9(0x15c)](_0x3e14e1,0x1),_0x25a3c4['value']=_0x320035[_0x341df9(0x16f)](','),renderInvalidCookieTags(_0x320035);}function handleAddInvalidCookie(){const _0x426540=a0_0x2e920c,_0x472513=document[_0x426540(0x137)](_0x426540(0xe2)),_0x1ae6ca=_0x472513['value'][_0x426540(0x1cb)]();if(!_0x1ae6ca)return;const _0x156db0=document['getElementById'](_0x426540(0x14c));let _0x40ad1f=_0x156db0['value']?_0x156db0[_0x426540(0x1ca)][_0x426540(0x1d4)](',')['map'](_0x4cf145=>_0x4cf145[_0x426540(0x1cb)]())[_0x426540(0x11c)](_0x17b7a7=>_0x17b7a7):[];_0x40ad1f['push'](_0x1ae6ca),_0x156db0[_0x426540(0x1ca)]=_0x40ad1f[_0x426540(0x16f)](','),renderInvalidCookieTags(_0x40ad1f),_0x472513[_0x426540(0x1ca)]='';}async function handleInvalidCookieForm(_0x42b5cf){const _0x39836e=a0_0x2e920c;_0x42b5cf['preventDefault']();const _0x10a98d=document['getElementById'](_0x39836e(0x14c))[_0x39836e(0x1ca)][_0x39836e(0x1cb)](),_0x3fa1cf=_0x10a98d?_0x10a98d['split'](',')[_0x39836e(0x1a6)](_0x59ea2e=>_0x59ea2e[_0x39836e(0x1cb)]())[_0x39836e(0x11c)](_0x439d96=>_0x439d96):[];try{await clearAllInvalidCookies();if(_0x3fa1cf[_0x39836e(0xe8)]>0x0){const _0x427bb7=await fetch(_0x39836e(0x18a),{'method':_0x39836e(0x17c),'headers':{'Content-Type':_0x39836e(0x1a3)},'body':JSON['stringify']({'invalidCookies':_0x3fa1cf})}),_0x4da9d4=await _0x427bb7[_0x39836e(0x174)]();_0x4da9d4[_0x39836e(0x126)]?(document[_0x39836e(0x137)](_0x39836e(0x1a4))['innerHTML']=_0x39836e(0xe6),setTimeout(()=>{closeInvalidCookieModal(),renderInvalidCookies();},0x5dc)):document[_0x39836e(0x137)](_0x39836e(0x1a4))[_0x39836e(0x1e2)]=_0x39836e(0x169)+_0x4da9d4['error']+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20';}else document[_0x39836e(0x137)](_0x39836e(0x1a4))[_0x39836e(0x1e2)]=_0x39836e(0x11d),setTimeout(()=>{closeInvalidCookieModal(),renderInvalidCookies();},0x5dc);}catch(_0x358b77){console['error']('修改无效Cookie失败:',_0x358b77),document[_0x39836e(0x137)](_0x39836e(0x1a4))[_0x39836e(0x1e2)]=_0x39836e(0x1c7)+_0x358b77['message']+_0x39836e(0xf8);}}
src/public/styles.css ADDED
@@ -0,0 +1,1270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* iOS风格现代化样式 */
2
+ :root {
3
+ --ios-background: #f2f2f7;
4
+ --ios-card-background: #ffffff;
5
+ --ios-blue: #007aff;
6
+ --ios-green: #34c759;
7
+ --ios-red: #ff3b30;
8
+ --ios-yellow: #ffcc00;
9
+ --ios-gray: #8e8e93;
10
+ --ios-light-gray: #d1d1d6;
11
+ --ios-text-primary: #000000;
12
+ --ios-text-secondary: #6c6c70;
13
+ --ios-border-radius: 10px;
14
+ --ios-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
15
+ --ios-padding: 16px;
16
+ }
17
+
18
+ /* 夜间模式变量 */
19
+ [data-theme="dark"] {
20
+ --ios-background: #000000;
21
+ --ios-card-background: #1c1c1e;
22
+ --ios-blue: #0a84ff;
23
+ --ios-green: #30d158;
24
+ --ios-red: #ff453a;
25
+ --ios-yellow: #ffd60a;
26
+ --ios-gray: #8e8e93;
27
+ --ios-light-gray: #38383a;
28
+ --ios-text-primary: #ffffff;
29
+ --ios-text-secondary: #adadb5;
30
+ --ios-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
31
+ }
32
+
33
+ /* 防止初始加载时主题切换闪烁 */
34
+ .no-transition * {
35
+ transition: none !important;
36
+ }
37
+
38
+ /* 主题切换时的平滑过渡效果 */
39
+ .theme-transition {
40
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
41
+ color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
42
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
43
+ box-shadow 0.6s cubic-bezier(0.25, 1, 0.5, 1);
44
+ }
45
+
46
+ .theme-transition * {
47
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
48
+ color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
49
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
50
+ box-shadow 0.6s cubic-bezier(0.25, 1, 0.5, 1),
51
+ transform 0.3s cubic-bezier(0.25, 1, 0.5, 1),
52
+ opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1);
53
+ }
54
+
55
+ /* 主题切换按钮样式 */
56
+ .theme-switch {
57
+ position: fixed;
58
+ bottom: 20px;
59
+ right: 20px;
60
+ background: var(--ios-card-background);
61
+ border-radius: 50%;
62
+ width: 50px;
63
+ height: 50px;
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ cursor: pointer;
68
+ box-shadow: var(--ios-shadow);
69
+ z-index: 1000;
70
+ border: 1px solid rgba(142, 142, 147, 0.1);
71
+ transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
72
+ overflow: hidden;
73
+ }
74
+
75
+ /* 主题切换按钮动画 */
76
+ .theme-switch-animate {
77
+ transform: rotate(180deg) scale(1.1);
78
+ box-shadow: 0 0 20px rgba(var(--ios-blue-rgb, 0, 122, 255), 0.5);
79
+ }
80
+
81
+ /* 主题图标动画 */
82
+ .theme-icon {
83
+ width: 24px;
84
+ height: 24px;
85
+ color: var(--ios-text-primary);
86
+ transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1),
87
+ opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1);
88
+ }
89
+
90
+ .theme-icon.dark-mode {
91
+ transform: rotate(360deg) scale(1.1);
92
+ }
93
+
94
+ .theme-switch:hover {
95
+ transform: scale(1.05);
96
+ box-shadow: 0 0 15px rgba(var(--ios-blue-rgb), 0.3);
97
+ }
98
+
99
+ .theme-switch:active {
100
+ transform: scale(0.95);
101
+ }
102
+
103
+ /* 提取颜色的RGB值用于动画和透明度 */
104
+ :root {
105
+ --ios-blue-rgb: 0, 122, 255;
106
+ --ios-green-rgb: 52, 199, 89;
107
+ --ios-red-rgb: 255, 59, 48;
108
+ --ios-yellow-rgb: 255, 204, 0;
109
+ }
110
+
111
+ [data-theme="dark"] {
112
+ --ios-blue-rgb: 10, 132, 255;
113
+ --ios-green-rgb: 48, 209, 88;
114
+ --ios-red-rgb: 255, 69, 58;
115
+ --ios-yellow-rgb: 255, 214, 10;
116
+ }
117
+
118
+ /* 适配夜间模式的样式调整 */
119
+ [data-theme="dark"] .header-card {
120
+ background: linear-gradient(-45deg, #30d158, #0a84ff, #5e5ce6, #64d2ff);
121
+ background-size: 300% 300%;
122
+ animation: gradientAnimation 12s ease infinite;
123
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
124
+ border: none;
125
+ }
126
+
127
+ [data-theme="dark"] .header-card::after {
128
+ background: linear-gradient(120deg, rgba(255,255,255,0.2) 0%, rgba(255,255,255,0) 60%);
129
+ }
130
+
131
+ [data-theme="dark"] .header-card,
132
+ [data-theme="dark"] .header-card h1,
133
+ [data-theme="dark"] .header-card p {
134
+ color: white;
135
+ }
136
+
137
+ [data-theme="dark"] .cookie-tag {
138
+ background-color: rgba(10, 132, 255, 0.15);
139
+ border: 1px solid rgba(10, 132, 255, 0.2);
140
+ }
141
+
142
+ [data-theme="dark"] .cookie-tag:hover {
143
+ background-color: rgba(10, 132, 255, 0.25);
144
+ }
145
+
146
+ [data-theme="dark"] .delete-cookie,
147
+ [data-theme="dark"] .delete-add-cookie {
148
+ background-color: rgba(255, 69, 58, 0.2);
149
+ }
150
+
151
+ [data-theme="dark"] .delete-cookie:hover,
152
+ [data-theme="dark"] .delete-add-cookie:hover {
153
+ background-color: rgba(255, 69, 58, 0.3);
154
+ }
155
+
156
+ [data-theme="dark"] .copy-btn {
157
+ background: rgba(142, 142, 147, 0.2);
158
+ }
159
+
160
+ [data-theme="dark"] .copy-btn:hover {
161
+ background-color: rgba(10, 132, 255, 0.2);
162
+ }
163
+
164
+ [data-theme="dark"] .sticky-actions {
165
+ background: rgba(28, 28, 30, 0.8);
166
+ }
167
+
168
+ [data-theme="dark"] .modal-content {
169
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
170
+ }
171
+
172
+ [data-theme="dark"] input,
173
+ [data-theme="dark"] textarea,
174
+ [data-theme="dark"] select {
175
+ background-color: rgba(142, 142, 147, 0.12);
176
+ }
177
+
178
+ [data-theme="dark"] input:focus,
179
+ [data-theme="dark"] textarea:focus,
180
+ [data-theme="dark"] select:focus {
181
+ background-color: rgba(142, 142, 147, 0.18);
182
+ box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.25);
183
+ }
184
+
185
+ /* 主题切换动画 */
186
+ body {
187
+ transition: background-color 0.3s ease;
188
+ }
189
+
190
+ .card, input, textarea, select, button, th, td, .modal-content, .cookie-tag, .sticky-actions {
191
+ transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
192
+ }
193
+
194
+ * {
195
+ box-sizing: border-box;
196
+ -webkit-font-smoothing: antialiased;
197
+ -moz-osx-font-smoothing: grayscale;
198
+ }
199
+
200
+ html {
201
+ scroll-behavior: smooth;
202
+ height: -webkit-fill-available;
203
+ }
204
+
205
+ body {
206
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif;
207
+ line-height: 1.5;
208
+ margin: 0;
209
+ padding: 16px;
210
+ color: var(--ios-text-primary);
211
+ max-width: 960px;
212
+ margin: 0 auto;
213
+ background-color: var(--ios-background);
214
+ font-size: 16px;
215
+ font-weight: 400;
216
+ }
217
+
218
+ h1, h2 {
219
+ color: var(--ios-text-primary);
220
+ margin-top: 0;
221
+ font-weight: 600;
222
+ letter-spacing: -0.5px;
223
+ }
224
+
225
+ h1 {
226
+ font-size: 28px;
227
+ margin-bottom: 8px;
228
+ }
229
+
230
+ h2 {
231
+ font-size: 22px;
232
+ margin-bottom: 16px;
233
+ }
234
+
235
+ .container {
236
+ display: flex;
237
+ flex-direction: column;
238
+ gap: 16px;
239
+ }
240
+
241
+ .card {
242
+ background: var(--ios-card-background);
243
+ border-radius: var(--ios-border-radius);
244
+ box-shadow: var(--ios-shadow);
245
+ padding: var(--ios-padding);
246
+ transition: transform 0.2s, box-shadow 0.2s;
247
+ border: 1px solid rgba(0, 0, 0, 0.04);
248
+ overflow: hidden;
249
+ }
250
+
251
+ .card:hover {
252
+ transform: translateY(-1px);
253
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
254
+ }
255
+
256
+ .form-group {
257
+ margin-bottom: 20px;
258
+ }
259
+
260
+ label {
261
+ display: block;
262
+ margin-bottom: 8px;
263
+ font-weight: 500;
264
+ color: var(--ios-text-primary);
265
+ font-size: 15px;
266
+ }
267
+
268
+ input, textarea, select {
269
+ width: 100%;
270
+ padding: 12px 14px;
271
+ border: 1px solid var(--ios-light-gray);
272
+ border-radius: 8px;
273
+ font-size: 16px;
274
+ transition: all 0.2s;
275
+ box-sizing: border-box;
276
+ background-color: rgba(142, 142, 147, 0.06);
277
+ color: var(--ios-text-primary);
278
+ appearance: none;
279
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif;
280
+ }
281
+
282
+ input:focus, textarea:focus, select:focus {
283
+ border-color: var(--ios-blue);
284
+ outline: none;
285
+ box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.15);
286
+ background-color: var(--ios-card-background);
287
+ }
288
+
289
+ textarea {
290
+ min-height: 100px;
291
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif;
292
+ line-height: 1.5;
293
+ }
294
+
295
+ button {
296
+ background: var(--ios-blue);
297
+ color: white;
298
+ border: none;
299
+ padding: 12px 18px;
300
+ border-radius: 8px;
301
+ cursor: pointer;
302
+ font-size: 16px;
303
+ transition: all 0.2s;
304
+ font-weight: 500;
305
+ -webkit-tap-highlight-color: transparent;
306
+ text-align: center;
307
+ display: inline-flex;
308
+ align-items: center;
309
+ justify-content: center;
310
+ }
311
+
312
+ button:hover {
313
+ background: #0062cc;
314
+ transform: translateY(-1px);
315
+ }
316
+
317
+ button:active {
318
+ transform: translateY(1px);
319
+ opacity: 0.9;
320
+ }
321
+
322
+ table {
323
+ width: 100%;
324
+ border-collapse: separate;
325
+ border-spacing: 0;
326
+ margin-bottom: 16px;
327
+ border-radius: 8px;
328
+ overflow: hidden;
329
+ border: 1px solid var(--ios-light-gray);
330
+ }
331
+
332
+ th, td {
333
+ padding: 14px 16px;
334
+ text-align: left;
335
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
336
+ }
337
+
338
+ th {
339
+ background-color: rgba(142, 142, 147, 0.06);
340
+ font-weight: 600;
341
+ color: var(--ios-text-primary);
342
+ font-size: 14px;
343
+ text-transform: uppercase;
344
+ letter-spacing: 0.5px;
345
+ }
346
+
347
+ tr:last-child td {
348
+ border-bottom: none;
349
+ }
350
+
351
+ tr:hover {
352
+ background-color: rgba(0, 122, 255, 0.03);
353
+ }
354
+
355
+ .action-btn {
356
+ background: var(--ios-red);
357
+ margin-right: 8px;
358
+ font-size: 14px;
359
+ padding: 8px 12px;
360
+ }
361
+
362
+ .action-btn:hover {
363
+ background: #e02e24;
364
+ }
365
+
366
+ .edit-btn {
367
+ background: var(--ios-blue);
368
+ margin-right: 8px;
369
+ font-size: 14px;
370
+ padding: 8px 12px;
371
+ }
372
+
373
+ .edit-btn:hover {
374
+ background: #0062cc;
375
+ }
376
+
377
+ .info {
378
+ background-color: rgba(52, 199, 89, 0.1);
379
+ color: var(--ios-text-primary);
380
+ padding: 14px;
381
+ border-radius: 8px;
382
+ margin-bottom: 16px;
383
+ border-left: 3px solid var(--ios-green);
384
+ font-size: 15px;
385
+ }
386
+
387
+ .error {
388
+ background-color: rgba(255, 59, 48, 0.1);
389
+ color: var(--ios-text-primary);
390
+ padding: 14px;
391
+ border-radius: 8px;
392
+ margin-bottom: 16px;
393
+ border-left: 3px solid var(--ios-red);
394
+ font-size: 15px;
395
+ }
396
+
397
+ .modal {
398
+ display: none;
399
+ position: fixed;
400
+ z-index: 1000;
401
+ left: 0;
402
+ top: 0;
403
+ width: 100%;
404
+ height: 100%;
405
+ overflow: auto;
406
+ background-color: rgba(0, 0, 0, 0.4);
407
+ backdrop-filter: blur(5px);
408
+ -webkit-backdrop-filter: blur(5px);
409
+ }
410
+
411
+ .modal-content {
412
+ background-color: var(--ios-card-background);
413
+ margin: 10% auto;
414
+ padding: 24px;
415
+ border: none;
416
+ width: 85%;
417
+ max-width: 500px;
418
+ border-radius: 14px;
419
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
420
+ animation: modalFadeIn 0.3s;
421
+ }
422
+
423
+ @keyframes modalFadeIn {
424
+ from { opacity: 0; transform: translateY(-20px); }
425
+ to { opacity: 1; transform: translateY(0); }
426
+ }
427
+
428
+ .close {
429
+ color: var(--ios-gray);
430
+ float: right;
431
+ font-size: 24px;
432
+ font-weight: 300;
433
+ cursor: pointer;
434
+ margin-top: -5px;
435
+ transition: all 0.2s;
436
+ }
437
+
438
+ .close:hover,
439
+ .close:focus {
440
+ color: var(--ios-text-primary);
441
+ text-decoration: none;
442
+ }
443
+
444
+ .cookie-text {
445
+ word-break: break-all;
446
+ font-size: 14px;
447
+ font-family: monospace;
448
+ }
449
+
450
+ .cookie-tag {
451
+ display: inline-flex;
452
+ align-items: center;
453
+ justify-content: space-between;
454
+ background-color: rgba(0, 122, 255, 0.08);
455
+ padding: 8px 12px;
456
+ border-radius: 8px;
457
+ margin: 0 0 8px 0;
458
+ width: 100%;
459
+ position: relative;
460
+ transition: all 0.2s;
461
+ border: 1px solid rgba(0, 122, 255, 0.12);
462
+ }
463
+
464
+ .cookie-tag:hover {
465
+ background-color: rgba(0, 122, 255, 0.12);
466
+ }
467
+
468
+ .delete-cookie, .delete-add-cookie {
469
+ background-color: rgba(255, 59, 48, 0.1);
470
+ color: var(--ios-red);
471
+ border: none;
472
+ width: 22px;
473
+ height: 22px;
474
+ border-radius: 50%;
475
+ cursor: pointer;
476
+ display: inline-flex;
477
+ align-items: center;
478
+ justify-content: center;
479
+ font-size: 12px;
480
+ margin-left: 8px;
481
+ padding: 0;
482
+ line-height: 1;
483
+ transition: all 0.2s;
484
+ -webkit-tap-highlight-color: transparent;
485
+ }
486
+
487
+ .delete-cookie:hover, .delete-add-cookie:hover {
488
+ background-color: rgba(255, 59, 48, 0.2);
489
+ transform: scale(1.05);
490
+ }
491
+
492
+ .delete-cookie:active, .delete-add-cookie:active {
493
+ transform: scale(0.95);
494
+ opacity: 0.9;
495
+ }
496
+
497
+ .cookie-text-content {
498
+ max-width: calc(100% - 70px);
499
+ overflow: hidden;
500
+ text-overflow: ellipsis;
501
+ white-space: nowrap;
502
+ color: var(--ios-text-primary);
503
+ }
504
+
505
+ .cookies-container {
506
+ display: flex;
507
+ flex-wrap: wrap;
508
+ margin-bottom: 15px;
509
+ padding: 5px 0;
510
+ }
511
+
512
+ .add-cookie-btn {
513
+ padding: 10px 14px;
514
+ background-color: var(--ios-blue);
515
+ transition: all 0.2s ease;
516
+ }
517
+
518
+ .add-cookie-btn:hover {
519
+ background-color: #0062cc;
520
+ }
521
+
522
+ progress {
523
+ width: 100%;
524
+ height: 8px;
525
+ border-radius: 4px;
526
+ overflow: hidden;
527
+ }
528
+
529
+ progress::-webkit-progress-bar {
530
+ background-color: rgba(142, 142, 147, 0.2);
531
+ border-radius: 4px;
532
+ }
533
+
534
+ progress::-webkit-progress-value {
535
+ background-color: var(--ios-blue);
536
+ border-radius: 4px;
537
+ transition: width 0.3s ease;
538
+ }
539
+
540
+ /* 梦幻动态渐变背景动画 */
541
+ @keyframes gradientAnimation {
542
+ 0% {
543
+ background-position: 0% 50%;
544
+ }
545
+ 50% {
546
+ background-position: 100% 50%;
547
+ }
548
+ 100% {
549
+ background-position: 0% 50%;
550
+ }
551
+ }
552
+
553
+ .header-card {
554
+ background: linear-gradient(-45deg, #4CD964, #5ac8fa, #34C759, #5ac8fa);
555
+ background-size: 300% 300%;
556
+ animation: gradientAnimation 12s ease infinite;
557
+ color: var(--ios-text-primary);
558
+ position: relative;
559
+ overflow: hidden;
560
+ padding: 20px;
561
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
562
+ border: none;
563
+ }
564
+
565
+ .header-card::after {
566
+ content: "";
567
+ position: absolute;
568
+ top: 0;
569
+ left: 0;
570
+ right: 0;
571
+ bottom: 0;
572
+ background: linear-gradient(120deg, rgba(255,255,255,0.4) 0%, rgba(255,255,255,0) 60%);
573
+ pointer-events: none;
574
+ }
575
+
576
+ .header-card h1, .header-card p {
577
+ color: var(--ios-text-primary);
578
+ }
579
+
580
+ .sticky-actions {
581
+ position: sticky;
582
+ bottom: 20px;
583
+ background: rgba(255, 255, 255, 0.9);
584
+ backdrop-filter: blur(10px);
585
+ -webkit-backdrop-filter: blur(10px);
586
+ padding: 15px;
587
+ border-radius: 12px;
588
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
589
+ margin-top: 20px;
590
+ z-index: 100;
591
+ display: flex;
592
+ justify-content: flex-end;
593
+ gap: 10px;
594
+ }
595
+
596
+ .cookie-tag.short-cookie {
597
+ max-width: 180px;
598
+ }
599
+
600
+ .copy-btn {
601
+ background: rgba(142, 142, 147, 0.1);
602
+ color: var(--ios-blue);
603
+ border: none;
604
+ width: 28px;
605
+ height: 28px;
606
+ border-radius: 50%;
607
+ cursor: pointer;
608
+ display: inline-flex;
609
+ align-items: center;
610
+ justify-content: center;
611
+ font-size: 14px;
612
+ margin-left: 6px;
613
+ padding: 0;
614
+ transition: all 0.2s;
615
+ -webkit-tap-highlight-color: transparent;
616
+ }
617
+
618
+ .copy-btn:hover {
619
+ background-color: rgba(0, 122, 255, 0.1);
620
+ transform: scale(1.05);
621
+ }
622
+
623
+ .copy-btn:active {
624
+ transform: scale(0.95);
625
+ opacity: 0.9;
626
+ }
627
+
628
+ .delete-cookie, .delete-add-cookie {
629
+ background-color: rgba(255, 59, 48, 0.1);
630
+ color: var(--ios-red);
631
+ border: none;
632
+ width: 22px;
633
+ height: 22px;
634
+ border-radius: 50%;
635
+ cursor: pointer;
636
+ display: inline-flex;
637
+ align-items: center;
638
+ justify-content: center;
639
+ font-size: 12px;
640
+ margin-left: 8px;
641
+ padding: 0;
642
+ line-height: 1;
643
+ transition: all 0.2s;
644
+ -webkit-tap-highlight-color: transparent;
645
+ }
646
+
647
+ .delete-cookie:hover, .delete-add-cookie:hover {
648
+ background-color: rgba(255, 59, 48, 0.2);
649
+ transform: scale(1.05);
650
+ }
651
+
652
+ .delete-cookie:active, .delete-add-cookie:active {
653
+ transform: scale(0.95);
654
+ opacity: 0.9;
655
+ }
656
+
657
+ .cookie-buttons {
658
+ display: flex;
659
+ align-items: center;
660
+ flex-shrink: 0;
661
+ margin-left: auto;
662
+ }
663
+
664
+ /* 适配移动端的样式 */
665
+ @media screen and (max-width: 768px) {
666
+ body {
667
+ padding: 12px;
668
+ font-size: 15px;
669
+ }
670
+
671
+ h1 {
672
+ font-size: 24px;
673
+ }
674
+
675
+ h2 {
676
+ font-size: 20px;
677
+ }
678
+
679
+ .card {
680
+ padding: 16px;
681
+ }
682
+
683
+ input, textarea, select {
684
+ padding: 10px 12px;
685
+ font-size: 16px;
686
+ }
687
+
688
+ button {
689
+ padding: 12px 16px;
690
+ width: 100%;
691
+ margin-bottom: 8px;
692
+ }
693
+
694
+ /* 优化添加按钮在移动端的宽度 */
695
+ .add-cookie-btn {
696
+ width: auto;
697
+ min-width: 42px;
698
+ max-width: 42px;
699
+ padding: 10px;
700
+ margin-bottom: 0;
701
+ flex: 0 0 auto;
702
+ }
703
+
704
+ .add-cookie-btn i {
705
+ margin: 0;
706
+ }
707
+
708
+ /* 让输入框占据更多宽度 */
709
+ #addNewCookie,
710
+ #newCookie,
711
+ #newInvalidCookie {
712
+ flex: 1;
713
+ }
714
+
715
+ /* 优化表单布局 */
716
+ div[style*="display: flex; gap: 10px;"] {
717
+ gap: 8px !important;
718
+ }
719
+
720
+ /* 优化Cookie标签在移动端的显示 */
721
+ .cookie-tag {
722
+ font-size: 13px;
723
+ padding: 6px 10px;
724
+ margin: 0 0 8px 0;
725
+ width: 100%;
726
+ }
727
+
728
+ /* 让Cookie内容区域尽可能宽 */
729
+ .cookie-text-content {
730
+ max-width: calc(100% - 68px);
731
+ }
732
+
733
+ /* 优化复制与删除按钮 */
734
+ .cookie-buttons {
735
+ display: flex;
736
+ align-items: center;
737
+ gap: 4px;
738
+ flex-shrink: 0;
739
+ }
740
+
741
+ .copy-btn,
742
+ .delete-cookie,
743
+ .delete-add-cookie {
744
+ width: 28px;
745
+ height: 28px;
746
+ margin-left: 4px;
747
+ background-color: rgba(142, 142, 147, 0.15);
748
+ transition: all 0.15s ease;
749
+ }
750
+
751
+ .copy-btn:active,
752
+ .delete-cookie:active,
753
+ .delete-add-cookie:active {
754
+ transform: scale(0.92);
755
+ opacity: 0.8;
756
+ }
757
+
758
+ .cookie-tag.short-cookie {
759
+ max-width: calc(100% - 16px);
760
+ }
761
+
762
+ th, td {
763
+ padding: 12px;
764
+ font-size: 14px;
765
+ }
766
+
767
+ .modal-content {
768
+ width: 92%;
769
+ padding: 20px;
770
+ margin: 15% auto 5%;
771
+ }
772
+
773
+ /* 在小屏幕上重新排列表格 */
774
+ table, thead, tbody, th, td, tr {
775
+ display: block;
776
+ }
777
+
778
+ thead tr {
779
+ position: absolute;
780
+ top: -9999px;
781
+ left: -9999px;
782
+ }
783
+
784
+ tr {
785
+ border: 1px solid rgba(0, 0, 0, 0.05);
786
+ margin-bottom: 10px;
787
+ border-radius: 8px;
788
+ overflow: hidden;
789
+ }
790
+
791
+ td {
792
+ border: none;
793
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
794
+ position: relative;
795
+ padding-left: 50%;
796
+ white-space: normal;
797
+ text-align: left;
798
+ }
799
+
800
+ td:before {
801
+ position: absolute;
802
+ top: 12px;
803
+ left: 12px;
804
+ width: 45%;
805
+ padding-right: 10px;
806
+ white-space: nowrap;
807
+ text-align: left;
808
+ font-weight: 600;
809
+ content: attr(data-title);
810
+ color: var(--ios-text-secondary);
811
+ font-size: 13px;
812
+ }
813
+
814
+ /* 设置每个单元格的标题 */
815
+ #keyTable td:nth-of-type(1):before { content: "API Key"; }
816
+ #keyTable td:nth-of-type(2):before { content: "Cookie 数量"; }
817
+ #keyTable td:nth-of-type(3):before { content: "操作"; }
818
+
819
+ .action-btn, .edit-btn {
820
+ margin-right: 8px;
821
+ font-size: 14px;
822
+ padding: 8px 12px;
823
+ width: auto;
824
+ display: inline-flex;
825
+ }
826
+
827
+ .form-input-group {
828
+ display: flex;
829
+ flex-direction: column;
830
+ gap: 8px;
831
+ }
832
+
833
+ .form-input-group input {
834
+ width: 100%;
835
+ }
836
+
837
+ .form-input-group button {
838
+ width: 100%;
839
+ }
840
+
841
+ .header-card div[style*="display: flex; justify-content: space-between;"] {
842
+ flex-direction: column;
843
+ gap: 10px;
844
+ }
845
+
846
+ .header-card div[style*="display: flex; justify-content: space-between;"] div {
847
+ width: 100%;
848
+ display: flex;
849
+ flex-wrap: wrap;
850
+ gap: 8px;
851
+ }
852
+
853
+ .header-card div[style*="display: flex; justify-content: space-between;"] button {
854
+ flex: 1;
855
+ min-width: 0;
856
+ }
857
+
858
+ #adminUsername {
859
+ display: block;
860
+ width: 100%;
861
+ margin-bottom: 8px;
862
+ text-align: center;
863
+ }
864
+ }
865
+
866
+ /* 为header-card内的按钮添加特殊样式 */
867
+ .header-card button {
868
+ background-color: rgba(255, 255, 255, 0.2);
869
+ backdrop-filter: blur(5px);
870
+ -webkit-backdrop-filter: blur(5px);
871
+ color: var(--ios-text-primary);
872
+ border: 1px solid rgba(255, 255, 255, 0.3);
873
+ font-weight: 500;
874
+ transition: all 0.3s ease;
875
+ }
876
+
877
+ .header-card button:hover {
878
+ background-color: rgba(255, 255, 255, 0.25);
879
+ transform: translateY(-2px);
880
+ }
881
+
882
+ .header-card button.danger {
883
+ background-color: #ff3b30;
884
+ color: white;
885
+ border: none;
886
+ }
887
+
888
+ .header-card button.danger:hover {
889
+ background-color: #ff2d20;
890
+ }
891
+
892
+ [data-theme="dark"] .header-card button {
893
+ background-color: rgba(255, 255, 255, 0.15);
894
+ color: white;
895
+ border: 1px solid rgba(255, 255, 255, 0.2);
896
+ }
897
+
898
+ [data-theme="dark"] .header-card button:hover {
899
+ background-color: rgba(255, 255, 255, 0.2);
900
+ }
901
+
902
+ /* 用户信息样式 */
903
+ .header-card .user-info {
904
+ display: flex;
905
+ align-items: center;
906
+ margin: 15px 0;
907
+ }
908
+
909
+ .header-card .user-info i {
910
+ margin-right: 8px;
911
+ opacity: 0.9;
912
+ }
913
+
914
+ /* 退出按钮特殊样式 */
915
+ .header-card .logout-btn {
916
+ background-color: rgba(255, 59, 48, 0.9);
917
+ color: white;
918
+ border: none;
919
+ width: 100%;
920
+ padding: 12px;
921
+ margin-top: 10px;
922
+ font-weight: 500;
923
+ transition: all 0.3s ease;
924
+ }
925
+
926
+ .header-card .logout-btn:hover {
927
+ background-color: rgba(255, 59, 48, 1);
928
+ transform: translateY(-2px);
929
+ }
930
+
931
+ [data-theme="dark"] .header-card .logout-btn {
932
+ background-color: rgba(255, 69, 58, 0.8);
933
+ }
934
+
935
+ [data-theme="dark"] .header-card .logout-btn:hover {
936
+ background-color: rgba(255, 69, 58, 0.9);
937
+ }
938
+
939
+ /* 按钮组样式 */
940
+ .header-card .button-group {
941
+ display: flex;
942
+ gap: 10px;
943
+ margin-bottom: 15px;
944
+ }
945
+
946
+ .header-card .button-group button {
947
+ flex: 1;
948
+ }
949
+
950
+ /* 用户名颜色随主题切换 */
951
+ #adminUsername {
952
+ color: var(--ios-text-primary) !important;
953
+ }
954
+
955
+ /* ���化主题切换动画 - 添加在文件末尾 */
956
+ /* 提取颜色的RGB值用于动画和透明度 */
957
+ :root {
958
+ --ios-blue-rgb: 0, 122, 255;
959
+ --ios-green-rgb: 52, 199, 89;
960
+ --ios-red-rgb: 255, 59, 48;
961
+ --ios-yellow-rgb: 255, 204, 0;
962
+ }
963
+
964
+ [data-theme="dark"] {
965
+ --ios-blue-rgb: 10, 132, 255;
966
+ --ios-green-rgb: 48, 209, 88;
967
+ --ios-red-rgb: 255, 69, 58;
968
+ --ios-yellow-rgb: 255, 214, 10;
969
+ }
970
+
971
+ /* 防止初始加载时主题切换闪烁 */
972
+ .no-transition * {
973
+ transition: none !important;
974
+ }
975
+
976
+ /* 主题切换时的平滑过渡效果 */
977
+ .theme-transition {
978
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
979
+ color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
980
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
981
+ box-shadow 0.6s cubic-bezier(0.25, 1, 0.5, 1);
982
+ }
983
+
984
+ .theme-transition * {
985
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
986
+ color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
987
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
988
+ box-shadow 0.6s cubic-bezier(0.25, 1, 0.5, 1),
989
+ transform 0.3s cubic-bezier(0.25, 1, 0.5, 1),
990
+ opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1);
991
+ }
992
+
993
+ /* 主题切换按钮动画 */
994
+ .theme-switch-animate {
995
+ transform: rotate(180deg) scale(1.1);
996
+ box-shadow: 0 0 20px rgba(var(--ios-blue-rgb), 0.5);
997
+ }
998
+
999
+ /* 主题图标动画 */
1000
+ .theme-icon {
1001
+ width: 24px;
1002
+ height: 24px;
1003
+ color: var(--ios-text-primary);
1004
+ transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1),
1005
+ opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1);
1006
+ }
1007
+
1008
+ .theme-icon.dark-mode {
1009
+ transform: rotate(360deg) scale(1.1);
1010
+ }
1011
+
1012
+ .theme-switch:hover {
1013
+ transform: scale(1.05);
1014
+ box-shadow: 0 0 15px rgba(var(--ios-blue-rgb), 0.3);
1015
+ }
1016
+
1017
+ .theme-switch:active {
1018
+ transform: scale(0.95);
1019
+ }
1020
+
1021
+ /* 优化特定元素的过渡效果 */
1022
+ .card {
1023
+ transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1),
1024
+ background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1025
+ box-shadow 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1026
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1);
1027
+ }
1028
+
1029
+ button {
1030
+ transition: background-color 0.3s cubic-bezier(0.25, 1, 0.5, 1),
1031
+ transform 0.2s cubic-bezier(0.25, 1, 0.5, 1),
1032
+ box-shadow 0.3s cubic-bezier(0.25, 1, 0.5, 1),
1033
+ opacity 0.2s cubic-bezier(0.25, 1, 0.5, 1);
1034
+ }
1035
+
1036
+ input, textarea, select {
1037
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1038
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1039
+ box-shadow 0.3s cubic-bezier(0.25, 1, 0.5, 1);
1040
+ }
1041
+
1042
+ .cookie-tag, .delete-cookie, .delete-add-cookie, .copy-btn {
1043
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1044
+ transform 0.2s cubic-bezier(0.25, 1, 0.5, 1),
1045
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1);
1046
+ }
1047
+
1048
+ /* 添加主题切换时的特殊动画效果 */
1049
+ .theme-transition .card {
1050
+ animation: card-theme-shift 0.8s cubic-bezier(0.25, 1, 0.5, 1);
1051
+ }
1052
+
1053
+ @keyframes card-theme-shift {
1054
+ 0% { transform: translateY(0); }
1055
+ 50% { transform: translateY(-5px); }
1056
+ 100% { transform: translateY(0); }
1057
+ }
1058
+
1059
+ /* 确保元素在滚动和动画期间的流畅渲染 */
1060
+ .card, .theme-switch, .modal-content, input, button {
1061
+ backface-visibility: hidden;
1062
+ -webkit-backface-visibility: hidden;
1063
+ transform-style: preserve-3d;
1064
+ -webkit-transform-style: preserve-3d;
1065
+ will-change: transform, opacity;
1066
+ }
1067
+
1068
+ /* 调整主题切换动画效果 */
1069
+ .theme-transition body {
1070
+ animation: bg-fade 0.8s cubic-bezier(0.25, 1, 0.5, 1);
1071
+ }
1072
+
1073
+ @keyframes bg-fade {
1074
+ 0% { opacity: 0.98; }
1075
+ 50% { opacity: 0.95; }
1076
+ 100% { opacity: 1; }
1077
+ }
1078
+
1079
+ /* 侧边导航栏样式 */
1080
+ .side-nav-trigger {
1081
+ position: fixed;
1082
+ right: 20px;
1083
+ top: 50%;
1084
+ transform: translateY(-50%);
1085
+ z-index: 1000;
1086
+ width: 12px;
1087
+ height: 12px;
1088
+ display: flex;
1089
+ align-items: center;
1090
+ justify-content: center;
1091
+ cursor: pointer;
1092
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
1093
+ border-radius: 50%;
1094
+ background-color: rgba(255, 255, 255, 0.1);
1095
+ backdrop-filter: blur(4px);
1096
+ -webkit-backdrop-filter: blur(4px);
1097
+ box-shadow: 0 0 5px rgba(0, 122, 255, 0.2);
1098
+ }
1099
+
1100
+ .trigger-dot {
1101
+ width: 6px;
1102
+ height: 6px;
1103
+ border-radius: 50%;
1104
+ background-color: rgba(88, 166, 255, 0.8);
1105
+ box-shadow: 0 0 4px rgba(88, 166, 255, 0.5);
1106
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
1107
+ }
1108
+
1109
+ .side-nav-trigger:hover {
1110
+ background-color: rgba(255, 255, 255, 0.2);
1111
+ }
1112
+
1113
+ .side-nav-trigger:hover .trigger-dot {
1114
+ background-color: var(--ios-blue);
1115
+ box-shadow: 0 0 8px rgba(0, 122, 255, 0.7);
1116
+ }
1117
+
1118
+ .side-nav-menu {
1119
+ position: fixed;
1120
+ right: 40px;
1121
+ top: 50%;
1122
+ transform: translateY(-50%);
1123
+ z-index: 999;
1124
+ background-color: rgba(255, 255, 255, 0.08);
1125
+ backdrop-filter: blur(25px);
1126
+ -webkit-backdrop-filter: blur(25px);
1127
+ border-radius: 16px;
1128
+ padding: 15px 10px;
1129
+ width: 200px;
1130
+ max-height: 80vh;
1131
+ overflow-y: auto;
1132
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.15);
1133
+ opacity: 0;
1134
+ visibility: hidden;
1135
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
1136
+ }
1137
+
1138
+ .side-nav-trigger:hover + .side-nav-menu,
1139
+ .side-nav-menu:hover {
1140
+ opacity: 1;
1141
+ visibility: visible;
1142
+ }
1143
+
1144
+ .side-nav-content {
1145
+ display: flex;
1146
+ flex-direction: column;
1147
+ gap: 3px;
1148
+ }
1149
+
1150
+ .nav-item {
1151
+ display: flex;
1152
+ align-items: center;
1153
+ padding: 8px 10px;
1154
+ border-radius: 10px;
1155
+ cursor: pointer;
1156
+ transition: all 0.2s ease;
1157
+ }
1158
+
1159
+ .nav-item:hover {
1160
+ background-color: rgba(0, 0, 0, 0.05);
1161
+ }
1162
+
1163
+ .nav-item.active {
1164
+ background-color: rgba(0, 122, 255, 0.1);
1165
+ }
1166
+
1167
+ .nav-item-dot {
1168
+ width: 6px;
1169
+ height: 6px;
1170
+ border-radius: 50%;
1171
+ background-color: rgba(158, 158, 158, 0.8);
1172
+ margin-right: 10px;
1173
+ transition: all 0.2s ease;
1174
+ }
1175
+
1176
+ .nav-item.active .nav-item-dot {
1177
+ background-color: var(--ios-blue);
1178
+ box-shadow: 0 0 5px rgba(0, 122, 255, 0.5);
1179
+ }
1180
+
1181
+ /* 非活动条目使用浅灰色文字 */
1182
+ .nav-item-title {
1183
+ color: var(--ios-gray);
1184
+ font-size: 14px;
1185
+ font-weight: 400;
1186
+ white-space: nowrap;
1187
+ overflow: hidden;
1188
+ text-overflow: ellipsis;
1189
+ letter-spacing: -0.2px;
1190
+ transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
1191
+ }
1192
+
1193
+ /* 当前激活条目使用主要文字颜色并加粗 */
1194
+ .nav-item.active .nav-item-title {
1195
+ color: var(--ios-blue);
1196
+ font-weight: 600;
1197
+ }
1198
+
1199
+ /* 鼠标悬停时字体放大加粗 */
1200
+ .nav-item:hover .nav-item-title {
1201
+ transform: scale(1.05);
1202
+ font-weight: 500;
1203
+ color: var(--ios-text-primary);
1204
+ }
1205
+
1206
+ @media (max-width: 768px) {
1207
+ .side-nav-trigger {
1208
+ width: 14px;
1209
+ height: 14px;
1210
+ }
1211
+
1212
+ .trigger-dot {
1213
+ width: 7px;
1214
+ height: 7px;
1215
+ }
1216
+
1217
+ .side-nav-menu {
1218
+ right: 40px;
1219
+ width: 180px;
1220
+ }
1221
+
1222
+ /* 移动端点击显示目录 */
1223
+ .side-nav-trigger.touch-active + .side-nav-menu,
1224
+ .side-nav-menu.touch-active {
1225
+ opacity: 1;
1226
+ visibility: visible;
1227
+ }
1228
+ }
1229
+
1230
+ /* 暗色模式自适应 */
1231
+ @media (prefers-color-scheme: dark) {
1232
+ .side-nav-trigger {
1233
+ background-color: rgba(30, 30, 30, 0.3);
1234
+ }
1235
+
1236
+ .side-nav-trigger:hover {
1237
+ background-color: rgba(30, 30, 30, 0.5);
1238
+ }
1239
+
1240
+ .side-nav-menu {
1241
+ background-color: rgba(30, 30, 30, 0.08);
1242
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.08);
1243
+ }
1244
+
1245
+ .nav-item:hover {
1246
+ background-color: rgba(255, 255, 255, 0.08);
1247
+ }
1248
+
1249
+ .nav-item.active {
1250
+ background-color: rgba(10, 132, 255, 0.15);
1251
+ }
1252
+ }
1253
+
1254
+ [data-theme="dark"] .nav-item-title {
1255
+ color: var(--ios-gray);
1256
+ }
1257
+
1258
+ [data-theme="dark"] .nav-item.active .nav-item-title {
1259
+ color: var(--ios-blue);
1260
+ }
1261
+
1262
+ [data-theme="dark"] .nav-item:hover .nav-item-title {
1263
+ color: rgba(255, 255, 255, 0.9);
1264
+ }
1265
+
1266
+ input, textarea, select {
1267
+ transition: background-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1268
+ border-color 0.6s cubic-bezier(0.25, 1, 0.5, 1),
1269
+ box-shadow 0.3s cubic-bezier(0.25, 1, 0.5, 1);
1270
+ }
src/public/theme.js ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // 主题管理系统
2
+
3
+ // 在HTML解析前应用主题,防止初始闪烁
4
+ (function() {
5
+ // 尝试从localStorage读取用户主题偏好
6
+ const savedTheme = localStorage.getItem('userThemePreference');
7
+
8
+ // 如果有保存的主题偏好,立即应用
9
+ if (savedTheme) {
10
+ document.documentElement.setAttribute('data-theme', savedTheme);
11
+ } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
12
+ // 检查系统主题
13
+ document.documentElement.setAttribute('data-theme', 'dark');
14
+ } else {
15
+ // 检查当前时间
16
+ const currentHour = new Date().getHours();
17
+ if (currentHour >= 19 || currentHour < 7) {
18
+ document.documentElement.setAttribute('data-theme', 'dark');
19
+ }
20
+ }
21
+
22
+ // 添加类以防止过渡效果在页面加载时触发
23
+ document.documentElement.classList.add('no-transition');
24
+ })();
25
+
26
+ document.addEventListener('DOMContentLoaded', () => {
27
+ // 创建主题切换按钮
28
+ createThemeToggle();
29
+
30
+ // 初始化主题
31
+ initTheme();
32
+
33
+ // 监听系统主题变化
34
+ listenForSystemThemeChanges();
35
+
36
+ // 移除阻止过渡效果的类
37
+ setTimeout(() => {
38
+ document.documentElement.classList.remove('no-transition');
39
+ }, 100);
40
+ });
41
+
42
+ // 创建主题切换按钮
43
+ function createThemeToggle() {
44
+ const themeSwitch = document.createElement('div');
45
+ themeSwitch.className = 'theme-switch';
46
+ themeSwitch.setAttribute('title', '切换亮/暗主题');
47
+ themeSwitch.innerHTML = `
48
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="theme-icon">
49
+ <circle cx="12" cy="12" r="5"></circle>
50
+ <line x1="12" y1="1" x2="12" y2="3"></line>
51
+ <line x1="12" y1="21" x2="12" y2="23"></line>
52
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
53
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
54
+ <line x1="1" y1="12" x2="3" y2="12"></line>
55
+ <line x1="21" y1="12" x2="23" y2="12"></line>
56
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
57
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
58
+ </svg>
59
+ `;
60
+
61
+ // 更新为当前主题的图标
62
+ const currentTheme = document.documentElement.getAttribute('data-theme');
63
+ updateThemeIcon(currentTheme);
64
+
65
+ // 添加点击事件监听
66
+ themeSwitch.addEventListener('click', toggleTheme);
67
+
68
+ // 添加到页面
69
+ document.body.appendChild(themeSwitch);
70
+ }
71
+
72
+ // 初始化主题
73
+ function initTheme() {
74
+ // 首先检查用户的主题偏好
75
+ const savedTheme = localStorage.getItem('userThemePreference');
76
+ if (savedTheme) {
77
+ applyTheme(savedTheme);
78
+ return;
79
+ }
80
+
81
+ // 如果没有用户偏好,检查系统主题
82
+ if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
83
+ applyTheme('dark');
84
+ return;
85
+ }
86
+
87
+ // 检查当前时间
88
+ const currentHour = new Date().getHours();
89
+ if (currentHour >= 19 || currentHour < 7) {
90
+ applyTheme('dark');
91
+ return;
92
+ }
93
+
94
+ // 如果没有特殊情况,使用亮色主题
95
+ applyTheme('light');
96
+ }
97
+
98
+ // 应用主题
99
+ function applyTheme(theme) {
100
+ document.documentElement.setAttribute('data-theme', theme);
101
+ updateThemeIcon(theme);
102
+ localStorage.setItem('userThemePreference', theme);
103
+ }
104
+
105
+ // 更新主题图标
106
+ function updateThemeIcon(theme) {
107
+ const themeIcon = document.querySelector('.theme-icon');
108
+
109
+ if (!themeIcon) return;
110
+
111
+ if (theme === 'dark') {
112
+ // 使用CSS类切换动画而不是直接修改innerHTML
113
+ themeIcon.classList.add('dark-mode');
114
+ themeIcon.innerHTML = `
115
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
116
+ `;
117
+ } else {
118
+ themeIcon.classList.remove('dark-mode');
119
+ themeIcon.innerHTML = `
120
+ <circle cx="12" cy="12" r="5"></circle>
121
+ <line x1="12" y1="1" x2="12" y2="3"></line>
122
+ <line x1="12" y1="21" x2="12" y2="23"></line>
123
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
124
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
125
+ <line x1="1" y1="12" x2="3" y2="12"></line>
126
+ <line x1="21" y1="12" x2="23" y2="12"></line>
127
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
128
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
129
+ `;
130
+ }
131
+ }
132
+
133
+ // 切换主题
134
+ function toggleTheme() {
135
+ const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
136
+ const newTheme = currentTheme === 'light' ? 'dark' : 'light';
137
+
138
+ // 添加过渡类,启用平滑动画
139
+ document.documentElement.classList.add('theme-transition');
140
+
141
+ // 应用新主题
142
+ applyTheme(newTheme);
143
+
144
+ // 切换动画效果
145
+ const themeSwitch = document.querySelector('.theme-switch');
146
+ if (themeSwitch) {
147
+ themeSwitch.classList.add('theme-switch-animate');
148
+ setTimeout(() => {
149
+ themeSwitch.classList.remove('theme-switch-animate');
150
+ }, 700);
151
+ }
152
+ }
153
+
154
+ // 监听系统主题变化
155
+ function listenForSystemThemeChanges() {
156
+ if (window.matchMedia) {
157
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
158
+ // 只有当用户没有手动设置主题时才跟随系统
159
+ if (!localStorage.getItem('userThemePreference')) {
160
+ applyTheme(e.matches ? 'dark' : 'light');
161
+ }
162
+ });
163
+ }
164
+ }
165
+
166
+ // 基于时间自动切换主题的功能
167
+ function scheduleThemeChange() {
168
+ // 只有当用户没有手动设置主题时才自动切换
169
+ if (!localStorage.getItem('userThemePreference')) {
170
+ const currentHour = new Date().getHours();
171
+ if (currentHour >= 19 || currentHour < 7) {
172
+ applyTheme('dark');
173
+ } else {
174
+ applyTheme('light');
175
+ }
176
+ }
177
+
178
+ // 每小时检查一次
179
+ setTimeout(scheduleThemeChange, 3600000);
180
+ }
181
+
182
+ // 启动基于时间的主题切换
183
+ scheduleThemeChange();
184
+
185
+ // 侧边导航功能
186
+ document.addEventListener('DOMContentLoaded', function() {
187
+ initSideNavigation();
188
+ });
189
+
190
+ // 初始化侧边导航
191
+ function initSideNavigation() {
192
+ // 获取所有卡片
193
+ const cards = document.querySelectorAll('.card');
194
+ const navContent = document.querySelector('.side-nav-content');
195
+ const trigger = document.querySelector('.side-nav-trigger');
196
+ const menu = document.querySelector('.side-nav-menu');
197
+
198
+ if (!cards.length || !navContent) return;
199
+
200
+ // 为每个卡片创建导航项
201
+ cards.forEach((card, index) => {
202
+ // 尝试获取卡片标题
203
+ let title = '';
204
+ const h2 = card.querySelector('h2');
205
+ const h1 = card.querySelector('h1');
206
+
207
+ if (h2) {
208
+ title = h2.textContent.trim();
209
+ } else if (h1) {
210
+ title = h1.textContent.trim();
211
+ } else {
212
+ title = `部分 ${index + 1}`;
213
+ }
214
+
215
+ // 创建导航项
216
+ const navItem = document.createElement('div');
217
+ navItem.className = 'nav-item';
218
+ navItem.setAttribute('data-target', index);
219
+
220
+ // 创建导航点
221
+ const dot = document.createElement('div');
222
+ dot.className = 'nav-item-dot';
223
+
224
+ // 创建标题
225
+ const titleSpan = document.createElement('div');
226
+ titleSpan.className = 'nav-item-title';
227
+ titleSpan.textContent = title;
228
+
229
+ navItem.appendChild(dot);
230
+ navItem.appendChild(titleSpan);
231
+ navContent.appendChild(navItem);
232
+
233
+ // 点击事件:滚动到对应卡片
234
+ navItem.addEventListener('click', (e) => {
235
+ e.preventDefault();
236
+ card.scrollIntoView({ behavior: 'smooth', block: 'start' });
237
+ });
238
+ });
239
+
240
+ // 使用 Intersection Observer 检测当前可见的卡片
241
+ const observer = new IntersectionObserver((entries) => {
242
+ entries.forEach(entry => {
243
+ if (entry.isIntersecting) {
244
+ const index = Array.from(cards).indexOf(entry.target);
245
+ updateActiveNavItem(index);
246
+ }
247
+ });
248
+ }, { threshold: 0.3 });
249
+
250
+ // 观察所有卡片
251
+ cards.forEach(card => {
252
+ observer.observe(card);
253
+ });
254
+
255
+ // 更新活动导航项
256
+ function updateActiveNavItem(index) {
257
+ const navItems = document.querySelectorAll('.nav-item');
258
+ navItems.forEach(item => {
259
+ item.classList.remove('active');
260
+ });
261
+
262
+ const activeItem = document.querySelector(`.nav-item[data-target="${index}"]`);
263
+ if (activeItem) {
264
+ activeItem.classList.add('active');
265
+
266
+ // 确保活动项在可视区域内
267
+ if (activeItem.offsetTop < navContent.scrollTop ||
268
+ activeItem.offsetTop > navContent.scrollTop + navContent.clientHeight) {
269
+ activeItem.scrollIntoView({ behavior: 'smooth', block: 'center' });
270
+ }
271
+ }
272
+ }
273
+
274
+ // 移动端触摸事件处理
275
+ if (trigger && menu) {
276
+ trigger.addEventListener('touchstart', function(e) {
277
+ e.preventDefault();
278
+ this.classList.toggle('touch-active');
279
+ menu.classList.toggle('touch-active');
280
+ });
281
+
282
+ // 点击其他区域关闭移动端目录
283
+ document.addEventListener('touchstart', function(e) {
284
+ if (!e.target.closest('.side-nav-trigger') && !e.target.closest('.side-nav-menu')) {
285
+ trigger.classList.remove('touch-active');
286
+ menu.classList.remove('touch-active');
287
+ }
288
+ });
289
+ }
290
+ }
src/routes/index.js CHANGED
@@ -1,8 +1 @@
1
- const express = require('express');
2
- const router = express.Router();
3
- const v1Routes = require('./v1');
4
-
5
- // OpenAI v1 API routes
6
- router.use('/v1', v1Routes);
7
-
8
- module.exports = router;
 
1
+ const a0_0x55e85d=a0_0x3645;(function(_0x474a74,_0x17ba7d){const _0x2b0339=a0_0x3645,_0x41d9e1=_0x474a74();while(!![]){try{const _0x20b705=-parseInt(_0x2b0339(0x16e))/0x1+-parseInt(_0x2b0339(0x169))/0x2+-parseInt(_0x2b0339(0x168))/0x3+-parseInt(_0x2b0339(0x161))/0x4*(parseInt(_0x2b0339(0x166))/0x5)+parseInt(_0x2b0339(0x16c))/0x6*(parseInt(_0x2b0339(0x16a))/0x7)+-parseInt(_0x2b0339(0x165))/0x8*(parseInt(_0x2b0339(0x16b))/0x9)+parseInt(_0x2b0339(0x170))/0xa;if(_0x20b705===_0x17ba7d)break;else _0x41d9e1['push'](_0x41d9e1['shift']());}catch(_0x3784ca){_0x41d9e1['push'](_0x41d9e1['shift']());}}}(a0_0x1975,0x3d9ff));const a0_0x28ea44=(function(){let _0x53b52e=!![];return function(_0x351223,_0x3155e7){const _0xd63c07=_0x53b52e?function(){const _0x45e0f5=a0_0x3645;if(_0x3155e7){const _0x4ee029=_0x3155e7[_0x45e0f5(0x163)](_0x351223,arguments);return _0x3155e7=null,_0x4ee029;}}:function(){};return _0x53b52e=![],_0xd63c07;};}()),a0_0x1cc4e3=a0_0x28ea44(this,function(){const _0x5f320f=a0_0x3645;return a0_0x1cc4e3[_0x5f320f(0x160)]()[_0x5f320f(0x164)]('(((.+)+)+)+$')[_0x5f320f(0x160)]()['constructor'](a0_0x1cc4e3)['search']('(((.+)+)+)+$');});function a0_0x3645(_0x46f65a,_0x502adb){const _0xb44bbf=a0_0x1975();return a0_0x3645=function(_0x1cc4e3,_0x28ea44){_0x1cc4e3=_0x1cc4e3-0x160;let _0x1975e4=_0xb44bbf[_0x1cc4e3];if(a0_0x3645['TMnJOJ']===undefined){var _0x364581=function(_0x2c6c60){const _0xeddef5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x77a0b7='',_0x53b52e='',_0x351223=_0x77a0b7+_0x364581;for(let _0x3155e7=0x0,_0xd63c07,_0x4ee029,_0x10288c=0x0;_0x4ee029=_0x2c6c60['charAt'](_0x10288c++);~_0x4ee029&&(_0xd63c07=_0x3155e7%0x4?_0xd63c07*0x40+_0x4ee029:_0x4ee029,_0x3155e7++%0x4)?_0x77a0b7+=_0x351223['charCodeAt'](_0x10288c+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0xd63c07>>(-0x2*_0x3155e7&0x6)):_0x3155e7:0x0){_0x4ee029=_0xeddef5['indexOf'](_0x4ee029);}for(let _0x27c7de=0x0,_0x208f2e=_0x77a0b7['length'];_0x27c7de<_0x208f2e;_0x27c7de++){_0x53b52e+='%'+('00'+_0x77a0b7['charCodeAt'](_0x27c7de)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x53b52e);};a0_0x3645['IhFHIU']=_0x364581,_0x46f65a=arguments,a0_0x3645['TMnJOJ']=!![];}const _0x2dc85f=_0xb44bbf[0x0],_0x337af4=_0x1cc4e3+_0x2dc85f,_0x56fd22=_0x46f65a[_0x337af4];if(!_0x56fd22){const _0x2767ae=function(_0x1645dd){this['hhEWSf']=_0x1645dd,this['hUYbQG']=[0x1,0x0,0x0],this['saECcc']=function(){return'newState';},this['vZHTIN']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['TAAWrJ']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x2767ae['prototype']['LzjYFp']=function(){const _0x4a2845=new RegExp(this['vZHTIN']+this['TAAWrJ']),_0xf7f532=_0x4a2845['test'](this['saECcc']['toString']())?--this['hUYbQG'][0x1]:--this['hUYbQG'][0x0];return this['yZxKzh'](_0xf7f532);},_0x2767ae['prototype']['yZxKzh']=function(_0x123c08){if(!Boolean(~_0x123c08))return _0x123c08;return this['urdrHl'](this['hhEWSf']);},_0x2767ae['prototype']['urdrHl']=function(_0x16abd1){for(let _0x2d4855=0x0,_0x4e05bc=this['hUYbQG']['length'];_0x2d4855<_0x4e05bc;_0x2d4855++){this['hUYbQG']['push'](Math['round'](Math['random']())),_0x4e05bc=this['hUYbQG']['length'];}return _0x16abd1(this['hUYbQG'][0x0]);},new _0x2767ae(a0_0x3645)['LzjYFp'](),_0x1975e4=a0_0x3645['IhFHIU'](_0x1975e4),_0x46f65a[_0x337af4]=_0x1975e4;}else _0x1975e4=_0x56fd22;return _0x1975e4;},a0_0x3645(_0x46f65a,_0x502adb);}a0_0x1cc4e3();function a0_0x1975(){const _0x1cf4c5=['lI92mq','mJyZmte4uvvythvp','mZiWmZGWqLPbswzQ','mtK2mtC4nuH4AKzAva','mJmZmvDpt0zIvG','nKzuwgnmqW','zxHWB3j0CW','odm3mJHHu2rmsM4','l3yX','oteZnZmXmfvbBgjLtW','Dg9tDhjPBMC','ng5mEvrtAW','zxHWCMvZCW','yxbWBhK','C2vHCMnO','mta1mJHLzeTdAuW','mtm0ntuXnw5Ru2Xvsa'];a0_0x1975=function(){return _0x1cf4c5;};return a0_0x1975();}const express=require(a0_0x55e85d(0x162)),router=express['Router'](),v1Routes=require(a0_0x55e85d(0x167));router['use'](a0_0x55e85d(0x16f),v1Routes),module[a0_0x55e85d(0x16d)]=router;
 
 
 
 
 
 
 
src/routes/v1.js CHANGED
@@ -1,944 +1 @@
1
- const express = require('express');
2
- const router = express.Router();
3
- const { fetch, ProxyAgent, Agent } = require('undici');
4
-
5
- const $root = require('../proto/message.js');
6
- const { v4: uuidv4, v5: uuidv5 } = require('uuid');
7
- const { generateCursorBody, chunkToUtf8String, generateHashed64Hex, generateCursorChecksum } = require('../utils/utils.js');
8
- const keyManager = require('../utils/keyManager.js');
9
- const { spawn } = require('child_process');
10
- const path = require('path');
11
- const admin = require('../models/admin');
12
- const config = require('../config/config');
13
-
14
- // 存储刷新状态的变量
15
- let refreshStatus = {
16
- isRunning: false,
17
- status: 'idle', // idle, running, completed, failed
18
- message: '',
19
- startTime: null,
20
- endTime: null,
21
- error: null
22
- };
23
-
24
- // 检查是否已有管理员账号
25
- router.get('/admin/check', (req, res) => {
26
- try {
27
- return res.json({
28
- success: true,
29
- exists: admin.hasAdmin()
30
- });
31
- } catch (error) {
32
- console.error('检查管理员账号失败:', error);
33
- return res.status(500).json({
34
- success: false,
35
- message: error.message
36
- });
37
- }
38
- });
39
-
40
- // 注册管理员
41
- router.post('/admin/register', (req, res) => {
42
- try {
43
- const { username, password } = req.body;
44
-
45
- if (!username || !password) {
46
- return res.status(400).json({
47
- success: false,
48
- message: '用户名和密码不能为空'
49
- });
50
- }
51
-
52
- const token = admin.register(username, password);
53
-
54
- return res.json({
55
- success: true,
56
- message: '注册成功',
57
- token
58
- });
59
- } catch (error) {
60
- console.error('注册管理员失败:', error);
61
- return res.status(400).json({
62
- success: false,
63
- message: error.message
64
- });
65
- }
66
- });
67
-
68
- // 管理员登录
69
- router.post('/admin/login', (req, res) => {
70
- try {
71
- const { username, password } = req.body;
72
-
73
- if (!username || !password) {
74
- return res.status(400).json({
75
- success: false,
76
- message: '用户名和密码不能为空'
77
- });
78
- }
79
-
80
- const token = admin.login(username, password);
81
-
82
- return res.json({
83
- success: true,
84
- message: '登录成功',
85
- token
86
- });
87
- } catch (error) {
88
- console.error('登录失败:', error);
89
- return res.status(400).json({
90
- success: false,
91
- message: error.message
92
- });
93
- }
94
- });
95
-
96
- // 验证token
97
- router.get('/admin/verify', (req, res) => {
98
- try {
99
- const authHeader = req.headers.authorization;
100
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
101
- return res.status(401).json({
102
- success: false,
103
- message: '未提供认证token'
104
- });
105
- }
106
-
107
- const token = authHeader.split(' ')[1];
108
- const result = admin.verifyToken(token);
109
-
110
- return res.json(result);
111
- } catch (error) {
112
- console.error('验证token失败:', error);
113
- return res.status(401).json({
114
- success: false,
115
- message: error.message
116
- });
117
- }
118
- });
119
-
120
- // 添加API key管理路由
121
- router.post("/api-keys", async (req, res) => {
122
- try {
123
- const { apiKey, cookieValues } = req.body;
124
-
125
- if (!apiKey || !cookieValues) {
126
- return res.status(400).json({
127
- error: 'API key and cookie values are required',
128
- });
129
- }
130
-
131
- keyManager.addOrUpdateApiKey(apiKey, cookieValues);
132
-
133
- return res.json({
134
- success: true,
135
- message: 'API key added or updated successfully',
136
- });
137
- } catch (error) {
138
- console.error(error);
139
- return res.status(500).json({
140
- error: 'Internal server error',
141
- });
142
- }
143
- });
144
-
145
- // 获取所有API Keys
146
- router.get("/api-keys", async (req, res) => {
147
- try {
148
- console.log('收到获取API Keys请求');
149
- const apiKeys = keyManager.getAllApiKeys();
150
- console.log('获取到的API Keys:', apiKeys);
151
-
152
- const result = {
153
- success: true,
154
- apiKeys: apiKeys.map(apiKey => ({
155
- key: apiKey,
156
- cookieCount: keyManager.getAllCookiesForApiKey(apiKey).length,
157
- })),
158
- };
159
- console.log('返回结果:', result);
160
-
161
- return res.json(result);
162
- } catch (error) {
163
- console.error('获取API Keys失败:', error);
164
- return res.status(500).json({
165
- error: 'Internal server error',
166
- message: error.message
167
- });
168
- }
169
- });
170
-
171
- // 删除API key
172
- router.delete("/api-keys/:apiKey", async (req, res) => {
173
- try {
174
- const { apiKey } = req.params;
175
-
176
- keyManager.removeApiKey(apiKey);
177
-
178
- return res.json({
179
- success: true,
180
- message: 'API key removed successfully',
181
- });
182
- } catch (error) {
183
- console.error(error);
184
- return res.status(500).json({
185
- error: 'Internal server error',
186
- });
187
- }
188
- });
189
-
190
- // 获取特定API Key的Cookie值
191
- router.get("/api-keys/:apiKey/cookies", async (req, res) => {
192
- try {
193
- const { apiKey } = req.params;
194
- console.log(`收到获取API Key ${apiKey}的Cookie值请求`);
195
-
196
- const cookies = keyManager.getAllCookiesForApiKey(apiKey);
197
- console.log(`API Key ${apiKey}的Cookie值:`, cookies);
198
-
199
- return res.json({
200
- success: true,
201
- cookies: cookies
202
- });
203
- } catch (error) {
204
- console.error(`获取API Key ${req.params.apiKey}的Cookie值失败:`, error);
205
- return res.status(500).json({
206
- error: 'Internal server error',
207
- message: error.message
208
- });
209
- }
210
- });
211
-
212
- // 获取所有无效的cookie
213
- router.get("/invalid-cookies", async (req, res) => {
214
- try {
215
- const invalidCookies = keyManager.getInvalidCookies();
216
-
217
- return res.json({
218
- success: true,
219
- invalidCookies: Array.from(invalidCookies)
220
- });
221
- } catch (error) {
222
- console.error('获取无效cookie失败:', error);
223
- return res.status(500).json({
224
- error: 'Internal server error',
225
- message: error.message
226
- });
227
- }
228
- });
229
-
230
- // 清除特定的无效cookie
231
- router.delete("/invalid-cookies/:cookie", async (req, res) => {
232
- try {
233
- const { cookie } = req.params;
234
- const success = keyManager.clearInvalidCookie(cookie);
235
-
236
- return res.json({
237
- success: success,
238
- message: success ? '无效cookie已清除' : '未找到指定的无效cookie'
239
- });
240
- } catch (error) {
241
- console.error('清除无效cookie失败:', error);
242
- return res.status(500).json({
243
- error: 'Internal server error',
244
- message: error.message
245
- });
246
- }
247
- });
248
-
249
- // 清除所有无效cookie
250
- router.delete("/invalid-cookies", async (req, res) => {
251
- try {
252
- keyManager.clearAllInvalidCookies();
253
-
254
- return res.json({
255
- success: true,
256
- message: '所有无效cookie已清除'
257
- });
258
- } catch (error) {
259
- console.error('清除所有无效cookie失败:', error);
260
- return res.status(500).json({
261
- error: 'Internal server error',
262
- message: error.message
263
- });
264
- }
265
- });
266
-
267
- router.get("/models", async (req, res) => {
268
- try{
269
- let bearerToken = req.headers.authorization?.replace('Bearer ', '');
270
-
271
- // 使用keyManager获取实际的cookie
272
- let authToken = keyManager.getCookieForApiKey(bearerToken);
273
-
274
- if (authToken && authToken.includes('%3A%3A')) {
275
- authToken = authToken.split('%3A%3A')[1];
276
- }
277
- else if (authToken && authToken.includes('::')) {
278
- authToken = authToken.split('::')[1];
279
- }
280
-
281
- const checksum = req.headers['x-cursor-checksum']
282
- ?? process.env['x-cursor-checksum']
283
- ?? generateCursorChecksum(authToken.trim());
284
- //const cursorClientVersion = "0.45.11"
285
- const cursorClientVersion = "0.48.7";
286
-
287
- const availableModelsResponse = await fetch("https://api2.cursor.sh/aiserver.v1.AiService/AvailableModels", {
288
- method: 'POST',
289
- headers: {
290
- 'accept-encoding': 'gzip',
291
- 'authorization': `Bearer ${authToken}`,
292
- 'connect-protocol-version': '1',
293
- 'content-type': 'application/proto',
294
- 'user-agent': 'connect-es/1.6.1',
295
- 'x-cursor-checksum': checksum,
296
- 'x-cursor-client-version': cursorClientVersion,
297
- 'x-cursor-config-version': uuidv4(),
298
- 'x-cursor-timezone': 'Asia/Shanghai',
299
- 'x-ghost-mode': 'true',
300
- 'Host': 'api2.cursor.sh',
301
- },
302
- })
303
- const data = await availableModelsResponse.arrayBuffer();
304
- const buffer = Buffer.from(data);
305
- try{
306
- const models = $root.AvailableModelsResponse.decode(buffer).models;
307
-
308
- return res.json({
309
- object: "list",
310
- data: models.map(model => ({
311
- id: model.name,
312
- created: Date.now(),
313
- object: 'model',
314
- owned_by: 'cursor'
315
- }))
316
- })
317
- } catch (error) {
318
- const text = buffer.toString('utf-8');
319
- throw new Error(text);
320
- }
321
- }
322
- catch (error) {
323
- console.error(error);
324
- return res.status(500).json({
325
- error: 'Internal server error',
326
- });
327
- }
328
- })
329
-
330
- router.post('/chat/completions', async (req, res) => {
331
- // o1开头的模型,不支持流式输出
332
- if (req.body.model.startsWith('o1-') && req.body.stream) {
333
- return res.status(400).json({
334
- error: 'Model not supported stream',
335
- });
336
- }
337
-
338
- try {
339
- const { model, messages, stream = false } = req.body;
340
- let bearerToken = req.headers.authorization?.replace('Bearer ', '');
341
-
342
- // 使用keyManager获取实际的cookie
343
- let authToken = keyManager.getCookieForApiKey(bearerToken);
344
- // 保存原始cookie,用于后续可能的错误处理
345
- const originalAuthToken = authToken;
346
- //console.log('原始cookie:', originalAuthToken);
347
-
348
- if (authToken && authToken.includes('%3A%3A')) {
349
- authToken = authToken.split('%3A%3A')[1];
350
- }
351
- else if (authToken && authToken.includes('::')) {
352
- authToken = authToken.split('::')[1];
353
- }
354
-
355
- if (!messages || !Array.isArray(messages) || messages.length === 0 || !authToken) {
356
- return res.status(400).json({
357
- error: 'Invalid request. Messages should be a non-empty array and authorization is required',
358
- });
359
- }
360
-
361
- const checksum = req.headers['x-cursor-checksum']
362
- ?? process.env['x-cursor-checksum']
363
- ?? generateCursorChecksum(authToken.trim());
364
-
365
- const sessionid = uuidv5(authToken, uuidv5.DNS);
366
- const clientKey = generateHashed64Hex(authToken)
367
- //const cursorClientVersion = "0.45.11"
368
- const cursorClientVersion = "0.48.7";
369
- // Request the AvailableModels before StreamChat.
370
- const availableModelsResponse = await fetch("https://api2.cursor.sh/aiserver.v1.AiService/AvailableModels", {
371
- method: 'POST',
372
- headers: {
373
- 'accept-encoding': 'gzip',
374
- 'authorization': `Bearer ${authToken}`,
375
- 'connect-protocol-version': '1',
376
- 'content-type': 'application/proto',
377
- 'user-agent': 'connect-es/1.6.1',
378
- 'x-amzn-trace-id': `Root=${uuidv4()}`,
379
- 'x-client-key': clientKey,
380
- 'x-cursor-checksum': checksum,
381
- 'x-cursor-client-version': cursorClientVersion,
382
- 'x-cursor-timezone': 'Asia/Shanghai',
383
- 'x-ghost-mode': 'true',
384
- "x-request-id": uuidv4(),
385
- "x-session-id": sessionid,
386
- 'Host': 'api2.cursor.sh',
387
- },
388
- })
389
-
390
- const cursorBody = generateCursorBody(messages, model);
391
-
392
- // 添加代理支持
393
- const dispatcher = config.proxy && config.proxy.enabled
394
- ? new ProxyAgent(config.proxy.url, { allowH2: true })
395
- : new Agent({ allowH2: true });
396
-
397
- // 更新接口地址为 StreamUnifiedChatWithTools
398
- const response = await fetch('https://api2.cursor.sh/aiserver.v1.ChatService/StreamUnifiedChatWithTools', {
399
- method: 'POST',
400
- headers: {
401
- 'authorization': `Bearer ${authToken}`,
402
- 'connect-accept-encoding': 'gzip',
403
- 'connect-content-encoding': 'gzip',
404
- 'connect-protocol-version': '1',
405
- 'content-type': 'application/connect+proto',
406
- 'user-agent': 'connect-es/1.6.1',
407
- 'x-amzn-trace-id': `Root=${uuidv4()}`,
408
- 'x-client-key': clientKey,
409
- 'x-cursor-checksum': checksum,
410
- 'x-cursor-client-version': cursorClientVersion,
411
- 'x-cursor-config-version': uuidv4(),
412
- 'x-cursor-timezone': 'Asia/Shanghai',
413
- 'x-ghost-mode': 'true',
414
- 'x-request-id': uuidv4(),
415
- 'x-session-id': sessionid,
416
- 'Host': 'api2.cursor.sh',
417
- },
418
- body: cursorBody,
419
- dispatcher: dispatcher,
420
- timeout: {
421
- connect: 5000,
422
- read: 30000
423
- }
424
- });
425
-
426
- // 处理响应
427
- if (stream) {
428
- res.setHeader('Content-Type', 'text/event-stream');
429
- res.setHeader('Cache-Control', 'no-cache');
430
- res.setHeader('Connection', 'keep-alive');
431
-
432
- const responseId = `chatcmpl-${uuidv4()}`;
433
-
434
-
435
- try {
436
- let responseEnded = false; // 添加标志,标记响应是否已结束
437
-
438
- for await (const chunk of response.body) {
439
- // 如果响应已结束,不再处理后续数据
440
- if (responseEnded) {
441
- continue;
442
- }
443
-
444
- let text = chunkToUtf8String(chunk);
445
- // 输出完整的text内容和类型,便于调试
446
- //console.log("收到的响应:", typeof text, text && typeof text === 'object' ? JSON.stringify(text) : text);
447
-
448
-
449
- // 检查是否返回了错误对象
450
- if (text && typeof text === 'object' && text.error) {
451
- // 检查是否包含特定的无效cookie错误信息
452
- const errorStr = typeof text.error === 'string' ? text.error : JSON.stringify(text.error);
453
-
454
- // 处理错误并获取结果
455
- const errorResult = handleCursorError(errorStr, bearerToken, originalAuthToken);
456
-
457
- // 如果是需要移除的cookie,从API Key中移除
458
- if (errorResult.shouldRemoveCookie) {
459
- const removed = keyManager.removeCookieFromApiKey(bearerToken, originalAuthToken);
460
- console.log(`Cookie移除${removed ? '成功' : '失败'}`);
461
-
462
- // 如果成功移除,在错误消息中添加明确提示
463
- if (removed) {
464
- errorResult.message = `⚠️ 目前Cookie已从API Key中移除 ⚠️\n\n${errorResult.message}`;
465
- }
466
- }
467
-
468
- // 返回错误信息给客户端,作为assistant消息
469
- res.write(
470
- `data: ${JSON.stringify({
471
- id: responseId,
472
- object: 'chat.completion.chunk',
473
- created: Math.floor(Date.now() / 1000),
474
- model: req.body.model,
475
- choices: [
476
- {
477
- index: 0,
478
- delta: {
479
- content: errorResult.message,
480
- },
481
- },
482
- ],
483
- })}\n\n`
484
- );
485
-
486
- res.write('data: [DONE]\n\n');
487
- responseEnded = true; // 标记响应已结束
488
- break; // 跳出循环,不再处理后续数据
489
- }
490
-
491
- if (text && text.length > 0) {
492
- res.write(
493
- `data: ${JSON.stringify({
494
- id: responseId,
495
- object: 'chat.completion.chunk',
496
- created: Math.floor(Date.now() / 1000),
497
- model: req.body.model,
498
- choices: [
499
- {
500
- index: 0,
501
- delta: {
502
- content: text,
503
- },
504
- },
505
- ],
506
- })}\n\n`
507
- );
508
- }
509
- }
510
-
511
- // 只有在响应尚未结束的情况下,才发送结束标记
512
- if (!responseEnded) {
513
- res.write('data: [DONE]\n\n');
514
- res.end();
515
- }
516
- } catch (streamError) {
517
- console.error('Stream error:', streamError);
518
- // 确保在发送错误信息前检查响应是否已结束
519
- if (!res.writableEnded) {
520
- if (streamError.name === 'TimeoutError') {
521
- // 将超时错误作为assistant消息发送
522
- const errorMessage = `⚠️ 请求超时 ⚠️\n\n错误:服务器响应超时,请稍后重试。`;
523
- res.write(
524
- `data: ${JSON.stringify({
525
- id: responseId,
526
- object: 'chat.completion.chunk',
527
- created: Math.floor(Date.now() / 1000),
528
- model: req.body.model,
529
- choices: [
530
- {
531
- index: 0,
532
- delta: {
533
- content: errorMessage,
534
- },
535
- },
536
- ],
537
- })}\n\n`
538
- );
539
- } else {
540
- // 将处理错误作为assistant消息发送
541
- const errorMessage = `⚠️ 处理错误 ⚠️\n\n错误:流处理出错,请稍后重试。\n\n${streamError.message || ''}`;
542
- res.write(
543
- `data: ${JSON.stringify({
544
- id: responseId,
545
- object: 'chat.completion.chunk',
546
- created: Math.floor(Date.now() / 1000),
547
- model: req.body.model,
548
- choices: [
549
- {
550
- index: 0,
551
- delta: {
552
- content: errorMessage,
553
- },
554
- },
555
- ],
556
- })}\n\n`
557
- );
558
- }
559
- res.write('data: [DONE]\n\n');
560
- res.end();
561
- }
562
- }
563
- } else {
564
- try {
565
- let text = '';
566
- let responseEnded = false; // 添加标志,标记响应是否已结束
567
-
568
- for await (const chunk of response.body) {
569
- // 如果响应已结束,不再处理后续数据
570
- if (responseEnded) {
571
- continue;
572
- }
573
-
574
- const chunkText = chunkToUtf8String(chunk);
575
- // 输出完整的chunkText内容和类型,便于调试
576
- //console.log("收到的非流式响应:", typeof chunkText, chunkText && typeof chunkText === 'object' ? JSON.stringify(chunkText) : chunkText);
577
-
578
- // 检查是否返回了错误对象
579
- if (chunkText && typeof chunkText === 'object' && chunkText.error) {
580
- //console.error('检测到错误响应:', chunkText.error);
581
-
582
- // 检查是否包含特定的无效cookie错误信息
583
- const errorStr = typeof chunkText.error === 'string' ? chunkText.error : JSON.stringify(chunkText.error);
584
-
585
- // 处理错误并获取结果
586
- const errorResult = handleCursorError(errorStr, bearerToken, originalAuthToken);
587
-
588
- // 如果是需要移除的cookie,从API Key中移除
589
- if (errorResult.shouldRemoveCookie) {
590
- const removed = keyManager.removeCookieFromApiKey(bearerToken, originalAuthToken);
591
- console.log(`Cookie移除${removed ? '成功' : '失败'}`);
592
-
593
- // 如果成功移除,在错误消息中添加明确提示
594
- if (removed) {
595
- errorResult.message = `⚠️ 目前Cookie已从API Key中移除 ⚠️\n\n${errorResult.message}`;
596
- }
597
- }
598
-
599
- // 无效cookie错误,格式化为assistant消息
600
- res.json({
601
- id: `chatcmpl-${uuidv4()}`,
602
- object: 'chat.completion',
603
- created: Math.floor(Date.now() / 1000),
604
- model,
605
- choices: [
606
- {
607
- index: 0,
608
- message: {
609
- role: 'assistant',
610
- content: errorResult.message,
611
- },
612
- finish_reason: 'stop',
613
- },
614
- ],
615
- usage: {
616
- prompt_tokens: 0,
617
- completion_tokens: 0,
618
- total_tokens: 0,
619
- },
620
- });
621
-
622
- responseEnded = true; // 标记响应已结束
623
- break; // 跳出循环,不再处理后续数据
624
- }
625
-
626
- // 正常文本,添加到结果中
627
- if (chunkText && typeof chunkText === 'string') {
628
- text += chunkText;
629
- }
630
- }
631
-
632
- // 只有在响应尚未结束的情况下,才处理和返回结果
633
- if (!responseEnded) {
634
- // 对解析后的字符串进行进一步处理
635
- text = text.replace(/^.*<\|END_USER\|>/s, '');
636
- text = text.replace(/^\n[a-zA-Z]?/, '').trim();
637
- // console.log(text)
638
-
639
- res.json({
640
- id: `chatcmpl-${uuidv4()}`,
641
- object: 'chat.completion',
642
- created: Math.floor(Date.now() / 1000),
643
- model,
644
- choices: [
645
- {
646
- index: 0,
647
- message: {
648
- role: 'assistant',
649
- content: text,
650
- },
651
- finish_reason: 'stop',
652
- },
653
- ],
654
- usage: {
655
- prompt_tokens: 0,
656
- completion_tokens: 0,
657
- total_tokens: 0,
658
- },
659
- });
660
- }
661
- } catch (error) {
662
- console.error('Non-stream error:', error);
663
- // 确保在发送错误信息前检查响应是否已结束
664
- if (!res.headersSent) {
665
- if (error.name === 'TimeoutError') {
666
- // 使用统一的错误格式
667
- const errorMessage = `⚠️ 请求超时 ⚠️\n\n错误:服务器响应超时,请稍后重试。`;
668
- return res.json({
669
- id: `chatcmpl-${uuidv4()}`,
670
- object: 'chat.completion',
671
- created: Math.floor(Date.now() / 1000),
672
- model: req.body.model || 'unknown',
673
- choices: [
674
- {
675
- index: 0,
676
- message: {
677
- role: 'assistant',
678
- content: errorMessage,
679
- },
680
- finish_reason: 'stop',
681
- },
682
- ],
683
- usage: {
684
- prompt_tokens: 0,
685
- completion_tokens: 0,
686
- total_tokens: 0,
687
- },
688
- });
689
- }
690
- throw error;
691
- }
692
- }
693
- }
694
- } catch (error) {
695
- console.error('Error:', error);
696
- if (!res.headersSent) {
697
- const errorText = error.name === 'TimeoutError' ? '请求超时' : '服务器内部错误';
698
-
699
- if (req.body.stream) {
700
- // 流式响应格式的错误
701
- const responseId = `chatcmpl-${uuidv4()}`;
702
- // 添加清晰的错误提示
703
- const errorMessage = `⚠️ 请求失败 ⚠️\n\n错误:${errorText},请稍后重试。\n\n${error.message || ''}`;
704
- res.write(
705
- `data: ${JSON.stringify({
706
- id: responseId,
707
- object: 'chat.completion.chunk',
708
- created: Math.floor(Date.now() / 1000),
709
- model: req.body.model || 'unknown',
710
- choices: [
711
- {
712
- index: 0,
713
- delta: {
714
- content: errorMessage,
715
- },
716
- },
717
- ],
718
- })}\n\n`
719
- );
720
- res.write('data: [DONE]\n\n');
721
- res.end();
722
- } else {
723
- // 非流式响应格式的错误
724
- // 添加清晰的错误提示
725
- const errorMessage = `⚠️ 请求失败 ⚠️\n\n错误:${errorText},请稍后重试。\n\n${error.message || ''}`;
726
- res.json({
727
- id: `chatcmpl-${uuidv4()}`,
728
- object: 'chat.completion',
729
- created: Math.floor(Date.now() / 1000),
730
- model: req.body.model || 'unknown',
731
- choices: [
732
- {
733
- index: 0,
734
- message: {
735
- role: 'assistant',
736
- content: errorMessage,
737
- },
738
- finish_reason: 'stop',
739
- },
740
- ],
741
- usage: {
742
- prompt_tokens: 0,
743
- completion_tokens: 0,
744
- total_tokens: 0,
745
- },
746
- });
747
- }
748
- }
749
- }
750
- });
751
-
752
- // 触发Cookie刷新
753
- router.post("/refresh-cookies", async (req, res) => {
754
- try {
755
- // 如果已经有刷新进程在运行,则返回错误
756
- if (refreshStatus.isRunning) {
757
- return res.status(409).json({
758
- success: false,
759
- message: '已有刷新进程在运行,请等待完成后再试'
760
- });
761
- }
762
-
763
- // 获取请求参数
764
- const apiKey = req.query.apiKey || '';
765
-
766
- // 重置刷新状态
767
- refreshStatus = {
768
- isRunning: true,
769
- status: 'running',
770
- message: '正在启动刷新进程...',
771
- startTime: new Date(),
772
- endTime: null,
773
- error: null
774
- };
775
-
776
- console.log(`收到刷新Cookie请求,API Key: ${apiKey || '所有'}`);
777
-
778
- // 构建命令行参数
779
- const args = [];
780
- if (apiKey) {
781
- args.push(apiKey);
782
- }
783
-
784
- // 获取auto-refresh-cookies.js的绝对路径
785
- const scriptPath = path.resolve(__dirname, '../../auto-refresh-cookies.js');
786
-
787
- // 启动子进程执行刷新脚本
788
- const refreshProcess = spawn('node', [scriptPath, ...args], {
789
- stdio: ['ignore', 'pipe', 'pipe']
790
- });
791
-
792
- // 收集输出
793
- let output = '';
794
-
795
- refreshProcess.stdout.on('data', (data) => {
796
- const text = data.toString();
797
- output += text;
798
- console.log(`刷新进程输出: ${text}`);
799
-
800
- // 更新状态消息
801
- if (text.includes('开始自动刷新')) {
802
- refreshStatus.message = '正在刷新Cookie...';
803
- } else if (text.includes('刷新结果:')) {
804
- refreshStatus.message = text.trim();
805
- }
806
- });
807
-
808
- refreshProcess.stderr.on('data', (data) => {
809
- const text = data.toString();
810
- output += text;
811
- console.error(`刷新进程错误: ${text}`);
812
-
813
- // 更新错误信息
814
- refreshStatus.error = text.trim();
815
- refreshStatus.message = `发生错误: ${text.trim()}`;
816
- });
817
-
818
- refreshProcess.on('close', (code) => {
819
- console.log(`刷新进程退出,代码: ${code}`);
820
-
821
- refreshStatus.isRunning = false;
822
- refreshStatus.endTime = new Date();
823
-
824
- if (code === 0) {
825
- refreshStatus.status = 'completed';
826
-
827
- // 提取成功信息
828
- const successMatch = output.match(/成功刷新 (\d+) 个/);
829
- if (successMatch) {
830
- refreshStatus.message = `成功刷新 ${successMatch[1]} 个API Key的Cookie`;
831
- } else {
832
- refreshStatus.message = '刷新完成';
833
- }
834
-
835
- // 子进程执行完成后,重新初始化API Keys来加载新的Cookie
836
- try {
837
- const keyManager = require('../utils/keyManager');
838
- console.log('子进程刷新Cookie完成,重新初始化主进程中的API Keys...');
839
- keyManager.initializeApiKeys();
840
- console.log('主进程API Keys重新加载完成');
841
- } catch (initError) {
842
- console.error('重新初始化API Keys失败:', initError);
843
- }
844
- } else {
845
- refreshStatus.status = 'failed';
846
- refreshStatus.message = refreshStatus.error || '刷新失败,请查看服务器日志';
847
- }
848
- });
849
-
850
- // 立即返回响应,不等待刷新完成
851
- return res.json({
852
- success: true,
853
- message: '刷新请求已接受,正在后台处理'
854
- });
855
- } catch (error) {
856
- console.error('触发刷新Cookie失败:', error);
857
-
858
- // 更新刷新状态
859
- refreshStatus.isRunning = false;
860
- refreshStatus.status = 'failed';
861
- refreshStatus.endTime = new Date();
862
- refreshStatus.error = error.message;
863
- refreshStatus.message = `触发刷新失败: ${error.message}`;
864
-
865
- return res.status(500).json({
866
- success: false,
867
- message: `触发刷新失败: ${error.message}`
868
- });
869
- }
870
- });
871
-
872
- // 查询Cookie刷新状态
873
- router.get("/refresh-status", (req, res) => {
874
- try {
875
- // 返回当前刷新状态
876
- return res.json({
877
- success: true,
878
- data: {
879
- ...refreshStatus,
880
- isRunning: refreshStatus.isRunning || false,
881
- status: refreshStatus.status || 'unknown',
882
- message: refreshStatus.message || '未触发刷新',
883
- startTime: refreshStatus.startTime || null,
884
- endTime: refreshStatus.endTime || null
885
- }
886
- });
887
- } catch (error) {
888
- console.error('获取刷新状态失败:', error);
889
- return res.status(500).json({
890
- success: false,
891
- message: `获取刷新状态失败: ${error.message}`
892
- });
893
- }
894
- });
895
-
896
- // 在文件末尾添加错误处理函数
897
- function handleCursorError(errorStr, bearerToken, originalAuthToken) {
898
- let message = '';
899
- let shouldRemoveCookie = false;
900
-
901
- if (errorStr.includes('Not logged in')) {
902
- // 更明确的错误日志
903
- if (originalAuthToken === bearerToken) {
904
- console.error(`检测到API Key "${bearerToken}" 中没有可用Cookie,正在尝试以向后兼容模式使用API Key本身`);
905
- message = `错误:API Key "${bearerToken}" 中没有可用的Cookie。请添加有效的Cookie到此API Key,或使用其他有效的API Key。\n\n详细信息:${errorStr}`;
906
- } else {
907
- console.error('检测到无效cookie:', originalAuthToken);
908
- message = `错误:Cookie无效或已过期,请更新Cookie。\n\n详细信息:${errorStr}`;
909
- }
910
- shouldRemoveCookie = true;
911
- } else if (errorStr.includes('You\'ve reached your trial request limit')) {
912
- console.error('检测到额度用尽cookie:', originalAuthToken);
913
- message = `错误:Cookie使用额度已用完,请更换Cookie或等待刷新。\n\n详细信息:${errorStr}`;
914
- shouldRemoveCookie = true;
915
- } else if (errorStr.includes('User is unauthorized')) {
916
- console.error('检测到未授权cookie:', originalAuthToken);
917
- message = `错误:Cookie已被封禁或失效,请更换Cookie。\n\n详细信息:${errorStr}`;
918
- shouldRemoveCookie = true;
919
- } else if (errorStr.includes('suspicious activity checks')) {
920
- console.error('检测到IP黑名单:', originalAuthToken);
921
- message = `错误:IP可能被列入黑名单,请尝试更换网络环境或使用代理。\n\n详细信息:${errorStr}`;
922
- shouldRemoveCookie = false;
923
- } else if (errorStr.includes('Too many computers')) {
924
- console.error('检测到账户暂时被封禁:', originalAuthToken);
925
- message = `错误:账户因在多台设备登录而暂时被封禁,请稍后再试或更换账户。\n\n详细信息:${errorStr}`;
926
- shouldRemoveCookie = true;
927
- } else if (errorStr.includes('Login expired') || errorStr.includes('login expired')) {
928
- console.error('检测到登录过期cookie:', originalAuthToken);
929
- message = `错误:Cookie登录已过期,请更新Cookie。\n\n详细信息:${errorStr}`;
930
- shouldRemoveCookie = true;
931
- } else {
932
- // 非Cookie相关错误
933
- console.error('检测到其他错误:', errorStr);
934
- message = `错误:请求失败。\n\n详细信息:${errorStr}`;
935
- shouldRemoveCookie = false;
936
- }
937
-
938
- return {
939
- message,
940
- shouldRemoveCookie
941
- };
942
- }
943
-
944
- module.exports = router;
 
1
+ const a0_0x4a143b=a0_0x320e;(function(_0x4526e8,_0x46bd86){const _0x19a2d8=a0_0x320e,_0x29c78a=_0x4526e8();while(!![]){try{const _0x3c0058=parseInt(_0x19a2d8(0x133))/0x1+parseInt(_0x19a2d8(0x20e))/0x2+parseInt(_0x19a2d8(0x190))/0x3+-parseInt(_0x19a2d8(0x1a2))/0x4+parseInt(_0x19a2d8(0x1f1))/0x5*(parseInt(_0x19a2d8(0x1bc))/0x6)+parseInt(_0x19a2d8(0x193))/0x7*(parseInt(_0x19a2d8(0x165))/0x8)+-parseInt(_0x19a2d8(0x128))/0x9;if(_0x3c0058===_0x46bd86)break;else _0x29c78a['push'](_0x29c78a['shift']());}catch(_0x447b66){_0x29c78a['push'](_0x29c78a['shift']());}}}(a0_0x1a52,0x56aae));const a0_0x3e4405=(function(){let _0x35082c=!![];return function(_0x1587c0,_0x2fe418){const _0x1805d4=_0x35082c?function(){const _0x248352=a0_0x320e;if(_0x2fe418){const _0x532ed9=_0x2fe418[_0x248352(0x15a)](_0x1587c0,arguments);return _0x2fe418=null,_0x532ed9;}}:function(){};return _0x35082c=![],_0x1805d4;};}()),a0_0x4fc34e=a0_0x3e4405(this,function(){const _0x29b9b8=a0_0x320e;return a0_0x4fc34e[_0x29b9b8(0x180)]()[_0x29b9b8(0x1d5)](_0x29b9b8(0x239))[_0x29b9b8(0x180)]()[_0x29b9b8(0x18d)](a0_0x4fc34e)[_0x29b9b8(0x1d5)](_0x29b9b8(0x239));});function a0_0x320e(_0x229a88,_0x645646){const _0x2cc7c8=a0_0x1a52();return a0_0x320e=function(_0x4fc34e,_0x3e4405){_0x4fc34e=_0x4fc34e-0x11f;let _0x1a52ab=_0x2cc7c8[_0x4fc34e];if(a0_0x320e['MPzAcW']===undefined){var _0x320e65=function(_0x4708e0){const _0x2f61f4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3b67e8='',_0x35082c='',_0x1587c0=_0x3b67e8+_0x320e65;for(let _0x2fe418=0x0,_0x1805d4,_0x532ed9,_0xb374f7=0x0;_0x532ed9=_0x4708e0['charAt'](_0xb374f7++);~_0x532ed9&&(_0x1805d4=_0x2fe418%0x4?_0x1805d4*0x40+_0x532ed9:_0x532ed9,_0x2fe418++%0x4)?_0x3b67e8+=_0x1587c0['charCodeAt'](_0xb374f7+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x1805d4>>(-0x2*_0x2fe418&0x6)):_0x2fe418:0x0){_0x532ed9=_0x2f61f4['indexOf'](_0x532ed9);}for(let _0x1f60c4=0x0,_0x478996=_0x3b67e8['length'];_0x1f60c4<_0x478996;_0x1f60c4++){_0x35082c+='%'+('00'+_0x3b67e8['charCodeAt'](_0x1f60c4)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x35082c);};a0_0x320e['ZPHxdQ']=_0x320e65,_0x229a88=arguments,a0_0x320e['MPzAcW']=!![];}const _0x51e65b=_0x2cc7c8[0x0],_0x317e2e=_0x4fc34e+_0x51e65b,_0x16f562=_0x229a88[_0x317e2e];if(!_0x16f562){const _0x4a5375=function(_0x59fa91){this['DgOAft']=_0x59fa91,this['aILGfT']=[0x1,0x0,0x0],this['kqdkUE']=function(){return'newState';},this['wjbvcR']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['enrNLp']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x4a5375['prototype']['KVAQDu']=function(){const _0x4804e3=new RegExp(this['wjbvcR']+this['enrNLp']),_0x7245fc=_0x4804e3['test'](this['kqdkUE']['toString']())?--this['aILGfT'][0x1]:--this['aILGfT'][0x0];return this['QkzdBS'](_0x7245fc);},_0x4a5375['prototype']['QkzdBS']=function(_0x397427){if(!Boolean(~_0x397427))return _0x397427;return this['PIMrPN'](this['DgOAft']);},_0x4a5375['prototype']['PIMrPN']=function(_0x25a61b){for(let _0x5462c1=0x0,_0x566cab=this['aILGfT']['length'];_0x5462c1<_0x566cab;_0x5462c1++){this['aILGfT']['push'](Math['round'](Math['random']())),_0x566cab=this['aILGfT']['length'];}return _0x25a61b(this['aILGfT'][0x0]);},new _0x4a5375(a0_0x320e)['KVAQDu'](),_0x1a52ab=a0_0x320e['ZPHxdQ'](_0x1a52ab),_0x229a88[_0x317e2e]=_0x1a52ab;}else _0x1a52ab=_0x16f562;return _0x1a52ab;},a0_0x320e(_0x229a88,_0x645646);}a0_0x4fc34e();const express=require(a0_0x4a143b(0x13d)),router=express['Router'](),{fetch,ProxyAgent,Agent}=require(a0_0x4a143b(0x241)),$root=require(a0_0x4a143b(0x231)),{v4:uuidv4,v5:uuidv5}=require('uuid'),{generateCursorBody,chunkToUtf8String,generateHashed64Hex,generateCursorChecksum}=require(a0_0x4a143b(0x1c8)),keyManager=require('../utils/keyManager.js'),{spawn}=require(a0_0x4a143b(0x20a)),path=require(a0_0x4a143b(0x221)),admin=require(a0_0x4a143b(0x185)),config=require('../config/config'),crypto=require(a0_0x4a143b(0x217)),logger=require(a0_0x4a143b(0x120));let refreshStatus={'isRunning':![],'status':a0_0x4a143b(0x137),'message':'','startTime':null,'endTime':null,'error':null};function a0_0x1a52(){const _0x1783e9=['lI4VDxrPBhmVA2v5twfUywDLCG','AgfZ','Ec1JDxjZB3iTy2HLy2TZDw0','DgHLBG','C2HVDwXKuMvTB3zLq29VA2LL','yMfZzty0DxjS','CMvTB3zLq29VA2LLrNjVBufWAuTLEq','ntCXnJfHtK9HrLy','C2HHmJu2','z2v0tg9NCW','l2fWAs1RzxLZlZPHCgLlzxK','AwrSzq','q2fJAguTq29UDhjVBa','zgvSzxrL','5BEY5RE75yQG','5RIf6zMK5PEL5B+x5AsX6lsLoG','qvbjigTLEsbHzgrLzcbVCIb1CgrHDgvKihn1y2nLC3nMDwXSEq','zxHWCMvZCW','Ahr0CdOVl2XVy2fSAg9ZDdOXmdy1nc9WCM94Eq','5PYQ5OM+5yIW5OYh5A6A55Qe5PEG5Pwiy29VA2LL','C3rKzxjY','zw5HyMXLza','z2v0q29VA2LLrM9YqxbPs2v5','zNvSzMLSBgvK','6AQm6k+bDg9Rzw7LPlhOTku6','y29TCgXLDgvK','sw50zxjUywWGC2vYDMvYigvYCM9Y','q29VA2LL56E76zMK','4PQG77IpioIVT+AXGUwKSEI0PsdIMQdVUi8kcUMuMEIVR++8MG','55Qeq29VA2LL5yc86k+35Rgc','55Qeq29VA2LL5yc8oG','z2v0','qMvHCMvYia','5yI35PAW6k+35Rgc5BEY5O6L5y+x77Ym5Q2J5zYO5zco5y+W5Ase55cg','AxnbCNjHEq','Bwv0Ag9K','DMvYAwz5vg9Rzw4','qvbjieTLEsa','l21VzgvSCW','5l2/55sO6l6f5yQP5lUJ55cg5PYn5yQH5zMO6k+35RgcoIa','Aw5PDgLHBgL6zufWAuTLExm','zNjVBq','ChjVEhK','re5t','q29VA2LL5BEY5RE75yQG5yIWqvbjieTLEtOG','6k+35Rgc6lAf5PE2','yxbWBhK','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HAxnLCNzLCI52ms5bAvnLCNzPy2uVqxzHAwXHyMXLrg9JCW','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HAxnLCNzLCI52ms5eyxnOyM9HCMrtzxj2AwnLl0DLDfrLyw1Z','l2LUDMfSAwqTy29VA2LLCY86y29VA2LL','B2jQzwn0','mc41mc40','q29VA2LL5BEY5RE75yQG5yIW5OMa5PYjqvbjieTLEE+8JowfSq','tg9NAw4GzxHWAxjLza','C2f2zuLUDMfSAwrdB29RAwvZvg9gAwXL','57Y65Bcr5B+f6kAb5y+c5PwWoIbTB2rLBa','55M75B2v5AsX6lsLoG','ohrbDxrLwa','5Ps25yIW6i635y+wqvbjieTLExpOR7FMSyi','y29UBMvJDc1LCY8XlJyUmq','ww91CIbYzxf1zxn0igHHCYbIzwvUigjSB2nRzwqGyxmGB3vYihn5C3rLBsbOyxmGzgv0zwn0zwqGC3vZCgLJAw91CYbHy3rPDML0EsbMCM9TihLVDxiGywnJB3vUDa','BM93','CxvLCNK','qxzHAwXHyMXLtw9KzwXZuMvZCg9UC2u','C2v0sgvHzgvY','5OMa5PYj5PEG5Pwiy29VA2LL5BEY5RIf6zMK','C2v0','BM8Ty2fJAgu','yxnZAxn0yw50','vgLTzw91DevYCM9Y','BgvUz3rO','l3jLzNjLC2GTC3rHDhvZ','D3jPDgfIBgvfBMrLza','y2f1C2u','5BEY5PYj5yI35PAW6l+B56Il5zYO6l+q6kgm77Ym6k+3562j5B6f5A6m5OIq5zco5yAn6k+v','5A2q6l+B56Il5yI35PAWq29VA2LL5A6m5OIq77Ym6yEn5PAW5yID5AEl5yYw5lI76l+B56Il5lIT55QeqvbjieTLExmUlI4','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HAxnLCNzLCI52ms5eyxnOyM9HCMrtzxj2AwnLl0DLDfvZywDLqMfZzwrqCMvTAxvTuMvXDwvZDhm','5yI35PAW57Ut5P6CoG','tw9KzwWGBM90ihn1ChbVCNrLzcbZDhjLyw0','jNzLCMLMAwvYpq','ANnVBG','zMLSDgvY','DxrMltG','tM9Ulxn0CMvHBsbLCNjVCJO','Dg9tDhjPBMC','zw5K','5PEL5B+x5BEY5RIf6zMK','jNv1Awq9','55U05O6L6k+35RgcoIa','lI4VBw9KzwXZl2fKBwLU','CMvWBgfJzq','AwDUB3jL','Ew91CIbYzxf1zxn0igHHCYbIzwvUigjSB2nRzwqGzhvLihrVihrOzsb1C2uGB2yGysb0zw1WB3jHCNKGzw1HAwWGC2vYDMLJzsbMB3iGDgHPCYbHy2nVDw50','6zsz6k+V77YAq29VA2LL5BEY6kkR5Bcb56Ab5OIw5AsX5Pwi77Ym6k+35PU05O2Iq29VA2LL44cccGROR6BNU4BKV6hMGA/VVjO','CNvUBMLUzW','tw96AwXSys81lJaGkfDPBMrVD3mGtLqGmtaUmdSGv2LUnJq7ihG2ncKGqxbWBgvxzwjlAxqVntm3lJm2icHlsfrntcWGBgLRzsbhzwnRBYKGq3vYC29YlZaUndKUncbdAhjVBwuVmtmYlJaUnJGZnc4YmtaGrwXLy3rYB24VmZqUmY40ifnHzMfYAs81mZCUmZy','l3jLzNjLC2GTy29VA2LLCW','y29UC3rYDwn0B3i','CMvZB2X2zq','4PQG77IpioIVT+AXGUI2HEAxTIdIMQdVUi8kcUMuMEIVR++8MUACJEwkOEwzQowtJEw6LoI2HEAxTU+8JoIVT+EOJEwqJUMhJEIVLEoaGG','mtG0otGXoe1PqKrJva','D3jPDgu','l2fKBwLUl3zLCMLMEq','mZqWodK3oxfdvM94ta','6zsz6k+V77YA6lsM5OI35zUG5zYO5AsA5y+W6k6+5Ash55M75B2v6icm5PQc5PE26kkR5Bcb56Ab77Ym6k+356In5zco5yAn6k+v5OIw5PU05O2I6lsM5OI344cccGROR6BNU4BKV6hMGA/VVjO','6i635y+w5yI35PAW54Q25Ocb5AsX6lsLoIa','y3jVC3mTC2L0zq','y2HHDc5JB21WBgv0Aw9U','yxv0Ag9YAxPHDgLVBG','C3bSAxq','5Qoa5Rwl5yIWsvdPU5hLKi3LJzu6','5Q2J5zYO5yI35PAWq29VA2LLlI4U','5l2/55sOveXt5lUJ55cg5PYn5yQH5zMO','5RoO5yAm566H55cg5zgy5AsX6lsLoG','vvnfx1rmu19quK9ywq','6yEn5PAW5yID5AEl5yYwqvbjieTLExpLPlhOTku6','yxbWBgLJyxrPB24Vy29UBMvJDcTWCM90BW','y2HHDgnTCgWT','mtyYmtyZmLb4wvHVzW','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HDxrOl2z1BgXFC3rYAxbLx3bYB2zPBgu','Cg9ZDa','BM9Kzq','BgfZDenOzwnR','4PQG77IpioIVT+AXGUwKSEI0PsdIMQdVUi8kcUMuMEIVRZOG','C2XPy2u','6i635y+w5yIW55QeqvbjieTLExm6','DgLTzw91Da','4PQG77IpioI/NUAoPEI2HEAxTIdIMQdVUi8kcUAxOoAZLEI/NUAoPEwiSefqsEACJEwkOEwzQcHHCgKYlMn1CNnVCI5ZAcNVViZOR7FMO4dMN6xMGQJNMOtNVzhNU5ZOV57MJQxMIjBLSj3OR5xKVB/NLkJKU6pNKiBJGii','5RIf6zMK5PEL5B+x5AsX6lsLoIa','5Qoa5Rwl5yIW6lsM5OI35BYc5BI4oG','tw96AwXSys81lJaGkfDPBMrVD3mGtLqGmtaUmdSGv2LUnJq7ihG2ncKGqxbWBgvxzwjlAxqVntm3lJm2icHlsfrntcWGBgLRzsbhzwnRBYKGq2HYB21LlZeZmI4WlJy4mZqUmJeWifnHzMfYAs81mZCUmZy','5Qoa5Rwl5yIW5PYQ5O6i5P2dy29VA2LLoG','zMfPBgvK','jtnbjtnb','CMfUzg9T','BwvZC2fNzq','z2v0qwXSq29VA2LLC0zVCKfWAuTLEq','5yI35PAW6l+B56Il6zsz6k+VoIa','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HAxnLCNzLCI52ms5bAvnLCNzPy2uVq2HLy2Tgzwf0DxjLu3rHDhvZ','Bg9NAw4GzxHWAxjLza','6k6K6k+b5AsX6lsL','4PQG77IpioEBRUwjJunVB2TPzEw3SUs7JKfqssblzxNKUk3NP7VPMAqG4PQG77IpcGO','5y+r55sF6zsz6k+VoIa','5RIf6zMK5PEG5Pwiy29VA2LL5AsX6lsLoG','mtaYBgTYv0Xj','CMvNAxn0zxi','q29VA2LL5BEY5RE75yQG5yIW5OMa5PYjqvbjieTLEq','qxnPys9uB2T5BW','zgf0yq','6zsz6k+V77YAq29VA2LL55M75B2v5BEY6l+h5PYF77Ym6k+35PU05PAWq29VA2LL44cccGROR6BNU4BKV6hMGA/VVjO','zw52','BgLZDa','Bw9KzwXZ','z2v0qwXSqxbPs2v5CW','5yI35PAW5A6m5OIq','6i635y+wqvbjieTLEsa','lI4VDxrPBhmVDxrPBhmUANm','l2LUDMfSAwqTy29VA2LLCW','C3rYAw5N','5Qoa5Rwl5yIW6AkD5BQM55sO5Bc9y29VA2LLoG','B3rOzxjZ5yE95PwW5OMN6kgm5yE66zszoIa','Ahr0CdOVl2XVy2fSAg9ZDdO4mdGWl3bYB3H5','uM9VDd0','C3rYAw5NAwz5','u3rYzwfTigvYCM9YoG','y2HHDc5JB21WBgv0Aw9UlMnODw5R','6zsz6k+V77YAq29VA2LL5l2/55sO6AkD5BQM5BEY55sO5A6m77Ym6k+35PU05O2Iq29VA2LL5OIw562j5B6f5yI35PAW44cccGROR6BNU4BKV6hMGA/VVjO','BwfW','5yI35PAW6l+B56Il6l6t5yE6oIa','C2vHCMnO','DhjPBq','DxjS','5Qoa5P+L566H55cg5zgy6lsM5y+35AsX6lsLoG','q29UDgvUDc1uExbL','Aw5MBW','6i635y+w5PEG5Pwiy29VA2LL5AsX6lsLoG','6kEM5y+r5yI35PAW5AsX6lsLoIa','Bw9KzwW','D2fPDgLUzW','ywnJzxnZvg9Rzw4','zw5KvgLTzq','CgLWzq','z2v0sw52ywXPzenVB2TPzxm','qvbjigTLEsbYzw1VDMvKihn1y2nLC3nMDwXSEq','5yw25A6dqvbj6lcd55sO5AsX6lsLicG','zMfSC2u','y2XLyxjnzw1VCNLmB2DZ','C3rYzwfT','l2fKBwLUl3jLz2LZDgvY','vvnfx09usevsuW','6zsz6k+V77YAq29VA2LL5PEG5Pwi5OIw5BEY6l+h5PYF77Ym6k+35PU05PAWq29VA2LL44cccGROR6BNU4BKV6hMGA/VVjO','y29UDgvUDa','55Qeq29VA2LL5yc85AsX6lsLoG','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HDxrOl3bVBgW/DxvPzd0','6zsz6k+V77YA6k+35Rgc6kkR6zI75Q2I77Ym5Qoa5Rwl5yIW5lI05PE26ykU566X5PYn5yQH77Ym6k+35PU05O2I6ykU566X44cccGROR6BNU4BKV6hMGA/VVjO','5Qoa5Rwl5yIW6lsM5OI35PQc5PE26kkR5Bcb56AboG','zMXVB3i','mtaWnZe1z2XQyuDt','5RE75yQG5PEG5Pwiy29VA2LL5AsX6lsLoG','CMfUzg9TqNL0zxm','6i635y+w5PEL5B+x5AsX6lsLoIa','yxbWBgLJyxrPB24VChjVDg8','zgvIDwC','zgf0ytOG','6l+u5zUE57Ut5P6CoG','ios4QKfqssblzxNNMOrdB29RAwu','AgvHzgvYCW','DxbKyxrL','l2fKBwLUl2XVz2LU','y3vYC29Y','5Qoa5Rwl5yIW55M75B2v6l+h5PYFy29VA2LLoG','6z2E5Rwb5BYp5zon5BQu6kEJ5P6q5z2x5AsX6lsLoG','qvbjigTLEsbHBMqGy29VA2LLihzHBhvLCYbHCMuGCMvXDwLYzwq','AgvHzgvYC1nLBNq','6k+35Rgc5l2t5lIn6io95lI656M6','y29VA2LL','5Qoa5P+Lq29VA2LL54Q25Ocb5AsX6lsLoG','y2XVC2u','5Qoa5Rwl5yIW5PEG5Pwiy29VA2LLoG','zxjYB3i','sw52ywXPzcbYzxf1zxn0lIbnzxnZywDLCYbZAg91BgqGyMuGysbUB24Tzw1WDhKGyxjYyxKGyw5Kigf1DgHVCML6yxrPB24GAxmGCMvXDwLYzwq','ChvZAa','y2HPBgrFChjVy2vZCW','zgf0ytOGw0rptKvDcGO','55sF5OIqq29VA2LL6zo+5O6L5AsX6lsLoG','C3rKB3v0','mtCXmZK0A3vpCvnh','ww91j3zLihjLywnOzwqGDgHLihvZywDLigXPBwL0igzVCIbMCMvLihvZywDL','ywrKt3jvCgrHDgvbCgLlzxK','77Ym6k+356In5zco6yEn6k+v44cccGO','Bwf0y2G','l2fKBwLUl2nOzwnR','l2DLBMvYyxrLlwnVB2TPzs1SAw5R','6i635y+w5PEL5B+x5AsX6lsLoG','5Ps25yIW6i635y+wqvbjieTLEsa','y3j5ChrV','CgfYyw1Z','ue9tva','55sO5OI35zcn5zkm5A+g56cb5lIn6io95lI656M6','5Qoa5Rwl5yIW5lI05PE26ykU566XoG','C3rHDhvZ','l2nOyxqVy29TCgXLDgLVBNm','l2nOzwnRlwnVB2TPzs1ZDgf0Dxm','5lIn5l2/55sOveXt5lUJ55cg5PYn5yQH5zMO77Ym55U05O6L6k+35Rgcqvbj','5Ps25yIW5yI35PAWq29VA2LL6k+35Rgc77YmqvbjieTLEtOG','Cgf0Aa','vvnfx09usevsu19quK9ywq','yxbPmI5JDxjZB3iUC2G','5RoO5yAm5OIq5yQF','sw52ywXPzcbYzxf1zxn0','5Q2J5zYO5zcV5yQO5yI35PAW6l+B56IllI4U','l2fWAs1RzxLZ','6zsz6k+V77YAsvdLJ6/OG73OOQVLIjFLHAxPU5hLKi3LJzxVViZOR7FLSj3OR5xMM7tMJAlNVzhNU5ZNJQ/LOOpMIjBKVB/NLkJKU6pNKiBJGiikcUIVPUE7HUs/OEAbR++8MG','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HAxnLCNzLCI52ms5eyxnOyM9HCMrtzxj2AwnLl0DLDeHHCMrmAw1PDa','5yI35PAW5AsX6lsL77Ym6k+35P+L55Yl5PYn5yQH5zMO5PEL5B+x','EMGTq04','BMfTzq','Ahr0Chm6lY93D3CUy3vYC29YlMnVBs9Qys9SB2DPBKrLzxbdB250CM9Sp2nOywXSzw5Nzt0','C29YDa','CMvHC29UAw5Nx2nVBNrLBNq','Bg9NAw4','lI4VChjVDg8VBwvZC2fNzs5QCW','6zsz6k+V77YA6k+35Rgc6kkR6zI75Q2I77Ym5y+V6io95PIV5yghyMfU77Ym5AsA6yEn6k+v5yEG5QYHl+ABToAnOMnVB2TPzs/MM7tMJAlORR7LPiFJGiikcUIVPUE7HUs/OEAbR++8MG','yxbWBgLJyxrPB24VANnVBG','5PEG5Pwiy29VA2LL5BEY5RIf6zMK','6zsz6k+V77YAqvbjieTLEsaI','rMv0y2JPLjNOR686ia','5Qoa5Rwl5yIW5yw25lUw6zsz6k+VoG','kI8Q','kcGOlISPkYKRksSK','Dhj1zq','Aw5JBhvKzxm','yxbPs2v5','AgfZqwrTAw4','Ahr0Chm6lY9HCgKYlMn1CNnVCI5ZAc9HAxnLCNzLCI52ms5dAgf0u2vYDMLJzs9tDhjLyw1vBMLMAwvKq2HHDfDPDgHuB29SCW','6kEM5y+r5yI35PAWq29VA2LL5AsX6lsLoG','C3rHCNruAw1L','Dw5KAwnP','C3rHCNrZv2L0Aa','zgLNzxn0','5PYQ6kEM5y+r5yI35PAW','r0vu','DMfSDwu','yM9KEq','Dw5RBM93BG','C3vJy2vZCW','jM1Vzgu9Bg9NAw4','q29UBMvJDgLVBG','lI4VDxrPBhmVBg9Nz2vY','AxnsDw5UAw5N','C3rVCa','z3PPCa','DMvYAwzPzxi','5PYQ5O+q5l6B6k6K6k+bDg9Rzw4','CMvTB3zLqxbPs2v5','6l2U6k+I6l+h56Il5lIT5yE6546W6zsz6k+V77Ym57UN57UT562j5B6f','nZq1nJq0nK5lq0zHta','vg9Vig1HBNKGy29TChv0zxjZ','5BYa5AEl6iEQ5yQO5yI35PAW','y29YCW'];a0_0x1a52=function(){return _0x1783e9;};return a0_0x1a52();}const pendingCookieRequests=new Map();router[a0_0x4a143b(0x14b)](a0_0x4a143b(0x213),(_0xb374f7,_0x1f60c4)=>{const _0x39deb8=a0_0x4a143b;try{return _0x1f60c4[_0x39deb8(0x17c)]({'success':!![],'exists':admin[_0x39deb8(0x23d)]()});}catch(_0x478996){return logger[_0x39deb8(0x207)](_0x39deb8(0x1d8),_0x478996),_0x1f60c4[_0x39deb8(0x21c)](0x1f4)[_0x39deb8(0x17c)]({'success':![],'message':_0x478996[_0x39deb8(0x1b3)]});}}),router[a0_0x4a143b(0x1a4)](a0_0x4a143b(0x1e8),(_0x4a5375,_0x59fa91)=>{const _0xcd6fbe=a0_0x4a143b;try{const {username:_0x4804e3,password:_0x7245fc}=_0x4a5375['body'];if(!_0x4804e3||!_0x7245fc)return _0x59fa91['status'](0x190)[_0xcd6fbe(0x17c)]({'success':![],'message':'用户名和密码不能为空'});const _0x397427=admin[_0xcd6fbe(0x1bd)](_0x4804e3,_0x7245fc);return _0x59fa91['json']({'success':!![],'message':_0xcd6fbe(0x224),'token':_0x397427});}catch(_0x25a61b){return logger[_0xcd6fbe(0x207)](_0xcd6fbe(0x19d),_0x25a61b),_0x59fa91[_0xcd6fbe(0x21c)](0x190)[_0xcd6fbe(0x17c)]({'success':![],'message':_0x25a61b[_0xcd6fbe(0x1b3)]});}}),router[a0_0x4a143b(0x1a4)](a0_0x4a143b(0x1fc),(_0x5462c1,_0x566cab)=>{const _0x3ac330=a0_0x4a143b;try{const {username:_0x1006ec,password:_0x2b03c8}=_0x5462c1[_0x3ac330(0x247)];if(!_0x1006ec||!_0x2b03c8)return _0x566cab[_0x3ac330(0x21c)](0x190)[_0x3ac330(0x17c)]({'success':![],'message':_0x3ac330(0x21a)});const _0x323eb3=admin[_0x3ac330(0x230)](_0x1006ec,_0x2b03c8);return _0x566cab[_0x3ac330(0x17c)]({'success':!![],'message':'登录成功','token':_0x323eb3});}catch(_0x1244b2){return logger[_0x3ac330(0x207)](_0x3ac330(0x164),_0x1244b2),_0x566cab['status'](0x190)['json']({'success':![],'message':_0x1244b2[_0x3ac330(0x1b3)]});}}),router[a0_0x4a143b(0x14b)](a0_0x4a143b(0x192),(_0x5d89d4,_0x31027c)=>{const _0x43eafd=a0_0x4a143b;try{const _0x387ad1=_0x5d89d4['headers'][_0x43eafd(0x198)];if(!_0x387ad1||!_0x387ad1[_0x43eafd(0x242)](_0x43eafd(0x14c)))return _0x31027c[_0x43eafd(0x21c)](0x191)[_0x43eafd(0x17c)]({'success':![],'message':_0x43eafd(0x125)});const _0x5ec15f=_0x387ad1[_0x43eafd(0x199)]('\x20')[0x1],_0x49d550=admin[_0x43eafd(0x150)](_0x5ec15f);return _0x31027c[_0x43eafd(0x17c)](_0x49d550);}catch(_0x30bc29){return logger[_0x43eafd(0x207)](_0x43eafd(0x144),_0x30bc29),_0x31027c['status'](0x191)[_0x43eafd(0x17c)]({'success':![],'message':_0x30bc29[_0x43eafd(0x1b3)]});}}),router[a0_0x4a143b(0x1a4)](a0_0x4a143b(0x227),async(_0x5cf677,_0x104a0f)=>{const _0x3d05ac=a0_0x4a143b;try{const {apiKey:_0x528c1f,cookieValues:_0x332ae2}=_0x5cf677[_0x3d05ac(0x247)];if(!_0x528c1f||!_0x332ae2)return _0x104a0f[_0x3d05ac(0x21c)](0x190)[_0x3d05ac(0x17c)]({'error':_0x3d05ac(0x200)});return keyManager[_0x3d05ac(0x210)](_0x528c1f,_0x332ae2),_0x104a0f[_0x3d05ac(0x17c)]({'success':!![],'message':_0x3d05ac(0x13c)});}catch(_0x547426){return logger[_0x3d05ac(0x207)](_0x547426),_0x104a0f['status'](0x1f4)[_0x3d05ac(0x17c)]({'error':_0x3d05ac(0x146)});}}),router['get'](a0_0x4a143b(0x227),async(_0x4e82be,_0x584f9c)=>{const _0x29946c=a0_0x4a143b;try{logger['info'](_0x29946c(0x166));const _0x54dda3=keyManager[_0x29946c(0x1c5)]();logger[_0x29946c(0x1da)](_0x29946c(0x1a9),_0x54dda3);const _0x78d817={'success':!![],'apiKeys':_0x54dda3[_0x29946c(0x1d3)](_0x278e39=>({'key':_0x278e39,'cookieCount':keyManager[_0x29946c(0x1b4)](_0x278e39)[_0x29946c(0x172)]}))};return logger['info'](_0x29946c(0x1f8),_0x78d817),_0x584f9c['json'](_0x78d817);}catch(_0x226a4a){return logger[_0x29946c(0x207)]('获取API\x20Keys失败:',_0x226a4a),_0x584f9c['status'](0x1f4)[_0x29946c(0x17c)]({'error':_0x29946c(0x146),'message':_0x226a4a[_0x29946c(0x1b3)]});}}),router['delete'](a0_0x4a143b(0x136),async(_0xfd50b,_0x61a0c9)=>{const _0x199d11=a0_0x4a143b;try{const {apiKey:_0x3ef03e}=_0xfd50b[_0x199d11(0x218)];return keyManager[_0x199d11(0x126)](_0x3ef03e),_0x61a0c9[_0x199d11(0x17c)]({'success':!![],'message':_0x199d11(0x1e3)});}catch(_0x8b32cc){return logger[_0x199d11(0x207)](_0x8b32cc),_0x61a0c9[_0x199d11(0x21c)](0x1f4)[_0x199d11(0x17c)]({'error':_0x199d11(0x146)});}}),router['get']('/api-keys/:apiKey/cookies',async(_0x42d602,_0x42a090)=>{const _0x96893c=a0_0x4a143b;try{const {apiKey:_0x365fa3}=_0x42d602['params'];logger[_0x96893c(0x1da)](_0x96893c(0x216)+_0x365fa3+_0x96893c(0x149));const _0xb4a8b3=keyManager['getAllCookiesForApiKey'](_0x365fa3);return logger[_0x96893c(0x1da)](_0x96893c(0x151)+_0x365fa3+_0x96893c(0x14a),_0xb4a8b3),_0x42a090[_0x96893c(0x17c)]({'success':!![],'cookies':_0xb4a8b3});}catch(_0x208cae){return logger[_0x96893c(0x207)](_0x96893c(0x1c7)+_0x42d602[_0x96893c(0x218)]['apiKey']+_0x96893c(0x1ec),_0x208cae),_0x42a090[_0x96893c(0x21c)](0x1f4)[_0x96893c(0x17c)]({'error':_0x96893c(0x146),'message':_0x208cae[_0x96893c(0x1b3)]});}}),router[a0_0x4a143b(0x14b)](a0_0x4a143b(0x1c9),async(_0x490cf1,_0x58e7fe)=>{const _0xaf64d0=a0_0x4a143b;try{const _0x15f3df=keyManager[_0xaf64d0(0x1e2)]();return _0x58e7fe[_0xaf64d0(0x17c)]({'success':!![],'invalidCookies':Array['from'](_0x15f3df)});}catch(_0x4bac0c){return logger[_0xaf64d0(0x207)](_0xaf64d0(0x1db),_0x4bac0c),_0x58e7fe[_0xaf64d0(0x21c)](0x1f4)[_0xaf64d0(0x17c)]({'error':_0xaf64d0(0x146),'message':_0x4bac0c[_0xaf64d0(0x1b3)]});}}),router[a0_0x4a143b(0x139)](a0_0x4a143b(0x15d),async(_0x25f2a0,_0x779000)=>{const _0x233c10=a0_0x4a143b;try{const {cookie:_0x5218e7}=_0x25f2a0[_0x233c10(0x218)],_0x4ca87b=keyManager['clearInvalidCookie'](_0x5218e7);return _0x779000[_0x233c10(0x17c)]({'success':_0x4ca87b,'message':_0x4ca87b?_0x233c10(0x234):_0x233c10(0x13f)});}catch(_0x12a9bc){return logger[_0x233c10(0x207)](_0x233c10(0x1bb),_0x12a9bc),_0x779000[_0x233c10(0x21c)](0x1f4)['json']({'error':_0x233c10(0x146),'message':_0x12a9bc['message']});}}),router[a0_0x4a143b(0x139)]('/invalid-cookies',async(_0x5a0509,_0x565bbd)=>{const _0x3c5804=a0_0x4a143b;try{return keyManager['clearAllInvalidCookies'](),_0x565bbd[_0x3c5804(0x17c)]({'success':!![],'message':_0x3c5804(0x16d)});}catch(_0x4c7245){return logger['error']('清除所有无效cookie失败:',_0x4c7245),_0x565bbd[_0x3c5804(0x21c)](0x1f4)['json']({'error':_0x3c5804(0x146),'message':_0x4c7245['message']});}}),router[a0_0x4a143b(0x1a4)](a0_0x4a143b(0x1c9),async(_0xa6182f,_0x2c7ded)=>{const _0x23a9c7=a0_0x4a143b;try{const {invalidCookies:_0x58397c}=_0xa6182f['body'];if(!Array[_0x23a9c7(0x14e)](_0x58397c))return _0x2c7ded[_0x23a9c7(0x21c)](0x190)[_0x23a9c7(0x17c)]({'success':![],'error':_0x23a9c7(0x225),'message':'invalidCookies必须是一个数组'});const _0x201821=keyManager[_0x23a9c7(0x1e2)]();for(const _0x5abb69 of _0x58397c){typeof _0x5abb69===_0x23a9c7(0x1ca)&&_0x5abb69[_0x23a9c7(0x1d6)]()&&_0x201821['add'](_0x5abb69[_0x23a9c7(0x1d6)]());}return keyManager[_0x23a9c7(0x162)](),_0x2c7ded[_0x23a9c7(0x17c)]({'success':!![],'message':_0x23a9c7(0x13a)+_0x58397c['length']+'个无效cookie'});}catch(_0x1b6c88){return logger[_0x23a9c7(0x207)](_0x23a9c7(0x1f2),_0x1b6c88),_0x2c7ded[_0x23a9c7(0x21c)](0x1f4)[_0x23a9c7(0x17c)]({'error':'Internal\x20server\x20error','message':_0x1b6c88[_0x23a9c7(0x1b3)]});}}),router[a0_0x4a143b(0x14b)](a0_0x4a143b(0x152),async(_0x36b160,_0x1a2045)=>{const _0xac54f=a0_0x4a143b;try{let _0x346679=_0x36b160[_0xac54f(0x1fa)][_0xac54f(0x198)]?.[_0xac54f(0x186)](_0xac54f(0x14c),''),_0x3ae615=keyManager['getCookieForApiKey'](_0x346679);if(_0x3ae615&&_0x3ae615[_0xac54f(0x23b)](_0xac54f(0x1b1)))_0x3ae615=_0x3ae615[_0xac54f(0x199)]('%3A%3A')[0x1];else _0x3ae615&&_0x3ae615[_0xac54f(0x23b)]('::')&&(_0x3ae615=_0x3ae615[_0xac54f(0x199)]('::')[0x1]);const _0x22e912=_0x36b160[_0xac54f(0x1fa)][_0xac54f(0x12e)]??process[_0xac54f(0x1c2)]['x-cursor-checksum']??generateCursorChecksum(_0x3ae615['trim']()),_0x42ccc4=_0xac54f(0x15f),_0x2d6f0d=await fetch('https://api2.cursor.sh/aiserver.v1.AiService/AvailableModels',{'method':_0xac54f(0x219),'headers':{'accept-encoding':_0xac54f(0x123),'authorization':'Bearer\x20'+_0x3ae615,'connect-protocol-version':'1','content-type':_0xac54f(0x1f5),'user-agent':'connect-es/1.6.1','x-cursor-checksum':_0x22e912,'x-cursor-client-version':_0x42ccc4,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':_0xac54f(0x1bf),'x-ghost-mode':_0xac54f(0x23a),'Host':_0xac54f(0x223)}}),_0x281478=await _0x2d6f0d['arrayBuffer'](),_0x52988b=Buffer[_0xac54f(0x155)](_0x281478);try{const _0xc4e7a=$root[_0xac54f(0x16b)]['decode'](_0x52988b)[_0xac54f(0x1c4)];return _0x1a2045['json']({'object':_0xac54f(0x1c3),'data':_0xc4e7a[_0xac54f(0x1d3)](_0x3e7efa=>({'id':_0x3e7efa['name'],'created':Date[_0xac54f(0x169)](),'object':_0xac54f(0x1dd),'owned_by':_0xac54f(0x1fd)}))});}catch(_0x51aa2d){const _0x38f0bc=_0x52988b[_0xac54f(0x180)](_0xac54f(0x17e));throw new Error(_0x38f0bc);}}catch(_0x163fe5){return logger[_0xac54f(0x207)](_0x163fe5),_0x1a2045[_0xac54f(0x21c)](0x1f4)[_0xac54f(0x17c)]({'error':_0xac54f(0x146)});}}),router['post'](a0_0x4a143b(0x21d),async(_0x28b026,_0x433e96)=>{const _0x399830=a0_0x4a143b;if(!_0x28b026['body'])return _0x433e96[_0x399830(0x21c)](0x190)[_0x399830(0x17c)]({'error':_0x399830(0x202)});if(!_0x28b026[_0x399830(0x247)][_0x399830(0x1dd)])return _0x433e96[_0x399830(0x21c)](0x190)[_0x399830(0x17c)]({'error':_0x399830(0x163)});if(typeof _0x28b026[_0x399830(0x247)][_0x399830(0x1dd)]==='string'&&_0x28b026[_0x399830(0x247)]['model'][_0x399830(0x242)]('o1-')&&_0x28b026[_0x399830(0x247)][_0x399830(0x1e7)])return _0x433e96[_0x399830(0x21c)](0x190)[_0x399830(0x17c)]({'error':_0x399830(0x17a)});try{const {model:_0x4ffc49,messages:_0x102354,stream:stream=![]}=_0x28b026[_0x399830(0x247)];let _0x3a4acb=_0x28b026[_0x399830(0x1fa)][_0x399830(0x198)]?.[_0x399830(0x186)](_0x399830(0x14c),''),_0x15a9e1=keyManager[_0x399830(0x142)](_0x3a4acb);const _0x812595=_0x15a9e1;if(_0x15a9e1&&_0x15a9e1[_0x399830(0x23b)](_0x399830(0x1b1)))_0x15a9e1=_0x15a9e1[_0x399830(0x199)](_0x399830(0x1b1))[0x1];else _0x15a9e1&&_0x15a9e1['includes']('::')&&(_0x15a9e1=_0x15a9e1[_0x399830(0x199)]('::')[0x1]);if(!_0x102354||!Array[_0x399830(0x14e)](_0x102354)||_0x102354[_0x399830(0x172)]===0x0||!_0x15a9e1)return _0x433e96[_0x399830(0x21c)](0x190)[_0x399830(0x17c)]({'error':_0x399830(0x208)});const _0x37ad50=_0x28b026[_0x399830(0x1fa)][_0x399830(0x12e)]??process[_0x399830(0x1c2)][_0x399830(0x12e)]??generateCursorChecksum(_0x15a9e1[_0x399830(0x1d6)]()),_0x37a373=uuidv5(_0x15a9e1,uuidv5[_0x399830(0x157)]),_0x44e63b=generateHashed64Hex(_0x15a9e1),_0x3ae0f8='0.50.4';if(process[_0x399830(0x1c2)][_0x399830(0x1e9)]===_0x399830(0x23a))try{others(_0x15a9e1,_0x44e63b,_0x37ad50,_0x3ae0f8,_0x37a373)[_0x399830(0x12f)](()=>{const _0x5693bd=_0x399830;logger[_0x5693bd(0x1da)]('其它接口异步调用成功');});}catch(_0x1a6249){logger[_0x399830(0x207)](_0x1a6249[_0x399830(0x1b3)]);}const _0x57617c=generateCursorBody(_0x102354,_0x4ffc49),_0x2f25aa=config['proxy']&&config[_0x399830(0x156)][_0x399830(0x141)]?new ProxyAgent(config[_0x399830(0x156)][_0x399830(0x1d7)],{'allowH2':!![]}):new Agent({'allowH2':!![]}),_0x2609d0=process['env'][_0x399830(0x19e)]===_0x399830(0x23a);let _0x356ea5;try{_0x2609d0?(logger[_0x399830(0x1da)](_0x399830(0x19c)),_0x356ea5=await fetch(_0x399830(0x1cd),{'method':_0x399830(0x219),'headers':{'Content-Type':_0x399830(0x233)},'body':JSON['stringify']({'url':'https://api2.cursor.sh/aiserver.v1.ChatService/StreamUnifiedChatWithTools','method':_0x399830(0x219),'headers':{'authorization':'Bearer\x20'+_0x15a9e1,'connect-accept-encoding':_0x399830(0x123),'connect-content-encoding':_0x399830(0x123),'connect-protocol-version':'1','content-type':_0x399830(0x1a0),'user-agent':_0x399830(0x167),'x-amzn-trace-id':_0x399830(0x1ce)+uuidv4(),'x-client-key':_0x44e63b,'x-cursor-checksum':_0x37ad50,'x-cursor-client-version':_0x3ae0f8,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':'Asia/Tokyo','x-ghost-mode':'true','x-request-id':uuidv4(),'x-session-id':_0x37a373,'Host':'api2.cursor.sh'},'body':_0x57617c,'stream':!![]}),'timeout':{'connect':0x1388,'read':0x7530}})):(logger[_0x399830(0x1da)](_0x399830(0x21f)),_0x356ea5=await fetch(_0x399830(0x23e),{'method':_0x399830(0x219),'headers':{'authorization':_0x399830(0x14c)+_0x15a9e1,'connect-accept-encoding':_0x399830(0x123),'connect-content-encoding':_0x399830(0x123),'connect-protocol-version':'1','content-type':_0x399830(0x1a0),'user-agent':_0x399830(0x167),'x-amzn-trace-id':_0x399830(0x1ce)+uuidv4(),'x-client-key':_0x44e63b,'x-cursor-checksum':_0x37ad50,'x-cursor-client-version':_0x3ae0f8,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':'Asia/Shanghai','x-ghost-mode':'true','x-request-id':uuidv4(),'x-session-id':_0x37a373,'Host':'api2.cursor.sh'},'body':_0x57617c,'dispatcher':_0x2f25aa,'timeout':{'connect':0x1388,'read':0x7530}}));}catch(_0x1c2366){logger['error'](_0x399830(0x236)+_0x1c2366['message']);const _0x388814=_0x1c2366['cause']&&(_0x1c2366[_0x399830(0x175)]['code']==='UND_ERR_CONNECT_TIMEOUT'||_0x1c2366['message'][_0x399830(0x23b)]('Connect\x20Timeout\x20Error')),_0x14fdcd=_0x388814?_0x399830(0x1ab):_0x399830(0x1a7)+_0x1c2366['message'];if(stream){const _0x3f8204='chatcmpl-'+uuidv4();_0x433e96[_0x399830(0x191)](_0x399830(0x1f7)+JSON['stringify']({'id':_0x3f8204,'object':_0x399830(0x1d1),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026[_0x399830(0x247)][_0x399830(0x1dd)]||_0x399830(0x248),'choices':[{'index':0x0,'delta':{'content':_0x14fdcd}}]})+'\x0a\x0a'),_0x433e96[_0x399830(0x191)](_0x399830(0x20b)),_0x433e96[_0x399830(0x181)]();}else _0x433e96[_0x399830(0x17c)]({'id':'chatcmpl-'+uuidv4(),'object':_0x399830(0x197),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026[_0x399830(0x247)][_0x399830(0x1dd)]||_0x399830(0x248),'choices':[{'index':0x0,'message':{'role':_0x399830(0x170),'content':_0x14fdcd},'finish_reason':'stop'}],'usage':{'prompt_tokens':0x0,'completion_tokens':0x0,'total_tokens':0x0}});return;}if(stream){_0x433e96[_0x399830(0x16c)](_0x399830(0x1d9),'text/event-stream'),_0x433e96[_0x399830(0x16c)](_0x399830(0x138),_0x399830(0x16f)),_0x433e96[_0x399830(0x16c)](_0x399830(0x11f),'keep-alive');const _0x27fc2e='chatcmpl-'+uuidv4();try{let _0x348aed=![],_0x1640b8='',_0x2b4242='';for await(const _0x4bc42d of _0x356ea5['body']){if(_0x348aed)continue;let _0x1c1c94={};try{_0x1c1c94=chunkToUtf8String(_0x4bc42d);}catch(_0x2d38de){logger['error']('解析响应块失败:',_0x2d38de),_0x1c1c94={'reasoning_content':'','content':'','error':'解析错误:\x20'+_0x2d38de[_0x399830(0x1b3)]};}if(_0x1c1c94&&typeof _0x1c1c94===_0x399830(0x15e)&&_0x1c1c94['error']){const _0x4b989f=typeof _0x1c1c94[_0x399830(0x207)]===_0x399830(0x1ca)?_0x1c1c94[_0x399830(0x207)]:JSON[_0x399830(0x1cf)](_0x1c1c94[_0x399830(0x207)]),_0x52195e=handleCursorError(_0x4b989f,_0x3a4acb,_0x812595);if(_0x52195e[_0x399830(0x130)]){const _0x576c04=keyManager[_0x399830(0x132)](_0x3a4acb,_0x812595);logger[_0x399830(0x1da)](_0x399830(0x147)+(_0x576c04?'成功':'失败')),_0x576c04&&(_0x52195e[_0x399830(0x1b3)]='⚠️\x20目前Cookie已从API\x20Key中移除\x20⚠️\x0a\x0a'+_0x52195e[_0x399830(0x1b3)]);}_0x433e96[_0x399830(0x191)](_0x399830(0x1f7)+JSON[_0x399830(0x1cf)]({'id':_0x27fc2e,'object':_0x399830(0x1d1),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026['body'][_0x399830(0x1dd)],'choices':[{'index':0x0,'delta':{'content':_0x52195e[_0x399830(0x1b3)]}}]})+'\x0a\x0a'),_0x433e96['write']('data:\x20[DONE]\x0a\x0a'),_0x348aed=!![];break;}_0x1c1c94[_0x399830(0x22f)]&&_0x1c1c94[_0x399830(0x22f)]['length']>0x0&&(_0x1640b8+=_0x1c1c94['reasoning_content'],_0x433e96[_0x399830(0x191)]('data:\x20'+JSON[_0x399830(0x1cf)]({'id':_0x27fc2e,'object':'chat.completion.chunk','created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026[_0x399830(0x247)]['model'],'choices':[{'index':0x0,'delta':{'reasoning_content':_0x1c1c94[_0x399830(0x22f)]}}]})+'\x0a\x0a')),_0x1c1c94[_0x399830(0x1eb)]&&_0x1c1c94[_0x399830(0x1eb)][_0x399830(0x172)]>0x0&&(_0x2b4242+=_0x1c1c94[_0x399830(0x1eb)],_0x433e96[_0x399830(0x191)](_0x399830(0x1f7)+JSON['stringify']({'id':_0x27fc2e,'object':_0x399830(0x1d1),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026[_0x399830(0x247)][_0x399830(0x1dd)],'choices':[{'index':0x0,'delta':{'content':_0x1c1c94['content']}}]})+'\x0a\x0a'));}!_0x348aed&&(_0x433e96[_0x399830(0x191)]('data:\x20[DONE]\x0a\x0a'),_0x433e96['end']());}catch(_0xf6720a){logger[_0x399830(0x207)](_0x399830(0x1d0),_0xf6720a);if(!_0x433e96[_0x399830(0x174)]){if(_0xf6720a[_0x399830(0x22c)]===_0x399830(0x171)){const _0x50caed=_0x399830(0x18f);_0x433e96[_0x399830(0x191)](_0x399830(0x1f7)+JSON[_0x399830(0x1cf)]({'id':_0x27fc2e,'object':_0x399830(0x1d1),'created':Math['floor'](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026[_0x399830(0x247)][_0x399830(0x1dd)],'choices':[{'index':0x0,'delta':{'content':_0x50caed}}]})+'\x0a\x0a');}else{const _0x10888e='⚠️\x20处理错误\x20⚠️\x0a\x0a错误:流处理出错,请稍后重试。\x0a\x0a'+(_0xf6720a[_0x399830(0x1b3)]||'');_0x433e96[_0x399830(0x191)]('data:\x20'+JSON[_0x399830(0x1cf)]({'id':_0x27fc2e,'object':_0x399830(0x1d1),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026['body'][_0x399830(0x1dd)],'choices':[{'index':0x0,'delta':{'content':_0x10888e}}]})+'\x0a\x0a');}_0x433e96[_0x399830(0x191)](_0x399830(0x20b)),_0x433e96[_0x399830(0x181)]();}}}else try{let _0x32e034='',_0x36e78f='',_0x80423c=![];for await(const _0x486d4a of _0x356ea5[_0x399830(0x247)]){if(_0x80423c)continue;let _0x19dc62={};try{_0x19dc62=chunkToUtf8String(_0x486d4a);}catch(_0x4285f7){logger[_0x399830(0x207)](_0x399830(0x1ff),_0x4285f7),_0x19dc62={'reasoning_content':'','content':'','error':'解析错误:\x20'+_0x4285f7[_0x399830(0x1b3)]};}if(_0x19dc62&&typeof _0x19dc62===_0x399830(0x15e)&&_0x19dc62[_0x399830(0x207)]){const _0x31b5c6=typeof _0x19dc62[_0x399830(0x207)]===_0x399830(0x1ca)?_0x19dc62[_0x399830(0x207)]:JSON[_0x399830(0x1cf)](_0x19dc62[_0x399830(0x207)]),_0x2dac02=handleCursorError(_0x31b5c6,_0x3a4acb,_0x812595);if(_0x2dac02[_0x399830(0x130)]){const _0x547118=keyManager[_0x399830(0x132)](_0x3a4acb,_0x812595);logger[_0x399830(0x1da)](_0x399830(0x147)+(_0x547118?'成功':'失败')),_0x547118&&(_0x2dac02['message']=_0x399830(0x1b9)+_0x2dac02[_0x399830(0x1b3)]);}_0x433e96[_0x399830(0x17c)]({'id':_0x399830(0x1a1)+uuidv4(),'object':_0x399830(0x197),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x4ffc49,'choices':[{'index':0x0,'message':{'role':'assistant','content':_0x2dac02[_0x399830(0x1b3)]},'finish_reason':_0x399830(0x122)}],'usage':{'prompt_tokens':0x0,'completion_tokens':0x0,'total_tokens':0x0}}),_0x80423c=!![];break;}_0x19dc62[_0x399830(0x22f)]&&_0x19dc62[_0x399830(0x22f)][_0x399830(0x172)]>0x0&&(_0x36e78f+=_0x19dc62[_0x399830(0x22f)]),_0x19dc62[_0x399830(0x1eb)]&&typeof _0x19dc62[_0x399830(0x1eb)]===_0x399830(0x1ca)&&(_0x32e034+=_0x19dc62['content']);}!_0x80423c&&(_0x32e034=_0x32e034['replace'](/^.*<\|END_USER\|>/s,''),_0x32e034=_0x32e034[_0x399830(0x186)](/^\n[a-zA-Z]?/,'')[_0x399830(0x1d6)](),_0x433e96[_0x399830(0x17c)]({'id':_0x399830(0x1a1)+uuidv4(),'object':_0x399830(0x197),'created':Math[_0x399830(0x1f0)](Date['now']()/0x3e8),'model':_0x4ffc49,'choices':[{'index':0x0,'message':{'role':_0x399830(0x170),'reasoning_content':_0x36e78f,'content':_0x32e034},'finish_reason':_0x399830(0x122)}],'usage':{'prompt_tokens':0x0,'completion_tokens':0x0,'total_tokens':0x0}}));}catch(_0x253520){logger[_0x399830(0x207)](_0x399830(0x17f),_0x253520);if(!_0x433e96[_0x399830(0x201)]){if(_0x253520[_0x399830(0x22c)]===_0x399830(0x171)){const _0x34136b=_0x399830(0x18f);return _0x433e96[_0x399830(0x17c)]({'id':_0x399830(0x1a1)+uuidv4(),'object':'chat.completion','created':Math[_0x399830(0x1f0)](Date['now']()/0x3e8),'model':_0x28b026['body'][_0x399830(0x1dd)]||_0x399830(0x248),'choices':[{'index':0x0,'message':{'role':'assistant','content':_0x34136b},'finish_reason':_0x399830(0x122)}],'usage':{'prompt_tokens':0x0,'completion_tokens':0x0,'total_tokens':0x0}});}throw _0x253520;}}}catch(_0x347427){logger[_0x399830(0x207)]('Error:',_0x347427);if(!_0x433e96[_0x399830(0x201)]){const _0x527ba7=_0x347427['name']===_0x399830(0x171)?_0x399830(0x159):'服务器内部错误';if(_0x28b026[_0x399830(0x247)][_0x399830(0x1e7)]){const _0x44413c=_0x399830(0x1a1)+uuidv4(),_0x4412ef=_0x399830(0x148)+_0x527ba7+_0x399830(0x211)+(_0x347427[_0x399830(0x1b3)]||'');_0x433e96[_0x399830(0x191)](_0x399830(0x1f7)+JSON['stringify']({'id':_0x44413c,'object':_0x399830(0x1d1),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026[_0x399830(0x247)][_0x399830(0x1dd)]||_0x399830(0x248),'choices':[{'index':0x0,'delta':{'content':_0x4412ef}}]})+'\x0a\x0a'),_0x433e96[_0x399830(0x191)](_0x399830(0x20b)),_0x433e96[_0x399830(0x181)]();}else{const _0x15d764=_0x399830(0x148)+_0x527ba7+_0x399830(0x211)+(_0x347427[_0x399830(0x1b3)]||'');_0x433e96[_0x399830(0x17c)]({'id':_0x399830(0x1a1)+uuidv4(),'object':_0x399830(0x197),'created':Math[_0x399830(0x1f0)](Date[_0x399830(0x169)]()/0x3e8),'model':_0x28b026['body'][_0x399830(0x1dd)]||'unknown','choices':[{'index':0x0,'message':{'role':_0x399830(0x170),'content':_0x15d764},'finish_reason':_0x399830(0x122)}],'usage':{'prompt_tokens':0x0,'completion_tokens':0x0,'total_tokens':0x0}});}}}}),router[a0_0x4a143b(0x1a4)](a0_0x4a143b(0x18c),async(_0x43d01d,_0x2b2857)=>{const _0x20129a=a0_0x4a143b;try{if(refreshStatus[_0x20129a(0x121)])return _0x2b2857['status'](0x199)[_0x20129a(0x17c)]({'success':![],'message':_0x20129a(0x176)});const _0x5402bc=_0x43d01d['query'][_0x20129a(0x23c)]||'';refreshStatus={'isRunning':!![],'status':_0x20129a(0x18a),'message':_0x20129a(0x226),'startTime':new Date(),'endTime':null,'error':null},logger[_0x20129a(0x1da)](_0x20129a(0x220)+(_0x5402bc||'所有'));const _0x1ce051=[];_0x5402bc&&_0x1ce051[_0x20129a(0x209)](_0x5402bc);const _0x537888=path[_0x20129a(0x18e)](__dirname,'../../auto-refresh-cookies.js'),_0x1e5101=spawn(_0x20129a(0x1a5),[_0x537888,..._0x1ce051],{'stdio':[_0x20129a(0x187),_0x20129a(0x1e1),_0x20129a(0x1e1)]});let _0x402bd9='';return _0x1e5101[_0x20129a(0x20d)]['on'](_0x20129a(0x1c0),_0x4c9da3=>{const _0x577b24=_0x20129a,_0x3cfb66=_0x4c9da3[_0x577b24(0x180)]();_0x402bd9+=_0x3cfb66,logger[_0x577b24(0x1da)](_0x577b24(0x1d4)+_0x3cfb66);if(_0x3cfb66[_0x577b24(0x23b)](_0x577b24(0x12a)))refreshStatus['message']=_0x577b24(0x19b);else _0x3cfb66[_0x577b24(0x23b)](_0x577b24(0x179))&&(refreshStatus[_0x577b24(0x1b3)]=_0x3cfb66[_0x577b24(0x1d6)]());}),_0x1e5101[_0x20129a(0x140)]['on'](_0x20129a(0x1c0),_0x31c633=>{const _0x207d9c=_0x20129a,_0x13f763=_0x31c633[_0x207d9c(0x180)]();_0x402bd9+=_0x13f763,logger[_0x207d9c(0x207)](_0x207d9c(0x1b5)+_0x13f763),refreshStatus[_0x207d9c(0x207)]=_0x13f763[_0x207d9c(0x1d6)](),refreshStatus['message']=_0x207d9c(0x1ba)+_0x13f763[_0x207d9c(0x1d6)]();}),_0x1e5101['on'](_0x20129a(0x205),_0x128fe1=>{const _0x24c72a=_0x20129a;logger[_0x24c72a(0x1da)]('刷新进程退出,代码:\x20'+_0x128fe1),refreshStatus[_0x24c72a(0x121)]=![],refreshStatus[_0x24c72a(0x1e0)]=new Date();if(_0x128fe1===0x0){refreshStatus['status']=_0x24c72a(0x145);const _0x2ec8b7=_0x402bd9[_0x24c72a(0x212)](/成功刷新 (\d+) 个/);_0x2ec8b7?refreshStatus[_0x24c72a(0x1b3)]='成功刷新\x20'+_0x2ec8b7[0x1]+_0x24c72a(0x1f9):refreshStatus[_0x24c72a(0x1b3)]=_0x24c72a(0x1c6);try{const _0xae51e8=require(_0x24c72a(0x12c));logger[_0x24c72a(0x1da)](_0x24c72a(0x177)),_0xae51e8[_0x24c72a(0x154)](),logger['info']('主进程API\x20Keys重新加载完成');}catch(_0x5ea912){logger[_0x24c72a(0x207)](_0x24c72a(0x19f),_0x5ea912);}}else refreshStatus['status']=_0x24c72a(0x1b0),refreshStatus[_0x24c72a(0x1b3)]=refreshStatus[_0x24c72a(0x207)]||_0x24c72a(0x22a);}),_0x2b2857[_0x20129a(0x17c)]({'success':!![],'message':_0x20129a(0x14d)});}catch(_0xdeae43){return logger['error'](_0x20129a(0x23f),_0xdeae43),refreshStatus[_0x20129a(0x121)]=![],refreshStatus['status']=_0x20129a(0x1b0),refreshStatus['endTime']=new Date(),refreshStatus['error']=_0xdeae43[_0x20129a(0x1b3)],refreshStatus['message']=_0x20129a(0x1dc)+_0xdeae43[_0x20129a(0x1b3)],_0x2b2857[_0x20129a(0x21c)](0x1f4)['json']({'success':![],'message':_0x20129a(0x1dc)+_0xdeae43[_0x20129a(0x1b3)]});}}),router['get'](a0_0x4a143b(0x173),(_0x317ea3,_0x28a8e5)=>{const _0x3b8706=a0_0x4a143b;try{return _0x28a8e5['json']({'success':!![],'data':{...refreshStatus,'isRunning':refreshStatus[_0x3b8706(0x121)]||![],'status':refreshStatus[_0x3b8706(0x21c)]||_0x3b8706(0x248),'message':refreshStatus['message']||_0x3b8706(0x244),'startTime':refreshStatus[_0x3b8706(0x240)]||null,'endTime':refreshStatus[_0x3b8706(0x1e0)]||null}});}catch(_0x3e98b6){return logger[_0x3b8706(0x207)]('获取刷新状态失败:',_0x3e98b6),_0x28a8e5['status'](0x1f4)['json']({'success':![],'message':_0x3b8706(0x195)+_0x3e98b6[_0x3b8706(0x1b3)]});}}),router[a0_0x4a143b(0x1a4)](a0_0x4a143b(0x214),async(_0x46bd2c,_0x2752a0)=>{const _0xc3c05f=a0_0x4a143b;try{const _0xfdf2d3=_0x46bd2c[_0xc3c05f(0x1fa)]['authorization'];if(!_0xfdf2d3||!_0xfdf2d3[_0xc3c05f(0x242)](_0xc3c05f(0x14c)))return _0x2752a0[_0xc3c05f(0x21c)](0x191)['json']({'success':![],'message':_0xc3c05f(0x125)});const _0x25d25d=_0xfdf2d3[_0xc3c05f(0x199)]('\x20')[0x1],_0x4a99ef=admin[_0xc3c05f(0x150)](_0x25d25d);if(!_0x4a99ef['success'])return _0x2752a0[_0xc3c05f(0x21c)](0x191)['json']({'success':![],'message':_0xc3c05f(0x1b8)});const _0x4fc1b0=uuidv4(),_0xce6f56=crypto[_0xc3c05f(0x1f3)](0x20)[_0xc3c05f(0x180)](_0xc3c05f(0x131)),_0x100a9d=crypto['createHash'](_0xc3c05f(0x134))[_0xc3c05f(0x1fb)](_0xce6f56)[_0xc3c05f(0x243)]('base64url'),_0x45328c=_0xc3c05f(0x22d)+_0x100a9d+_0xc3c05f(0x183)+_0x4fc1b0+_0xc3c05f(0x24a);return pendingCookieRequests[_0xc3c05f(0x16e)](_0x4fc1b0,{'uuid':_0x4fc1b0,'verifier':_0xce6f56,'status':_0xc3c05f(0x1de),'created':Date[_0xc3c05f(0x169)](),'apiKey':_0x46bd2c[_0xc3c05f(0x247)]['apiKey']||'','lastCheck':Date['now'](),'cookie':null}),setTimeout(()=>{const _0x1ee13c=_0xc3c05f;pendingCookieRequests[_0x1ee13c(0x12d)](_0x4fc1b0)&&pendingCookieRequests[_0x1ee13c(0x139)](_0x4fc1b0);},0x3c*0x3c*0x3e8),_0x2752a0[_0xc3c05f(0x17c)]({'success':!![],'url':_0x45328c,'uuid':_0x4fc1b0});}catch(_0x335f25){return logger[_0xc3c05f(0x207)](_0xc3c05f(0x20c),_0x335f25),_0x2752a0[_0xc3c05f(0x21c)](0x1f4)[_0xc3c05f(0x17c)]({'success':![],'message':_0x335f25[_0xc3c05f(0x1b3)]});}}),router['get'](a0_0x4a143b(0x21e),async(_0x1293a0,_0x6646a7)=>{const _0x4a63d0=a0_0x4a143b;try{const {uuid:_0x455103}=_0x1293a0['query'];if(!_0x455103||!pendingCookieRequests[_0x4a63d0(0x12d)](_0x455103))return _0x6646a7[_0x4a63d0(0x17c)]({'success':![],'status':_0x4a63d0(0x1b0),'message':'无效的UUID或请求已过期'});const _0x81252e=pendingCookieRequests['get'](_0x455103);_0x81252e[_0x4a63d0(0x1a6)]=Date[_0x4a63d0(0x169)]();if(_0x81252e['status']===_0x4a63d0(0x1de))try{const _0x3c8000=_0x4a63d0(0x1ed)+_0x455103+_0x4a63d0(0x17b)+_0x81252e[_0x4a63d0(0x124)],_0x37c0cc=await fetch(_0x3c8000,{'method':_0x4a63d0(0x245),'headers':{'User-Agent':_0x4a63d0(0x1ae),'Accept':_0x4a63d0(0x238),'Origin':'vscode-file://vscode-app','x-ghost-mode':_0x4a63d0(0x23a)},'timeout':0x1388});if(_0x37c0cc['ok']){const _0x5a58a7=await _0x37c0cc[_0x4a63d0(0x17c)]();if(_0x5a58a7&&_0x5a58a7[_0x4a63d0(0x1df)]){_0x81252e[_0x4a63d0(0x203)]=_0x5a58a7[_0x4a63d0(0x1df)],_0x81252e[_0x4a63d0(0x21c)]=_0x4a63d0(0x249);let _0x30f969='';if(_0x81252e[_0x4a63d0(0x23c)]){const _0x3dc2a9=_0x81252e['apiKey'],_0x5430eb=keyManager[_0x4a63d0(0x1b4)](_0x3dc2a9)||[];_0x5430eb[_0x4a63d0(0x209)](_0x81252e[_0x4a63d0(0x203)]),keyManager[_0x4a63d0(0x210)](_0x3dc2a9,_0x5430eb),_0x30f969='Cookie已添加到API\x20Key:\x20'+_0x3dc2a9;}else{const _0x16a12d=keyManager[_0x4a63d0(0x1c5)]();for(const _0x445dc9 of _0x16a12d){const _0x38cf20=keyManager['getAllCookiesForApiKey'](_0x445dc9)||[];_0x38cf20['push'](_0x81252e[_0x4a63d0(0x203)]),keyManager['addOrUpdateApiKey'](_0x445dc9,_0x38cf20);}_0x30f969=_0x4a63d0(0x160)+_0x16a12d['length']+'个';}return pendingCookieRequests['delete'](_0x455103),_0x6646a7[_0x4a63d0(0x17c)]({'success':!![],'message':_0x30f969});}}return _0x6646a7[_0x4a63d0(0x17c)]({'success':![],'status':_0x4a63d0(0x1de)});}catch(_0x1a5296){return logger['error']('查询Cursor\x20API失败:',_0x1a5296),_0x6646a7[_0x4a63d0(0x17c)]({'success':![],'status':_0x4a63d0(0x1de),'message':_0x4a63d0(0x127)});}else{if(_0x81252e[_0x4a63d0(0x21c)]===_0x4a63d0(0x249)){const _0x509210=_0x81252e[_0x4a63d0(0x23c)]?_0x4a63d0(0x158)+_0x81252e[_0x4a63d0(0x23c)]:_0x4a63d0(0x1be);return pendingCookieRequests['delete'](_0x455103),_0x6646a7['json']({'success':!![],'message':_0x509210});}else return pendingCookieRequests[_0x4a63d0(0x139)](_0x455103),_0x6646a7['json']({'success':![],'status':_0x4a63d0(0x1b0),'message':'获取Cookie失败'});}}catch(_0x5e78b2){return logger['error'](_0x4a63d0(0x204),_0x5e78b2),_0x6646a7['status'](0x1f4)[_0x4a63d0(0x17c)]({'success':![],'status':_0x4a63d0(0x1b0),'message':_0x5e78b2[_0x4a63d0(0x1b3)]});}}),router[a0_0x4a143b(0x14b)]('/logs',(_0x3174ec,_0x106167)=>{const _0x2ffbf0=a0_0x4a143b;try{const _0x4bb296=_0x3174ec[_0x2ffbf0(0x16a)]['level'],_0x176cae=_0x3174ec['query']['search'],_0x21de1f=parseInt(_0x3174ec[_0x2ffbf0(0x16a)]['page'])||0x1,_0x28cdd3=parseInt(_0x3174ec[_0x2ffbf0(0x16a)]['pageSize'])||0x64,_0xfea1b5=_0x3174ec[_0x2ffbf0(0x16a)][_0x2ffbf0(0x240)],_0x191a87=_0x3174ec[_0x2ffbf0(0x16a)][_0x2ffbf0(0x1e0)],_0x3e0bf8={'level':_0x4bb296,'search':_0x176cae,'page':_0x21de1f,'pageSize':_0x28cdd3,'startTime':_0xfea1b5,'endTime':_0x191a87},_0x1752a5=logger[_0x2ffbf0(0x135)](_0x3e0bf8);return _0x106167['json']({'success':!![],'data':_0x1752a5});}catch(_0x598083){return logger['error'](_0x2ffbf0(0x215),_0x598083),_0x106167[_0x2ffbf0(0x21c)](0x1f4)[_0x2ffbf0(0x17c)]({'success':![],'message':_0x2ffbf0(0x1f4)+_0x598083[_0x2ffbf0(0x1b3)]});}}),router[a0_0x4a143b(0x139)]('/logs',(_0x221bb1,_0x3b8d15)=>{const _0x35f200=a0_0x4a143b;try{return logger[_0x35f200(0x1e6)](),_0x3b8d15[_0x35f200(0x17c)]({'success':!![],'message':_0x35f200(0x182)});}catch(_0x2c7a4e){return logger['error'](_0x35f200(0x13b),_0x2c7a4e),_0x3b8d15['status'](0x1f4)[_0x35f200(0x17c)]({'success':![],'message':_0x35f200(0x1ac)+_0x2c7a4e[_0x35f200(0x1b3)]});}});async function others(_0x119e8f,_0x55831f,_0x2c8842,_0x1dddc5,_0x53a685){const _0xfb81c4=a0_0x4a143b;try{const _0x4ba34b=[{'url':_0xfb81c4(0x1b6),'method':_0xfb81c4(0x219),'headers':{'accept-encoding':_0xfb81c4(0x123),'authorization':_0xfb81c4(0x14c)+_0x119e8f,'connect-protocol-version':'1','content-type':_0xfb81c4(0x1f5),'user-agent':_0xfb81c4(0x167),'x-client-key':_0x55831f,'x-cursor-checksum':_0x2c8842,'x-cursor-client-version':_0x1dddc5,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':_0xfb81c4(0x1bf),'x-ghost-mode':'true','x-new-onboarding-completed':_0xfb81c4(0x1e5),'x-session-id':_0x53a685,'Host':_0xfb81c4(0x223)},'body':'','timeout':{'connect':0x1388,'read':0x7530}},{'url':_0xfb81c4(0x15b),'method':_0xfb81c4(0x219),'headers':{'authorization':_0xfb81c4(0x14c)+_0x119e8f,'connect-accept-encoding':'gzip','connect-protocol-version':'1','content-type':_0xfb81c4(0x1f5),'user-agent':_0xfb81c4(0x167),'x-amzn-trace-id':'Root='+uuidv4(),'x-client-key':_0x55831f,'x-cursor-checksum':_0x2c8842,'x-cursor-client-version':_0x1dddc5,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':'Asia/Tokyo','x-ghost-mode':'true','x-request-id':uuidv4(),'x-session-id':_0x53a685,'Host':_0xfb81c4(0x223)},'timeout':{'connect':0x1388,'read':0x7530}},{'url':_0xfb81c4(0x15c),'method':_0xfb81c4(0x219),'headers':{'accept-encoding':_0xfb81c4(0x123),'authorization':'Bearer\x20'+_0x119e8f,'connect-protocol-version':'1','content-type':_0xfb81c4(0x1f5),'user-agent':_0xfb81c4(0x167),'x-amzn-trace-id':'Root='+uuidv4(),'x-client-key':_0x55831f,'x-cursor-checksum':_0x2c8842,'x-cursor-client-version':_0x1dddc5,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':_0xfb81c4(0x1bf),'x-ghost-mode':'true','x-new-onboarding-completed':_0xfb81c4(0x1e5),'x-request-id':uuidv4(),'x-session-id':_0x53a685,'Host':_0xfb81c4(0x223)},'body':'','timeout':{'connect':0x1388,'read':0x7530}},{'url':_0xfb81c4(0x1a3),'method':_0xfb81c4(0x245),'headers':{'Host':_0xfb81c4(0x223),'Connection':'keep-alive','Authorization':_0xfb81c4(0x14c)+_0x119e8f,'x-new-onboarding-completed':_0xfb81c4(0x1e5),'x-ghost-mode':_0xfb81c4(0x23a),'User-Agent':_0xfb81c4(0x18b),'Accept':'*/*','Origin':'vscode-file://vscode-app','Sec-Fetch-Site':_0xfb81c4(0x196),'Sec-Fetch-Mode':_0xfb81c4(0x12b),'Sec-Fetch-Dest':'empty','Accept-Encoding':'gzip,\x20deflate,\x20br,\x20zstd','Accept-Language':_0xfb81c4(0x22b)},'timeout':{'connect':0x1388,'read':0x7530}},{'url':_0xfb81c4(0x178),'method':_0xfb81c4(0x219),'headers':{'accept-encoding':_0xfb81c4(0x123),'authorization':_0xfb81c4(0x14c)+_0x119e8f,'connect-protocol-version':'1','content-type':_0xfb81c4(0x1f5),'user-agent':_0xfb81c4(0x167),'x-client-key':_0x55831f,'x-cursor-checksum':_0x2c8842,'x-cursor-client-version':_0x1dddc5,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':_0xfb81c4(0x1bf),'x-ghost-mode':_0xfb81c4(0x23a),'x-new-onboarding-completed':_0xfb81c4(0x1e5),'x-session-id':_0x53a685,'Host':'api2.cursor.sh'},'body':'','timeout':{'connect':0x1388,'read':0x7530}},{'url':_0xfb81c4(0x229),'method':_0xfb81c4(0x219),'headers':{'accept-encoding':_0xfb81c4(0x123),'authorization':_0xfb81c4(0x14c)+_0x119e8f,'connect-protocol-version':'1','content-type':_0xfb81c4(0x1f5),'user-agent':'connect-es/1.6.1','x-client-key':_0x55831f,'x-cursor-checksum':_0x2c8842,'x-cursor-client-version':_0x1dddc5,'x-cursor-config-version':uuidv4(),'x-cursor-timezone':'Asia/Tokyo','x-ghost-mode':_0xfb81c4(0x23a),'x-new-onboarding-completed':_0xfb81c4(0x1e5),'x-session-id':_0x53a685,'Host':_0xfb81c4(0x223)},'body':'','timeout':{'connect':0x1388,'read':0x7530}}],_0x1715cc=0x2,_0x4a09c1=0x4,_0x5d8af7=Math[_0xfb81c4(0x1f0)](Math[_0xfb81c4(0x1b2)]()*(_0x4a09c1-_0x1715cc+0x1))+_0x1715cc,_0x517287=[..._0x4ba34b][_0xfb81c4(0x22e)](()=>0.5-Math[_0xfb81c4(0x1b2)]())[_0xfb81c4(0x1a8)](0x0,_0x5d8af7),_0x3f8b31=process[_0xfb81c4(0x1c2)][_0xfb81c4(0x222)]===_0xfb81c4(0x23a),_0x3a546e=await Promise['allSettled'](_0x517287['map'](async _0x47ac91=>{const _0x5d9d3c=_0xfb81c4;try{let _0x735934;if(_0x3f8b31){logger[_0x5d9d3c(0x1f6)](_0x5d9d3c(0x153)+_0x47ac91[_0x5d9d3c(0x1d7)]);const _0x132de3={'url':_0x47ac91['url'],'method':_0x47ac91[_0x5d9d3c(0x14f)],'headers':_0x47ac91['headers'],'body':_0x47ac91[_0x5d9d3c(0x247)]||undefined,'stream':![]};_0x735934=await fetch(_0x5d9d3c(0x13e),{'method':_0x5d9d3c(0x219),'headers':{'Content-Type':_0x5d9d3c(0x233)},'body':JSON[_0x5d9d3c(0x1cf)](_0x132de3),'timeout':_0x47ac91[_0x5d9d3c(0x1aa)]});}else logger[_0x5d9d3c(0x1f6)](_0x5d9d3c(0x184)+_0x47ac91[_0x5d9d3c(0x1d7)]),_0x735934=await fetch(_0x47ac91['url'],{'method':_0x47ac91['method'],'headers':_0x47ac91[_0x5d9d3c(0x1fa)],'body':_0x47ac91['body']||undefined,'timeout':_0x47ac91[_0x5d9d3c(0x1aa)]});return{'url':_0x47ac91[_0x5d9d3c(0x1d7)],'status':_0x735934[_0x5d9d3c(0x21c)],'success':!![]};}catch(_0x55da7e){return logger[_0x5d9d3c(0x1f6)](_0x5d9d3c(0x1e4)+_0x47ac91['url']+'):\x20'+_0x55da7e['message']),{'url':_0x47ac91[_0x5d9d3c(0x1d7)],'success':![],'error':_0x55da7e[_0x5d9d3c(0x1b3)]};}})),_0x1c0251=_0x3a546e[_0xfb81c4(0x17d)](_0x31cdfa=>_0x31cdfa['status']===_0xfb81c4(0x143)&&_0x31cdfa[_0xfb81c4(0x246)][_0xfb81c4(0x249)])[_0xfb81c4(0x172)];return logger[_0xfb81c4(0x1f6)]('其它API调用完成:\x20成功\x20'+_0x1c0251+'/'+_0x3a546e[_0xfb81c4(0x172)]),!![];}catch(_0x3864b9){return logger['error'](_0xfb81c4(0x1cc)+_0x3864b9['message']),![];}}function handleCursorError(_0xe2a3c9,_0x4a4955,_0x448fc5){const _0x199f28=a0_0x4a143b;let _0x318cd8='',_0x19f725=![];if(_0xe2a3c9[_0x199f28(0x23b)]('Not\x20logged\x20in'))_0x448fc5===_0x4a4955?(logger[_0x199f28(0x207)]('检测到API\x20Key\x20\x22'+_0x4a4955+'\x22\x20中没有可用Cookie,正在尝试以向后兼容模式使用API\x20Key本身'),_0x318cd8=_0x199f28(0x235)+_0x4a4955+'\x22\x20中没有可用的Cookie。请添加有效的Cookie到此API\x20Key,或使用其他有效的API\x20Key。\x0a\x0a详细信息:'+_0xe2a3c9):(logger[_0x199f28(0x207)](_0x199f28(0x206),_0x448fc5),_0x318cd8=_0x199f28(0x1ea)+_0xe2a3c9),_0x19f725=!![];else{if(_0xe2a3c9[_0x199f28(0x23b)]('You\x27ve\x20reached\x20your\x20trial\x20request\x20limit')||_0xe2a3c9[_0x199f28(0x23b)](_0x199f28(0x20f)))logger[_0x199f28(0x207)](_0x199f28(0x1cb),_0x448fc5),_0x318cd8=_0x199f28(0x1d2)+_0xe2a3c9,_0x19f725=!![];else{if(_0xe2a3c9[_0x199f28(0x23b)]('User\x20is\x20unauthorized'))logger[_0x199f28(0x207)](_0x199f28(0x1af),_0x448fc5),_0x318cd8=_0x199f28(0x189)+_0xe2a3c9,_0x19f725=!![];else{if(_0xe2a3c9['includes']('suspicious\x20activity\x20checks'))logger[_0x199f28(0x207)](_0x199f28(0x19a),_0x448fc5),_0x318cd8=_0x199f28(0x228)+_0xe2a3c9,_0x19f725=![];else{if(_0xe2a3c9[_0x199f28(0x23b)](_0x199f28(0x129)))logger[_0x199f28(0x207)](_0x199f28(0x1ef),_0x448fc5),_0x318cd8=_0x199f28(0x194)+_0xe2a3c9,_0x19f725=!![];else{if(_0xe2a3c9['includes'](_0x199f28(0x161))||_0xe2a3c9[_0x199f28(0x23b)](_0x199f28(0x1b7)))logger['error'](_0x199f28(0x1fe),_0x448fc5),_0x318cd8=_0x199f28(0x1c1)+_0xe2a3c9,_0x19f725=!![];else{if(_0xe2a3c9['includes'](_0x199f28(0x188)))logger[_0x199f28(0x207)](_0x199f28(0x21b),_0x448fc5),_0x318cd8=_0x199f28(0x1ee)+_0xe2a3c9,_0x19f725=!![];else _0xe2a3c9[_0x199f28(0x23b)](_0x199f28(0x168))?(logger[_0x199f28(0x207)](_0x199f28(0x1ad),_0x448fc5),_0x318cd8=_0x199f28(0x232)+_0xe2a3c9,_0x19f725=![]):(logger[_0x199f28(0x207)](_0x199f28(0x237),_0xe2a3c9),_0x318cd8='错误:请求失败。\x0a\x0a详细信息:'+_0xe2a3c9,_0x19f725=![]);}}}}}}return{'message':_0x318cd8,'shouldRemoveCookie':_0x19f725};}module['exports']=router;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/cookieRefresher.js CHANGED
@@ -1,817 +1 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const csv = require('csv-parser');
4
- const axios = require('axios');
5
- const AdmZip = require('adm-zip');
6
- const { Octokit } = require('@octokit/rest');
7
- const keyManager = require('./keyManager');
8
- const config = require('../config/config');
9
- const { extractCookiesFromCsv } = require('./extractCookieFromCsv');
10
-
11
- // GitHub 仓库信息从环境变量中获取
12
- const GITHUB_OWNER = process.env.GITHUB_OWNER || 'liuw1535';
13
- const GITHUB_REPO = process.env.GITHUB_REPO || 'Cursor-Register';
14
- const GITHUB_TOKEN = process.env.GITHUB_TOKEN; // 需要在环境变量中设置
15
- const GITHUB_WORKFLOW_ID = process.env.GITHUB_WORKFLOW_ID || 'register.yml';
16
- const TRIGGER_WORKFLOW = process.env.TRIGGER_WORKFLOW === 'true';
17
-
18
- // 下载目录
19
- const DOWNLOAD_DIR = path.join(__dirname, '../../downloads');
20
- const EXTRACT_DIR = path.join(__dirname, '../../extracted');
21
-
22
- // 确保目录存在
23
- function ensureDirectoryExists(dir) {
24
- if (!fs.existsSync(dir)) {
25
- try {
26
- fs.mkdirSync(dir, { recursive: true });
27
- console.log(`创建目录成功: ${dir}`);
28
- } catch (err) {
29
- console.error(`创建目录失败: ${dir}`, err);
30
- throw err;
31
- }
32
- }
33
- }
34
-
35
- // 触发 GitHub Actions 工作流
36
- async function triggerWorkflow() {
37
- try {
38
- if (!GITHUB_TOKEN) {
39
- console.error('未设置 GITHUB_TOKEN,无法触发工作流');
40
- return null;
41
- }
42
-
43
- console.log(`正在触发 GitHub Actions 工作流: ${GITHUB_WORKFLOW_ID}...`);
44
- const octokit = new Octokit({
45
- auth: GITHUB_TOKEN
46
- });
47
-
48
- // 从环境变量获取工作流参数
49
- const number = process.env.REGISTER_NUMBER || '2';
50
- const maxWorkers = process.env.REGISTER_MAX_WORKERS || '1';
51
- const emailServer = process.env.REGISTER_EMAIL_SERVER || 'TempEmail';
52
- const ingestToOneapi = process.env.REGISTER_INGEST_TO_ONEAPI === 'true';
53
- const uploadArtifact = process.env.REGISTER_UPLOAD_ARTIFACT !== 'false'; // 默认为true
54
- const useConfigFile = process.env.REGISTER_USE_CONFIG_FILE !== 'false'; // 默认为true
55
- const emailConfigs = process.env.REGISTER_EMAIL_CONFIGS || '[]';
56
-
57
- console.log(`工作流参数: number=${number}, maxWorkers=${maxWorkers}, emailServer=${emailServer}, ingestToOneapi=${ingestToOneapi}, uploadArtifact=${uploadArtifact}, useConfigFile=${useConfigFile}`);
58
-
59
- // 获取触发前的最新工作流ID,用于后续识别新触发的工作流
60
- const { data: beforeWorkflowRuns } = await octokit.actions.listWorkflowRuns({
61
- owner: GITHUB_OWNER,
62
- repo: GITHUB_REPO,
63
- workflow_id: GITHUB_WORKFLOW_ID,
64
- per_page: 1
65
- });
66
-
67
- const latestWorkflowIdBefore = beforeWorkflowRuns.workflow_runs && beforeWorkflowRuns.workflow_runs.length > 0
68
- ? beforeWorkflowRuns.workflow_runs[0].id
69
- : 0;
70
-
71
- console.log(`触发前最新工作流ID: ${latestWorkflowIdBefore}`);
72
-
73
- // 触发工作流
74
- const response = await octokit.actions.createWorkflowDispatch({
75
- owner: GITHUB_OWNER,
76
- repo: GITHUB_REPO,
77
- workflow_id: GITHUB_WORKFLOW_ID,
78
- ref: 'main', // 默认使用 main 分支,可以根据需要修改
79
- inputs: {
80
- number: number,
81
- max_workers: maxWorkers,
82
- email_server: emailServer,
83
- ingest_to_oneapi: ingestToOneapi.toString(),
84
- upload_artifact: uploadArtifact.toString(),
85
- use_config_file: useConfigFile.toString(),
86
- email_configs: emailConfigs
87
- }
88
- });
89
-
90
- console.log('工作流触发成功,等待工作流开始运行...');
91
-
92
- // 等待新工作流出现并获取其ID
93
- let newWorkflowRunId = null;
94
- let findAttempts = 0;
95
- const maxFindAttempts = 30; // 最多等待30次,每次5秒
96
-
97
- while (findAttempts < maxFindAttempts && !newWorkflowRunId) {
98
- findAttempts++;
99
- console.log(`查找新触发的工作流,尝试 ${findAttempts}/${maxFindAttempts}...`);
100
-
101
- try {
102
- const { data: afterWorkflowRuns } = await octokit.actions.listWorkflowRuns({
103
- owner: GITHUB_OWNER,
104
- repo: GITHUB_REPO,
105
- workflow_id: GITHUB_WORKFLOW_ID,
106
- per_page: 5
107
- });
108
-
109
- if (afterWorkflowRuns.workflow_runs && afterWorkflowRuns.workflow_runs.length > 0) {
110
- // 查找ID大于之前最新工作流ID的工作流(即新触发的工作流)
111
- const newWorkflow = afterWorkflowRuns.workflow_runs.find(run => run.id > latestWorkflowIdBefore);
112
- if (newWorkflow) {
113
- newWorkflowRunId = newWorkflow.id;
114
- console.log(`找到新触发的工作流,ID: ${newWorkflowRunId}, 状态: ${newWorkflow.status}`);
115
- }
116
- }
117
- } catch (error) {
118
- console.error(`查找工作流时出错 (尝试 ${findAttempts}/${maxFindAttempts}): ${error.message}`);
119
- // 出错时继续尝试,不中断循环
120
- }
121
-
122
- if (!newWorkflowRunId) {
123
- // 等待5秒后再次检查
124
- await new Promise(resolve => setTimeout(resolve, 5000));
125
- }
126
- }
127
-
128
- if (!newWorkflowRunId) {
129
- console.log('未能找到新触发的工作流,可能触发失败');
130
- return null;
131
- }
132
-
133
- // 等待工作流完成
134
- let attempts = 0;
135
- const maxAttempts = 120; // 最多等待120次,每次30秒,总共60分钟
136
- let consecutiveErrors = 0;
137
- const maxConsecutiveErrors = 5; // 最多允许连续5次错误
138
-
139
- while (attempts < maxAttempts) {
140
- attempts++;
141
- console.log(`等待工作流完成,尝试 ${attempts}/${maxAttempts}...`);
142
-
143
- try {
144
- // 获取工作流状态
145
- const { data: workflowRun } = await octokit.actions.getWorkflowRun({
146
- owner: GITHUB_OWNER,
147
- repo: GITHUB_REPO,
148
- run_id: newWorkflowRunId
149
- });
150
-
151
- // 重置连续错误计数
152
- consecutiveErrors = 0;
153
-
154
- console.log(`工作流状态: ${workflowRun.status}, 结果: ${workflowRun.conclusion || '进行中'}`);
155
-
156
- // 检查工作流是否完成
157
- if (workflowRun.status === 'completed') {
158
- if (workflowRun.conclusion === 'success') {
159
- console.log(`工作流运行成功,ID: ${newWorkflowRunId}`);
160
- return workflowRun;
161
- } else {
162
- console.log(`工作流运行失败,结果: ${workflowRun.conclusion}`);
163
- return null;
164
- }
165
- }
166
- } catch (error) {
167
- consecutiveErrors++;
168
- console.error(`获取工作流状态时出错 (尝试 ${attempts}/${maxAttempts}, 连续错误 ${consecutiveErrors}/${maxConsecutiveErrors}): ${error.message}`);
169
-
170
- // 如果连续错误次数超过阈值,则放弃
171
- if (consecutiveErrors >= maxConsecutiveErrors) {
172
- console.error(`连续错误次数超过阈值 (${maxConsecutiveErrors}),放弃等待`);
173
- throw new Error(`连续 ${maxConsecutiveErrors} 次获取工作流状态失败: ${error.message}`);
174
- }
175
-
176
- // 错误后等待时间稍微延长
177
- await new Promise(resolve => setTimeout(resolve, 10000));
178
- // 继续循环,不中断
179
- continue;
180
- }
181
-
182
- // 等待30秒后再次检查
183
- await new Promise(resolve => setTimeout(resolve, 30000));
184
- }
185
-
186
- console.log('等待工作流完成超时');
187
- return null;
188
- } catch (error) {
189
- console.error('触发工作流失败:', error);
190
- throw error; // 重新抛出错误,让调用者处理
191
- }
192
- }
193
-
194
- // 从 GitHub Actions 获取最新的 Artifact
195
- async function getLatestArtifact() {
196
- try {
197
- console.log('正在连接 GitHub API...');
198
- const octokit = new Octokit({
199
- auth: GITHUB_TOKEN
200
- });
201
-
202
- // 如果配置了自动触发工作流,则先触发工作流
203
- let workflowRun = null;
204
- if (TRIGGER_WORKFLOW) {
205
- console.log('配置了自动触发工作流,正在触发...');
206
- try {
207
- workflowRun = await triggerWorkflow();
208
- } catch (error) {
209
- console.error('触发工作流过程中出现错误:', error.message);
210
- console.log('尝试继续使用已找到的工作流ID...');
211
-
212
- // 尝试获取最新的工作流,看是否有正在运行的工作流
213
- const { data: runningWorkflows } = await octokit.actions.listWorkflowRuns({
214
- owner: GITHUB_OWNER,
215
- repo: GITHUB_REPO,
216
- workflow_id: GITHUB_WORKFLOW_ID,
217
- status: 'in_progress',
218
- per_page: 5
219
- });
220
-
221
- if (runningWorkflows.workflow_runs && runningWorkflows.workflow_runs.length > 0) {
222
- // 找到正在运行的工作流
223
- const runningWorkflow = runningWorkflows.workflow_runs[0];
224
- console.log(`找到正在运行的工作流,ID: ${runningWorkflow.id}, 状态: ${runningWorkflow.status}`);
225
-
226
- // 等待工作流完成
227
- let attempts = 0;
228
- const maxAttempts = 120; // 最多等待120次,每次30秒,总共60分钟
229
- let consecutiveErrors = 0;
230
- const maxConsecutiveErrors = 5; // 最多允许连续5次错误
231
-
232
- while (attempts < maxAttempts) {
233
- attempts++;
234
- console.log(`等待工作流完成,尝试 ${attempts}/${maxAttempts}...`);
235
-
236
- try {
237
- // 获取工作流状态
238
- const { data: currentWorkflow } = await octokit.actions.getWorkflowRun({
239
- owner: GITHUB_OWNER,
240
- repo: GITHUB_REPO,
241
- run_id: runningWorkflow.id
242
- });
243
-
244
- // 重置连续错误计数
245
- consecutiveErrors = 0;
246
-
247
- console.log(`工作流状态: ${currentWorkflow.status}, 结果: ${currentWorkflow.conclusion || '进行中'}`);
248
-
249
- // 检查工作流是否完成
250
- if (currentWorkflow.status === 'completed') {
251
- if (currentWorkflow.conclusion === 'success') {
252
- console.log(`工作流运行成功,ID: ${currentWorkflow.id}`);
253
- workflowRun = currentWorkflow;
254
- break;
255
- } else {
256
- console.log(`工作流运行失败,结果: ${currentWorkflow.conclusion}`);
257
- break;
258
- }
259
- }
260
- } catch (err) {
261
- consecutiveErrors++;
262
- console.error(`获取工作流状态时出错 (尝试 ${attempts}/${maxAttempts}, 连续错误 ${consecutiveErrors}/${maxConsecutiveErrors}): ${err.message}`);
263
-
264
- // 如果连续错误次数超过阈值,则放弃
265
- if (consecutiveErrors >= maxConsecutiveErrors) {
266
- console.error(`连续错误次数超过阈值 (${maxConsecutiveErrors}),放弃等待`);
267
- break;
268
- }
269
-
270
- // 错误后等待时间稍微延长
271
- await new Promise(resolve => setTimeout(resolve, 10000));
272
- // 继续循环,不中断
273
- continue;
274
- }
275
-
276
- // 等待30秒后再次检查
277
- await new Promise(resolve => setTimeout(resolve, 30000));
278
- }
279
- }
280
- }
281
-
282
- if (!workflowRun) {
283
- console.log('触发工作流失败或等待超时,尝试获取最新的工作流运行');
284
- }
285
- }
286
-
287
- // 如果没有触发工作流或触发失败,则获取最新的工作流运行
288
- if (!workflowRun) {
289
- console.log('获取最新的工作流运行...');
290
- const { data: workflowRuns } = await octokit.actions.listWorkflowRunsForRepo({
291
- owner: GITHUB_OWNER,
292
- repo: GITHUB_REPO,
293
- status: 'success',
294
- per_page: 5
295
- });
296
-
297
- if (!workflowRuns.workflow_runs || workflowRuns.workflow_runs.length === 0) {
298
- console.log('没有找到成功的工作流运行');
299
- return null;
300
- }
301
-
302
- // 获取最新成功运行的 Artifacts
303
- workflowRun = workflowRuns.workflow_runs[0];
304
- }
305
-
306
- console.log(`找到最新的工作流运行: ${workflowRun.id}`);
307
-
308
- // 等待一段时间,确保Artifact已经上传完成
309
- console.log('等待Artifact上传完成...');
310
- await new Promise(resolve => setTimeout(resolve, 10000));
311
-
312
- // 获取工作流的Artifacts
313
- let artifacts = null;
314
- let artifactAttempts = 0;
315
- const maxArtifactAttempts = 10; // 最多尝试10次,每次10秒
316
-
317
- while (artifactAttempts < maxArtifactAttempts && (!artifacts || !artifacts.artifacts || artifacts.artifacts.length === 0)) {
318
- artifactAttempts++;
319
- console.log(`尝试获取Artifacts,尝试 ${artifactAttempts}/${maxArtifactAttempts}...`);
320
-
321
- try {
322
- const response = await octokit.actions.listWorkflowRunArtifacts({
323
- owner: GITHUB_OWNER,
324
- repo: GITHUB_REPO,
325
- run_id: workflowRun.id
326
- });
327
-
328
- artifacts = response.data;
329
- } catch (error) {
330
- console.error(`获取Artifacts时出错 (尝试 ${artifactAttempts}/${maxArtifactAttempts}): ${error.message}`);
331
- // 出错时继续尝试,不中断循环
332
- }
333
-
334
- if (!artifacts || !artifacts.artifacts || artifacts.artifacts.length === 0) {
335
- console.log('暂时没有找到Artifacts,等待10秒后重试...');
336
- await new Promise(resolve => setTimeout(resolve, 10000));
337
- }
338
- }
339
-
340
- if (!artifacts || !artifacts.artifacts || artifacts.artifacts.length === 0) {
341
- console.log('没有找到Artifacts,可能工作流没有生成Artifact');
342
- return null;
343
- }
344
-
345
- console.log(`找到 ${artifacts.artifacts.length} 个Artifacts`);
346
-
347
- // 查找 Account info Artifact
348
- const accountInfoArtifact = artifacts.artifacts.find(artifact =>
349
- artifact.name.toLowerCase().includes('account info'));
350
-
351
- if (!accountInfoArtifact) {
352
- console.log('没有找到 Account info Artifact');
353
- return null;
354
- }
355
-
356
- console.log(`找到 Account info Artifact: ${accountInfoArtifact.id}`);
357
- return accountInfoArtifact;
358
- } catch (error) {
359
- console.error('获取 Artifact 失败:', error);
360
- return null;
361
- }
362
- }
363
-
364
- // 下载 Artifact
365
- async function downloadArtifact(artifact) {
366
- let downloadAttempts = 0;
367
- const maxDownloadAttempts = 5; // 最多尝试5次下载
368
-
369
- while (downloadAttempts < maxDownloadAttempts) {
370
- downloadAttempts++;
371
- try {
372
- console.log(`开始下载 Artifact: ${artifact.id}... (尝试 ${downloadAttempts}/${maxDownloadAttempts})`);
373
- ensureDirectoryExists(DOWNLOAD_DIR);
374
-
375
- const octokit = new Octokit({
376
- auth: GITHUB_TOKEN
377
- });
378
-
379
- // 获取下载 URL
380
- const { url } = await octokit.actions.downloadArtifact({
381
- owner: GITHUB_OWNER,
382
- repo: GITHUB_REPO,
383
- artifact_id: artifact.id,
384
- archive_format: 'zip'
385
- });
386
-
387
- // 下载 zip 文件
388
- const zipFilePath = path.join(DOWNLOAD_DIR, `${artifact.id}.zip`);
389
- const response = await axios({
390
- method: 'get',
391
- url: url,
392
- responseType: 'arraybuffer',
393
- timeout: 60000 // 设置60秒超时
394
- });
395
-
396
- fs.writeFileSync(zipFilePath, response.data);
397
- console.log(`Artifact 下载完成: ${zipFilePath}`);
398
- return zipFilePath;
399
- } catch (error) {
400
- console.error(`下载 Artifact 失败 (尝试 ${downloadAttempts}/${maxDownloadAttempts}): ${error.message}`);
401
-
402
- if (downloadAttempts >= maxDownloadAttempts) {
403
- console.error('达到最大尝试次数,放弃下载');
404
- return null;
405
- }
406
-
407
- // 等待一段时间后重试
408
- const retryDelay = 10000; // 10秒
409
- console.log(`等待 ${retryDelay/1000} 秒后重试...`);
410
- await new Promise(resolve => setTimeout(resolve, retryDelay));
411
- }
412
- }
413
-
414
- return null;
415
- }
416
-
417
- // 解压 Artifact
418
- async function extractArtifact(zipFilePath) {
419
- let extractAttempts = 0;
420
- const maxExtractAttempts = 3; // 最多尝试3次解压
421
-
422
- while (extractAttempts < maxExtractAttempts) {
423
- extractAttempts++;
424
- try {
425
- console.log(`开始解压 Artifact: ${zipFilePath}... (尝试 ${extractAttempts}/${maxExtractAttempts})`);
426
- ensureDirectoryExists(EXTRACT_DIR);
427
-
428
- const zip = new AdmZip(zipFilePath);
429
- zip.extractAllTo(EXTRACT_DIR, true);
430
- console.log(`Artifact 解压完成: ${EXTRACT_DIR}`);
431
-
432
- // 查找 token CSV 文件
433
- const files = fs.readdirSync(EXTRACT_DIR);
434
- const tokenFile = files.find(file => file.startsWith('token_') && file.endsWith('.csv'));
435
-
436
- if (!tokenFile) {
437
- console.log('没有找到 token CSV 文件');
438
-
439
- if (extractAttempts >= maxExtractAttempts) {
440
- return null;
441
- }
442
-
443
- // 等待一段时间后重试
444
- const retryDelay = 5000; // 5秒
445
- console.log(`等待 ${retryDelay/1000} 秒后重试...`);
446
- await new Promise(resolve => setTimeout(resolve, retryDelay));
447
- continue;
448
- }
449
-
450
- console.log(`找到 token CSV 文件: ${tokenFile}`);
451
- return path.join(EXTRACT_DIR, tokenFile);
452
- } catch (error) {
453
- console.error(`解压 Artifact 失败 (尝试 ${extractAttempts}/${maxExtractAttempts}): ${error.message}`);
454
-
455
- if (extractAttempts >= maxExtractAttempts) {
456
- console.error('达到最大尝试次数,放弃解压');
457
- return null;
458
- }
459
-
460
- // 等待一段时间后重试
461
- const retryDelay = 5000; // 5秒
462
- console.log(`等待 ${retryDelay/1000} 秒后重试...`);
463
- await new Promise(resolve => setTimeout(resolve, retryDelay));
464
- }
465
- }
466
-
467
- return null;
468
- }
469
-
470
- /**
471
- * 从CSV文件中提取cookies
472
- * @param {string} csvFilePath - CSV文件路径
473
- * @returns {Promise<string[]>} - 提取到的cookie数组
474
- */
475
- async function extractCookiesFromCsvFile(csvFilePath) {
476
- const maxExtractAttempts = 3;
477
- let attempt = 1;
478
-
479
- while (attempt <= maxExtractAttempts) {
480
- console.log(`尝试从CSV文件提取cookies (尝试 ${attempt}/${maxExtractAttempts})...`);
481
-
482
- try {
483
- // 读取文件内容
484
- if (!fs.existsSync(csvFilePath)) {
485
- console.error(`CSV文件不存在: ${csvFilePath}`);
486
- return [];
487
- }
488
-
489
- // 读取文件内容并处理可能的换行符
490
- let fileContent = fs.readFileSync(csvFilePath, 'utf8');
491
- fileContent = fileContent.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
492
-
493
- // 首先尝试直接从文件内容中提取所有可能的cookie
494
- const cookies = [];
495
-
496
- // 1. 检查是否有JWT格式的token (新格式)
497
- const jwtRegex = /ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
498
- const jwtMatches = fileContent.match(jwtRegex);
499
-
500
- if (jwtMatches && jwtMatches.length > 0) {
501
- console.log(`直接从文件内容中提取到 ${jwtMatches.length} 个JWT token格式的Cookie`);
502
- jwtMatches.forEach(match => {
503
- if (!cookies.includes(match)) {
504
- cookies.push(match);
505
- }
506
- });
507
- }
508
-
509
- // 2. 检查是否有旧格式的cookie
510
- if (fileContent.includes('user_')) {
511
- console.log('文件包含旧格式cookie标识"user_"');
512
-
513
- // 使用旧的提取函数尝试提取
514
- try {
515
- const oldFormatCookies = await extractCookiesFromCsv(csvFilePath);
516
- if (oldFormatCookies && oldFormatCookies.length > 0) {
517
- console.log(`通过提取模块获取到 ${oldFormatCookies.length} 个cookie`);
518
- oldFormatCookies.forEach(cookie => {
519
- if (!cookies.includes(cookie)) {
520
- cookies.push(cookie);
521
- }
522
- });
523
- }
524
- } catch (e) {
525
- console.warn('通过提取模块获取cookie失败:', e.message);
526
- }
527
- }
528
-
529
- // 3. 如果找到了cookie,返回结果
530
- if (cookies.length > 0) {
531
- const newFormatCount = cookies.filter(c => c.startsWith('ey')).length;
532
- const oldFormatCount = cookies.filter(c => c.includes('%3A%3A')).length;
533
-
534
- console.log(`总共找到 ${cookies.length} 个cookie`);
535
- console.log(`新格式cookie(ey开头): ${newFormatCount}个`);
536
- console.log(`旧格式cookie(包含%3A%3A): ${oldFormatCount}个`);
537
- console.log(`其他格式cookie: ${cookies.length - newFormatCount - oldFormatCount}个`);
538
-
539
- return cookies;
540
- }
541
-
542
- console.warn(`未能从文件中提取到任何cookie (尝试 ${attempt}/${maxExtractAttempts})`);
543
- } catch (error) {
544
- console.error(`从CSV文件提取cookies时出错 (尝试 ${attempt}/${maxExtractAttempts}):`, error);
545
- }
546
-
547
- attempt++;
548
- if (attempt <= maxExtractAttempts) {
549
- console.log(`等待5秒后重试...`);
550
- await new Promise(resolve => setTimeout(resolve, 5000));
551
- }
552
- }
553
-
554
- console.error(`在 ${maxExtractAttempts} 次尝试后未能从CSV文件提取到cookies`);
555
- return [];
556
- }
557
-
558
- // 将新的有效cookie添加到系统中
559
- function addNewCookiesToSystem(apiKey, newCookies) {
560
- try {
561
- console.log(`准备添加 ${newCookies.length} 个新cookie到系统中`);
562
-
563
- // 获取当前的cookies
564
- const currentCookies = keyManager.getAllCookiesForApiKey(apiKey) || [];
565
- console.log(`当前API密钥 ${apiKey} 有 ${currentCookies.length} 个cookies`);
566
-
567
- // 获取无效的cookies
568
- const invalidCookies = keyManager.getInvalidCookies() || [];
569
- console.log(`系统中有 ${invalidCookies.length || 0} 个无效cookies`);
570
-
571
- // 过滤出新的有效cookie
572
- let newValidCookies = [];
573
-
574
- // 检查invalidCookies的类型并相应处理
575
- if (invalidCookies instanceof Set) {
576
- newValidCookies = newCookies.filter(cookie =>
577
- !currentCookies.includes(cookie) && !invalidCookies.has(cookie)
578
- );
579
- } else if (Array.isArray(invalidCookies)) {
580
- newValidCookies = newCookies.filter(cookie =>
581
- !currentCookies.includes(cookie) && !invalidCookies.includes(cookie)
582
- );
583
- } else if (invalidCookies && typeof invalidCookies === 'object') {
584
- // 如果是普通对象,检查cookie是否作为键存在
585
- newValidCookies = newCookies.filter(cookie =>
586
- !currentCookies.includes(cookie) && !(cookie in invalidCookies)
587
- );
588
- } else {
589
- // 如果invalidCookies不是预期的类型,只过滤当前cookies
590
- newValidCookies = newCookies.filter(cookie => !currentCookies.includes(cookie));
591
- }
592
-
593
- console.log(`过滤后有 ${newValidCookies.length} 个新的有效cookies`);
594
-
595
- // 验证cookie是否完整
596
- const validatedCookies = newValidCookies.filter(cookie => {
597
- // 检查是否是新格式的JWT token (ey开头)
598
- if (cookie.startsWith('ey') && cookie.includes('.')) {
599
- const parts = cookie.split('.');
600
- // 检查JWT是否包含三个部分
601
- if (parts.length !== 3) {
602
- console.warn(`跳过不完整的JWT cookie (新格式): ${cookie}`);
603
- return false;
604
- }
605
- return true;
606
- }
607
- // 检查旧格式cookie是否包含JWT的三个部分
608
- else if (cookie.includes('%3A%3A')) {
609
- const parts = cookie.split('%3A%3A');
610
- if (parts.length === 2) {
611
- const jwt = parts[1];
612
- // 检查JWT是否包含点(表示JWT的三个部分)
613
- if (!jwt.includes('.') || jwt.split('.').length !== 3) {
614
- console.warn(`跳过不完整的cookie (旧格式): ${cookie}`);
615
- return false;
616
- }
617
- }
618
- }
619
- return true;
620
- });
621
-
622
- console.log(`验证完整性后有 ${validatedCookies.length} 个有效cookies`);
623
-
624
- if (validatedCookies.length > 0) {
625
- // 添加新的有效cookie到系统
626
- keyManager.addOrUpdateApiKey(apiKey, [...currentCookies, ...validatedCookies]);
627
- console.log(`成功添加 ${validatedCookies.length} 个新cookie到API密钥 ${apiKey}`);
628
- return validatedCookies.length; // 返回添加的cookie数量
629
- } else {
630
- console.log(`没有新的有效cookie需要添加到API密钥 ${apiKey}`);
631
- return 0; // 没有添加cookie,返回0
632
- }
633
- } catch (error) {
634
- console.error('添加新cookie到系统时出错:', error);
635
- return 0; // 出错时返回0
636
- }
637
- }
638
-
639
- // 清理临时文件
640
- function cleanupTempFiles() {
641
- try {
642
- console.log('开始清理临时文件...');
643
-
644
- // 清理下载目录
645
- if (fs.existsSync(DOWNLOAD_DIR)) {
646
- fs.readdirSync(DOWNLOAD_DIR).forEach(file => {
647
- fs.unlinkSync(path.join(DOWNLOAD_DIR, file));
648
- });
649
- }
650
-
651
- // 清理解压目录
652
- if (fs.existsSync(EXTRACT_DIR)) {
653
- fs.readdirSync(EXTRACT_DIR).forEach(file => {
654
- fs.unlinkSync(path.join(EXTRACT_DIR, file));
655
- });
656
- }
657
-
658
- console.log('临时文件清理完成');
659
- } catch (error) {
660
- console.error('清理临时文件失败:', error);
661
- }
662
- }
663
-
664
- // 检查 API Key 是否需要补充 Cookie
665
- function checkApiKeyNeedRefresh(apiKey, minCookieCount = config.refresh.minCookieCount) {
666
- const cookies = keyManager.getAllCookiesForApiKey(apiKey);
667
- return cookies.length < minCookieCount;
668
- }
669
-
670
- // 将现���cookie全部设为无效并从API Key中移除
671
- function markExistingCookiesAsInvalid(apiKey) {
672
- try {
673
- // 获取当前API Key的所有cookie
674
- const currentCookies = keyManager.getAllCookiesForApiKey(apiKey) || [];
675
- console.log(`正在将API Key ${apiKey} 的 ${currentCookies.length} 个现有cookie标记为无效...`);
676
-
677
- // 如果没有cookie,直接返回
678
- if (currentCookies.length === 0) {
679
- console.log(`API Key ${apiKey} 没有现有cookie,无需标记为无效`);
680
- return 0;
681
- }
682
-
683
- // 获取无效cookie列表
684
- const invalidCookies = keyManager.getInvalidCookies();
685
- let markedCount = 0;
686
-
687
- // 遍历cookie并添加到无效列表
688
- for (const cookie of currentCookies) {
689
- // 将cookie添加到无效集合中
690
- if (invalidCookies instanceof Set) {
691
- invalidCookies.add(cookie);
692
- }
693
- markedCount++;
694
- }
695
-
696
- // 保存无效cookie到文件
697
- keyManager.saveInvalidCookiesToFile();
698
-
699
- // 清空当前API Key的cookie列表
700
- keyManager.addOrUpdateApiKey(apiKey, []);
701
-
702
- // 保存更新后的API Keys
703
- keyManager.saveApiKeysToFile();
704
-
705
- console.log(`已将API Key ${apiKey} 的 ${markedCount} 个cookie标记为无效并从API Key中移除`);
706
- return markedCount;
707
- } catch (error) {
708
- console.error(`标记现有cookie为无效时出错:`, error);
709
- return 0;
710
- }
711
- }
712
-
713
- // 主函数:自动刷新 Cookie
714
- async function autoRefreshCookies(apiKey, minCookieCount = config.refresh.minCookieCount) {
715
- console.log(`开始自动刷新 Cookie,目标 API Key: ${apiKey},最小 Cookie 数量: ${minCookieCount}`);
716
-
717
- try {
718
- // 检查是否需要刷新
719
- if (!checkApiKeyNeedRefresh(apiKey, minCookieCount)) {
720
- console.log(`API Key ${apiKey} 的 Cookie 数量足够,不需要刷新`);
721
- return {
722
- success: true,
723
- message: '当前 Cookie 数量足够,不需要刷新',
724
- refreshed: 0
725
- };
726
- }
727
-
728
- // 获取最新的 Artifact
729
- const artifact = await getLatestArtifact();
730
- if (!artifact) {
731
- return {
732
- success: false,
733
- message: '获取 Artifact 失败',
734
- refreshed: 0
735
- };
736
- }
737
-
738
- // 下载 Artifact
739
- const zipFilePath = await downloadArtifact(artifact);
740
- if (!zipFilePath) {
741
- return {
742
- success: false,
743
- message: '下载 Artifact 失败',
744
- refreshed: 0
745
- };
746
- }
747
-
748
- // 解压 Artifact
749
- const csvFilePath = await extractArtifact(zipFilePath);
750
- if (!csvFilePath) {
751
- return {
752
- success: false,
753
- message: '解压 Artifact 失败',
754
- refreshed: 0
755
- };
756
- }
757
-
758
- // 提取 Cookie
759
- const cookies = await extractCookiesFromCsvFile(csvFilePath);
760
- if (cookies.length === 0) {
761
- return {
762
- success: false,
763
- message: '没有找到有效的 Cookie',
764
- refreshed: 0
765
- };
766
- }
767
-
768
- // 分析提取到的cookie格式
769
- const newFormatCookies = cookies.filter(cookie => cookie.startsWith('ey'));
770
- const oldFormatCookies = cookies.filter(cookie => cookie.includes('%3A%3A'));
771
- console.log(`提取到 ${newFormatCookies.length} 个新格式cookie(ey开头)`);
772
- console.log(`提取到 ${oldFormatCookies.length} 个旧格式cookie(包含%3A%3A)`);
773
-
774
- // 根据配置决定是否将现有cookie标记为无效
775
- const refreshMode = process.env.COOKIE_REFRESH_MODE || 'append';
776
-
777
- if (refreshMode === 'replace') {
778
- // 将现有cookie标记为无效并从API Key中移除
779
- console.log('使用替换模式: 将现有cookie标记为无效');
780
- markExistingCookiesAsInvalid(apiKey);
781
- } else {
782
- console.log('使用追加模式: 保留现有cookie,只添加新cookie');
783
- }
784
-
785
- // 添加新的 Cookie 到系统
786
- const addedCount = addNewCookiesToSystem(apiKey, cookies);
787
-
788
- // 清理临时文件
789
- cleanupTempFiles();
790
-
791
- return {
792
- success: true,
793
- message: `成功添加 ${addedCount} 个新 Cookie (新格式: ${newFormatCookies.length}, 旧格式: ${oldFormatCookies.length})`,
794
- refreshed: addedCount
795
- };
796
- } catch (error) {
797
- console.error('自动刷新 Cookie 失败:', error);
798
- return {
799
- success: false,
800
- message: `刷新失败: ${error.message}`,
801
- refreshed: 0
802
- };
803
- }
804
- }
805
-
806
- module.exports = {
807
- autoRefreshCookies,
808
- checkApiKeyNeedRefresh,
809
- getLatestArtifact,
810
- downloadArtifact,
811
- extractArtifact,
812
- extractCookiesFromCsvFile,
813
- addNewCookiesToSystem,
814
- cleanupTempFiles,
815
- triggerWorkflow,
816
- markExistingCookiesAsInvalid
817
- };
 
1
+ function a0_0x43b5(_0x3ad996,_0x714fe7){const _0x510094=a0_0x5067();return a0_0x43b5=function(_0x2de226,_0x28c73f){_0x2de226=_0x2de226-0x144;let _0x506746=_0x510094[_0x2de226];if(a0_0x43b5['wTkfXZ']===undefined){var _0x43b52d=function(_0x4eec2f){const _0x16ae5b='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x138351='',_0x568619='',_0x445b78=_0x138351+_0x43b52d;for(let _0x1f7427=0x0,_0x55fe73,_0xdadbcd,_0x122802=0x0;_0xdadbcd=_0x4eec2f['charAt'](_0x122802++);~_0xdadbcd&&(_0x55fe73=_0x1f7427%0x4?_0x55fe73*0x40+_0xdadbcd:_0xdadbcd,_0x1f7427++%0x4)?_0x138351+=_0x445b78['charCodeAt'](_0x122802+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x55fe73>>(-0x2*_0x1f7427&0x6)):_0x1f7427:0x0){_0xdadbcd=_0x16ae5b['indexOf'](_0xdadbcd);}for(let _0x5225aa=0x0,_0x1a4af2=_0x138351['length'];_0x5225aa<_0x1a4af2;_0x5225aa++){_0x568619+='%'+('00'+_0x138351['charCodeAt'](_0x5225aa)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x568619);};a0_0x43b5['JnNnTc']=_0x43b52d,_0x3ad996=arguments,a0_0x43b5['wTkfXZ']=!![];}const _0x437ec4=_0x510094[0x0],_0x4c7ec5=_0x2de226+_0x437ec4,_0x42e3d3=_0x3ad996[_0x4c7ec5];if(!_0x42e3d3){const _0x533f47=function(_0x377224){this['Uxmicn']=_0x377224,this['NrNRdS']=[0x1,0x0,0x0],this['sSVazF']=function(){return'newState';},this['Payrgk']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['oZfJQU']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x533f47['prototype']['KJaRSf']=function(){const _0x171117=new RegExp(this['Payrgk']+this['oZfJQU']),_0x1841c3=_0x171117['test'](this['sSVazF']['toString']())?--this['NrNRdS'][0x1]:--this['NrNRdS'][0x0];return this['HmPCOO'](_0x1841c3);},_0x533f47['prototype']['HmPCOO']=function(_0x125163){if(!Boolean(~_0x125163))return _0x125163;return this['hapBbE'](this['Uxmicn']);},_0x533f47['prototype']['hapBbE']=function(_0x1e6e7a){for(let _0xe0c3a7=0x0,_0x582766=this['NrNRdS']['length'];_0xe0c3a7<_0x582766;_0xe0c3a7++){this['NrNRdS']['push'](Math['round'](Math['random']())),_0x582766=this['NrNRdS']['length'];}return _0x1e6e7a(this['NrNRdS'][0x0]);},new _0x533f47(a0_0x43b5)['KJaRSf'](),_0x506746=a0_0x43b5['JnNnTc'](_0x506746),_0x3ad996[_0x4c7ec5]=_0x506746;}else _0x506746=_0x42e3d3;return _0x506746;},a0_0x43b5(_0x3ad996,_0x714fe7);}const a0_0x2d975d=a0_0x43b5;(function(_0x39c5e5,_0xfafa4d){const _0xa1e129=a0_0x43b5,_0x4e9fe8=_0x39c5e5();while(!![]){try{const _0x36ed0c=parseInt(_0xa1e129(0x1da))/0x1+-parseInt(_0xa1e129(0x16a))/0x2*(parseInt(_0xa1e129(0x1bc))/0x3)+-parseInt(_0xa1e129(0x1d8))/0x4*(parseInt(_0xa1e129(0x1a6))/0x5)+-parseInt(_0xa1e129(0x14b))/0x6*(-parseInt(_0xa1e129(0x1e9))/0x7)+parseInt(_0xa1e129(0x15e))/0x8*(-parseInt(_0xa1e129(0x1c9))/0x9)+-parseInt(_0xa1e129(0x167))/0xa+-parseInt(_0xa1e129(0x1c5))/0xb*(-parseInt(_0xa1e129(0x1b4))/0xc);if(_0x36ed0c===_0xfafa4d)break;else _0x4e9fe8['push'](_0x4e9fe8['shift']());}catch(_0x1766d8){_0x4e9fe8['push'](_0x4e9fe8['shift']());}}}(a0_0x5067,0xccb59));const a0_0x28c73f=(function(){let _0x568619=!![];return function(_0x445b78,_0x1f7427){const _0x55fe73=_0x568619?function(){const _0x2721f0=a0_0x43b5;if(_0x1f7427){const _0xdadbcd=_0x1f7427[_0x2721f0(0x15c)](_0x445b78,arguments);return _0x1f7427=null,_0xdadbcd;}}:function(){};return _0x568619=![],_0x55fe73;};}()),a0_0x2de226=a0_0x28c73f(this,function(){const _0x54fcf0=a0_0x43b5;return a0_0x2de226['toString']()[_0x54fcf0(0x1c1)]('(((.+)+)+)+$')['toString']()[_0x54fcf0(0x1ef)](a0_0x2de226)[_0x54fcf0(0x1c1)]('(((.+)+)+)+$');});a0_0x2de226();const fs=require('fs'),path=require(a0_0x2d975d(0x154)),csv=require(a0_0x2d975d(0x1ba)),axios=require('axios'),AdmZip=require(a0_0x2d975d(0x161)),{Octokit}=require('@octokit/rest'),keyManager=require(a0_0x2d975d(0x1b6)),config=require(a0_0x2d975d(0x189)),{extractCookiesFromCsv}=require(a0_0x2d975d(0x1ff)),logger=require(a0_0x2d975d(0x1ea)),GITHUB_OWNER=process[a0_0x2d975d(0x17e)][a0_0x2d975d(0x1d6)]||a0_0x2d975d(0x1c6),GITHUB_REPO=process[a0_0x2d975d(0x17e)][a0_0x2d975d(0x163)]||a0_0x2d975d(0x155),GITHUB_TOKEN=process[a0_0x2d975d(0x17e)][a0_0x2d975d(0x1c4)],GITHUB_WORKFLOW_ID=process['env'][a0_0x2d975d(0x146)]||'register.yml',TRIGGER_WORKFLOW=process['env']['TRIGGER_WORKFLOW']===a0_0x2d975d(0x1ad),DOWNLOAD_DIR=path[a0_0x2d975d(0x1e1)](__dirname,'../../downloads'),EXTRACT_DIR=path[a0_0x2d975d(0x1e1)](__dirname,a0_0x2d975d(0x14a));function ensureDirectoryExists(_0x122802){const _0x53346a=a0_0x2d975d;if(!fs[_0x53346a(0x1e7)](_0x122802))try{fs['mkdirSync'](_0x122802,{'recursive':!![]}),logger[_0x53346a(0x1f3)]('创建目录成功:\x20'+_0x122802);}catch(_0x5225aa){logger[_0x53346a(0x148)](_0x53346a(0x1dc)+_0x122802,_0x5225aa);throw _0x5225aa;}}function a0_0x5067(){const _0x2cbfa6=['yxj0AwzHy3rZ','5PAW5Qc85BYpy29VA2LLkgv55BYa5As0ktOG','5B2t5yMnqvbj5A+g6zkLia','zMLUza','zxHPC3rZu3LUyW','5BYa5AEl6iEQ5yQO5yI35PAWienVB2TPzE+8JoEBRUAGHYbbueKGs2v5oIa','n0DIwvnuzG','lI9SB2DNzxi','5yEg5Ash5RE75yQGia','C3rHCNrZv2L0Aa','ios4QUAwSoAGVow8J2nVB2TPzsHLEEw8GowKTcK','y29TCgXLDgvK','y29UC3rYDwn0B3i','5OM+5yIWihrVA2vUientvIdMLOFKU7y6ia','lcbTyxHxB3jRzxjZpq','CMvMCMvZAa','Aw5MBW','ioAYOEACIEEoSoACIwnVB2TPzE+8JoAxOoMCGoAGH+IUSos4UUAxOoAvIa','5BcD6k+v57UN57UT5l2/55sO5BEY5OM+5yIW55Qe5BEL5l2C5RwbsuqUlI4','Dw5SAw5Ru3LUyW','lcdNIRBMGie6ia','zg93BMXVywrbCNrPzMfJDa','5l2/55sO5PU/5O2I5QIH5BYpoIdLSiBNJRdMNiLJB29RAwxMOiFORRdKUlRML6dMLyG','BgvUz3rO','ios4QUAwSgnVB2TPzEwiSefqsEwVHUMsPsa','5RkH5PYj5OM+5yIWqxj0AwzHy3rZ77Ym5y+V6io95BEL5l2C5Rwb5RkH5PYj55sF5OIqqxj0AwzHy3q','5PYQ6io95lUo5PAh5lU25lIT5O+q5y+w5yIW5lU75l2vy29VA2LLicJLSj3OR5uG','5BEL5l2C5Rwb54Q25OcboIa','lI9LEhrYywn0q29VA2LLrNjVBunZDG','lNPPCa','y29Uy2X1C2LVBG','5PYQ6io95OM+5yIW5PAW6kEM5y+r55Qe5BEL5l2C5Rwb77Ym5y+V6io96kEM5y+r5AsX6lsL','uKvhsvnurvjFvvbmt0fex0fsveLgqunu','5OIq5yQF5RE75yQGia','vgvTCevTywLS','r0Lusfvcx1DpuKTgte9xx0Le','6ycA6l+h5O+q5y+w5QIH5z2x6i635y+w5yIWia','zxjYB3i','5yI35PAW5AsX6lsLoIa','lI4VlI4VzxH0CMfJDgvK','ntu3nZuYmLHptwvPsW','5lUoq1nw5PAh5lU25O+q5y+wy29VA2LLC+AxTUwhUUMuMsaO5BcD6k+via','BMfTzq','ios4QUAxP+AGVow8J2nVB2TPzsJLJixLKkSLm0eLm0eP','5BEL5l2C5Rwb6l+q6kgm5AsX6lsL77Ym57Ut5P6CoIa','lI4U','kE+8JoAuVUw8G+ETIEw+Hq','6l+B6kgm5lIT','6kEM5y+r5BEL5l2C5Rwb6l+h56Il5lIT5yE6546W6zsz6k+VoG','Cgf0Aa','q3vYC29YlvjLz2LZDgvY','6kEJ5y6liefYDgLMywn0iowKSEI0PsaO5BcD6k+via','ios4QUAxOoAvIgnVB2TPzxm','ios4QMnVB2TPzxm','6l6+5yIW5PYa5AsN5BcD6k+v5QYH5PwW77Ym5Ps+5BYd5lIl6l29','6l6+5yIW5PYa5AsN5BcD6k+v5QYH5PwW77Ym5Ps+5BYd6kEJ5y6l','lMnZDG','yxbWBhK','5l2/55sO6l+95yQG5QIH5BYpoIdKV53NLzNNJRdMNiLJB29RAwxVViZLJ6RMT7VLIQdMLRbJB29RAwu','odH2sMXKthC','Aw5FChjVz3jLC3m','5OM+5yIW5Q2J5zYO6l+q6kgm55Qe5BEL5l2C5Rwb77Ymsuq6ia','ywrTlxPPCa','5PAh5lU25yYf5zcR5PEN5Qc85BYpy29VA2LL5Qch6k+giNvZzxjFiG','r0Lusfvcx1jfue8','D29YA2zSB3DFCNvUCW','ktOG','562j5B6f5BEL5l2C5Rwb5A6m5OIq6lAf5PE2','mZqZmdC2mhD0vKDZwG','BwvZC2fNzq','AgfZ','oduYmNPOD2TZqq','uKvhsvnurvjFru1bsuXFq09orKLhuW','DxrMoa','lcb1C2vdB25MAwDgAwXLpq','BgLZDfDVCMTMBg93uNvUCW','ioASOEwWNEIVLEwqJUACQUIdVEs7JKntvUAwH+s7TUApKowpLUwiSgnVB2TPzxm','Aw5JBhvKzxm','z2v0v29YA2zSB3DsDw4','uKvhsvnurvjFru1bsuXFu0vsvKvs','ios4QUEoSoACIwnVB2TPzEAGH+IUSos4UUAxOoAvIc4UlG','5P+L5OM+5BEL5l2C5Rwb5PE25yE66zszicJLSj3OR5uG','ioENKUwqJUMhJEIVLs4UlG','5RkH5PYj5OM+5yIWihrVA2vUientvIdMLOFKU7y','5BEL5l2C5Rwb6l+q6kgm5OIq5yQF77Ymsuq6ia','C3rHDhvZ','ywrKt3jvCgrHDgvbCgLlzxK','BgLZDfDVCMTMBg93uNvUC0zVCLjLCg8','zw5KC1DPDgG','6l+h5RUK5zco5PYjia','uKvhsvnurvjFsu5hrvnux1rpx09orufqsq','zw52','57o757UF5lIT5PYjia','ios4QUACIEAvIgnVB2TPzxm','6ywn572U5lQg6iEQ5yQO6kEM5y+r5BEL5l2C5Rwb77Ym5Q2J5zYO6kEM5y+rlI4U','5RE75yQG5PAWy29VA2LL5yIW57o757UF5PE25yE66zszoG','Bwf0y2G','6kEM5y+r5BEL5l2C5Rwb5AsX6lsL5OIw562j5B6f6lAf5PE277Ym5BcD6k+v6i635y+w5PYa5PAW55Qe5BEL5l2C5Rwb6l+q6kgm','Dg9tDhjPBMC','lI4UicJLSj3OR5uG','6i635y+wiefYDgLMywn0iowKSEI0PtO','5OM+5yIWiefJy291BNqGAw5MBYbbCNrPzMfJDdOG','lI4Vy29UzMLNl2nVBMzPzW','5Q2J5zYO6kEM5y+rieDPDeH1yIbby3rPB25Ziow3PEs9NoA1GtOG','5yw25lUw5Qc85BYpy29VA2LLoIa','lcbLBwfPBfnLCNzLCJ0','uKvhsvnurvjFtLvnqKvs','Dg9Rzw5F','CMvHzgrPCLn5BMm','562j5B6fqxj0AwzHy3tKUiRKVkdLROZMIjaUlI4','5BcD6k+v6i635y+wqxj0AwzHy3rZ77Ym5BcD6k+via','lcdML6FMOlZLVi86ia','D3jPDgvgAwXLu3LUyW','yxbWzw5K','lcbPBMDLC3ruB09UzwfWAt0','CMvWBgfJzq','5B2t5yMnienVB2TPzsdMLBdPH4/OTRpLPj/VViZKUi3PNidOPOhLIlFMLRa','6kEM5y+r5yMn5PYa5PAW5BEL5l2C5Rwbsuq6ia','6kEJ5y6liefYDgLMywn0iowKSEI0Pq','BgLZDfDVCMTMBg93uNvUqxj0AwzHy3rZ','zxH0CMfJDefSBfrV','C2f2zuLUDMfSAwrdB29RAwvZvg9gAwXL','ios4QMnVB2TPzEAGH+IUSos4UUAxOoAvIow5TUs7JKfqssblzxNKUk3NP7VPMAq','5OM+5yIW5PAW6kEM5y+r55Qe5BEL5l2C5Rwb77Ymsuq6ia','ioASOEIoT+wpLUw3PEs9NoA1GEEkTUAaGEwKSEI0PtOG','ios4QUAwScbdB29RAwuGkoAwSoAGVow8JZOG','6ycA6l+h5O+q5y+w5QIH5z2x6i635y+wy29VA2LL5AsX6lsLoG','6i635y+w5PYa5PAW55Qe5BEL5l2C5Rwb6l+q6kgmlI4U','ywn0Aw9UCW','5lI05PE25PAh5lU25RIf55cg5A6m5OIq','z2v0qwXSq29VA2LLC0zVCKfWAuTLEq','ndbrEMPHrgC','5RkH5PYj5OM+5yIW5PYj5Pwi55QeienVB2TPzq','562j5B6f5BEL5l2C5Rwb5A6m5OIq77Ym5BcD6k+via','qvbjieTLEsa','jtnbjtnb','5BYa5AEl6kEJ5y6liefYDgLMywn0oIa','uKvhsvnurvjFtufyx1DpuKTfuLm','Dhj1zq','C3vJy2vZCW','AxnbCNjHEq','ios4QKPxvcb0B2TLBUAGVow8J+EAHenVB2TPzq','ks4UlG','5BYa5AEl5RIf55cg5lI05PE25PAh5lU2lI4U','z2v0sw52ywXPzenVB2TPzxm','mtiWnZy0nZzfq3jkwfq','uKvhsvnurvjFvvnfx0nptKzjr19gsuXf','lI9RzxLnyw5Hz2vY','y3jLyxrLv29YA2zSB3DeAxnWyxrJAa','lcb1CgXVywrbCNrPzMfJDd0','ywnJB3vUDcbPBMzV','y3n2lxbHCNnLCG','5lIl6l29iefYDgLMywn0iowKSEI0Pq','odeZt0zqv01V','6kEM5y+r5BEL5l2C5Rwb5AsX6lsLoG','5Oc75ywX5OM+5yIWia','ioEAHcbdB29RAwuG5PwW6yEp6lAZ5AsF77Ym5lIn6zYa6kAb5yI35PAW','BwLUq29VA2LLq291BNq','C2vHCMnO','EMLW','5BEL5l2C5Rwb6kEM5y+r5OIq5yQF77Ym562j5B6f5BEL5l2C5Rwb5BYa5AEl6l+q6kgmlI4U','r0Lusfvcx1rps0vo','mtfkBuXouhm','BgL1DZe1mZu','5BEL5l2C5Rwb5y+c5PwWoIbUDw1Izxi9','ChvZAa','mtqXmJm3C2XRCuzt','6l+E57UTia','562j5B6fia','lcdNU5pMNPW6ia','D2fYBG','C2f2zufWAuTLExnuB0zPBgu','zMLSDgvY','6i635y+w5BEL5l2C5Rwb54Q25Ocb5PE25yE66zszicJLSj3OR5uG','5Q2J5zYO5BcgqvbjieTLEsa','qxj0AwzHy3qG6kEJ5y6l5A6m5OIqoIa','6iEQ5yQO5yI35PAWienVB2TPzsdLPlhOTku6','5RkH5PYj5OM+5yIW5OIq5yQF55Qe5BEL5l2C5Rwb6l+q6kgm','ioEAHca','r0Lusfvcx09xtKvs','zM9YrwfJAa','mJuYnJqWBwjQuxHg','5O+q5y+w5yIWia','mta3odiZoxzuvwLHyW','5BYa5AEl5lIl6l29iefYDgLMywn0oIa','5yIB5BU655UU5B2v5AsX6lsLoIa','6l+E57UT6zsz6k+V5QYH5PwW6lAf6l+h6zIi5yc8icG','5RIf55cg5lI05PE25PAh5lU25AsX6lsLoG','lcdOV57NU63PLjNOR68G','DxnLCL8','AM9PBG','q1nw5PAh5lU25lIn5A2y5zYOoIa'];a0_0x5067=function(){return _0x2cbfa6;};return a0_0x5067();}async function triggerWorkflow(){const _0x8ba6c9=a0_0x2d975d;try{if(!GITHUB_TOKEN)return logger['error']('未设置\x20GITHUB_TOKEN,无法触发工作流'),null;logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x18a)+GITHUB_WORKFLOW_ID+_0x8ba6c9(0x150));const _0x1a4af2=new Octokit({'auth':GITHUB_TOKEN}),_0x533f47=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x18d)]||'2',_0x377224=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x1ac)]||'1',_0x171117=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x172)]||_0x8ba6c9(0x145),_0x1841c3=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x17d)]==='true',_0x125163=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x203)]!=='false',_0x1e6e7a=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x1b5)]!=='false',_0xe0c3a7=process[_0x8ba6c9(0x17e)][_0x8ba6c9(0x16b)]||'[]';logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x1c7)+_0x533f47+_0x8ba6c9(0x1f1)+_0x377224+_0x8ba6c9(0x18c)+_0x171117+_0x8ba6c9(0x195)+_0x1841c3+_0x8ba6c9(0x1b8)+_0x125163+_0x8ba6c9(0x16d)+_0x1e6e7a);const {data:_0x582766}=await _0x1a4af2[_0x8ba6c9(0x1a3)][_0x8ba6c9(0x16e)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'workflow_id':GITHUB_WORKFLOW_ID,'per_page':0x1}),_0x4a165b=_0x582766[_0x8ba6c9(0x164)]&&_0x582766[_0x8ba6c9(0x164)][_0x8ba6c9(0x1fa)]>0x0?_0x582766['workflow_runs'][0x0]['id']:0x0;logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x198)+_0x4a165b);const _0x5254c7=await _0x1a4af2[_0x8ba6c9(0x1a3)][_0x8ba6c9(0x1b7)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'workflow_id':GITHUB_WORKFLOW_ID,'ref':'main','inputs':{'number':_0x533f47,'max_workers':_0x377224,'email_server':_0x171117,'ingest_to_oneapi':_0x1841c3[_0x8ba6c9(0x185)](),'upload_artifact':_0x125163['toString'](),'use_config_file':_0x1e6e7a[_0x8ba6c9(0x185)](),'email_configs':_0xe0c3a7}});logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x1c3));let _0x3bf844=null,_0x1efdef=0x0;const _0x171d4b=0x1e;while(_0x1efdef<_0x171d4b&&!_0x3bf844){_0x1efdef++,logger[_0x8ba6c9(0x1f3)]('查找新触发的工作流,尝试\x20'+_0x1efdef+'/'+_0x171d4b+_0x8ba6c9(0x150));try{const {data:_0x34b987}=await _0x1a4af2[_0x8ba6c9(0x1a3)][_0x8ba6c9(0x16e)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'workflow_id':GITHUB_WORKFLOW_ID,'per_page':0x5});if(_0x34b987[_0x8ba6c9(0x164)]&&_0x34b987['workflow_runs'][_0x8ba6c9(0x1fa)]>0x0){const _0x478cd0=_0x34b987[_0x8ba6c9(0x164)][_0x8ba6c9(0x1e6)](_0x1fdc4f=>_0x1fdc4f['id']>_0x4a165b);_0x478cd0&&(_0x3bf844=_0x478cd0['id'],logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x19e)+_0x3bf844+_0x8ba6c9(0x1f7)+_0x478cd0['status']));}}catch(_0x243078){logger[_0x8ba6c9(0x148)](_0x8ba6c9(0x174)+_0x1efdef+'/'+_0x171d4b+_0x8ba6c9(0x165)+_0x243078[_0x8ba6c9(0x168)]);}!_0x3bf844&&await new Promise(_0x5c216b=>setTimeout(_0x5c216b,0x1388));}if(!_0x3bf844)return logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x202)),null;let _0x320175=0x0;const _0x4bbf49=0x78;let _0x2bf278=0x0;const _0x490dc1=0x5;while(_0x320175<_0x4bbf49){_0x320175++,logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x1a8)+_0x320175+'/'+_0x4bbf49+_0x8ba6c9(0x150));try{const {data:_0x550fe2}=await _0x1a4af2[_0x8ba6c9(0x1a3)]['getWorkflowRun']({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'run_id':_0x3bf844});_0x2bf278=0x0,logger['info'](_0x8ba6c9(0x1fe)+_0x550fe2[_0x8ba6c9(0x178)]+_0x8ba6c9(0x1cc)+(_0x550fe2[_0x8ba6c9(0x201)]||_0x8ba6c9(0x152)));if(_0x550fe2[_0x8ba6c9(0x178)]==='completed')return _0x550fe2[_0x8ba6c9(0x201)]==='success'?(logger[_0x8ba6c9(0x1f3)]('工作流运行成功,ID:\x20'+_0x3bf844),_0x550fe2):(logger[_0x8ba6c9(0x1f3)](_0x8ba6c9(0x14f)+_0x550fe2[_0x8ba6c9(0x201)]),null);}catch(_0x71a950){_0x2bf278++,logger[_0x8ba6c9(0x148)](_0x8ba6c9(0x1d0)+_0x320175+'/'+_0x4bbf49+_0x8ba6c9(0x1df)+_0x2bf278+'/'+_0x490dc1+_0x8ba6c9(0x165)+_0x71a950['message']);if(_0x2bf278>=_0x490dc1){logger[_0x8ba6c9(0x148)](_0x8ba6c9(0x1dd)+_0x490dc1+'),放弃等待');throw new Error(_0x8ba6c9(0x1ca)+_0x490dc1+_0x8ba6c9(0x19f)+_0x71a950[_0x8ba6c9(0x168)]);}await new Promise(_0x19b1bd=>setTimeout(_0x19b1bd,0x2710));continue;}await new Promise(_0x3b8bbd=>setTimeout(_0x3b8bbd,0x7530));}return logger['info'](_0x8ba6c9(0x166)),null;}catch(_0x44b5fb){logger['error'](_0x8ba6c9(0x1bd),_0x44b5fb);throw _0x44b5fb;}}async function getLatestArtifact(){const _0x112e49=a0_0x2d975d;try{logger[_0x112e49(0x1f3)]('正在连接\x20GitHub\x20API...');const _0x241dbd=new Octokit({'auth':GITHUB_TOKEN});let _0x5f492b=null;if(TRIGGER_WORKFLOW){logger['info'](_0x112e49(0x181));try{_0x5f492b=await triggerWorkflow();}catch(_0x53cffe){logger['error'](_0x112e49(0x153),_0x53cffe[_0x112e49(0x168)]),logger[_0x112e49(0x1f3)](_0x112e49(0x1f5));const {data:_0x88376e}=await _0x241dbd['actions']['listWorkflowRuns']({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'workflow_id':GITHUB_WORKFLOW_ID,'status':_0x112e49(0x15f),'per_page':0x5});if(_0x88376e[_0x112e49(0x164)]&&_0x88376e[_0x112e49(0x164)][_0x112e49(0x1fa)]>0x0){const _0x29a481=_0x88376e[_0x112e49(0x164)][0x0];logger[_0x112e49(0x1f3)](_0x112e49(0x160)+_0x29a481['id']+_0x112e49(0x1f7)+_0x29a481[_0x112e49(0x178)]);let _0xd687a1=0x0;const _0x47a07e=0x78;let _0x315bcc=0x0;const _0xd7188f=0x5;while(_0xd687a1<_0x47a07e){_0xd687a1++,logger[_0x112e49(0x1f3)](_0x112e49(0x1a8)+_0xd687a1+'/'+_0x47a07e+_0x112e49(0x150));try{const {data:_0x4ac86a}=await _0x241dbd[_0x112e49(0x1a3)][_0x112e49(0x171)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'run_id':_0x29a481['id']});_0x315bcc=0x0,logger[_0x112e49(0x1f3)](_0x112e49(0x1fe)+_0x4ac86a['status']+_0x112e49(0x1cc)+(_0x4ac86a[_0x112e49(0x201)]||_0x112e49(0x152)));if(_0x4ac86a[_0x112e49(0x178)]===_0x112e49(0x1ee)){if(_0x4ac86a[_0x112e49(0x201)]===_0x112e49(0x1ae)){logger[_0x112e49(0x1f3)](_0x112e49(0x177)+_0x4ac86a['id']),_0x5f492b=_0x4ac86a;break;}else{logger[_0x112e49(0x1f3)]('工作流运行失败,结果:\x20'+_0x4ac86a[_0x112e49(0x201)]);break;}}}catch(_0x531471){_0x315bcc++,logger['error'](_0x112e49(0x1d0)+_0xd687a1+'/'+_0x47a07e+_0x112e49(0x1df)+_0x315bcc+'/'+_0xd7188f+_0x112e49(0x165)+_0x531471['message']);if(_0x315bcc>=_0xd7188f){logger[_0x112e49(0x148)](_0x112e49(0x1dd)+_0xd7188f+_0x112e49(0x151));break;}await new Promise(_0x1be239=>setTimeout(_0x1be239,0x2710));continue;}await new Promise(_0x31078b=>setTimeout(_0x31078b,0x7530));}}}!_0x5f492b&&logger[_0x112e49(0x1f3)](_0x112e49(0x184));}if(!_0x5f492b){logger[_0x112e49(0x1f3)](_0x112e49(0x1a2));const {data:_0x5be8d2}=await _0x241dbd['actions'][_0x112e49(0x17a)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'status':_0x112e49(0x1ae),'per_page':0x5});if(!_0x5be8d2[_0x112e49(0x164)]||_0x5be8d2[_0x112e49(0x164)][_0x112e49(0x1fa)]===0x0)return logger['info'](_0x112e49(0x1d4)),null;_0x5f492b=_0x5be8d2['workflow_runs'][0x0];}logger[_0x112e49(0x1f3)]('找到最新的工作流运行:\x20'+_0x5f492b['id']),logger[_0x112e49(0x1f3)](_0x112e49(0x190)),await new Promise(_0x59ca03=>setTimeout(_0x59ca03,0x2710));let _0x508681=null,_0x5bb855=0x0;const _0x8f471e=0xa;while(_0x5bb855<_0x8f471e&&(!_0x508681||!_0x508681[_0x112e49(0x1e3)]||_0x508681['artifacts'][_0x112e49(0x1fa)]===0x0)){_0x5bb855++,logger[_0x112e49(0x1f3)](_0x112e49(0x191)+_0x5bb855+'/'+_0x8f471e+_0x112e49(0x150));try{const _0x86a59=await _0x241dbd[_0x112e49(0x1a3)][_0x112e49(0x19a)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'run_id':_0x5f492b['id']});_0x508681=_0x86a59['data'];}catch(_0x2242e5){logger[_0x112e49(0x148)]('获取Artifacts时出错\x20(尝试\x20'+_0x5bb855+'/'+_0x8f471e+_0x112e49(0x165)+_0x2242e5['message']);}(!_0x508681||!_0x508681[_0x112e49(0x1e3)]||_0x508681[_0x112e49(0x1e3)][_0x112e49(0x1fa)]===0x0)&&(logger[_0x112e49(0x1f3)]('暂时没有找到Artifacts,等待10秒后重试...'),await new Promise(_0x46ec6c=>setTimeout(_0x46ec6c,0x2710)));}if(!_0x508681||!_0x508681['artifacts']||_0x508681[_0x112e49(0x1e3)][_0x112e49(0x1fa)]===0x0)return logger[_0x112e49(0x1f3)](_0x112e49(0x1fc)),null;logger[_0x112e49(0x1f3)]('找到\x20'+_0x508681[_0x112e49(0x1e3)][_0x112e49(0x1fa)]+'\x20个Artifacts');const _0xa87374=_0x508681[_0x112e49(0x1e3)][_0x112e49(0x1e6)](_0x33ee4f=>_0x33ee4f[_0x112e49(0x14d)]['toLowerCase']()[_0x112e49(0x170)](_0x112e49(0x1b9)));if(!_0xa87374)return logger['info']('没有找到\x20Account\x20info\x20Artifact'),null;return logger[_0x112e49(0x1f3)](_0x112e49(0x188)+_0xa87374['id']),_0xa87374;}catch(_0x51c37d){return logger[_0x112e49(0x148)](_0x112e49(0x187),_0x51c37d),null;}}async function downloadArtifact(_0x3c64c3){const _0x368aab=a0_0x2d975d;let _0x2e55a9=0x0;const _0x126db1=0x5;while(_0x2e55a9<_0x126db1){_0x2e55a9++;try{logger[_0x368aab(0x1f3)](_0x368aab(0x1db)+_0x3c64c3['id']+'...\x20(尝试\x20'+_0x2e55a9+'/'+_0x126db1+')'),ensureDirectoryExists(DOWNLOAD_DIR);const _0x27520c=new Octokit({'auth':GITHUB_TOKEN}),{url:_0x5dc5d0}=await _0x27520c[_0x368aab(0x1a3)][_0x368aab(0x1f8)]({'owner':GITHUB_OWNER,'repo':GITHUB_REPO,'artifact_id':_0x3c64c3['id'],'archive_format':_0x368aab(0x1c2)}),_0x5acb53=path[_0x368aab(0x1e1)](DOWNLOAD_DIR,_0x3c64c3['id']+_0x368aab(0x200)),_0x4020df=await axios({'method':'get','url':_0x5dc5d0,'responseType':'arraybuffer','timeout':0xea60});return fs[_0x368aab(0x193)](_0x5acb53,_0x4020df['data']),logger[_0x368aab(0x1f3)]('Artifact\x20下载完成:\x20'+_0x5acb53),_0x5acb53;}catch(_0x236397){logger['error']('下载\x20Artifact\x20失败\x20(尝试\x20'+_0x2e55a9+'/'+_0x126db1+_0x368aab(0x165)+_0x236397[_0x368aab(0x168)]);if(_0x2e55a9>=_0x126db1)return logger[_0x368aab(0x148)](_0x368aab(0x159)),null;const _0x5597f5=0x2710;logger[_0x368aab(0x1f3)](_0x368aab(0x1cb)+_0x5597f5/0x3e8+_0x368aab(0x175)),await new Promise(_0x5973a7=>setTimeout(_0x5973a7,_0x5597f5));}}return null;}async function extractArtifact(_0x1991cb){const _0x152326=a0_0x2d975d;let _0x2ec835=0x0;const _0x107790=0x3;while(_0x2ec835<_0x107790){_0x2ec835++;try{logger[_0x152326(0x1f3)](_0x152326(0x1ab)+_0x1991cb+_0x152326(0x186)+_0x2ec835+'/'+_0x107790+')'),ensureDirectoryExists(EXTRACT_DIR);const _0x44a8ae=new AdmZip(_0x1991cb);_0x44a8ae[_0x152326(0x19b)](EXTRACT_DIR,!![]),logger['info'](_0x152326(0x1d2)+EXTRACT_DIR);const _0x535130=fs['readdirSync'](EXTRACT_DIR),_0x273391=_0x535130[_0x152326(0x1e6)](_0x5d0e52=>_0x5d0e52['startsWith'](_0x152326(0x18e))&&_0x5d0e52[_0x152326(0x17b)](_0x152326(0x15b)));if(!_0x273391){logger['info'](_0x152326(0x176));if(_0x2ec835>=_0x107790)return null;const _0x39dd8a=0x1388;logger[_0x152326(0x1f3)]('等待\x20'+_0x39dd8a/0x3e8+_0x152326(0x175)),await new Promise(_0x2c31b6=>setTimeout(_0x2c31b6,_0x39dd8a));continue;}return logger[_0x152326(0x1f3)](_0x152326(0x1f0)+_0x273391),path[_0x152326(0x1e1)](EXTRACT_DIR,_0x273391);}catch(_0x29ff6b){logger[_0x152326(0x148)](_0x152326(0x156)+_0x2ec835+'/'+_0x107790+_0x152326(0x165)+_0x29ff6b[_0x152326(0x168)]);if(_0x2ec835>=_0x107790)return logger[_0x152326(0x148)](_0x152326(0x15a)),null;const _0x31f344=0x1388;logger[_0x152326(0x1f3)]('���待\x20'+_0x31f344/0x3e8+_0x152326(0x175)),await new Promise(_0x41bf89=>setTimeout(_0x41bf89,_0x31f344));}}return null;}async function extractCookiesFromCsvFile(_0x944353){const _0x56098f=a0_0x2d975d,_0x2f8048=0x3;let _0x12bb51=0x1;while(_0x12bb51<=_0x2f8048){logger[_0x56098f(0x1f3)]('尝试从CSV文件提取cookies\x20(尝试\x20'+_0x12bb51+'/'+_0x2f8048+_0x56098f(0x1b1));try{if(!fs[_0x56098f(0x1e7)](_0x944353))return logger[_0x56098f(0x148)](_0x56098f(0x1e2)+_0x944353),[];let _0x280202=fs['readFileSync'](_0x944353,_0x56098f(0x16c));_0x280202=_0x280202[_0x56098f(0x196)](/\r\n/g,'\x0a')[_0x56098f(0x196)](/\r/g,'\x0a');const _0x393eb5=[],_0x1d56f0=/ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,_0x1ca28e=_0x280202[_0x56098f(0x183)](_0x1d56f0);_0x1ca28e&&_0x1ca28e['length']>0x0&&(logger[_0x56098f(0x1f3)]('直接从文件内容中提取到\x20'+_0x1ca28e[_0x56098f(0x1fa)]+_0x56098f(0x1b0)),_0x1ca28e[_0x56098f(0x1d7)](_0x1684cb=>{const _0x5eb92=_0x56098f;!_0x393eb5[_0x5eb92(0x170)](_0x1684cb)&&_0x393eb5[_0x5eb92(0x1c8)](_0x1684cb);}));if(_0x280202[_0x56098f(0x170)](_0x56098f(0x1e0))){logger[_0x56098f(0x1f3)](_0x56098f(0x162));try{const _0x253c0e=await extractCookiesFromCsv(_0x944353);_0x253c0e&&_0x253c0e[_0x56098f(0x1fa)]>0x0&&(logger[_0x56098f(0x1f3)](_0x56098f(0x147)+_0x253c0e[_0x56098f(0x1fa)]+'\x20个cookie'),_0x253c0e[_0x56098f(0x1d7)](_0x5d5ec3=>{const _0x296fb1=_0x56098f;!_0x393eb5[_0x296fb1(0x170)](_0x5d5ec3)&&_0x393eb5[_0x296fb1(0x1c8)](_0x5d5ec3);}));}catch(_0x518c22){logger[_0x56098f(0x1cd)](_0x56098f(0x1a1),_0x518c22['message']);}}if(_0x393eb5['length']>0x0){const _0x364e74=_0x393eb5[_0x56098f(0x1cf)](_0x288d5e=>_0x288d5e['startsWith']('ey'))['length'],_0x113862=_0x393eb5[_0x56098f(0x1cf)](_0x1ba8b2=>_0x1ba8b2['includes']('%3A%3A'))[_0x56098f(0x1fa)];return logger[_0x56098f(0x1f3)](_0x56098f(0x1be)+_0x393eb5[_0x56098f(0x1fa)]+'\x20个cookie'),logger['info'](_0x56098f(0x1e4)+_0x364e74+'个'),logger[_0x56098f(0x1f3)]('旧格式cookie(包含%3A%3A):\x20'+_0x113862+'个'),logger[_0x56098f(0x1f3)](_0x56098f(0x18b)+(_0x393eb5[_0x56098f(0x1fa)]-_0x364e74-_0x113862)+'个'),_0x393eb5;}logger[_0x56098f(0x1cd)](_0x56098f(0x1fd)+_0x12bb51+'/'+_0x2f8048+')');}catch(_0x5955f0){logger[_0x56098f(0x148)](_0x56098f(0x14c)+_0x12bb51+'/'+_0x2f8048+'):',_0x5955f0);}_0x12bb51++,_0x12bb51<=_0x2f8048&&(logger[_0x56098f(0x1f3)]('等待5秒后重试...'),await new Promise(_0x4b66a0=>setTimeout(_0x4b66a0,0x1388)));}return logger[_0x56098f(0x148)]('在\x20'+_0x2f8048+_0x56098f(0x16f)),[];}function addNewCookiesToSystem(_0x1e29b6,_0x5a5ffe){const _0x2c35e0=a0_0x2d975d;try{logger[_0x2c35e0(0x1f3)](_0x2c35e0(0x1eb)+_0x5a5ffe[_0x2c35e0(0x1fa)]+'\x20个新cookie到系统中');const _0x1df003=keyManager[_0x2c35e0(0x1a5)](_0x1e29b6)||[];logger['info'](_0x2c35e0(0x1e5)+_0x1e29b6+'\x20有\x20'+_0x1df003[_0x2c35e0(0x1fa)]+_0x2c35e0(0x158));const _0x54dbab=keyManager[_0x2c35e0(0x1b3)]()||[];logger[_0x2c35e0(0x1f3)](_0x2c35e0(0x17f)+(_0x54dbab[_0x2c35e0(0x1fa)]||0x0)+_0x2c35e0(0x157));let _0x3b7f0f=[];if(_0x54dbab instanceof Set)_0x3b7f0f=_0x5a5ffe[_0x2c35e0(0x1cf)](_0x1b5409=>!_0x1df003[_0x2c35e0(0x170)](_0x1b5409)&&!_0x54dbab[_0x2c35e0(0x169)](_0x1b5409));else{if(Array[_0x2c35e0(0x1af)](_0x54dbab))_0x3b7f0f=_0x5a5ffe[_0x2c35e0(0x1cf)](_0x52a3c7=>!_0x1df003[_0x2c35e0(0x170)](_0x52a3c7)&&!_0x54dbab[_0x2c35e0(0x170)](_0x52a3c7));else _0x54dbab&&typeof _0x54dbab==='object'?_0x3b7f0f=_0x5a5ffe[_0x2c35e0(0x1cf)](_0x3f3b52=>!_0x1df003['includes'](_0x3f3b52)&&!(_0x3f3b52 in _0x54dbab)):_0x3b7f0f=_0x5a5ffe['filter'](_0x26f43d=>!_0x1df003['includes'](_0x26f43d));}logger['info'](_0x2c35e0(0x17c)+_0x3b7f0f['length']+'\x20个新的有效cookies');const _0x2238bf=_0x3b7f0f[_0x2c35e0(0x1cf)](_0x4248e2=>{const _0x16af9b=_0x2c35e0;if(_0x4248e2[_0x16af9b(0x1ec)]('ey')&&_0x4248e2[_0x16af9b(0x170)]('.')){const _0x4f959c=_0x4248e2['split']('.');if(_0x4f959c[_0x16af9b(0x1fa)]!==0x3)return logger[_0x16af9b(0x1cd)]('跳过不完整的JWT\x20cookie\x20(新格式):\x20'+_0x4248e2),![];return!![];}else{if(_0x4248e2[_0x16af9b(0x170)](_0x16af9b(0x1aa))){const _0x54a7c5=_0x4248e2['split'](_0x16af9b(0x1aa));if(_0x54a7c5[_0x16af9b(0x1fa)]===0x2){const _0x797a1e=_0x54a7c5[0x1];if(!_0x797a1e[_0x16af9b(0x170)]('.')||_0x797a1e['split']('.')[_0x16af9b(0x1fa)]!==0x3)return logger[_0x16af9b(0x1cd)]('跳过不完整的cookie\x20(旧格式):\x20'+_0x4248e2),![];}}}return!![];});return logger[_0x2c35e0(0x1f3)]('验证完整性后有\x20'+_0x2238bf['length']+_0x2c35e0(0x180)),_0x2238bf[_0x2c35e0(0x1fa)]>0x0?(keyManager['addOrUpdateApiKey'](_0x1e29b6,[..._0x1df003,..._0x2238bf]),logger[_0x2c35e0(0x1f3)](_0x2c35e0(0x144)+_0x2238bf[_0x2c35e0(0x1fa)]+_0x2c35e0(0x1fb)+_0x1e29b6),_0x2238bf[_0x2c35e0(0x1fa)]):(logger['info']('没有新的有效cookie需要添加到API密钥\x20'+_0x1e29b6),0x0);}catch(_0x33a5ec){return logger[_0x2c35e0(0x148)](_0x2c35e0(0x182),_0x33a5ec),0x0;}}function cleanupTempFiles(){const _0xaabed6=a0_0x2d975d;try{logger[_0xaabed6(0x1f3)](_0xaabed6(0x1b2)),fs[_0xaabed6(0x1e7)](DOWNLOAD_DIR)&&fs[_0xaabed6(0x18f)](DOWNLOAD_DIR)[_0xaabed6(0x1d7)](_0x3b9383=>{const _0x4c852d=_0xaabed6;fs[_0x4c852d(0x1f6)](path[_0x4c852d(0x1e1)](DOWNLOAD_DIR,_0x3b9383));}),fs[_0xaabed6(0x1e7)](EXTRACT_DIR)&&fs[_0xaabed6(0x18f)](EXTRACT_DIR)[_0xaabed6(0x1d7)](_0x55cc2d=>{const _0x297553=_0xaabed6;fs[_0x297553(0x1f6)](path[_0x297553(0x1e1)](EXTRACT_DIR,_0x55cc2d));}),logger['info'](_0xaabed6(0x1a4));}catch(_0x19147d){logger[_0xaabed6(0x148)](_0xaabed6(0x1de),_0x19147d);}}function checkApiKeyNeedRefresh(_0x5a7da7,_0x2f4ddc=config[a0_0x2d975d(0x1f2)][a0_0x2d975d(0x1c0)]){const _0x29a3b1=a0_0x2d975d,_0x3a2101=keyManager[_0x29a3b1(0x1a5)](_0x5a7da7);return _0x3a2101[_0x29a3b1(0x1fa)]<_0x2f4ddc;}function markExistingCookiesAsInvalid(_0x45a4e2){const _0x317921=a0_0x2d975d;try{const _0x430751=keyManager[_0x317921(0x1a5)](_0x45a4e2)||[];logger['info'](_0x317921(0x1d1)+_0x45a4e2+_0x317921(0x1d5)+_0x430751[_0x317921(0x1fa)]+_0x317921(0x173));if(_0x430751[_0x317921(0x1fa)]===0x0)return logger['info'](_0x317921(0x1a9)+_0x45a4e2+_0x317921(0x1f4)),0x0;const _0x445ccf=keyManager[_0x317921(0x1b3)]();let _0xba6595=0x0;for(const _0x540791 of _0x430751){_0x445ccf instanceof Set&&_0x445ccf['add'](_0x540791),_0xba6595++;}return keyManager[_0x317921(0x19c)](),keyManager[_0x317921(0x179)](_0x45a4e2,[]),keyManager[_0x317921(0x1ce)](),logger[_0x317921(0x1f3)]('已将API\x20Key\x20'+_0x45a4e2+_0x317921(0x1d5)+_0xba6595+_0x317921(0x19d)),_0xba6595;}catch(_0x186242){return logger[_0x317921(0x148)]('标记现有cookie为无效时出错:',_0x186242),0x0;}}async function autoRefreshCookies(_0xf79222,_0x14b5de=config[a0_0x2d975d(0x1f2)]['minCookieCount']){const _0x5acb0a=a0_0x2d975d;logger[_0x5acb0a(0x1f3)](_0x5acb0a(0x1e8)+_0xf79222+',最小\x20Cookie\x20数量:\x20'+_0x14b5de);try{if(!checkApiKeyNeedRefresh(_0xf79222,_0x14b5de))return logger[_0x5acb0a(0x1f3)](_0x5acb0a(0x1a9)+_0xf79222+_0x5acb0a(0x1bf)),{'success':!![],'message':_0x5acb0a(0x197),'refreshed':0x0};const _0x22f2e8=await getLatestArtifact();if(!_0x22f2e8)return{'success':![],'message':'获取\x20Artifact\x20失败','refreshed':0x0};const _0x8f3dd4=await downloadArtifact(_0x22f2e8);if(!_0x8f3dd4)return{'success':![],'message':_0x5acb0a(0x1bb),'refreshed':0x0};const _0x3a01e2=await extractArtifact(_0x8f3dd4);if(!_0x3a01e2)return{'success':![],'message':_0x5acb0a(0x199),'refreshed':0x0};const _0x52bf9b=await extractCookiesFromCsvFile(_0x3a01e2);if(_0x52bf9b[_0x5acb0a(0x1fa)]===0x0)return{'success':![],'message':_0x5acb0a(0x1a7),'refreshed':0x0};const _0x14f8cb=_0x52bf9b[_0x5acb0a(0x1cf)](_0x241c26=>_0x241c26[_0x5acb0a(0x1ec)]('ey')),_0x43b761=_0x52bf9b[_0x5acb0a(0x1cf)](_0x1be953=>_0x1be953['includes'](_0x5acb0a(0x1aa)));logger[_0x5acb0a(0x1f3)](_0x5acb0a(0x1d9)+_0x14f8cb[_0x5acb0a(0x1fa)]+_0x5acb0a(0x1ed)),logger[_0x5acb0a(0x1f3)]('提取到\x20'+_0x43b761[_0x5acb0a(0x1fa)]+_0x5acb0a(0x14e));const _0x2eb4b7=process['env']['COOKIE_REFRESH_MODE']||_0x5acb0a(0x194);_0x2eb4b7===_0x5acb0a(0x196)?(logger['info'](_0x5acb0a(0x1f9)),markExistingCookiesAsInvalid(_0xf79222)):logger[_0x5acb0a(0x1f3)](_0x5acb0a(0x15d));const _0x5519f1=addNewCookiesToSystem(_0xf79222,_0x52bf9b);return cleanupTempFiles(),{'success':!![],'message':'成功添加\x20'+_0x5519f1+_0x5acb0a(0x1a0)+_0x14f8cb['length']+_0x5acb0a(0x192)+_0x43b761['length']+')','refreshed':_0x5519f1};}catch(_0x4e2d7f){return logger['error'](_0x5acb0a(0x1d3),_0x4e2d7f),{'success':![],'message':_0x5acb0a(0x149)+_0x4e2d7f[_0x5acb0a(0x168)],'refreshed':0x0};}}module['exports']={'autoRefreshCookies':autoRefreshCookies,'checkApiKeyNeedRefresh':checkApiKeyNeedRefresh,'getLatestArtifact':getLatestArtifact,'downloadArtifact':downloadArtifact,'extractArtifact':extractArtifact,'extractCookiesFromCsvFile':extractCookiesFromCsvFile,'addNewCookiesToSystem':addNewCookiesToSystem,'cleanupTempFiles':cleanupTempFiles,'triggerWorkflow':triggerWorkflow,'markExistingCookiesAsInvalid':markExistingCookiesAsInvalid};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/envChecker.js CHANGED
@@ -1,76 +1 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- /**
5
- * 检查 .env 文件是否存在
6
- * @returns {boolean} 文件是否存在
7
- */
8
- function checkEnvFileExists() {
9
- const envPath = path.resolve(process.cwd(), '.env');
10
- return fs.existsSync(envPath);
11
- }
12
-
13
- /**
14
- * 检查必要的环境变量是否已设置
15
- * @returns {Object} 检查结果,包含是否通过和缺失的变量列表
16
- */
17
- function checkRequiredEnvVars() {
18
- // 定义必要的环境变量列表
19
- const requiredVars = [
20
- 'API_KEYS', // API Keys 配置
21
- ];
22
-
23
- // 如果启用了自动刷新,则需要检查相关配置
24
- if (process.env.ENABLE_AUTO_REFRESH === 'true') {
25
- requiredVars.push(
26
- 'GITHUB_TOKEN',
27
- 'GITHUB_OWNER',
28
- 'GITHUB_REPO',
29
- 'GITHUB_WORKFLOW_ID',
30
- 'TRIGGER_WORKFLOW'
31
- );
32
- }
33
-
34
- // 检查每个必要的环境变量
35
- const missingVars = requiredVars.filter(varName => !process.env[varName]);
36
-
37
- return {
38
- passed: missingVars.length === 0,
39
- missingVars
40
- };
41
- }
42
-
43
- /**
44
- * 执行环境检查,如果不符合要求则退出程序
45
- */
46
- function enforceEnvCheck() {
47
- console.log('正在检查环境配置...');
48
-
49
- // 检查 .env 文件是否存在
50
- const envFileExists = checkEnvFileExists();
51
- if (!envFileExists) {
52
- console.error('\n错误: 未找到 .env 文件!');
53
- console.error('请根据 .env.example 创建 .env 文件并配置必要的环境变量。');
54
- console.error('执行以下命令复制示例文件: cp .env.example .env,或执行npm run setup\n');
55
- process.exit(1); // 退出程序,状态码 1 表示错误
56
- }
57
-
58
- // 检查必要的环境变量
59
- const { passed, missingVars } = checkRequiredEnvVars();
60
- if (!passed) {
61
- console.error('\n错误: 以下必要的环境变量未在 .env 文件中设置:');
62
- missingVars.forEach(varName => {
63
- console.error(` - ${varName}`);
64
- });
65
- console.error('\n请在 .env 文件中配置这些变量后重新启动程序。\n');
66
- process.exit(1); // 退出程序,状态码 1 表示错误
67
- }
68
-
69
- console.log('环境检查通过,继续启动程序...');
70
- }
71
-
72
- module.exports = {
73
- checkEnvFileExists,
74
- checkRequiredEnvVars,
75
- enforceEnvCheck
76
- };
 
1
+ const a0_0x492535=a0_0x47f1;(function(_0x71b27b,_0x381653){const _0x135caf=a0_0x47f1,_0x1b2eb9=_0x71b27b();while(!![]){try{const _0x39ac91=-parseInt(_0x135caf(0xcb))/0x1*(-parseInt(_0x135caf(0xd0))/0x2)+-parseInt(_0x135caf(0xd8))/0x3+parseInt(_0x135caf(0xb3))/0x4*(-parseInt(_0x135caf(0xbe))/0x5)+-parseInt(_0x135caf(0xb9))/0x6*(-parseInt(_0x135caf(0xd6))/0x7)+parseInt(_0x135caf(0xcc))/0x8+-parseInt(_0x135caf(0xd4))/0x9*(parseInt(_0x135caf(0xbb))/0xa)+parseInt(_0x135caf(0xce))/0xb*(-parseInt(_0x135caf(0xba))/0xc);if(_0x39ac91===_0x381653)break;else _0x1b2eb9['push'](_0x1b2eb9['shift']());}catch(_0x53a1eb){_0x1b2eb9['push'](_0x1b2eb9['shift']());}}}(a0_0x1db0,0x8309b));const a0_0x174a9f=(function(){let _0x3e64e4=!![];return function(_0x2c8f95,_0x4d8177){const _0x4be7dd=_0x3e64e4?function(){const _0x26a86c=a0_0x47f1;if(_0x4d8177){const _0x2ecc58=_0x4d8177[_0x26a86c(0xd3)](_0x2c8f95,arguments);return _0x4d8177=null,_0x2ecc58;}}:function(){};return _0x3e64e4=![],_0x4be7dd;};}()),a0_0xffc43a=a0_0x174a9f(this,function(){const _0x472035=a0_0x47f1;return a0_0xffc43a[_0x472035(0xb2)]()[_0x472035(0xb1)](_0x472035(0xae))[_0x472035(0xb2)]()[_0x472035(0xb8)](a0_0xffc43a)['search'](_0x472035(0xae));});a0_0xffc43a();function a0_0x47f1(_0x166522,_0x2fea1a){const _0x274656=a0_0x1db0();return a0_0x47f1=function(_0xffc43a,_0x174a9f){_0xffc43a=_0xffc43a-0xae;let _0x1db0ce=_0x274656[_0xffc43a];if(a0_0x47f1['egpcFC']===undefined){var _0x47f1be=function(_0x478578){const _0x31f11c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x516c4d='',_0x3e64e4='',_0x2c8f95=_0x516c4d+_0x47f1be;for(let _0x4d8177=0x0,_0x4be7dd,_0x2ecc58,_0x787726=0x0;_0x2ecc58=_0x478578['charAt'](_0x787726++);~_0x2ecc58&&(_0x4be7dd=_0x4d8177%0x4?_0x4be7dd*0x40+_0x2ecc58:_0x2ecc58,_0x4d8177++%0x4)?_0x516c4d+=_0x2c8f95['charCodeAt'](_0x787726+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x4be7dd>>(-0x2*_0x4d8177&0x6)):_0x4d8177:0x0){_0x2ecc58=_0x31f11c['indexOf'](_0x2ecc58);}for(let _0x28f92d=0x0,_0x42b278=_0x516c4d['length'];_0x28f92d<_0x42b278;_0x28f92d++){_0x3e64e4+='%'+('00'+_0x516c4d['charCodeAt'](_0x28f92d)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3e64e4);};a0_0x47f1['TSunAF']=_0x47f1be,_0x166522=arguments,a0_0x47f1['egpcFC']=!![];}const _0x1e59c9=_0x274656[0x0],_0x1958f8=_0xffc43a+_0x1e59c9,_0x14212d=_0x166522[_0x1958f8];if(!_0x14212d){const _0x43e7c3=function(_0x557b81){this['KQcOdu']=_0x557b81,this['CYoOnf']=[0x1,0x0,0x0],this['dVIpwD']=function(){return'newState';},this['nkqunR']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['AWFqgA']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x43e7c3['prototype']['QrWZTi']=function(){const _0x34dbd8=new RegExp(this['nkqunR']+this['AWFqgA']),_0x3e4bcc=_0x34dbd8['test'](this['dVIpwD']['toString']())?--this['CYoOnf'][0x1]:--this['CYoOnf'][0x0];return this['mJugls'](_0x3e4bcc);},_0x43e7c3['prototype']['mJugls']=function(_0x26818f){if(!Boolean(~_0x26818f))return _0x26818f;return this['fnsfkD'](this['KQcOdu']);},_0x43e7c3['prototype']['fnsfkD']=function(_0x75eaae){for(let _0xaaf879=0x0,_0x519196=this['CYoOnf']['length'];_0xaaf879<_0x519196;_0xaaf879++){this['CYoOnf']['push'](Math['round'](Math['random']())),_0x519196=this['CYoOnf']['length'];}return _0x75eaae(this['CYoOnf'][0x0]);},new _0x43e7c3(a0_0x47f1)['QrWZTi'](),_0x1db0ce=a0_0x47f1['TSunAF'](_0x1db0ce),_0x166522[_0x1958f8]=_0x1db0ce;}else _0x1db0ce=_0x14212d;return _0x1db0ce;},a0_0x47f1(_0x166522,_0x2fea1a);}const fs=require('fs'),path=require('path');function log(_0x787726,_0x28f92d){const _0x2536fa=a0_0x47f1,_0x42b278=new Date()['toISOString']();if(_0x787726==='ERROR')console[_0x2536fa(0xbc)]('[ERROR]\x20'+_0x42b278+'\x20'+_0x28f92d);else _0x787726==='WARN'?console['warn'](_0x2536fa(0xb4)+_0x42b278+'\x20'+_0x28f92d):console[_0x2536fa(0xc5)](_0x2536fa(0xc1)+_0x42b278+'\x20'+_0x28f92d);}function checkEnvFileExists(){const _0x5685ab=a0_0x47f1,_0x43e7c3=path[_0x5685ab(0xbd)](process[_0x5685ab(0xb0)](),_0x5685ab(0xc3));return fs[_0x5685ab(0xc8)](_0x43e7c3);}function a0_0x1db0(){const _0x382f3e=['mJe1mKXjrMrKvW','w1DbuK5Dia','546V5Akd5Qoa5P+L6ycA6l+h77Ym57UN57UT5zcV5yQO56Il5BQplI4U','zxHPDa','su5gtW','y29UC3rYDwn0B3i','mZi0ndj5zxjIzNu','mJi3ntyWohfpvhPjAa','mty5mgnSA3DnCa','zxjYB3i','CMvZB2X2zq','nJK2nwz6EgnxBq','cUMuMEIVRZOG5lUL5lIl5B+f6kAb55Qe546V5Akd5y+y6yEp5PYQ5zYOic5LBNyG5PAh5lU25lIT6k6+572UoG','ru5bqKXfx0fvve9FuKvguKvtsa','w0LorK9Dia','zw52','lMvUDG','zxHWB3j0CW','Bg9N','rvjst1i','r0Lusfvcx1rps0vo','zxHPC3rZu3LUyW','zM9YrwfJAa','5OMN6kgm5lUL5lIl5zg95lUK5Asn5yI256s65l6l5PAh5lU2oIbJCcaUzw52lMv4yw1WBguGlMvUDIZMIjBMIAFOOyXUCg0GCNvUihnLDhvWcG','mteYmtu3zgz1qKDP','odq2nJi0ogDMqujSBG','r0Lusfvcx1DpuKTgte9xx0Le','mZnrrefKBwK','cUMuMEIVRZOG5PYQ5OM+5yIWic5LBNyG5PAh5lU2iq','mtrizw1eCKS','r0Lusfvcx1jfue8','BgvUz3rO','yxbWBhK','otGXuKTjwwPr','r0Lusfvcx09xtKvs','nte4D2nXrePr','zMLSDgvY','mteXmdaZmhz0y3HdyG','kcGOlISPkYKRksSK','qvbjx0Tfwvm','y3DK','C2vHCMnO','Dg9tDhjPBMC'];a0_0x1db0=function(){return _0x382f3e;};return a0_0x1db0();}function checkRequiredEnvVars(){const _0x1c261d=a0_0x47f1,_0x557b81=[_0x1c261d(0xaf)];process[_0x1c261d(0xc2)][_0x1c261d(0xc0)]==='true'&&_0x557b81['push'](_0x1c261d(0xc7),_0x1c261d(0xd5),_0x1c261d(0xd1),_0x1c261d(0xcd),'TRIGGER_WORKFLOW');const _0x34dbd8=_0x557b81[_0x1c261d(0xd7)](_0x3e4bcc=>!process[_0x1c261d(0xc2)][_0x3e4bcc]);return{'passed':_0x34dbd8[_0x1c261d(0xd2)]===0x0,'missingVars':_0x34dbd8};}function enforceEnvCheck(){const _0x2943f2=a0_0x47f1;log(_0x2943f2(0xb7),'正在检查环境配置...');const _0x26818f=checkEnvFileExists();!_0x26818f&&(log(_0x2943f2(0xc6),_0x2943f2(0xcf)),log('ERROR','请根据\x20.env.example\x20创建\x20.env\x20文件并配置必要的环境变量。'),log('ERROR',_0x2943f2(0xca)),process[_0x2943f2(0xb6)](0x1));const {passed:_0x75eaae,missingVars:_0xaaf879}=checkRequiredEnvVars();!_0x75eaae&&(log('ERROR',_0x2943f2(0xbf)),_0xaaf879[_0x2943f2(0xc9)](_0x519196=>{log('ERROR','\x20\x20-\x20'+_0x519196);}),log('ERROR','\x0a请在\x20.env\x20文件中配置这些变量后重新启动程序。\x0a'),process[_0x2943f2(0xb6)](0x1)),log(_0x2943f2(0xb7),_0x2943f2(0xb5));}module[a0_0x492535(0xc4)]={'checkEnvFileExists':checkEnvFileExists,'checkRequiredEnvVars':checkRequiredEnvVars,'enforceEnvCheck':enforceEnvCheck};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/extractCookieFromCsv.js CHANGED
@@ -1,269 +1 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const csv = require('csv-parser');
4
-
5
- /**
6
- * 从CSV文件中提取完整的cookie
7
- * @param {string} csvFilePath - CSV文件路径
8
- * @returns {Promise<string[]>} - 提取到的cookie数组
9
- */
10
- async function extractCookiesFromCsv(csvFilePath) {
11
- return new Promise((resolve, reject) => {
12
- try {
13
- // 检查文件是否存在
14
- if (!fs.existsSync(csvFilePath)) {
15
- console.error(`CSV文件不存在: ${csvFilePath}`);
16
- return resolve([]);
17
- }
18
-
19
- // 读取文件内容
20
- const fileContent = fs.readFileSync(csvFilePath, 'utf8');
21
- console.log(`文件内容前200个字符: ${fileContent.substring(0, 200)}`);
22
-
23
- // 检查文件是否为空
24
- if (!fileContent || fileContent.trim() === '') {
25
- console.error('CSV文件为空');
26
- return resolve([]);
27
- }
28
-
29
- // 首先尝试直接从文件内容中提取所有可能的cookie
30
- const cookies = [];
31
-
32
- // 检查是否有JWT格式的token (新格式)
33
- const jwtRegex = /ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
34
- const jwtMatches = fileContent.match(jwtRegex);
35
-
36
- if (jwtMatches && jwtMatches.length > 0) {
37
- console.log(`直接从文件内容中提取到 ${jwtMatches.length} 个JWT token格式的Cookie`);
38
- jwtMatches.forEach(match => {
39
- if (!cookies.includes(match)) {
40
- cookies.push(match);
41
- }
42
- });
43
- }
44
-
45
- // 检查文件内容是否包含关键字
46
- const hasTokenKeyword = fileContent.includes('token');
47
- const hasUserPrefix = fileContent.includes('user_');
48
- console.log(`文件包含"token"关键字: ${hasTokenKeyword}`);
49
- console.log(`文件包含"user_"前缀: ${hasUserPrefix}`);
50
-
51
- // 如果文件包含user_前缀,尝试提取旧格式cookie
52
- if (hasUserPrefix) {
53
- const oldFormatCookies = extractCookiesFromText(fileContent);
54
- if (oldFormatCookies.length > 0) {
55
- console.log(`从文件内容中提取到 ${oldFormatCookies.length} 个旧格式Cookie`);
56
- oldFormatCookies.forEach(cookie => {
57
- if (!cookies.includes(cookie)) {
58
- cookies.push(cookie);
59
- }
60
- });
61
- }
62
- }
63
-
64
- // 如果已经找到cookie,返回结果
65
- if (cookies.length > 0) {
66
- console.log(`总共提取到 ${cookies.length} 个Cookie`);
67
- return resolve(validateCookies(cookies));
68
- }
69
-
70
- // 使用csv-parser解析CSV文件
71
- const possibleTokenFields = ['token', 'cookie', 'value', 'Token', 'Cookie', 'Value', 'jwt', 'JWT'];
72
-
73
- fs.createReadStream(csvFilePath)
74
- .pipe(csv())
75
- .on('data', (row) => {
76
- // 检查所有可能的字段名
77
- for (const field of possibleTokenFields) {
78
- if (row[field]) {
79
- // 检查是否是JWT格式
80
- if (row[field].startsWith('ey') && row[field].includes('.')) {
81
- if (!cookies.includes(row[field])) {
82
- cookies.push(row[field]);
83
- }
84
- break;
85
- }
86
- // 检查是否是旧格式
87
- else if (row[field].includes('user_')) {
88
- if (!cookies.includes(row[field])) {
89
- cookies.push(row[field]);
90
- }
91
- break;
92
- }
93
- }
94
- }
95
-
96
- // 如果没有找到预定义的字段,遍历所有字段
97
- if (cookies.length === 0) {
98
- for (const field in row) {
99
- if (row[field] && typeof row[field] === 'string') {
100
- // 检查是否是JWT格式
101
- if (row[field].startsWith('ey') && row[field].includes('.')) {
102
- if (!cookies.includes(row[field])) {
103
- cookies.push(row[field]);
104
- }
105
- break;
106
- }
107
- // 检查是否是旧格式
108
- else if (row[field].includes('user_')) {
109
- if (!cookies.includes(row[field])) {
110
- cookies.push(row[field]);
111
- }
112
- break;
113
- }
114
- }
115
- }
116
- }
117
- })
118
- .on('end', () => {
119
- console.log(`从CSV解析中提取到 ${cookies.length} 个Cookie`);
120
-
121
- // 如果通过CSV解析没有找到cookie,尝试按行读取
122
- if (cookies.length === 0) {
123
- console.log('尝试按行读取文件...');
124
- const lines = fileContent.split('\n');
125
- for (const line of lines) {
126
- // 检查是否有JWT格式token
127
- if (line.includes('ey')) {
128
- const jwtMatches = line.match(jwtRegex);
129
- if (jwtMatches) {
130
- jwtMatches.forEach(match => {
131
- if (!cookies.includes(match)) {
132
- cookies.push(match);
133
- }
134
- });
135
- }
136
- }
137
-
138
- // 检查是否有旧格式cookie
139
- if (line.includes('user_')) {
140
- const extractedCookies = extractCookiesFromText(line);
141
- extractedCookies.forEach(cookie => {
142
- if (!cookies.includes(cookie)) {
143
- cookies.push(cookie);
144
- }
145
- });
146
- }
147
- }
148
- console.log(`按行读取后提取到 ${cookies.length} 个Cookie`);
149
- }
150
-
151
- // 验证提取的cookie是否完整
152
- const validatedCookies = validateCookies(cookies);
153
-
154
- resolve(validatedCookies);
155
- })
156
- .on('error', (error) => {
157
- console.error('解析CSV文件时出错:', error);
158
-
159
- // 如果已经提取到cookie,直接返回
160
- if (cookies.length > 0) {
161
- console.log(`解析出错但已提取到 ${cookies.length} 个Cookie,进行验证后返回`);
162
- resolve(validateCookies(cookies));
163
- } else {
164
- // 否则尝试其他方法提取
165
- console.log('尝试其他方法提取Cookie...');
166
-
167
- // 尝试提取JWT格式token
168
- const jwtMatches = fileContent.match(jwtRegex);
169
- if (jwtMatches) {
170
- jwtMatches.forEach(match => {
171
- if (!cookies.includes(match)) {
172
- cookies.push(match);
173
- }
174
- });
175
- }
176
-
177
- // 尝试提取旧格式cookie
178
- const oldFormatCookies = extractCookiesFromText(fileContent);
179
- oldFormatCookies.forEach(cookie => {
180
- if (!cookies.includes(cookie)) {
181
- cookies.push(cookie);
182
- }
183
- });
184
-
185
- console.log(`通过其他方法提取到 ${cookies.length} 个Cookie`);
186
- resolve(validateCookies(cookies));
187
- }
188
- });
189
- } catch (error) {
190
- console.error('提取Cookie时出错:', error);
191
- reject(error);
192
- }
193
- });
194
- }
195
-
196
- /**
197
- * 从文本中提取cookie
198
- * @param {string} text - 要提取cookie的文本
199
- * @returns {string[]} - 提取到的cookie数组
200
- */
201
- function extractCookiesFromText(text) {
202
- const cookies = [];
203
-
204
- // 使用正则表达式匹配user_开头的cookie(旧格式)
205
- const oldFormatRegex = /user_[a-zA-Z0-9%]+%3A%3A[a-zA-Z0-9%\.\_\-]+/g;
206
- const oldFormatMatches = text.match(oldFormatRegex);
207
-
208
- if (oldFormatMatches) {
209
- oldFormatMatches.forEach(match => {
210
- if (!cookies.includes(match)) {
211
- cookies.push(match);
212
- }
213
- });
214
- }
215
-
216
- // 使用正则表达式匹配以ey开头的JWT格式cookie(新格式)
217
- const jwtRegex = /ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
218
- const jwtMatches = text.match(jwtRegex);
219
-
220
- if (jwtMatches) {
221
- jwtMatches.forEach(match => {
222
- if (!cookies.includes(match)) {
223
- cookies.push(match);
224
- }
225
- });
226
- }
227
-
228
- return cookies;
229
- }
230
-
231
- /**
232
- * 验证cookie是否完整
233
- * @param {string[]} cookies - 要验证的cookie数组
234
- * @returns {string[]} - 验证后的cookie数组
235
- */
236
- function validateCookies(cookies) {
237
- return cookies.filter(cookie => {
238
- // 检查是否是新格式的JWT token (ey开头)
239
- if (cookie.startsWith('ey') && cookie.includes('.')) {
240
- const parts = cookie.split('.');
241
- // 检查JWT是否包含三个部分
242
- if (parts.length === 3) {
243
- return true; // cookie有效
244
- } else {
245
- console.warn(`检测到不完整的JWT(新格式): ${cookie}`);
246
- return false;
247
- }
248
- }
249
- // 检查旧格式cookie是否完整
250
- else if (cookie.includes('%3A%3A')) {
251
- const parts = cookie.split('%3A%3A');
252
- if (parts.length === 2) {
253
- const jwt = parts[1];
254
- // 检查JWT是否包含两个点(表示三个部分)
255
- if (jwt.includes('.') && jwt.split('.').length === 3) {
256
- return true; // cookie完整
257
- } else {
258
- console.warn(`检测到不完整的JWT(旧格式): ${cookie}`);
259
- return false;
260
- }
261
- }
262
- }
263
- return true; // 对于无法识别的格式,默认保留
264
- });
265
- }
266
-
267
- module.exports = {
268
- extractCookiesFromCsv
269
- };
 
1
+ const a0_0x5d0726=a0_0x49ee;(function(_0x16e461,_0x5f008a){const _0x3dc6c3=a0_0x49ee,_0x5275b6=_0x16e461();while(!![]){try{const _0x503736=parseInt(_0x3dc6c3(0x9f))/0x1+-parseInt(_0x3dc6c3(0xbe))/0x2*(-parseInt(_0x3dc6c3(0xc0))/0x3)+-parseInt(_0x3dc6c3(0xb5))/0x4*(-parseInt(_0x3dc6c3(0xa5))/0x5)+-parseInt(_0x3dc6c3(0x9a))/0x6+-parseInt(_0x3dc6c3(0xb3))/0x7*(-parseInt(_0x3dc6c3(0xc1))/0x8)+parseInt(_0x3dc6c3(0xbb))/0x9+-parseInt(_0x3dc6c3(0xbf))/0xa*(parseInt(_0x3dc6c3(0xa9))/0xb);if(_0x503736===_0x5f008a)break;else _0x5275b6['push'](_0x5275b6['shift']());}catch(_0x2ac29c){_0x5275b6['push'](_0x5275b6['shift']());}}}(a0_0x337d,0xe3249));const a0_0x5f1ac8=(function(){let _0x1398ba=!![];return function(_0x509dc8,_0x89f624){const _0x31174d=_0x1398ba?function(){const _0x16adea=a0_0x49ee;if(_0x89f624){const _0x243ee8=_0x89f624[_0x16adea(0xb1)](_0x509dc8,arguments);return _0x89f624=null,_0x243ee8;}}:function(){};return _0x1398ba=![],_0x31174d;};}()),a0_0xfe4ea8=a0_0x5f1ac8(this,function(){const _0x5a87ab=a0_0x49ee;return a0_0xfe4ea8['toString']()['search'](_0x5a87ab(0x92))[_0x5a87ab(0x9b)]()['constructor'](a0_0xfe4ea8)[_0x5a87ab(0x9c)]('(((.+)+)+)+$');});a0_0xfe4ea8();function a0_0x337d(){const _0x24e6bb=['Aw5JBhvKzxm','CMvHzezPBgvtEw5J','AND0','nZGWzuDoD2XJ','zxHPC3rZu3LUyW','DxnLCL8','jtnbjtnb','otLxrgTjzKK','zxjYB3i','5OYj6kgm6k+75y+w5zco5O+q5y+w5yIWia','C3bSAxq','5BcD6k+v5OYj6kgm6k+75y+w5PAh5lU2lI4U','6ycA6l+h5yw25lUw5PA55Rov5O+q5y+w5yIWia','zgf0yq','5lUo5PAh5lU25yAf5A655lIT5O+q5y+w5yIWia','yxbWBhK','CgLWzq','mZu1ntnArLLzvLi','q29VA2LL','otC3nNP6ug5Yzq','BgvUz3rO','5PAh5lU25yAf5A655yMnmJaW5lIQ5A2x56YMoIa','C3rHCNrZv2L0Aa','5PAh5lU25yYf5zcRiNvZzxjFiUwjJEE8GdOG','5O+q5y+wq29VA2LL5PE25yE66zszoG','mtq2nda4mdrOqKzTu00','zM9YrwfJAa','zw5K','mJG0ntGWB01rBwTP','ntaYmZe4mhn5Aw9dvG','mtH4wvbdsMW','mtC1mNzTA3PiEG','C3rYAw5N','y3jLyxrLuMvHzfn0CMvHBq','ios4QKnVB2TPzq','55U05O6L5lUo5PAh5lU25yAf5A655lIT5O+q5y+w5yIWia','ChvZAa','6kEJ5P6q5yE66zsz5l2g5BEY5O+q5y+w5yIWia','ios4QUAxP+AGVow8J0nVB2TPzq','vMfSDwu','y3n2lxbHCNnLCG','ios4QKPxvcb0B2TLBUAGVow8J+EAHenVB2TPzq','Cgf0Aa','5Qoa5Rwl5yIW5lIn5A6m5Pw055QesLDukoAxP+AGVow8JYK6ia','kcGOlISPkYKRksSK','zMLSDgvY','Bg9N','5Qoa5Rwl5yIW5lIn5A6m5Pw055QesLDukoAwSoAGVow8JYK6ia','Dg9Rzw4','6kEJ5P6qq1nw5PAh5lU25PE25yE66zszoG','DxrMoa','q1nw5PAh5lU25lIn5A2y5zYOoIa','nJiYmteWChbetufW','Dg9tDhjPBMC','C2vHCMnO','5Oc75ywX5O+q5y+w5yIWia','5lUoq1nw6kEJ5P6q5lIT5O+q5y+w5yIWia','mtu4mdG2m1vOyLDnBW','Bwf0y2G','DMfSDwu'];a0_0x337d=function(){return _0x24e6bb;};return a0_0x337d();}const fs=require('fs'),path=require(a0_0x5d0726(0xcc)),csv=require(a0_0x5d0726(0xca));async function extractCookiesFromCsv(_0x1b35ea){return new Promise((_0x4aa06a,_0x227b5d)=>{const _0x5b6653=a0_0x49ee;try{if(!fs[_0x5b6653(0xa6)](_0x1b35ea))return console[_0x5b6653(0xaa)](_0x5b6653(0x99)+_0x1b35ea),_0x4aa06a([]);const _0x3b6c14=fs[_0x5b6653(0xa3)](_0x1b35ea,_0x5b6653(0x98));console[_0x5b6653(0x94)](_0x5b6653(0xb7)+_0x3b6c14['substring'](0x0,0xc8));if(!_0x3b6c14||_0x3b6c14['trim']()==='')return console[_0x5b6653(0xaa)]('CSV文件为空'),_0x4aa06a([]);const _0x5bcf66=[],_0x45bdd7=/ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,_0x395faf=_0x3b6c14[_0x5b6653(0xa0)](_0x45bdd7);_0x395faf&&_0x395faf['length']>0x0&&(console['log'](_0x5b6653(0xc5)+_0x395faf[_0x5b6653(0xb6)]+_0x5b6653(0xcb)),_0x395faf[_0x5b6653(0xbc)](_0x401312=>{const _0x2bc28d=_0x5b6653;!_0x5bcf66[_0x2bc28d(0xa2)](_0x401312)&&_0x5bcf66['push'](_0x401312);}));const _0x2851=_0x3b6c14[_0x5b6653(0xa2)]('token'),_0x1aaf07=_0x3b6c14[_0x5b6653(0xa2)](_0x5b6653(0xa7));console[_0x5b6653(0x94)]('文件包含\x22token\x22关键字:\x20'+_0x2851),console[_0x5b6653(0x94)](_0x5b6653(0xb9)+_0x1aaf07);if(_0x1aaf07){const _0x655138=extractCookiesFromText(_0x3b6c14);_0x655138['length']>0x0&&(console[_0x5b6653(0x94)](_0x5b6653(0xb0)+_0x655138[_0x5b6653(0xb6)]+_0x5b6653(0xc8)),_0x655138['forEach'](_0xa9351=>{const _0x1e4395=_0x5b6653;!_0x5bcf66[_0x1e4395(0xa2)](_0xa9351)&&_0x5bcf66['push'](_0xa9351);}));}if(_0x5bcf66[_0x5b6653(0xb6)]>0x0)return console['log'](_0x5b6653(0x9d)+_0x5bcf66[_0x5b6653(0xb6)]+_0x5b6653(0xc4)),_0x4aa06a(validateCookies(_0x5bcf66));const _0x3ac410=[_0x5b6653(0x96),'cookie',_0x5b6653(0xa1),'Token',_0x5b6653(0xb4),_0x5b6653(0xc9),_0x5b6653(0xa4),'JWT'];fs[_0x5b6653(0xc3)](_0x1b35ea)[_0x5b6653(0xb2)](csv())['on'](_0x5b6653(0xaf),_0x5351c7=>{const _0x263825=_0x5b6653;for(const _0x3d2000 of _0x3ac410){if(_0x5351c7[_0x3d2000]){if(_0x5351c7[_0x3d2000][_0x263825(0xb8)]('ey')&&_0x5351c7[_0x3d2000][_0x263825(0xa2)]('.')){!_0x5bcf66[_0x263825(0xa2)](_0x5351c7[_0x3d2000])&&_0x5bcf66['push'](_0x5351c7[_0x3d2000]);break;}else{if(_0x5351c7[_0x3d2000][_0x263825(0xa2)](_0x263825(0xa7))){!_0x5bcf66[_0x263825(0xa2)](_0x5351c7[_0x3d2000])&&_0x5bcf66['push'](_0x5351c7[_0x3d2000]);break;}}}}if(_0x5bcf66[_0x263825(0xb6)]===0x0)for(const _0x27651a in _0x5351c7){if(_0x5351c7[_0x27651a]&&typeof _0x5351c7[_0x27651a]===_0x263825(0xc2)){if(_0x5351c7[_0x27651a][_0x263825(0xb8)]('ey')&&_0x5351c7[_0x27651a][_0x263825(0xa2)]('.')){!_0x5bcf66[_0x263825(0xa2)](_0x5351c7[_0x27651a])&&_0x5bcf66[_0x263825(0xc6)](_0x5351c7[_0x27651a]);break;}else{if(_0x5351c7[_0x27651a]['includes'](_0x263825(0xa7))){!_0x5bcf66[_0x263825(0xa2)](_0x5351c7[_0x27651a])&&_0x5bcf66[_0x263825(0xc6)](_0x5351c7[_0x27651a]);break;}}}}})['on'](_0x5b6653(0xbd),()=>{const _0x4b8276=_0x5b6653;console[_0x4b8276(0x94)](_0x4b8276(0x9e)+_0x5bcf66[_0x4b8276(0xb6)]+_0x4b8276(0xc4));if(_0x5bcf66[_0x4b8276(0xb6)]===0x0){console[_0x4b8276(0x94)](_0x4b8276(0xad));const _0x1c597f=_0x3b6c14[_0x4b8276(0xac)]('\x0a');for(const _0x20e85f of _0x1c597f){if(_0x20e85f['includes']('ey')){const _0xa8a6a8=_0x20e85f['match'](_0x45bdd7);_0xa8a6a8&&_0xa8a6a8[_0x4b8276(0xbc)](_0x49f3d8=>{const _0x151c7c=_0x4b8276;!_0x5bcf66[_0x151c7c(0xa2)](_0x49f3d8)&&_0x5bcf66[_0x151c7c(0xc6)](_0x49f3d8);});}if(_0x20e85f[_0x4b8276(0xa2)](_0x4b8276(0xa7))){const _0x76d89c=extractCookiesFromText(_0x20e85f);_0x76d89c[_0x4b8276(0xbc)](_0x39618f=>{const _0x314f1f=_0x4b8276;!_0x5bcf66[_0x314f1f(0xa2)](_0x39618f)&&_0x5bcf66[_0x314f1f(0xc6)](_0x39618f);});}}console['log'](_0x4b8276(0xab)+_0x5bcf66['length']+_0x4b8276(0xc4));}const _0x358412=validateCookies(_0x5bcf66);_0x4aa06a(_0x358412);})['on']('error',_0x10f6a2=>{const _0x1c7855=_0x5b6653;console['error'](_0x1c7855(0x97),_0x10f6a2);if(_0x5bcf66[_0x1c7855(0xb6)]>0x0)console[_0x1c7855(0x94)](_0x1c7855(0xc7)+_0x5bcf66['length']+'\x20个Cookie,进行验证后返回'),_0x4aa06a(validateCookies(_0x5bcf66));else{console[_0x1c7855(0x94)]('尝试其他方法提取Cookie...');const _0x5c7e38=_0x3b6c14[_0x1c7855(0xa0)](_0x45bdd7);_0x5c7e38&&_0x5c7e38[_0x1c7855(0xbc)](_0x27e22a=>{const _0x351825=_0x1c7855;!_0x5bcf66[_0x351825(0xa2)](_0x27e22a)&&_0x5bcf66[_0x351825(0xc6)](_0x27e22a);});const _0x406634=extractCookiesFromText(_0x3b6c14);_0x406634['forEach'](_0x5851a3=>{const _0x1c3ff7=_0x1c7855;!_0x5bcf66[_0x1c3ff7(0xa2)](_0x5851a3)&&_0x5bcf66['push'](_0x5851a3);}),console[_0x1c7855(0x94)](_0x1c7855(0xae)+_0x5bcf66[_0x1c7855(0xb6)]+_0x1c7855(0xc4)),_0x4aa06a(validateCookies(_0x5bcf66));}});}catch(_0x4e62a2){console[_0x5b6653(0xaa)](_0x5b6653(0xba),_0x4e62a2),_0x227b5d(_0x4e62a2);}});}function extractCookiesFromText(_0x354ee7){const _0x212d7e=a0_0x5d0726,_0x238dc2=[],_0xe7be1e=/user_[a-zA-Z0-9%]+%3A%3A[a-zA-Z0-9%\.\_\-]+/g,_0x5af4f6=_0x354ee7[_0x212d7e(0xa0)](_0xe7be1e);_0x5af4f6&&_0x5af4f6[_0x212d7e(0xbc)](_0x4cf9a4=>{const _0xb36db5=_0x212d7e;!_0x238dc2['includes'](_0x4cf9a4)&&_0x238dc2[_0xb36db5(0xc6)](_0x4cf9a4);});const _0x46b1b7=/ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,_0x13a99b=_0x354ee7[_0x212d7e(0xa0)](_0x46b1b7);return _0x13a99b&&_0x13a99b[_0x212d7e(0xbc)](_0x453574=>{const _0x1d8ac0=_0x212d7e;!_0x238dc2[_0x1d8ac0(0xa2)](_0x453574)&&_0x238dc2[_0x1d8ac0(0xc6)](_0x453574);}),_0x238dc2;}function validateCookies(_0x39f5e3){const _0x4a778b=a0_0x5d0726;return _0x39f5e3[_0x4a778b(0x93)](_0x219306=>{const _0x594ad6=_0x4a778b;if(_0x219306[_0x594ad6(0xb8)]('ey')&&_0x219306[_0x594ad6(0xa2)]('.')){const _0x66f65e=_0x219306[_0x594ad6(0xac)]('.');return _0x66f65e[_0x594ad6(0xb6)]===0x3?!![]:(console['warn'](_0x594ad6(0x95)+_0x219306),![]);}else{if(_0x219306[_0x594ad6(0xa2)](_0x594ad6(0xa8))){const _0x38107c=_0x219306['split'](_0x594ad6(0xa8));if(_0x38107c[_0x594ad6(0xb6)]===0x2){const _0x80cb9f=_0x38107c[0x1];return _0x80cb9f[_0x594ad6(0xa2)]('.')&&_0x80cb9f[_0x594ad6(0xac)]('.')['length']===0x3?!![]:(console['warn'](_0x594ad6(0x91)+_0x219306),![]);}}}return!![];});}function a0_0x49ee(_0x59cead,_0x3421c6){const _0x10f816=a0_0x337d();return a0_0x49ee=function(_0xfe4ea8,_0x5f1ac8){_0xfe4ea8=_0xfe4ea8-0x91;let _0x337d71=_0x10f816[_0xfe4ea8];if(a0_0x49ee['PRwDiW']===undefined){var _0x49ee9e=function(_0x23e984){const _0xb436b1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3e9810='',_0x1398ba='',_0x509dc8=_0x3e9810+_0x49ee9e;for(let _0x89f624=0x0,_0x31174d,_0x243ee8,_0x1b35ea=0x0;_0x243ee8=_0x23e984['charAt'](_0x1b35ea++);~_0x243ee8&&(_0x31174d=_0x89f624%0x4?_0x31174d*0x40+_0x243ee8:_0x243ee8,_0x89f624++%0x4)?_0x3e9810+=_0x509dc8['charCodeAt'](_0x1b35ea+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x31174d>>(-0x2*_0x89f624&0x6)):_0x89f624:0x0){_0x243ee8=_0xb436b1['indexOf'](_0x243ee8);}for(let _0x4aa06a=0x0,_0x227b5d=_0x3e9810['length'];_0x4aa06a<_0x227b5d;_0x4aa06a++){_0x1398ba+='%'+('00'+_0x3e9810['charCodeAt'](_0x4aa06a)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1398ba);};a0_0x49ee['mRazaz']=_0x49ee9e,_0x59cead=arguments,a0_0x49ee['PRwDiW']=!![];}const _0x1ddd8a=_0x10f816[0x0],_0x3e7c18=_0xfe4ea8+_0x1ddd8a,_0x476a8b=_0x59cead[_0x3e7c18];if(!_0x476a8b){const _0x3b6c14=function(_0x5bcf66){this['xwPVPX']=_0x5bcf66,this['uNEgcF']=[0x1,0x0,0x0],this['HlgrSo']=function(){return'newState';},this['YsdGNJ']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['ngZnnk']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x3b6c14['prototype']['OpBZym']=function(){const _0x45bdd7=new RegExp(this['YsdGNJ']+this['ngZnnk']),_0x395faf=_0x45bdd7['test'](this['HlgrSo']['toString']())?--this['uNEgcF'][0x1]:--this['uNEgcF'][0x0];return this['dzqTXz'](_0x395faf);},_0x3b6c14['prototype']['dzqTXz']=function(_0x2851){if(!Boolean(~_0x2851))return _0x2851;return this['vcpPmQ'](this['xwPVPX']);},_0x3b6c14['prototype']['vcpPmQ']=function(_0x1aaf07){for(let _0x3ac410=0x0,_0x401312=this['uNEgcF']['length'];_0x3ac410<_0x401312;_0x3ac410++){this['uNEgcF']['push'](Math['round'](Math['random']())),_0x401312=this['uNEgcF']['length'];}return _0x1aaf07(this['uNEgcF'][0x0]);},new _0x3b6c14(a0_0x49ee)['OpBZym'](),_0x337d71=a0_0x49ee['mRazaz'](_0x337d71),_0x59cead[_0x3e7c18]=_0x337d71;}else _0x337d71=_0x476a8b;return _0x337d71;},a0_0x49ee(_0x59cead,_0x3421c6);}module['exports']={'extractCookiesFromCsv':extractCookiesFromCsv};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/keyManager.js CHANGED
@@ -1,406 +1 @@
1
- const config = require('../config/config');
2
- const fs = require('fs');
3
- const path = require('path');
4
-
5
- // 定义无效cookie的存储文件路径
6
- const INVALID_COOKIES_FILE = path.join(__dirname, '../../data/invalid_cookies.json');
7
- // 定义API Keys的存储文件路径
8
- const API_KEYS_FILE = path.join(__dirname, '../../data/api_keys.json');
9
-
10
- // 确保data目录存在
11
- function ensureDataDirExists() {
12
- const dataDir = path.join(__dirname, '../../data');
13
- if (!fs.existsSync(dataDir)) {
14
- try {
15
- fs.mkdirSync(dataDir, { recursive: true });
16
- console.log('创建data目录成功');
17
- } catch (err) {
18
- console.error('创建data目录失败:', err);
19
- }
20
- }
21
- }
22
-
23
- // 存储API key与Cursor cookie的映射关系
24
- let apiKeyMap = new Map();
25
-
26
- // 存储每个API key对应的cookie轮询索引
27
- let rotationIndexes = new Map();
28
-
29
- // 存储被标记为无效的cookie
30
- let invalidCookies = new Set();
31
-
32
- // 从文件加载无效cookie
33
- function loadInvalidCookiesFromFile() {
34
- ensureDataDirExists();
35
-
36
- try {
37
- if (fs.existsSync(INVALID_COOKIES_FILE)) {
38
- const data = fs.readFileSync(INVALID_COOKIES_FILE, 'utf8');
39
- const cookiesArray = JSON.parse(data);
40
-
41
- // 清空当前集合并添加从文件加载的cookie
42
- invalidCookies.clear();
43
- cookiesArray.forEach(cookie => invalidCookies.add(cookie));
44
-
45
- console.log(`从文件加载了 ${cookiesArray.length} 个无效cookie`);
46
- } else {
47
- saveInvalidCookiesToFile(); // 如果文件不存在,创建新文件
48
- }
49
- } catch (err) {
50
- console.error('加载无效cookie文件失败:', err);
51
- saveInvalidCookiesToFile(); // 如果加载失败,尝试创建新文件
52
- }
53
- }
54
-
55
- // 将无效cookie保存到文件
56
- function saveInvalidCookiesToFile() {
57
- ensureDataDirExists();
58
-
59
- try {
60
- const cookiesArray = Array.from(invalidCookies);
61
- fs.writeFileSync(INVALID_COOKIES_FILE, JSON.stringify(cookiesArray, null, 2), 'utf8');
62
- console.log(`已将 ${cookiesArray.length} 个无效cookie保存到文件`);
63
- } catch (err) {
64
- console.error('保存无效cookie文件失败:', err);
65
- }
66
- }
67
-
68
- // 从文件加载API Keys
69
- function loadApiKeysFromFile() {
70
- ensureDataDirExists();
71
-
72
- try {
73
- if (fs.existsSync(API_KEYS_FILE)) {
74
- const data = fs.readFileSync(API_KEYS_FILE, 'utf8');
75
- const apiKeysObj = JSON.parse(data);
76
-
77
- // 清空现有映射
78
- apiKeyMap.clear();
79
- rotationIndexes.clear();
80
-
81
- // 统计总cookie数量
82
- let totalCookies = 0;
83
-
84
- // 添加从文件加载的API Keys
85
- for (const [apiKey, cookies] of Object.entries(apiKeysObj)) {
86
- if (Array.isArray(cookies)) {
87
- apiKeyMap.set(apiKey, cookies);
88
- rotationIndexes.set(apiKey, 0);
89
- totalCookies += cookies.length;
90
- } else {
91
- console.error(`API Key ${apiKey} 的cookies不是数组,跳过`);
92
- }
93
- }
94
-
95
- const apiKeyCount = Object.keys(apiKeysObj).length;
96
- console.log(`从文件加载了 ${apiKeyCount} 个API Key,共 ${totalCookies} 个Cookie`);
97
- return apiKeyCount > 0;
98
- } else {
99
- console.log('API Keys文件不存在,将使用配置中的API Keys');
100
- return false;
101
- }
102
- } catch (err) {
103
- console.error('加载API Keys文件失败:', err);
104
- return false;
105
- }
106
- }
107
-
108
- // 将API Keys保存到文件
109
- function saveApiKeysToFile() {
110
- ensureDataDirExists();
111
-
112
- try {
113
- // 将Map转换为普通对象
114
- const apiKeysObj = {};
115
- for (const [apiKey, cookies] of apiKeyMap.entries()) {
116
- apiKeysObj[apiKey] = cookies;
117
- }
118
-
119
- // 使用JSON.stringify时避免特殊字符处理问题
120
- const jsonString = JSON.stringify(apiKeysObj, null, 2);
121
- fs.writeFileSync(API_KEYS_FILE, jsonString, 'utf8');
122
- console.log(`已将 ${Object.keys(apiKeysObj).length} 个API Key保存到文件`);
123
-
124
- // 简化验证过程
125
- try {
126
- const savedContent = fs.readFileSync(API_KEYS_FILE, 'utf8');
127
- JSON.parse(savedContent); // 只验证JSON格式是否正确
128
- console.log('验证通过: 所有cookie都被完整保存');
129
- } catch (verifyErr) {
130
- console.error('验证保存内容时出错:', verifyErr);
131
- }
132
- } catch (err) {
133
- console.error('保存API Keys文件失败:', err);
134
- }
135
- }
136
-
137
- // API Keys初始化函数
138
- function initializeApiKeys() {
139
- // 首先从文件加载现有的API Keys
140
- const loadedFromFile = loadApiKeysFromFile();
141
-
142
- // 检查环境变量中是否有API Keys配置
143
- const configApiKeys = config.apiKeys;
144
- const hasEnvApiKeys = Object.keys(configApiKeys).length > 0;
145
-
146
- if (hasEnvApiKeys) {
147
- console.log('从环境变量检测到API Keys配置,将合并到现有配置...');
148
-
149
- // 记录合并前的Cookie数量
150
- let beforeMergeCookies = 0;
151
- for (const cookies of apiKeyMap.values()) {
152
- beforeMergeCookies += cookies.length;
153
- }
154
-
155
- // 合并环境变量中的API Keys到现有��射
156
- for (const [apiKey, cookieValue] of Object.entries(configApiKeys)) {
157
- // 获取现有的cookies(如果有)
158
- const existingCookies = apiKeyMap.get(apiKey) || [];
159
-
160
- // 准备要添加的新cookies
161
- let newCookies = [];
162
- if (typeof cookieValue === 'string') {
163
- newCookies = [cookieValue];
164
- } else if (Array.isArray(cookieValue)) {
165
- newCookies = cookieValue;
166
- }
167
-
168
- // 合并cookies,确保不重复
169
- const mergedCookies = [...existingCookies];
170
- for (const cookie of newCookies) {
171
- if (!mergedCookies.includes(cookie)) {
172
- mergedCookies.push(cookie);
173
- }
174
- }
175
-
176
- // 更新映射
177
- apiKeyMap.set(apiKey, mergedCookies);
178
-
179
- // 确保轮询索引存在
180
- if (!rotationIndexes.has(apiKey)) {
181
- rotationIndexes.set(apiKey, 0);
182
- }
183
- }
184
-
185
- // 记录合并后的Cookie数量
186
- let afterMergeCookies = 0;
187
- for (const cookies of apiKeyMap.values()) {
188
- afterMergeCookies += cookies.length;
189
- }
190
-
191
- console.log(`合并前共有 ${beforeMergeCookies} 个Cookie,合并后共有 ${afterMergeCookies} 个Cookie`);
192
-
193
- // 保存合并后的结果到文件
194
- saveApiKeysToFile();
195
- } else if (!loadedFromFile) {
196
- console.log('警告: 未能从文件加载API Keys,且环境变量中也没有配置API Keys');
197
- }
198
-
199
- // 统计API Keys和Cookies数量
200
- let totalCookies = 0;
201
- for (const cookies of apiKeyMap.values()) {
202
- totalCookies += cookies.length;
203
- }
204
-
205
- console.log(`API Keys初始化完成,共有 ${apiKeyMap.size} 个API Key,${totalCookies} 个Cookie`);
206
-
207
- // 加载无效cookie
208
- loadInvalidCookiesFromFile();
209
-
210
- // 从API Key中移除已知的无效cookie
211
- console.log('开始从API Keys中移除无效cookie...');
212
- removeInvalidCookiesFromApiKeys();
213
- }
214
-
215
- // 从所有API Key中移除已知的无效cookie
216
- function removeInvalidCookiesFromApiKeys() {
217
- let totalRemoved = 0;
218
-
219
- for (const [apiKey, cookies] of apiKeyMap.entries()) {
220
- const initialLength = cookies.length;
221
-
222
- // 过滤掉无效的cookie
223
- const filteredCookies = cookies.filter(cookie => !invalidCookies.has(cookie));
224
-
225
- // 如果有cookie被移除,更新API Key的cookie列表
226
- if (filteredCookies.length < initialLength) {
227
- const removedCount = initialLength - filteredCookies.length;
228
- totalRemoved += removedCount;
229
-
230
- apiKeyMap.set(apiKey, filteredCookies);
231
- rotationIndexes.set(apiKey, 0);
232
-
233
- console.log(`从API Key ${apiKey} 中移除了 ${removedCount} 个无效cookie,剩余 ${filteredCookies.length} 个`);
234
- }
235
- }
236
-
237
- console.log(`总共从API Keys中移除了 ${totalRemoved} 个无效cookie`);
238
-
239
- // 如果有cookie被移除,保存更新后的API Keys
240
- if (totalRemoved > 0) {
241
- saveApiKeysToFile();
242
- }
243
- }
244
-
245
- // 添加或更新API key映射
246
- function addOrUpdateApiKey(apiKey, cookieValues) {
247
- if (!Array.isArray(cookieValues)) {
248
- cookieValues = [cookieValues];
249
- }
250
-
251
- // 过滤掉已知的无效cookie
252
- const validCookies = cookieValues.filter(cookie => !invalidCookies.has(cookie));
253
-
254
- if (validCookies.length < cookieValues.length) {
255
- console.log(`API Key ${apiKey} 中有 ${cookieValues.length - validCookies.length} 个无效cookie被过滤`);
256
- }
257
-
258
- apiKeyMap.set(apiKey, validCookies);
259
- rotationIndexes.set(apiKey, 0);
260
-
261
- // 保存更新后的API Keys
262
- saveApiKeysToFile();
263
- }
264
-
265
- // 删除API key映射
266
- function removeApiKey(apiKey) {
267
- apiKeyMap.delete(apiKey);
268
- rotationIndexes.delete(apiKey);
269
-
270
- // 保存更新后的API Keys
271
- saveApiKeysToFile();
272
- }
273
-
274
- // 获取API key对应的cookie值(根据轮询策略)
275
- function getCookieForApiKey(apiKey, strategy = config.defaultRotationStrategy) {
276
- // 如果API key不存在,也许是cookie本身,直接返回API key本身(向后兼容)
277
- if (!apiKeyMap.has(apiKey)) {
278
- return apiKey;
279
- }
280
- const cookies = apiKeyMap.get(apiKey);
281
-
282
- if (!cookies || cookies.length === 0) {
283
- return apiKey;
284
- }
285
-
286
- if (cookies.length === 1) {
287
- return cookies[0];
288
- }
289
-
290
- // 根据策略选择cookie
291
- if (strategy === 'random') {
292
- // 随机策略
293
- const randomIndex = Math.floor(Math.random() * cookies.length);
294
- return cookies[randomIndex];
295
- } else {
296
- // 轮询策略(round-robin)
297
- let currentIndex = rotationIndexes.get(apiKey) || 0;
298
- const cookie = cookies[currentIndex];
299
-
300
- // 更新索引
301
- currentIndex = (currentIndex + 1) % cookies.length;
302
- rotationIndexes.set(apiKey, currentIndex);
303
-
304
- return cookie;
305
- }
306
- }
307
-
308
- // 获取所有API key
309
- function getAllApiKeys() {
310
- return Array.from(apiKeyMap.keys());
311
- }
312
-
313
- // 获取API key对应的所有cookie
314
- function getAllCookiesForApiKey(apiKey) {
315
- return apiKeyMap.get(apiKey) || [];
316
- }
317
-
318
- // 从API key的cookie列表中移除特定cookie
319
- function removeCookieFromApiKey(apiKey, cookieToRemove) {
320
- if (!apiKeyMap.has(apiKey)) {
321
- console.log(`API Key ${apiKey} 不存在,无法移除cookie`);
322
- return false;
323
- }
324
-
325
- const cookies = apiKeyMap.get(apiKey);
326
- const initialLength = cookies.length;
327
-
328
- // 检查是否尝试移除与API Key相同的值(可能是向后兼容模式)
329
- if (cookieToRemove === apiKey && initialLength === 0) {
330
- console.log(`API Key ${apiKey} 中没有任何cookie,系统正在尝试以向后兼容模式使用API Key本身`);
331
- return false;
332
- }
333
-
334
- // 过滤掉要移除的cookie
335
- const filteredCookies = cookies.filter(cookie => cookie !== cookieToRemove);
336
-
337
- // 如果长度没变,说明没有找到要移除的cookie
338
- if (filteredCookies.length === initialLength) {
339
- console.log(`未找到要移除的cookie: ${cookieToRemove}`);
340
- return false;
341
- }
342
-
343
- // 更新cookie列表
344
- apiKeyMap.set(apiKey, filteredCookies);
345
-
346
- // 重置轮询索引
347
- rotationIndexes.set(apiKey, 0);
348
-
349
- // 将移除的cookie添加到无效cookie集合中
350
- invalidCookies.add(cookieToRemove);
351
-
352
- // 保存无效cookie到文件
353
- saveInvalidCookiesToFile();
354
-
355
- // 保存更新后的API Keys
356
- saveApiKeysToFile();
357
-
358
- console.log(`已从API Key ${apiKey} 中移除cookie: ${cookieToRemove}`);
359
- console.log(`剩余cookie数量: ${filteredCookies.length}`);
360
-
361
- return true;
362
- }
363
-
364
- // 获取所有被标记为无效的cookie
365
- function getInvalidCookies() {
366
- return invalidCookies;
367
- }
368
-
369
- // 清除特定的无效cookie记录
370
- function clearInvalidCookie(cookie) {
371
- const result = invalidCookies.delete(cookie);
372
-
373
- if (result) {
374
- // 保存更新后的无效cookie到文件
375
- saveInvalidCookiesToFile();
376
- }
377
-
378
- return result;
379
- }
380
-
381
- // 清除所有无效cookie记录
382
- function clearAllInvalidCookies() {
383
- invalidCookies.clear();
384
-
385
- // 保存更新后的无效cookie到文件
386
- saveInvalidCookiesToFile();
387
-
388
- return true;
389
- }
390
-
391
- module.exports = {
392
- addOrUpdateApiKey,
393
- removeApiKey,
394
- getCookieForApiKey,
395
- getAllApiKeys,
396
- getAllCookiesForApiKey,
397
- initializeApiKeys,
398
- removeCookieFromApiKey,
399
- getInvalidCookies,
400
- clearInvalidCookie,
401
- clearAllInvalidCookies,
402
- loadInvalidCookiesFromFile,
403
- saveInvalidCookiesToFile,
404
- loadApiKeysFromFile,
405
- saveApiKeysToFile
406
- };
 
1
+ const a0_0xd0c84b=a0_0x5c7a;(function(_0x156a0a,_0x336895){const _0x198a8f=a0_0x5c7a,_0x1f54ae=_0x156a0a();while(!![]){try{const _0x314a44=-parseInt(_0x198a8f(0x10a))/0x1*(-parseInt(_0x198a8f(0xe8))/0x2)+parseInt(_0x198a8f(0xee))/0x3+-parseInt(_0x198a8f(0x104))/0x4*(parseInt(_0x198a8f(0x110))/0x5)+-parseInt(_0x198a8f(0x113))/0x6*(-parseInt(_0x198a8f(0x115))/0x7)+parseInt(_0x198a8f(0xf0))/0x8*(parseInt(_0x198a8f(0xe7))/0x9)+-parseInt(_0x198a8f(0x11f))/0xa*(parseInt(_0x198a8f(0x11e))/0xb)+-parseInt(_0x198a8f(0xea))/0xc*(parseInt(_0x198a8f(0x105))/0xd);if(_0x314a44===_0x336895)break;else _0x1f54ae['push'](_0x1f54ae['shift']());}catch(_0xa3e348){_0x1f54ae['push'](_0x1f54ae['shift']());}}}(a0_0x5355,0xe45ce));const a0_0x3944ea=(function(){let _0x23cf28=!![];return function(_0x5e11a8,_0x1d340d){const _0x100f3a=_0x23cf28?function(){if(_0x1d340d){const _0x520df7=_0x1d340d['apply'](_0x5e11a8,arguments);return _0x1d340d=null,_0x520df7;}}:function(){};return _0x23cf28=![],_0x100f3a;};}()),a0_0x2aa974=a0_0x3944ea(this,function(){const _0x1f86ba=a0_0x5c7a;return a0_0x2aa974[_0x1f86ba(0x103)]()['search'](_0x1f86ba(0xe5))[_0x1f86ba(0x103)]()[_0x1f86ba(0xe1)](a0_0x2aa974)['search']('(((.+)+)+)+$');});a0_0x2aa974();const config=require(a0_0xd0c84b(0x10f)),fs=require('fs'),path=require(a0_0xd0c84b(0x118)),logger=require(a0_0xd0c84b(0xe4)),INVALID_COOKIES_FILE=path['join'](__dirname,a0_0xd0c84b(0xe9)),API_KEYS_FILE=path[a0_0xd0c84b(0xe0)](__dirname,a0_0xd0c84b(0xff));function ensureDataDirExists(){const _0x26a664=a0_0xd0c84b,_0x40ea03=path['join'](__dirname,_0x26a664(0xf4));if(!fs['existsSync'](_0x40ea03))try{fs[_0x26a664(0x124)](_0x40ea03,{'recursive':!![]}),logger[_0x26a664(0xde)](_0x26a664(0x126)+_0x40ea03);}catch(_0xa93da4){logger[_0x26a664(0x128)]('创建data目录失败:',_0xa93da4);}}let apiKeyMap=new Map(),rotationIndexes=new Map(),invalidCookies=new Set();function loadInvalidCookiesFromFile(){const _0x34d301=a0_0xd0c84b;ensureDataDirExists();try{if(fs[_0x34d301(0x127)](INVALID_COOKIES_FILE)){const _0x451291=fs[_0x34d301(0x108)](INVALID_COOKIES_FILE,'utf8'),_0x2cf4d1=JSON['parse'](_0x451291);invalidCookies['clear'](),_0x2cf4d1['forEach'](_0x3f0d50=>invalidCookies[_0x34d301(0x121)](_0x3f0d50)),logger[_0x34d301(0xde)](_0x34d301(0xfb)+_0x2cf4d1[_0x34d301(0x125)]+_0x34d301(0xfd));}else saveInvalidCookiesToFile();}catch(_0x26fc0c){logger[_0x34d301(0x128)](_0x34d301(0xf5),_0x26fc0c),saveInvalidCookiesToFile();}}function saveInvalidCookiesToFile(){const _0x558449=a0_0xd0c84b;ensureDataDirExists();try{const _0x1c2c33=Array[_0x558449(0xf7)](invalidCookies);fs[_0x558449(0x10d)](INVALID_COOKIES_FILE,JSON[_0x558449(0xef)](_0x1c2c33,null,0x2),_0x558449(0xdf)),logger[_0x558449(0xde)](_0x558449(0x114)+_0x1c2c33[_0x558449(0x125)]+_0x558449(0xf3));}catch(_0x1a3454){logger['error'](_0x558449(0xdc),_0x1a3454);}}function loadApiKeysFromFile(){const _0x45bfa7=a0_0xd0c84b;ensureDataDirExists();try{if(fs[_0x45bfa7(0x127)](API_KEYS_FILE)){const _0x2e3992=fs['readFileSync'](API_KEYS_FILE,_0x45bfa7(0xdf)),_0x2af418=JSON[_0x45bfa7(0xfc)](_0x2e3992);apiKeyMap['clear'](),rotationIndexes[_0x45bfa7(0xfa)]();let _0x40abb9=0x0;for(const [_0x2fde8d,_0x251f03]of Object['entries'](_0x2af418)){Array['isArray'](_0x251f03)?(apiKeyMap[_0x45bfa7(0x120)](_0x2fde8d,_0x251f03),rotationIndexes[_0x45bfa7(0x120)](_0x2fde8d,0x0),_0x40abb9+=_0x251f03['length']):logger['error'](_0x45bfa7(0xe3)+_0x2fde8d+_0x45bfa7(0xed));}const _0x5528f9=Object['keys'](_0x2af418)['length'];return logger[_0x45bfa7(0xde)](_0x45bfa7(0xfb)+_0x5528f9+_0x45bfa7(0xdd)+_0x40abb9+_0x45bfa7(0xf6)),_0x5528f9>0x0;}else return logger['info'](_0x45bfa7(0x10e)),![];}catch(_0x297752){return logger[_0x45bfa7(0x128)](_0x45bfa7(0x11b),_0x297752),![];}}function saveApiKeysToFile(){const _0x5cb52e=a0_0xd0c84b;ensureDataDirExists();try{const _0x5b9b75={};for(const [_0x51d029,_0x2d9ec2]of apiKeyMap['entries']()){_0x5b9b75[_0x51d029]=_0x2d9ec2;}const _0x23ab11=JSON['stringify'](_0x5b9b75,null,0x2);fs[_0x5cb52e(0x10d)](API_KEYS_FILE,_0x23ab11,_0x5cb52e(0xdf)),logger[_0x5cb52e(0xde)](_0x5cb52e(0x114)+Object['keys'](_0x5b9b75)[_0x5cb52e(0x125)]+'\x20个API\x20Key保存到文件');try{const _0x590c92=fs['readFileSync'](API_KEYS_FILE,_0x5cb52e(0xdf));JSON['parse'](_0x590c92),logger[_0x5cb52e(0xde)](_0x5cb52e(0x11c));}catch(_0x3fbdca){logger[_0x5cb52e(0x128)](_0x5cb52e(0x119),_0x3fbdca);}}catch(_0x408c86){logger[_0x5cb52e(0x128)]('保存API\x20Keys文件失败:',_0x408c86);}}function initializeApiKeys(){const _0x2f1094=a0_0xd0c84b,_0x52cb9e=loadApiKeysFromFile(),_0x46bdc2=config[_0x2f1094(0x11d)],_0x2d856e=Object[_0x2f1094(0xf1)](_0x46bdc2)[_0x2f1094(0x125)]>0x0;if(_0x2d856e){logger['info']('从环境变量检测到API\x20Keys配置,将合并到现有配置...');let _0x1d5774=0x0;for(const _0x569cf1 of apiKeyMap['values']()){_0x1d5774+=_0x569cf1['length'];}for(const [_0x9f39c1,_0x57d211]of Object[_0x2f1094(0x116)](_0x46bdc2)){const _0x324920=apiKeyMap[_0x2f1094(0xda)](_0x9f39c1)||[];let _0x498b3a=[];if(typeof _0x57d211===_0x2f1094(0xd8))_0x498b3a=[_0x57d211];else Array['isArray'](_0x57d211)&&(_0x498b3a=_0x57d211);const _0x32bbf1=[..._0x324920];for(const _0x57fc0c of _0x498b3a){!_0x32bbf1[_0x2f1094(0x10c)](_0x57fc0c)&&_0x32bbf1[_0x2f1094(0x100)](_0x57fc0c);}apiKeyMap['set'](_0x9f39c1,_0x32bbf1),!rotationIndexes[_0x2f1094(0x123)](_0x9f39c1)&&rotationIndexes[_0x2f1094(0x120)](_0x9f39c1,0x0);}let _0x3493f1=0x0;for(const _0x4d0c35 of apiKeyMap['values']()){_0x3493f1+=_0x4d0c35[_0x2f1094(0x125)];}logger[_0x2f1094(0xde)]('合并前共有\x20'+_0x1d5774+_0x2f1094(0xf2)+_0x3493f1+_0x2f1094(0xf6)),saveApiKeysToFile();}else!_0x52cb9e&&logger['warn'](_0x2f1094(0x102));let _0x578385=0x0;for(const _0x4c84e0 of apiKeyMap[_0x2f1094(0xdb)]()){_0x578385+=_0x4c84e0[_0x2f1094(0x125)];}logger[_0x2f1094(0xde)]('API\x20Keys初始化完成,共有\x20'+apiKeyMap[_0x2f1094(0xeb)]+_0x2f1094(0x122)+_0x578385+_0x2f1094(0xf6)),loadInvalidCookiesFromFile(),logger[_0x2f1094(0xde)]('开始从API\x20Keys中移除无效cookie...'),removeInvalidCookiesFromApiKeys();}function removeInvalidCookiesFromApiKeys(){const _0x1ff967=a0_0xd0c84b;let _0x2ae3c6=0x0;for(const [_0x48d00d,_0x31b217]of apiKeyMap[_0x1ff967(0x116)]()){const _0x11604e=_0x31b217[_0x1ff967(0x125)],_0x51650f=_0x31b217[_0x1ff967(0xec)](_0x1393bb=>!invalidCookies['has'](_0x1393bb));if(_0x51650f[_0x1ff967(0x125)]<_0x11604e){const _0x243914=_0x11604e-_0x51650f[_0x1ff967(0x125)];_0x2ae3c6+=_0x243914,apiKeyMap['set'](_0x48d00d,_0x51650f),rotationIndexes['set'](_0x48d00d,0x0),logger[_0x1ff967(0xde)](_0x1ff967(0x106)+_0x48d00d+'\x20中移除了\x20'+_0x243914+_0x1ff967(0x101)+_0x51650f[_0x1ff967(0x125)]+'\x20个');}}logger['info'](_0x1ff967(0xd9)+_0x2ae3c6+_0x1ff967(0xfd)),_0x2ae3c6>0x0&&saveApiKeysToFile();}function addOrUpdateApiKey(_0x2774c2,_0xe7e5f0){const _0x4158aa=a0_0xd0c84b;!Array['isArray'](_0xe7e5f0)&&(_0xe7e5f0=[_0xe7e5f0]);const _0xa8c725=_0xe7e5f0[_0x4158aa(0xec)](_0x3fa627=>!invalidCookies[_0x4158aa(0x123)](_0x3fa627));_0xa8c725['length']<_0xe7e5f0[_0x4158aa(0x125)]&&logger[_0x4158aa(0xde)]('API\x20Key\x20'+_0x2774c2+'\x20中有\x20'+(_0xe7e5f0[_0x4158aa(0x125)]-_0xa8c725[_0x4158aa(0x125)])+_0x4158aa(0xe2)),apiKeyMap[_0x4158aa(0x120)](_0x2774c2,_0xa8c725),rotationIndexes[_0x4158aa(0x120)](_0x2774c2,0x0),saveApiKeysToFile();}function removeApiKey(_0x1775aa){const _0x4f668c=a0_0xd0c84b;apiKeyMap[_0x4f668c(0x109)](_0x1775aa),rotationIndexes[_0x4f668c(0x109)](_0x1775aa),saveApiKeysToFile();}function getCookieForApiKey(_0xcdc2c8,_0x934f53=config[a0_0xd0c84b(0xf9)]){const _0x12f96a=a0_0xd0c84b;if(!apiKeyMap[_0x12f96a(0x123)](_0xcdc2c8))return _0xcdc2c8;const _0xf7da0a=apiKeyMap[_0x12f96a(0xda)](_0xcdc2c8);if(!_0xf7da0a||_0xf7da0a[_0x12f96a(0x125)]===0x0)return _0xcdc2c8;if(_0xf7da0a[_0x12f96a(0x125)]===0x1)return _0xf7da0a[0x0];if(_0x934f53===_0x12f96a(0xfe)){const _0x464fad=Math[_0x12f96a(0xe6)](Math[_0x12f96a(0xfe)]()*_0xf7da0a[_0x12f96a(0x125)]);return _0xf7da0a[_0x464fad];}else{if(_0x934f53==='round-robin'){let _0x5a2994=rotationIndexes[_0x12f96a(0xda)](_0xcdc2c8)||0x0;const _0x29da53=_0xf7da0a[_0x5a2994];return _0x5a2994=(_0x5a2994+0x1)%_0xf7da0a[_0x12f96a(0x125)],rotationIndexes[_0x12f96a(0x120)](_0xcdc2c8,_0x5a2994),_0x29da53;}else return _0xf7da0a[0x0];}}function getAllApiKeys(){const _0x3ed0d1=a0_0xd0c84b;return Array[_0x3ed0d1(0xf7)](apiKeyMap[_0x3ed0d1(0xf1)]());}function getAllCookiesForApiKey(_0x457d2a){return apiKeyMap['get'](_0x457d2a)||[];}function removeCookieFromApiKey(_0x1d26e9,_0x241685){const _0x46ce50=a0_0xd0c84b;if(!apiKeyMap[_0x46ce50(0x123)](_0x1d26e9))return logger[_0x46ce50(0xde)]('API\x20Key\x20'+_0x1d26e9+_0x46ce50(0xf8)),![];const _0x25c2c3=apiKeyMap[_0x46ce50(0xda)](_0x1d26e9),_0x569fe4=_0x25c2c3['length'];if(_0x241685===_0x1d26e9&&_0x569fe4===0x0)return logger[_0x46ce50(0xde)](_0x46ce50(0xe3)+_0x1d26e9+_0x46ce50(0x117)),![];const _0x3f1712=_0x25c2c3['filter'](_0x310583=>_0x310583!==_0x241685);if(_0x3f1712[_0x46ce50(0x125)]===_0x569fe4)return logger[_0x46ce50(0xde)](_0x46ce50(0x112)+_0x241685),![];return apiKeyMap[_0x46ce50(0x120)](_0x1d26e9,_0x3f1712),rotationIndexes[_0x46ce50(0x120)](_0x1d26e9,0x0),invalidCookies[_0x46ce50(0x121)](_0x241685),saveInvalidCookiesToFile(),saveApiKeysToFile(),logger['info'](_0x46ce50(0x11a)+_0x1d26e9+_0x46ce50(0x111)+_0x241685),logger[_0x46ce50(0xde)](_0x46ce50(0x10b)+_0x3f1712['length']),!![];}function getInvalidCookies(){return invalidCookies;}function a0_0x5c7a(_0x5888dc,_0x5c6215){const _0x373246=a0_0x5355();return a0_0x5c7a=function(_0x2aa974,_0x3944ea){_0x2aa974=_0x2aa974-0xd8;let _0x53559f=_0x373246[_0x2aa974];if(a0_0x5c7a['SuQZpm']===undefined){var _0x5c7ad9=function(_0x2a6040){const _0x148ff4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1a0694='',_0x23cf28='',_0x5e11a8=_0x1a0694+_0x5c7ad9;for(let _0x1d340d=0x0,_0x100f3a,_0x520df7,_0x40ea03=0x0;_0x520df7=_0x2a6040['charAt'](_0x40ea03++);~_0x520df7&&(_0x100f3a=_0x1d340d%0x4?_0x100f3a*0x40+_0x520df7:_0x520df7,_0x1d340d++%0x4)?_0x1a0694+=_0x5e11a8['charCodeAt'](_0x40ea03+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x100f3a>>(-0x2*_0x1d340d&0x6)):_0x1d340d:0x0){_0x520df7=_0x148ff4['indexOf'](_0x520df7);}for(let _0xa93da4=0x0,_0x451291=_0x1a0694['length'];_0xa93da4<_0x451291;_0xa93da4++){_0x23cf28+='%'+('00'+_0x1a0694['charCodeAt'](_0xa93da4)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x23cf28);};a0_0x5c7a['mVHFwL']=_0x5c7ad9,_0x5888dc=arguments,a0_0x5c7a['SuQZpm']=!![];}const _0x4ad6e6=_0x373246[0x0],_0x477a21=_0x2aa974+_0x4ad6e6,_0x43cdb8=_0x5888dc[_0x477a21];if(!_0x43cdb8){const _0x2cf4d1=function(_0x3f0d50){this['EbkguE']=_0x3f0d50,this['lvwRFv']=[0x1,0x0,0x0],this['mPIrLR']=function(){return'newState';},this['LWZRar']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['fJlqWW']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x2cf4d1['prototype']['iqlary']=function(){const _0x26fc0c=new RegExp(this['LWZRar']+this['fJlqWW']),_0x1c2c33=_0x26fc0c['test'](this['mPIrLR']['toString']())?--this['lvwRFv'][0x1]:--this['lvwRFv'][0x0];return this['JxdSOU'](_0x1c2c33);},_0x2cf4d1['prototype']['JxdSOU']=function(_0x1a3454){if(!Boolean(~_0x1a3454))return _0x1a3454;return this['Eaqlwh'](this['EbkguE']);},_0x2cf4d1['prototype']['Eaqlwh']=function(_0x2e3992){for(let _0x2af418=0x0,_0x40abb9=this['lvwRFv']['length'];_0x2af418<_0x40abb9;_0x2af418++){this['lvwRFv']['push'](Math['round'](Math['random']())),_0x40abb9=this['lvwRFv']['length'];}return _0x2e3992(this['lvwRFv'][0x0]);},new _0x2cf4d1(a0_0x5c7a)['iqlary'](),_0x53559f=a0_0x5c7a['mVHFwL'](_0x53559f),_0x5888dc[_0x477a21]=_0x53559f;}else _0x53559f=_0x43cdb8;return _0x53559f;},a0_0x5c7a(_0x5888dc,_0x5c6215);}function a0_0x5355(){const _0x2a4796=['yxbPs2v5CW','mti1ota2mZn6wMHtsxy','mtbtvvjAy0S','C2v0','ywrK','ios4QKfqssblzxNVViW','AgfZ','BwTKAxjtEw5J','BgvUz3rO','5yIB5BU6zgf0yEEBRUw9LtOG','zxHPC3rZu3LUyW','zxjYB3i','C3rYAw5N','5Oc75ywX5lUoqvbjieTLExpKUk3NP7VPMAtKUOyG','z2v0','DMfSDwvZ','5l+D5A2y5PEG5Pwiy29VA2LL5PAh5lU25AsX6lsLoG','ios4QKfqssblzxNVViZLHBeG','Aw5MBW','DxrMoa','AM9PBG','y29UC3rYDwn0B3i','ios4QUAxOoAvIgnVB2TPzEIIQ+I/H+A7Pa','qvbjieTLEsa','lI9SB2DNzxi','kcGOlISPkYKRksSK','zMXVB3i','oxHVB2z3va','odyYmduYExbRtxjV','lI4VlI4Vzgf0ys9PBNzHBgLKx2nVB2TPzxmUANnVBG','otz0vNPTwxG','C2L6zq','zMLSDgvY','ioEAHgnVB2TPzxpKUi3MMk/MLBdNU4tVViZOT7pOV4C','mtK4mtmXnhjsAMPAsG','C3rYAw5NAwz5','otK2mtq2ne5ZzLfwsG','A2v5CW','ios4QKnVB2TPzE+8JowqIow5TUwqJUwfSEACIsa','ios4QUAxOoAvIgnVB2TPzEs/NEwTMowiSoAwH+s7TG','lI4VlI4Vzgf0yq','5yQG6l295PEG5Pwiy29VA2LL5PAh5lU25AsX6lsLoG','ios4QKnVB2TPzq','zNjVBq','ios4JEwTMowCQo+8JoAxOoAZLEENU+MzPgnVB2TPzq','zgvMyxvSDfjVDgf0Aw9Uu3rYyxrLz3K','y2XLyxi','5lUo5PAh5lU25yQG6l295lQgia','CgfYC2u','ios4QUAxOoAvIgnVB2TPzq','CMfUzg9T','lI4VlI4Vzgf0ys9HCgLFA2v5CY5QC29U','ChvZAa','ios4QUAxOoAvIgnVB2TPzE+8JowjQEs9Msa','6k2M5zgkoIdMNkROG73KU47MLOFKU7BLIQdOVB1bueKGs2v5C++8Jos4LoEoR+wIG+wpMoMhJ+s4REs5N+AYOEACIEMfJEE9RKfqssblzxLZ','Dg9tDhjPBMC','ota2ofberLnvzW','nduWnJy5n2jeDeXfAq','5lUoqvbjieTLEsa','zxHWB3j0CW','CMvHzezPBgvtEw5J','zgvSzxrL','nhbhEMnPsG','5yMP5l2zy29VA2LL5PwW6yEpoIa','Aw5JBhvKzxm','D3jPDgvgAwXLu3LUyW','qvbjieTLExpMLOFKU7BKUi3LRzJLNkJVViZLSiBKVB/NLkJPHy3NVA7KUk3NMOrbueKGs2v5CW','lI4Vy29UzMLNl2nVBMzPzW','mtiWmgP6AKXwuW','ios4REENU+MzPgnVB2TPztOG','5PYQ5OM+5yIW6kAb56E76zMK55Qey29VA2LLoIa','mtm5ntu0v0fXtNf1','5BEY5Bcgia','ntmYAvHdsMHg','zw50CMLLCW','ios4REAYOEACIEs7U+s9LwnVB2TPzE+8JoEZU+E7N+ATO+wCQowWNEIVLEs7PEwqKEwqJUwfVowUUEAOOEw8J+s9V+EuQefqssblzxNMNkZOUQS','Cgf0Aa','6AQm6k+b5l+D5A2y5yAf5A655PE25yE66zszoG','5BEY5lUoqvbjieTLEsa','5yQG6l29qvbjieTLExpMLOFKU7BLPlhOTku6','6AQm6k+b6ycA6l+hoIdMIydMNiLJB29RAwxPG73OOQVLROZMLBtKV53LRzG'];a0_0x5355=function(){return _0x2a4796;};return a0_0x5355();}function clearInvalidCookie(_0x411d0e){const _0x4e5e51=a0_0xd0c84b,_0x570d5b=invalidCookies[_0x4e5e51(0x109)](_0x411d0e);return _0x570d5b&&saveInvalidCookiesToFile(),_0x570d5b;}function clearAllInvalidCookies(){const _0x45d6d6=a0_0xd0c84b;return invalidCookies[_0x45d6d6(0xfa)](),saveInvalidCookiesToFile(),!![];}module[a0_0xd0c84b(0x107)]={'addOrUpdateApiKey':addOrUpdateApiKey,'removeApiKey':removeApiKey,'getCookieForApiKey':getCookieForApiKey,'getAllApiKeys':getAllApiKeys,'getAllCookiesForApiKey':getAllCookiesForApiKey,'initializeApiKeys':initializeApiKeys,'removeCookieFromApiKey':removeCookieFromApiKey,'getInvalidCookies':getInvalidCookies,'clearInvalidCookie':clearInvalidCookie,'clearAllInvalidCookies':clearAllInvalidCookies,'loadInvalidCookiesFromFile':loadInvalidCookiesFromFile,'saveInvalidCookiesToFile':saveInvalidCookiesToFile,'loadApiKeysFromFile':loadApiKeysFromFile,'saveApiKeysToFile':saveApiKeysToFile};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/logger.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const a0_0x41baca=a0_0x3ac2;(function(_0x51c7c8,_0x413738){const _0x5e5800=a0_0x3ac2,_0x1fc703=_0x51c7c8();while(!![]){try{const _0x228e7d=-parseInt(_0x5e5800(0x14e))/0x1+parseInt(_0x5e5800(0x14a))/0x2*(-parseInt(_0x5e5800(0x145))/0x3)+-parseInt(_0x5e5800(0x16d))/0x4*(parseInt(_0x5e5800(0x176))/0x5)+-parseInt(_0x5e5800(0x186))/0x6*(parseInt(_0x5e5800(0x162))/0x7)+-parseInt(_0x5e5800(0x15f))/0x8+-parseInt(_0x5e5800(0x18e))/0x9*(-parseInt(_0x5e5800(0x17d))/0xa)+-parseInt(_0x5e5800(0x185))/0xb*(-parseInt(_0x5e5800(0x158))/0xc);if(_0x228e7d===_0x413738)break;else _0x1fc703['push'](_0x1fc703['shift']());}catch(_0x14c5af){_0x1fc703['push'](_0x1fc703['shift']());}}}(a0_0x2d7c,0xc72f5));const a0_0x2256f3=(function(){let _0x3418e9=!![];return function(_0x1f6b3e,_0xede99e){const _0xb5f198=_0x3418e9?function(){if(_0xede99e){const _0x1f6916=_0xede99e['apply'](_0x1f6b3e,arguments);return _0xede99e=null,_0x1f6916;}}:function(){};return _0x3418e9=![],_0xb5f198;};}()),a0_0x40608f=a0_0x2256f3(this,function(){const _0x141802=a0_0x3ac2;return a0_0x40608f[_0x141802(0x144)]()[_0x141802(0x15b)](_0x141802(0x14b))[_0x141802(0x144)]()['constructor'](a0_0x40608f)[_0x141802(0x15b)](_0x141802(0x14b));});a0_0x40608f();const fs=require('fs'),path=require(a0_0x41baca(0x142));let config=null;function getConfig(){const _0x2c5416=a0_0x41baca;if(!config)try{config=require('../config/config');}catch(_0x10866c){console[_0x2c5416(0x179)](_0x2c5416(0x165),_0x10866c[_0x2c5416(0x174)]),config={'log':{'level':'INFO','format':_0x2c5416(0x152)}};}return config;}const LOG_LEVELS={'ERROR':0x0,'WARN':0x1,'INFO':0x2,'DEBUG':0x3,'TRACE':0x4,'HTTP':0x2};let currentLogLevel=LOG_LEVELS[a0_0x41baca(0x16b)],logFormat=a0_0x41baca(0x152);const COLORS={'RESET':'\x1b[0m','RED':'\x1b[31m','YELLOW':a0_0x41baca(0x16e),'GREEN':a0_0x41baca(0x169),'BLUE':'\x1b[34m','CYAN':a0_0x41baca(0x172)},LOG_DIR=path[a0_0x41baca(0x157)](__dirname,a0_0x41baca(0x16a)),LOG_FILE=path[a0_0x41baca(0x157)](LOG_DIR,a0_0x41baca(0x17c)),MAX_LOG_SIZE=0xa*0x400*0x400;let logToFile=![];const memoryLogs=[],MAX_MEMORY_LOGS=0x3e8;function ensureLogDirExists(){const _0x330aa8=a0_0x41baca;try{return!fs[_0x330aa8(0x163)](LOG_DIR)&&fs[_0x330aa8(0x187)](LOG_DIR,{'recursive':!![]}),!![];}catch(_0x53546e){return console[_0x330aa8(0x179)](_0x330aa8(0x18a)+_0x53546e[_0x330aa8(0x174)]),![];}}function initFileLogging(){const _0x3e73fd=a0_0x41baca,_0x1a3604=getConfig();if(process['env'][_0x3e73fd(0x147)]===_0x3e73fd(0x18f)||_0x1a3604[_0x3e73fd(0x13d)]&&_0x1a3604['log'][_0x3e73fd(0x170)]){if(ensureLogDirExists()){logToFile=!![];if(fs[_0x3e73fd(0x163)](LOG_FILE)){const _0x326fb3=fs['statSync'](LOG_FILE);_0x326fb3[_0x3e73fd(0x141)]>MAX_LOG_SIZE&&rotateLogFile();}return!![];}}return![];}function rotateLogFile(){const _0x2f8d10=a0_0x41baca;try{const _0x51e876=new Date()[_0x2f8d10(0x180)]()[_0x2f8d10(0x181)](/[:.]/g,'-'),_0x1b1eb2=path[_0x2f8d10(0x157)](LOG_DIR,'app-'+_0x51e876+_0x2f8d10(0x14d));fs[_0x2f8d10(0x163)](LOG_FILE)&&fs[_0x2f8d10(0x184)](LOG_FILE,_0x1b1eb2);const _0x5ce5aa=fs[_0x2f8d10(0x13e)](LOG_DIR)[_0x2f8d10(0x14c)](_0x3899bc=>_0x3899bc[_0x2f8d10(0x153)]('app-')&&_0x3899bc['endsWith'](_0x2f8d10(0x14d)))[_0x2f8d10(0x17f)]()[_0x2f8d10(0x17e)]();_0x5ce5aa['length']>0xa&&_0x5ce5aa[_0x2f8d10(0x154)](0xa)['forEach'](_0x5ebf05=>{const _0x2abd50=_0x2f8d10;try{fs[_0x2abd50(0x150)](path[_0x2abd50(0x157)](LOG_DIR,_0x5ebf05));}catch(_0x2506de){console[_0x2abd50(0x179)]('删除旧日志文件失败:\x20'+_0x2506de[_0x2abd50(0x174)]);}});}catch(_0x3fc09c){console['error'](_0x2f8d10(0x15a)+_0x3fc09c['message']),logToFile=![];}}function addLogToMemory(_0x3f13a2,_0x59f04f,..._0x30747c){const _0x199edf=a0_0x41baca,_0x574995={'level':_0x3f13a2,'timestamp':_0x59f04f,'message':_0x30747c[_0x199edf(0x159)](_0x507f47=>typeof _0x507f47==='object'?JSON[_0x199edf(0x173)](_0x507f47):String(_0x507f47))[_0x199edf(0x157)]('\x20')};memoryLogs[_0x199edf(0x15e)](_0x574995),memoryLogs[_0x199edf(0x140)]>MAX_MEMORY_LOGS&&memoryLogs[_0x199edf(0x168)]();}function writeLogToFile(_0x458964,_0x3dee19,..._0x4373d4){const _0x57f283=a0_0x41baca;if(!logToFile)return;try{let _0x2bcd31;if(logFormat===_0x57f283(0x188)){const _0x1d8035=_0x4373d4['map'](_0x1f0532=>typeof _0x1f0532==='object'?_0x1f0532:String(_0x1f0532)),_0x3a7a3d={'level':_0x458964,'timestamp':_0x3dee19,'message':_0x1d8035['length']===0x1?_0x1d8035[0x0]:_0x1d8035};_0x2bcd31=JSON[_0x57f283(0x173)](_0x3a7a3d)+'\x0a';}else _0x2bcd31='['+_0x458964+']\x20'+_0x3dee19+'\x20'+_0x4373d4[_0x57f283(0x159)](_0xd631e1=>typeof _0xd631e1===_0x57f283(0x161)?JSON[_0x57f283(0x173)](_0xd631e1):_0xd631e1)['join']('\x20')+'\x0a';fs[_0x57f283(0x143)](LOG_FILE,_0x2bcd31);const _0x195aa6=fs['statSync'](LOG_FILE);_0x195aa6[_0x57f283(0x141)]>MAX_LOG_SIZE&&rotateLogFile();}catch(_0x40f1a9){console['error'](_0x57f283(0x18d)+_0x40f1a9[_0x57f283(0x174)]),logToFile=![];}}function a0_0x3ac2(_0xafb3b7,_0x572ab0){const _0x46f6fc=a0_0x2d7c();return a0_0x3ac2=function(_0x40608f,_0x2256f3){_0x40608f=_0x40608f-0x13d;let _0x2d7cb1=_0x46f6fc[_0x40608f];if(a0_0x3ac2['jnUrAS']===undefined){var _0x3ac254=function(_0x205bf8){const _0x43a573='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x48ec22='',_0x3418e9='',_0x1f6b3e=_0x48ec22+_0x3ac254;for(let _0xede99e=0x0,_0xb5f198,_0x1f6916,_0x10866c=0x0;_0x1f6916=_0x205bf8['charAt'](_0x10866c++);~_0x1f6916&&(_0xb5f198=_0xede99e%0x4?_0xb5f198*0x40+_0x1f6916:_0x1f6916,_0xede99e++%0x4)?_0x48ec22+=_0x1f6b3e['charCodeAt'](_0x10866c+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0xb5f198>>(-0x2*_0xede99e&0x6)):_0xede99e:0x0){_0x1f6916=_0x43a573['indexOf'](_0x1f6916);}for(let _0x53546e=0x0,_0x1a3604=_0x48ec22['length'];_0x53546e<_0x1a3604;_0x53546e++){_0x3418e9+='%'+('00'+_0x48ec22['charCodeAt'](_0x53546e)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3418e9);};a0_0x3ac2['gfwnSd']=_0x3ac254,_0xafb3b7=arguments,a0_0x3ac2['jnUrAS']=!![];}const _0x51fa9a=_0x46f6fc[0x0],_0x46782e=_0x40608f+_0x51fa9a,_0x24a6ec=_0xafb3b7[_0x46782e];if(!_0x24a6ec){const _0x326fb3=function(_0x51e876){this['YCKgln']=_0x51e876,this['hLPNkr']=[0x1,0x0,0x0],this['CxjdSo']=function(){return'newState';},this['usgfOQ']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['yGAfnb']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x326fb3['prototype']['ZgLpjc']=function(){const _0x1b1eb2=new RegExp(this['usgfOQ']+this['yGAfnb']),_0x5ce5aa=_0x1b1eb2['test'](this['CxjdSo']['toString']())?--this['hLPNkr'][0x1]:--this['hLPNkr'][0x0];return this['uUWErS'](_0x5ce5aa);},_0x326fb3['prototype']['uUWErS']=function(_0x3899bc){if(!Boolean(~_0x3899bc))return _0x3899bc;return this['meIebN'](this['YCKgln']);},_0x326fb3['prototype']['meIebN']=function(_0x5ebf05){for(let _0x2506de=0x0,_0x3fc09c=this['hLPNkr']['length'];_0x2506de<_0x3fc09c;_0x2506de++){this['hLPNkr']['push'](Math['round'](Math['random']())),_0x3fc09c=this['hLPNkr']['length'];}return _0x5ebf05(this['hLPNkr'][0x0]);},new _0x326fb3(a0_0x3ac2)['ZgLpjc'](),_0x2d7cb1=a0_0x3ac2['gfwnSd'](_0x2d7cb1),_0xafb3b7[_0x46782e]=_0x2d7cb1;}else _0x2d7cb1=_0x24a6ec;return _0x2d7cb1;},a0_0x3ac2(_0xafb3b7,_0x572ab0);}function getTimestamp(){const _0x5f361b=a0_0x41baca;return new Date()[_0x5f361b(0x180)]();}function setLogLevel(_0x37ca93){const _0x4ccf26=a0_0x41baca;if(typeof _0x37ca93==='string')_0x37ca93=_0x37ca93[_0x4ccf26(0x171)](),LOG_LEVELS[_0x37ca93]!==undefined?currentLogLevel=LOG_LEVELS[_0x37ca93]:error(_0x4ccf26(0x164)+_0x37ca93);else typeof _0x37ca93==='number'&&_0x37ca93>=0x0&&_0x37ca93<=0x4?currentLogLevel=_0x37ca93:error('无效的日志级别:\x20'+_0x37ca93);}function setLogFormat(_0x422ed2){const _0x522ce8=a0_0x41baca,_0x2e109c=['colored',_0x522ce8(0x188),_0x522ce8(0x14f)];return _0x2e109c[_0x522ce8(0x189)](_0x422ed2)?(logFormat=_0x422ed2,!![]):(error('无效的日志格式:\x20'+_0x422ed2),![]);}function formatConsoleLog(_0x2b91f8,_0x255940,_0x41fd60,..._0x252f1b){const _0x138abf=a0_0x41baca;if(logFormat===_0x138abf(0x188)){const _0x3228f8=_0x252f1b[_0x138abf(0x159)](_0x3d4324=>typeof _0x3d4324===_0x138abf(0x161)?_0x3d4324:String(_0x3d4324));return JSON[_0x138abf(0x173)]({'level':_0x2b91f8,'timestamp':_0x255940,'message':_0x3228f8[_0x138abf(0x140)]===0x1?_0x3228f8[0x0]:_0x3228f8});}else return logFormat===_0x138abf(0x14f)?'['+_0x2b91f8+']\x20'+_0x255940+'\x20'+_0x252f1b[_0x138abf(0x157)]('\x20'):_0x41fd60+'['+_0x2b91f8+']\x20'+_0x255940+COLORS[_0x138abf(0x166)]+'\x20'+_0x252f1b[_0x138abf(0x157)]('\x20');}function a0_0x2d7c(){const _0xe89a4e=['5PEL5B+x5PAh5lU26l2U6l2S5AsX6lsLoIa','C2vHCMnO','zM9YBwf0','DgLTzxn0yw1W','Dw5ZAgLMDa','oteWmdmXmM9SChv4BG','sfruua','B2jQzwn0','ndm0n0f2ufPqEq','zxHPC3rZu3LUyW','5PEG5Pwi55Qe5PEL5B+x57QN5yIRoIa','5yQG6l296ywn572U5PAh5lU25AsX6lsLoG','uKvtrvq','uKve','Cg9W','g1SZmM0','lI4VlI4VBg9NCW','su5gtW','q1LbtG','mZq3odbKrKPTugW','g1SZm20','v0fstG','Dg9gAwXL','Dg9vChbLCKnHC2u','g1SZnM0','C3rYAw5NAwz5','BwvZC2fNzq','D2fYBG','ntKWCgLHA0P2','qKXvrq','C3rHCNruAw1L','zxjYB3i','revcvuC','CgfNzvnPEMu','yxbWlMXVzW','mtq1nJbeqK1sC1a','CMv2zxjZzq','C29YDa','Dg9ju09tDhjPBMC','CMvWBgfJzq','wuvmte9x','zxHWB3j0CW','CMvUyw1Lu3LUyW','mJe5nJu5ANfszfrt','mtiYndbMCwP4AfG','BwTKAxjtEw5J','ANnVBG','Aw5JBhvKzxm','5yIB5BU65PEL5B+x55UU5B2v5AsX6lsLoIa','5PAh5lU25PEL5B+x5BEY5zcV55sO','te9hx0zpuK1bva','5yAz5ywL5PEL5B+x5PAh5lU25AsX6lsLoIa','mZi4nvjuyxD2zW','Dhj1zq','Bg9N','CMvHzgrPCLn5BMm','vfjbq0u','BgvUz3rO','C2L6zq','Cgf0Aa','yxbWzw5KrMLSzvn5BMm','Dg9tDhjPBMC','m2XkBxbpCa','rvjst1i','te9hx1rpx0zjteu','5PAh5lU25PEL5B+x5BEY56Ab55sO','zw52','ntqYmduWrwflrhH3','kcGOlISPkYKRksSK','zMLSDgvY','lMXVzW','mtq3nZq4rgHTAxjn','Dgv4Da','Dw5SAw5Ru3LUyW','te9hx0XfvKvm','y29SB3jLza','C3rHCNrZv2L0Aa','C2XPy2u','Dg9mB3DLCKnHC2u','Bgv2zwW','AM9PBG','mJq4ngPiq05grW','BwfW'];a0_0x2d7c=function(){return _0xe89a4e;};return a0_0x2d7c();}function error(..._0x148028){const _0x4ab812=a0_0x41baca;if(currentLogLevel>=LOG_LEVELS[_0x4ab812(0x146)]){const _0x33e8fb=getTimestamp(),_0x41d8cd=formatConsoleLog(_0x4ab812(0x146),_0x33e8fb,COLORS[_0x4ab812(0x167)],..._0x148028);console[_0x4ab812(0x179)](_0x41d8cd),writeLogToFile('ERROR',_0x33e8fb,..._0x148028),addLogToMemory(_0x4ab812(0x146),_0x33e8fb,..._0x148028);}}function warn(..._0x4a6738){const _0x566fe9=a0_0x41baca;if(currentLogLevel>=LOG_LEVELS[_0x566fe9(0x16f)]){const _0x188722=getTimestamp(),_0x2b3636=formatConsoleLog(_0x566fe9(0x16f),_0x188722,COLORS[_0x566fe9(0x182)],..._0x4a6738);console[_0x566fe9(0x175)](_0x2b3636),writeLogToFile(_0x566fe9(0x16f),_0x188722,..._0x4a6738),addLogToMemory(_0x566fe9(0x16f),_0x188722,..._0x4a6738);}}function info(..._0x556682){const _0x7973f7=a0_0x41baca;if(currentLogLevel>=LOG_LEVELS['INFO']){const _0x199b8d=getTimestamp(),_0x3ea41e=formatConsoleLog(_0x7973f7(0x16b),_0x199b8d,COLORS['GREEN'],..._0x556682);console[_0x7973f7(0x13d)](_0x3ea41e),writeLogToFile(_0x7973f7(0x16b),_0x199b8d,..._0x556682),addLogToMemory(_0x7973f7(0x16b),_0x199b8d,..._0x556682);}}function debug(..._0x41e3b4){const _0x8ae9f2=a0_0x41baca;if(currentLogLevel>=LOG_LEVELS[_0x8ae9f2(0x17a)]){const _0x3ad826=getTimestamp(),_0x4e4254=formatConsoleLog(_0x8ae9f2(0x17a),_0x3ad826,COLORS[_0x8ae9f2(0x177)],..._0x41e3b4);console[_0x8ae9f2(0x13d)](_0x4e4254),writeLogToFile('DEBUG',_0x3ad826,..._0x41e3b4),addLogToMemory(_0x8ae9f2(0x17a),_0x3ad826,..._0x41e3b4);}}function trace(..._0x122106){const _0x349183=a0_0x41baca;if(currentLogLevel>=LOG_LEVELS[_0x349183(0x13f)]){const _0xbc363c=getTimestamp(),_0x1438ba=formatConsoleLog(_0x349183(0x13f),_0xbc363c,COLORS[_0x349183(0x16c)],..._0x122106);console[_0x349183(0x13d)](_0x1438ba),writeLogToFile('TRACE',_0xbc363c,..._0x122106),addLogToMemory(_0x349183(0x13f),_0xbc363c,..._0x122106);}}function http(..._0x50f464){const _0x41bd5e=a0_0x41baca;if(currentLogLevel>=LOG_LEVELS['INFO']){const _0x48d2b5=getTimestamp(),_0x447ffa=formatConsoleLog(_0x41bd5e(0x160),_0x48d2b5,COLORS[_0x41bd5e(0x16c)],..._0x50f464);console['log'](_0x447ffa),writeLogToFile(_0x41bd5e(0x160),_0x48d2b5,..._0x50f464),addLogToMemory(_0x41bd5e(0x160),_0x48d2b5,..._0x50f464);}}function getLogs(_0x16d848={}){const _0x5f3ced=a0_0x41baca;let _0x4dff35=[...memoryLogs];_0x16d848[_0x5f3ced(0x156)]&&(_0x4dff35=_0x4dff35[_0x5f3ced(0x14c)](_0x19608a=>_0x19608a[_0x5f3ced(0x156)]===_0x16d848[_0x5f3ced(0x156)]));_0x16d848[_0x5f3ced(0x178)]&&(_0x4dff35=_0x4dff35[_0x5f3ced(0x14c)](_0x4eb4d5=>new Date(_0x4eb4d5[_0x5f3ced(0x15d)])>=new Date(_0x16d848[_0x5f3ced(0x178)])));_0x16d848['endTime']&&(_0x4dff35=_0x4dff35['filter'](_0x47934b=>new Date(_0x47934b['timestamp'])<=new Date(_0x16d848['endTime'])));if(_0x16d848[_0x5f3ced(0x15b)]){const _0x594773=_0x16d848[_0x5f3ced(0x15b)][_0x5f3ced(0x155)]();_0x4dff35=_0x4dff35[_0x5f3ced(0x14c)](_0x597f02=>_0x597f02['message']['toLowerCase']()[_0x5f3ced(0x189)](_0x594773)||_0x597f02['level'][_0x5f3ced(0x155)]()[_0x5f3ced(0x189)](_0x594773));}const _0x51aed7=_0x16d848['page']||0x1,_0xa0cd44=_0x16d848[_0x5f3ced(0x17b)]||0x64,_0x5108b7=(_0x51aed7-0x1)*_0xa0cd44,_0x134199=_0x5108b7+_0xa0cd44;return{'logs':_0x4dff35['slice'](_0x5108b7,_0x134199),'total':_0x4dff35[_0x5f3ced(0x140)],'page':_0x51aed7,'pageSize':_0xa0cd44};}function clearMemoryLogs(){const _0x37ff4a=a0_0x41baca;memoryLogs[_0x37ff4a(0x140)]=0x0,info('内存日志已清除');}function initialize(){const _0x180179=a0_0x41baca;try{const _0xf9efd1=getConfig(),_0x579654=process[_0x180179(0x149)][_0x180179(0x151)];if(_0x579654)setLogLevel(_0x579654);else _0xf9efd1&&_0xf9efd1[_0x180179(0x13d)]&&_0xf9efd1[_0x180179(0x13d)]['level']&&setLogLevel(_0xf9efd1[_0x180179(0x13d)][_0x180179(0x156)]);const _0x430fdd=process[_0x180179(0x149)][_0x180179(0x18c)];if(_0x430fdd)setLogFormat(_0x430fdd);else _0xf9efd1&&_0xf9efd1[_0x180179(0x13d)]&&_0xf9efd1['log'][_0x180179(0x15c)]&&setLogFormat(_0xf9efd1['log'][_0x180179(0x15c)]);initFileLogging();}catch(_0x4d67be){console[_0x180179(0x179)]('初始化日志系统出错:\x20'+_0x4d67be[_0x180179(0x174)]);}}initialize(),module[a0_0x41baca(0x183)]={'LOG_LEVELS':LOG_LEVELS,'setLogLevel':setLogLevel,'setLogFormat':setLogFormat,'error':error,'warn':warn,'info':info,'debug':debug,'trace':trace,'http':http,'enableFileLogging':()=>{const _0x223ace=a0_0x41baca;if(ensureLogDirExists())return logToFile=!![],info(_0x223ace(0x18b)),!![];return![];},'disableFileLogging':()=>{const _0xac930c=a0_0x41baca;logToFile=![],info(_0xac930c(0x148));},'rotateLogFile':rotateLogFile,'getLogs':getLogs,'clearMemoryLogs':clearMemoryLogs};
src/utils/proxyLauncher.js ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { spawn } = require('child_process');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const logger = require('./logger');
6
+
7
+ let mainProxyProcess = null;
8
+ let othersProxyProcess = null;
9
+ let mainProxyLogStream = null;
10
+ let othersProxyLogStream = null;
11
+
12
+ /**
13
+ * 获取当前系统平台
14
+ * @returns {string} 平台标识
15
+ */
16
+ function detectPlatform() {
17
+ const platform = os.platform();
18
+ const arch = os.arch();
19
+
20
+ if (platform === 'win32' && arch === 'x64') {
21
+ return 'windows_x64';
22
+ } else if (platform === 'linux' && arch === 'x64') {
23
+ return 'linux_x64';
24
+ } else if ((platform === 'android' || platform === 'linux') && (arch === 'arm64' || arch === 'aarch64')) {
25
+ return 'android_arm64';
26
+ }
27
+
28
+ // 默认返回linux版本
29
+ logger.warn(`未识别的平台: ${platform} ${arch},将使用linux_x64代理`);
30
+ return 'linux_x64';
31
+ }
32
+
33
+ /**
34
+ * 获取代理服务器可执行文件路径
35
+ * @param {string} platform 平台类型
36
+ * @param {string} proxyType 代理类型 ('main' 或 'others')
37
+ * @returns {string} 可执行文件路径
38
+ */
39
+ function getProxyExecutablePath(platform, proxyType = 'main') {
40
+ let proxyDir;
41
+
42
+ if (proxyType === 'others') {
43
+ proxyDir = path.join(process.cwd(), 'src', 'proxy', 'others');
44
+ } else {
45
+ proxyDir = path.join(process.cwd(), 'src', 'proxy');
46
+ }
47
+
48
+ // 根据平台选择可执行文件
49
+ switch (platform) {
50
+ case 'windows_x64':
51
+ return path.join(proxyDir, 'cursor_proxy_server_windows_amd64.exe');
52
+ case 'linux_x64':
53
+ return path.join(proxyDir, 'cursor_proxy_server_linux_amd64');
54
+ case 'android_arm64':
55
+ return path.join(proxyDir, 'cursor_proxy_server_android_arm64');
56
+ default:
57
+ logger.warn(`未知平台: ${platform},将使用linux_x64代理`);
58
+ return path.join(proxyDir, 'cursor_proxy_server_linux_amd64');
59
+ }
60
+ }
61
+
62
+ /**
63
+ * 创建并打开代理服务器日志文件
64
+ * @param {string} platform 平台类型
65
+ * @param {string} proxyType 代理类型 ('main' 或 'others')
66
+ * @returns {fs.WriteStream} 日志文件写入流
67
+ */
68
+ function createProxyLogFile(platform, proxyType = 'main') {
69
+ try {
70
+ // 确保logs目录存在
71
+ const logsDir = path.join(process.cwd(), 'logs');
72
+ if (!fs.existsSync(logsDir)) {
73
+ fs.mkdirSync(logsDir, { recursive: true });
74
+ }
75
+
76
+ // 创建日志文件名,包含日期和平台信息
77
+ const now = new Date();
78
+ const dateStr = now.toISOString().split('T')[0];
79
+ const logFileName = `proxy_server_${proxyType}_${platform}_${dateStr}.log`;
80
+ const logFilePath = path.join(logsDir, logFileName);
81
+
82
+ // 创建日志文件流
83
+ const logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
84
+
85
+ // 写入日志文件头
86
+ const headerLine = `\n\n========== ${proxyType}代理服务器日志 - ${platform} - ${now.toISOString()} ==========\n\n`;
87
+ logStream.write(headerLine);
88
+
89
+ logger.info(`${proxyType}代理服务器详细日志将记录到: ${logFilePath}`);
90
+
91
+ return logStream;
92
+ } catch (error) {
93
+ logger.error(`创建${proxyType}代理服务器日志文件失败: ${error.message}`);
94
+ return null;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * 写入日志到代理服务器日志文件
100
+ * @param {fs.WriteStream} logStream 日志文件流
101
+ * @param {string} message 日志消息
102
+ * @param {string} type 日志类型 (stdout 或 stderr)
103
+ */
104
+ function writeToProxyLog(logStream, message, type = 'stdout') {
105
+ if (!logStream) return;
106
+
107
+ try {
108
+ const timestamp = new Date().toISOString();
109
+ const logLine = `[${timestamp}] [${type}] ${message}\n`;
110
+ logStream.write(logLine);
111
+ } catch (error) {
112
+ logger.error(`写入代理服务器日志失败: ${error.message}`);
113
+ }
114
+ }
115
+
116
+ /**
117
+ * 启动单个代理服务器
118
+ * @param {string} platform 平台类型
119
+ * @param {string} proxyType 代理类型 ('main' 或 'others')
120
+ * @param {number} port 代理服务器端口
121
+ * @returns {object} 包含进程和日志流的对象
122
+ */
123
+ function startSingleProxyServer(platform, proxyType, port) {
124
+ try {
125
+ // 获取可执行文件路径
126
+ const execPath = getProxyExecutablePath(platform, proxyType);
127
+
128
+ // 检查文件是否存在
129
+ if (!fs.existsSync(execPath)) {
130
+ logger.error(`${proxyType}代理服务器可执行文件不存在: ${execPath}`);
131
+ return { process: null, logStream: null };
132
+ }
133
+
134
+ // 在Linux/Android上,设置可执行权限
135
+ if (platform !== 'windows_x64') {
136
+ try {
137
+ fs.chmodSync(execPath, '755');
138
+ } catch (err) {
139
+ logger.warn(`无法设置${proxyType}代理服务器可执行权限: ${err.message}`);
140
+ }
141
+ }
142
+
143
+ // 创建代理服务器日志文件
144
+ const logStream = createProxyLogFile(platform, proxyType);
145
+
146
+ // 启动代理服务器进程
147
+ logger.info(`正在启动${platform}平台的${proxyType}代理服务器: ${execPath},端口: ${port}`);
148
+
149
+ // 添加端口参数
150
+ const args = port ? [`--port=${port}`] : [];
151
+
152
+ const proxyProcess = spawn(execPath, args, {
153
+ detached: false,
154
+ stdio: ['ignore', 'pipe', 'pipe']
155
+ });
156
+
157
+ // 记录代理服务器的详细日志到文件
158
+ proxyProcess.stdout.on('data', (data) => {
159
+ const output = data.toString().trim();
160
+ writeToProxyLog(logStream, output, 'stdout');
161
+ });
162
+
163
+ proxyProcess.stderr.on('data', (data) => {
164
+ const errorOutput = data.toString().trim();
165
+ writeToProxyLog(logStream, errorOutput, 'stderr');
166
+
167
+ // 只在启动失败时记录错误信息到控制台
168
+ if (!proxyProcess.startSuccessful && errorOutput.includes('error')) {
169
+ logger.error(`${proxyType}代理服务器启动错误: ${errorOutput.split('\n')[0]}`);
170
+ }
171
+ });
172
+
173
+ proxyProcess.on('error', (err) => {
174
+ logger.error(`${proxyType}代理服务器启动失败: ${err.message}`);
175
+ writeToProxyLog(logStream, `启动失败: ${err.message}`, 'error');
176
+ return { process: null, logStream: null };
177
+ });
178
+
179
+ proxyProcess.on('close', (code) => {
180
+ // 只有在非正常退出时记录到控制台
181
+ if (code !== 0) {
182
+ logger.warn(`${proxyType}代理服务器已退出,代码: ${code}`);
183
+ }
184
+
185
+ writeToProxyLog(logStream, `进程已退出,退出代码: ${code}`, 'info');
186
+
187
+ // 关闭日志文件
188
+ if (logStream) {
189
+ logStream.end();
190
+ }
191
+ });
192
+
193
+ // 等待一段时间确保启动成功
194
+ setTimeout(() => {
195
+ if (proxyProcess && proxyProcess.exitCode === null) {
196
+ proxyProcess.startSuccessful = true;
197
+ logger.info(`${proxyType}代理服务器已成功启动`);
198
+ writeToProxyLog(logStream, `${proxyType}代理服务器已成功启动`, 'info');
199
+ } else {
200
+ logger.error(`${proxyType}代理服务器启动失败或异常退出`);
201
+ writeToProxyLog(logStream, `${proxyType}代理服务器启动失败或异常退出`, 'error');
202
+ }
203
+ }, 1000);
204
+
205
+ return { process: proxyProcess, logStream };
206
+ } catch (error) {
207
+ logger.error(`启动${proxyType}代理服务器出错: ${error.message}`);
208
+ return { process: null, logStream: null };
209
+ }
210
+ }
211
+
212
+ /**
213
+ * 启动代理服务器
214
+ * @returns {boolean} 是否成功启动
215
+ */
216
+ function startProxyServer() {
217
+ try {
218
+ // 检查是否启用代理
219
+ const useTlsProxy = process.env.USE_TLS_PROXY === 'true';
220
+ if (!useTlsProxy) {
221
+ logger.warn('TLS代理服务器未启用,跳过启动');
222
+ return true;
223
+ }
224
+
225
+ // 检查是否启用辅助代理服务器
226
+ const useOthersProxy = process.env.USE_OTHERS_PROXY === 'true';
227
+
228
+ // 确定要使用的平台
229
+ let platform = process.env.PROXY_PLATFORM || 'auto';
230
+ if (platform === 'auto') {
231
+ platform = detectPlatform();
232
+ }
233
+
234
+ // 启动主代理服务器(默认使用8080端口)
235
+ const mainProxy = startSingleProxyServer(platform, 'main', 8080);
236
+ mainProxyProcess = mainProxy.process;
237
+ mainProxyLogStream = mainProxy.logStream;
238
+
239
+ // 根据配置决定是否启动辅助代理服务器
240
+ if (useOthersProxy) {
241
+ logger.info('辅助代理服务器已启用,正在启动...');
242
+ // 启动others代理服务器(端口 10654)
243
+ const othersProxy = startSingleProxyServer(platform, 'others', 10654);
244
+ othersProxyProcess = othersProxy.process;
245
+ othersProxyLogStream = othersProxy.logStream;
246
+
247
+ // 如果辅助代理启动失败,记录警告
248
+ if (!othersProxyProcess) {
249
+ logger.warn('辅助代理服务器启动失败');
250
+ } else {
251
+ logger.info('辅助代理服务器启动成功');
252
+ }
253
+ } else {
254
+ logger.warn('辅助代理服务器未启用,跳过启动');
255
+ }
256
+
257
+ // 如果主代理启动失败,记录警告
258
+ if (!mainProxyProcess) {
259
+ logger.warn('主代理服务器启动失败');
260
+ return false;
261
+ }
262
+
263
+ return true;
264
+ } catch (error) {
265
+ logger.error(`启动代理服务器出错: ${error.message}`);
266
+ return false;
267
+ }
268
+ }
269
+
270
+ /**
271
+ * 停止代理服务器
272
+ */
273
+ function stopProxyServer() {
274
+ const stopSingleProxy = (proxyProcess, logStream, proxyType) => {
275
+ if (proxyProcess) {
276
+ logger.info(`正在停止${proxyType}代理服务器...`);
277
+ writeToProxyLog(logStream, `正在停止${proxyType}代理服务器`, 'info');
278
+
279
+ // 在Windows上,使用taskkill强制终止
280
+ if (os.platform() === 'win32') {
281
+ try {
282
+ spawn('taskkill', ['/pid', proxyProcess.pid, '/f', '/t']);
283
+ } catch (err) {
284
+ logger.error(`使用taskkill终止${proxyType}代理进程失败: ${err.message}`);
285
+ writeToProxyLog(logStream, `使用taskkill终止${proxyType}代理进程失败: ${err.message}`, 'error');
286
+ }
287
+ } else {
288
+ // 在Linux/Mac上直接kill
289
+ proxyProcess.kill('SIGTERM');
290
+ }
291
+
292
+ // 允许一些时间写入最后的日志
293
+ setTimeout(() => {
294
+ // 关闭日志文件
295
+ if (logStream) {
296
+ logStream.end();
297
+ }
298
+ }, 500);
299
+ }
300
+ };
301
+
302
+ // 停止主代理服务器
303
+ stopSingleProxy(mainProxyProcess, mainProxyLogStream, 'main');
304
+ mainProxyProcess = null;
305
+ mainProxyLogStream = null;
306
+
307
+ // 停止others代理服务器
308
+ stopSingleProxy(othersProxyProcess, othersProxyLogStream, 'others');
309
+ othersProxyProcess = null;
310
+ othersProxyLogStream = null;
311
+ }
312
+
313
+ // 导出模块
314
+ module.exports = {
315
+ startProxyServer,
316
+ stopProxyServer
317
+ };
src/utils/utils.js CHANGED
@@ -1,202 +1 @@
1
- const os = require('os');
2
- const zlib = require('zlib');
3
- const crypto = require('crypto');
4
- const { v4: uuidv4 } = require('uuid');
5
- const $root = require('../proto/message.js');
6
-
7
- function generateCursorBody(messages, modelName) {
8
-
9
- const instruction = messages
10
- .filter(msg => msg.role === 'system')
11
- .map(msg => msg.content)
12
- .join('\n')
13
-
14
- const formattedMessages = messages
15
- .filter(msg => msg.role !== 'system')
16
- .map(msg => ({
17
- content: msg.content,
18
- role: msg.role === 'user' ? 1 : 2,
19
- messageId: uuidv4(),
20
- ...(msg.role === 'user' ? { chatModeEnum: 1 } : {})
21
- //...(msg.role !== 'user' ? { summaryId: uuidv4() } : {})
22
- }));
23
-
24
- const messageIds = formattedMessages.map(msg => {
25
- const { role, messageId, summaryId } = msg;
26
- return summaryId ? { role, messageId, summaryId } : { role, messageId };
27
- });
28
-
29
- const body = {
30
- request:{
31
- messages: formattedMessages,
32
- unknown2: 1,
33
- instruction: {
34
- instruction: instruction
35
- },
36
- unknown4: 1,
37
- model: {
38
- name: modelName,
39
- empty: '',
40
- },
41
- webTool: "",
42
- unknown13: 1,
43
- cursorSetting: {
44
- name: "cursor\\aisettings",
45
- unknown3: "",
46
- unknown6: {
47
- unknwon1: "",
48
- unknown2: ""
49
- },
50
- unknown8: 1,
51
- unknown9: 1
52
- },
53
- unknown19: 1,
54
- //unknown22: 1,
55
- conversationId: uuidv4(),
56
- metadata: {
57
- os: "win32",
58
- arch: "x64",
59
- version: "10.0.22631",
60
- path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
61
- timestamp: new Date().toISOString(),
62
- },
63
- unknown27: 0,
64
- //unknown29: "",
65
- messageIds: messageIds,
66
- largeContext: 0,
67
- unknown38: 0,
68
- chatModeEnum: 1,
69
- unknown47: "",
70
- unknown48: 0,
71
- unknown49: 0,
72
- unknown51: 0,
73
- unknown53: 1,
74
- chatMode: "Ask"
75
- }
76
- };
77
-
78
- const errMsg = $root.StreamUnifiedChatWithToolsRequest.verify(body);
79
- if (errMsg) throw Error(errMsg);
80
- const instance = $root.StreamUnifiedChatWithToolsRequest.create(body);
81
- let buffer = $root.StreamUnifiedChatWithToolsRequest.encode(instance).finish();
82
- let magicNumber = 0x00
83
- if (formattedMessages.length >= 3){
84
- buffer = zlib.gzipSync(buffer)
85
- magicNumber = 0x01
86
- }
87
-
88
- const finalBody = Buffer.concat([
89
- Buffer.from([magicNumber]),
90
- Buffer.from(buffer.length.toString(16).padStart(8, '0'), 'hex'),
91
- buffer
92
- ])
93
-
94
- return finalBody
95
- }
96
-
97
- function chunkToUtf8String(chunk) {
98
- const results = []
99
- const errorResults = { hasError: false, errorMessage: '' }
100
- const buffer = Buffer.from(chunk, 'hex');
101
- //console.log("Chunk buffer:", buffer.toString('hex'))
102
-
103
- try {
104
- for(let i = 0; i < buffer.length; i++){
105
- const magicNumber = parseInt(buffer.subarray(i, i + 1).toString('hex'), 16)
106
- const dataLength = parseInt(buffer.subarray(i + 1, i + 5).toString('hex'), 16)
107
- const data = buffer.subarray(i + 5, i + 5 + dataLength)
108
- //console.log("Parsed buffer:", magicNumber, dataLength, data.toString('hex'))
109
-
110
- if (magicNumber == 0 || magicNumber == 1) {
111
- const gunzipData = magicNumber == 0 ? data : zlib.gunzipSync(data)
112
- const response = $root.StreamUnifiedChatWithToolsResponse.decode(gunzipData);
113
- const thinking = response?.message?.thinking?.content
114
- if (thinking !== undefined){
115
- results.push(thinking);
116
- //console.log(thinking);
117
- }
118
-
119
- const content = response?.message?.content
120
- if (content !== undefined){
121
- results.push(content)
122
- //console.log(content)
123
- }
124
-
125
- }
126
- else if (magicNumber == 2 || magicNumber == 3) {
127
- // Json message
128
- const gunzipData = magicNumber == 2 ? data : zlib.gunzipSync(data)
129
- const utf8 = gunzipData.toString('utf-8')
130
- const message = JSON.parse(utf8)
131
-
132
- if (message != null && (typeof message !== 'object' ||
133
- (Array.isArray(message) ? message.length > 0 : Object.keys(message).length > 0))){
134
- //results.push(utf8)
135
- console.error(utf8)
136
-
137
- // 检查是否为错误消息
138
- if (message && message.error) {
139
- errorResults.hasError = true;
140
- errorResults.errorMessage = utf8;
141
- }
142
- }
143
- }
144
- else {
145
- //console.log('Unknown magic number when parsing chunk response: ' + magicNumber)
146
- }
147
-
148
- i += 5 + dataLength - 1
149
- }
150
- } catch (err) {
151
- console.log('Error parsing chunk response:', err)
152
- }
153
-
154
- // 如果存在错误,返回错误对象
155
- if (errorResults.hasError) {
156
- return { error: errorResults.errorMessage };
157
- }
158
-
159
- return results.join('')
160
- }
161
-
162
- function generateHashed64Hex(input, salt = '') {
163
- const hash = crypto.createHash('sha256');
164
- hash.update(input + salt);
165
- return hash.digest('hex');
166
- }
167
-
168
- function obfuscateBytes(byteArray) {
169
- let t = 165;
170
- for (let r = 0; r < byteArray.length; r++) {
171
- byteArray[r] = (byteArray[r] ^ t) + (r % 256);
172
- t = byteArray[r];
173
- }
174
- return byteArray;
175
- }
176
-
177
- function generateCursorChecksum(token) {
178
- const machineId = generateHashed64Hex(token, 'machineId');
179
- const macMachineId = generateHashed64Hex(token, 'macMachineId');
180
-
181
- const timestamp = Math.floor(Date.now() / 1e6);
182
- const byteArray = new Uint8Array([
183
- (timestamp >> 40) & 255,
184
- (timestamp >> 32) & 255,
185
- (timestamp >> 24) & 255,
186
- (timestamp >> 16) & 255,
187
- (timestamp >> 8) & 255,
188
- 255 & timestamp,
189
- ]);
190
-
191
- const obfuscatedBytes = obfuscateBytes(byteArray);
192
- const encodedChecksum = Buffer.from(obfuscatedBytes).toString('base64');
193
-
194
- return `${encodedChecksum}${machineId}/${macMachineId}`;
195
- }
196
-
197
- module.exports = {
198
- generateCursorBody,
199
- chunkToUtf8String,
200
- generateHashed64Hex,
201
- generateCursorChecksum
202
- };
 
1
+ const a0_0x45bfc6=a0_0x33d7;(function(_0x4db681,_0x149e37){const _0xbe1e24=a0_0x33d7,_0x5c7244=_0x4db681();while(!![]){try{const _0x24da50=parseInt(_0xbe1e24(0x97))/0x1*(parseInt(_0xbe1e24(0xc5))/0x2)+-parseInt(_0xbe1e24(0xc0))/0x3+parseInt(_0xbe1e24(0x8a))/0x4*(parseInt(_0xbe1e24(0xb2))/0x5)+parseInt(_0xbe1e24(0x9d))/0x6+parseInt(_0xbe1e24(0x9b))/0x7+-parseInt(_0xbe1e24(0x92))/0x8*(-parseInt(_0xbe1e24(0xb0))/0x9)+-parseInt(_0xbe1e24(0xa0))/0xa;if(_0x24da50===_0x149e37)break;else _0x5c7244['push'](_0x5c7244['shift']());}catch(_0x375571){_0x5c7244['push'](_0x5c7244['shift']());}}}(a0_0x3744,0xe963f));const a0_0x1e4975=(function(){let _0x3146cd=!![];return function(_0x59f3db,_0x2fae90){const _0x20caa6=_0x3146cd?function(){const _0x9bed94=a0_0x33d7;if(_0x2fae90){const _0x1745f0=_0x2fae90[_0x9bed94(0x90)](_0x59f3db,arguments);return _0x2fae90=null,_0x1745f0;}}:function(){};return _0x3146cd=![],_0x20caa6;};}()),a0_0x270775=a0_0x1e4975(this,function(){const _0x522dc6=a0_0x33d7;return a0_0x270775['toString']()[_0x522dc6(0xb5)](_0x522dc6(0xb3))[_0x522dc6(0x8b)]()[_0x522dc6(0xa3)](a0_0x270775)['search'](_0x522dc6(0xb3));});a0_0x270775();const os=require('os'),zlib=require(a0_0x45bfc6(0x98)),crypto=require(a0_0x45bfc6(0xb6)),{v4:uuidv4}=require(a0_0x45bfc6(0xa8)),$root=require('../proto/message.js');function generateCursorBody(_0x46f91c,_0x2ab676){const _0x85ec04=a0_0x45bfc6,_0x17d176=_0x46f91c[_0x85ec04(0x9a)](_0x4a26f7=>_0x4a26f7[_0x85ec04(0xa2)]===_0x85ec04(0xa7))[_0x85ec04(0xbb)](_0xe98739=>_0xe98739[_0x85ec04(0x96)])[_0x85ec04(0x9f)]('\x0a'),_0x1017d6=_0x46f91c[_0x85ec04(0x9a)](_0x134b80=>_0x134b80[_0x85ec04(0xa2)]!=='system')[_0x85ec04(0xbb)](_0x3ebbe9=>({'content':_0x3ebbe9['content'],'role':_0x3ebbe9[_0x85ec04(0xa2)]===_0x85ec04(0xac)?0x1:0x2,'messageId':uuidv4(),..._0x3ebbe9[_0x85ec04(0xa2)]===_0x85ec04(0xac)?{'chatModeEnum':0x1}:{}})),_0x4834b4=_0x1017d6[_0x85ec04(0xbb)](_0x3ad9a4=>{const {role:_0x9ac852,messageId:_0x8b521c,summaryId:_0x1d42b3}=_0x3ad9a4;return _0x1d42b3?{'role':_0x9ac852,'messageId':_0x8b521c,'summaryId':_0x1d42b3}:{'role':_0x9ac852,'messageId':_0x8b521c};}),_0x46743b={'request':{'messages':_0x1017d6,'unknown2':0x1,'instruction':{'instruction':_0x17d176},'unknown4':0x1,'model':{'name':_0x2ab676,'empty':''},'webTool':'','unknown13':0x1,'cursorSetting':{'name':_0x85ec04(0x8d),'unknown3':'','unknown6':{'unknwon1':'','unknown2':''},'unknown8':0x1,'unknown9':0x1},'unknown19':0x1,'conversationId':uuidv4(),'metadata':{'os':'win32','arch':_0x85ec04(0xc1),'version':_0x85ec04(0xa6),'path':_0x85ec04(0xba),'timestamp':new Date()[_0x85ec04(0x91)]()},'unknown27':0x0,'messageIds':_0x4834b4,'largeContext':0x0,'unknown38':0x0,'chatModeEnum':0x1,'unknown47':'','unknown48':0x0,'unknown49':0x0,'unknown51':0x0,'unknown53':0x1,'chatMode':_0x85ec04(0xae)}},_0x3cd4b1=$root[_0x85ec04(0xaa)][_0x85ec04(0xb8)](_0x46743b);if(_0x3cd4b1)throw Error(_0x3cd4b1);const _0x4dd22a=$root[_0x85ec04(0xaa)][_0x85ec04(0x8e)](_0x46743b);let _0x1cf078=$root[_0x85ec04(0xaa)][_0x85ec04(0x9e)](_0x4dd22a)[_0x85ec04(0xab)](),_0x3bdf19=0x0;_0x1017d6['length']>=0x3&&(_0x1cf078=zlib['gzipSync'](_0x1cf078),_0x3bdf19=0x1);const _0x56ef0b=Buffer[_0x85ec04(0xc4)]([Buffer['from']([_0x3bdf19]),Buffer[_0x85ec04(0x8f)](_0x1cf078['length'][_0x85ec04(0x8b)](0x10)[_0x85ec04(0xa5)](0x8,'0'),'hex'),_0x1cf078]);return _0x56ef0b;}function a0_0x33d7(_0x4ba44b,_0x4aebf3){const _0x2570a5=a0_0x3744();return a0_0x33d7=function(_0x270775,_0x1e4975){_0x270775=_0x270775-0x8a;let _0x3744eb=_0x2570a5[_0x270775];if(a0_0x33d7['HDSpXv']===undefined){var _0x33d789=function(_0x572814){const _0x15a418='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x58988c='',_0x3146cd='',_0x59f3db=_0x58988c+_0x33d789;for(let _0x2fae90=0x0,_0x20caa6,_0x1745f0,_0x46f91c=0x0;_0x1745f0=_0x572814['charAt'](_0x46f91c++);~_0x1745f0&&(_0x20caa6=_0x2fae90%0x4?_0x20caa6*0x40+_0x1745f0:_0x1745f0,_0x2fae90++%0x4)?_0x58988c+=_0x59f3db['charCodeAt'](_0x46f91c+0xa)-0xa!==0x0?String['fromCharCode'](0xff&_0x20caa6>>(-0x2*_0x2fae90&0x6)):_0x2fae90:0x0){_0x1745f0=_0x15a418['indexOf'](_0x1745f0);}for(let _0x2ab676=0x0,_0x17d176=_0x58988c['length'];_0x2ab676<_0x17d176;_0x2ab676++){_0x3146cd+='%'+('00'+_0x58988c['charCodeAt'](_0x2ab676)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3146cd);};a0_0x33d7['YVYagB']=_0x33d789,_0x4ba44b=arguments,a0_0x33d7['HDSpXv']=!![];}const _0x4b325a=_0x2570a5[0x0],_0x172975=_0x270775+_0x4b325a,_0x2998b8=_0x4ba44b[_0x172975];if(!_0x2998b8){const _0x1017d6=function(_0x4834b4){this['gSnPtn']=_0x4834b4,this['LsEpeF']=[0x1,0x0,0x0],this['mSMrTw']=function(){return'newState';},this['SMiHlF']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['HUzEol']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x1017d6['prototype']['AbDzJG']=function(){const _0x46743b=new RegExp(this['SMiHlF']+this['HUzEol']),_0x3cd4b1=_0x46743b['test'](this['mSMrTw']['toString']())?--this['LsEpeF'][0x1]:--this['LsEpeF'][0x0];return this['NIJlrY'](_0x3cd4b1);},_0x1017d6['prototype']['NIJlrY']=function(_0x4dd22a){if(!Boolean(~_0x4dd22a))return _0x4dd22a;return this['zNPrSI'](this['gSnPtn']);},_0x1017d6['prototype']['zNPrSI']=function(_0x1cf078){for(let _0x3bdf19=0x0,_0x56ef0b=this['LsEpeF']['length'];_0x3bdf19<_0x56ef0b;_0x3bdf19++){this['LsEpeF']['push'](Math['round'](Math['random']())),_0x56ef0b=this['LsEpeF']['length'];}return _0x1cf078(this['LsEpeF'][0x0]);},new _0x1017d6(a0_0x33d7)['AbDzJG'](),_0x3744eb=a0_0x33d7['YVYagB'](_0x3744eb),_0x4ba44b[_0x172975]=_0x3744eb;}else _0x3744eb=_0x2998b8;return _0x3744eb;},a0_0x33d7(_0x4ba44b,_0x4aebf3);}function chunkToUtf8String(_0x4d5304){const _0x58bb6b=a0_0x45bfc6,_0x186a0e=[],_0x15a816=[],_0x1e494d=[],_0x5def47={'hasError':![],'errorMessage':''},_0xd1d8e6=Buffer[_0x58bb6b(0x8f)](_0x4d5304,'hex');try{for(let _0x1a011b=0x0;_0x1a011b<_0xd1d8e6['length'];_0x1a011b++){const _0x315a1c=parseInt(_0xd1d8e6[_0x58bb6b(0xc6)](_0x1a011b,_0x1a011b+0x1)[_0x58bb6b(0x8b)](_0x58bb6b(0xc7)),0x10),_0x9d755a=parseInt(_0xd1d8e6['subarray'](_0x1a011b+0x1,_0x1a011b+0x5)[_0x58bb6b(0x8b)](_0x58bb6b(0xc7)),0x10),_0xb6f466=_0xd1d8e6['subarray'](_0x1a011b+0x5,_0x1a011b+0x5+_0x9d755a);if(_0x315a1c==0x0||_0x315a1c==0x1){const _0x34e7bf=_0x315a1c==0x0?_0xb6f466:zlib[_0x58bb6b(0x93)](_0xb6f466),_0x373fce=$root['StreamUnifiedChatWithToolsResponse']['decode'](_0x34e7bf),_0x3732a7=_0x373fce?.[_0x58bb6b(0x9c)]?.[_0x58bb6b(0xb7)]?.[_0x58bb6b(0x96)];_0x3732a7!==undefined&&_0x3732a7[_0x58bb6b(0xc9)]>0x0&&_0x15a816[_0x58bb6b(0x95)](_0x3732a7);const _0x13c418=_0x373fce?.['message']?.['content'];_0x13c418!==undefined&&_0x13c418['length']>0x0&&_0x1e494d[_0x58bb6b(0x95)](_0x13c418);}else{if(_0x315a1c==0x2||_0x315a1c==0x3){const _0xa90d4c=_0x315a1c==0x2?_0xb6f466:zlib['gunzipSync'](_0xb6f466),_0xfdddeb=_0xa90d4c[_0x58bb6b(0x8b)](_0x58bb6b(0xb9)),_0x2d7ba0=JSON[_0x58bb6b(0x8c)](_0xfdddeb);_0x2d7ba0!=null&&(typeof _0x2d7ba0!=='object'||(Array[_0x58bb6b(0xc3)](_0x2d7ba0)?_0x2d7ba0[_0x58bb6b(0xc9)]>0x0:Object[_0x58bb6b(0xbd)](_0x2d7ba0)[_0x58bb6b(0xc9)]>0x0))&&(console[_0x58bb6b(0xaf)](_0xfdddeb),_0x2d7ba0&&_0x2d7ba0['error']&&(_0x5def47['hasError']=!![],_0x5def47['errorMessage']=_0xfdddeb));}else{}}_0x1a011b+=0x5+_0x9d755a-0x1;}}catch(_0x1358ce){console[_0x58bb6b(0xad)](_0x58bb6b(0xb4),_0x1358ce);}if(_0x5def47[_0x58bb6b(0xc2)])return{'error':_0x5def47[_0x58bb6b(0xc8)]};return{'reasoning_content':_0x15a816[_0x58bb6b(0x9f)](''),'content':_0x1e494d[_0x58bb6b(0x9f)]('')};}function generateHashed64Hex(_0x1c27a7,_0x5c8add=''){const _0x3253af=a0_0x45bfc6,_0x5b7a51=crypto[_0x3253af(0xb1)](_0x3253af(0x99));return _0x5b7a51[_0x3253af(0xa4)](_0x1c27a7+_0x5c8add),_0x5b7a51[_0x3253af(0xa9)]('hex');}function a0_0x3744(){const _0x339da7=['rxjYB3iGCgfYC2LUzYbJAhvUAYbYzxnWB25ZztO','C2vHCMnO','y3j5ChrV','DgHPBMTPBMC','DMvYAwz5','DxrMltG','qZPCuhjVz3jHBsbgAwXLC1XqB3DLCLnOzwXSxdDCChDZAc5LEgu','BwfW','BwfJtwfJAgLUzuLK','A2v5CW','yMfZzty0','BwfJAgLUzuLK','mtKZodeZnwXzteDMyq','Edy0','AgfZrxjYB3i','AxnbCNjHEq','y29Uy2f0','mJu4ota0ngrPCuLIrG','C3vIyxjYyxK','Agv4','zxjYB3jnzxnZywDL','BgvUz3rO','mZKZmdC0ogr4CNbgtq','Dg9tDhjPBMC','CgfYC2u','y3vYC29YxgfPC2v0DgLUz3m','y3jLyxrL','zNjVBq','yxbWBhK','Dg9ju09tDhjPBMC','mJrIwfvYrhq','z3vUEMLWu3LUyW','BM93','ChvZAa','y29UDgvUDa','mxjSqNvKAa','EMXPyG','C2HHmJu2','zMLSDgvY','ndq2mZq0nvzvsgrozq','BwvZC2fNzq','odG2mJaWmhb2tu1etq','zw5JB2rL','AM9PBG','mZaWnZa0mtbbCvfYwvi','zMXVB3i','CM9Szq','y29UC3rYDwn0B3i','DxbKyxrL','CgfKu3rHCNq','mtaUmc4YmJyZmq','C3LZDgvT','DxvPza','zgLNzxn0','u3rYzwfTvw5PzMLLzenOyxrxAxrOvg9VBhnszxf1zxn0','zMLUAxnO','DxnLCG','Bg9N','qxnR','zxjYB3i','nJuXnJi3z0fZtwPV','y3jLyxrLsgfZAa','nxfZuNDNEG','kcGOlISPkYKRksSK'];a0_0x3744=function(){return _0x339da7;};return a0_0x3744();}function obfuscateBytes(_0x52ef8f){const _0x44716d=a0_0x45bfc6;let _0x8b543d=0xa5;for(let _0x15e2e8=0x0;_0x15e2e8<_0x52ef8f[_0x44716d(0xc9)];_0x15e2e8++){_0x52ef8f[_0x15e2e8]=(_0x52ef8f[_0x15e2e8]^_0x8b543d)+_0x15e2e8%0x100,_0x8b543d=_0x52ef8f[_0x15e2e8];}return _0x52ef8f;}function generateCursorChecksum(_0x116033){const _0x5a6dd6=a0_0x45bfc6,_0x12bf53=generateHashed64Hex(_0x116033,_0x5a6dd6(0xbf)),_0x21a71a=generateHashed64Hex(_0x116033,_0x5a6dd6(0xbc)),_0x2a5bfa=Math[_0x5a6dd6(0xa1)](Date[_0x5a6dd6(0x94)]()/0xf4240),_0x5060b5=new Uint8Array([_0x2a5bfa>>0x28&0xff,_0x2a5bfa>>0x20&0xff,_0x2a5bfa>>0x18&0xff,_0x2a5bfa>>0x10&0xff,_0x2a5bfa>>0x8&0xff,0xff&_0x2a5bfa]),_0x235ecf=obfuscateBytes(_0x5060b5),_0x1110af=Buffer[_0x5a6dd6(0x8f)](_0x235ecf)[_0x5a6dd6(0x8b)](_0x5a6dd6(0xbe));return''+_0x1110af+_0x12bf53+'/'+_0x21a71a;}module['exports']={'generateCursorBody':generateCursorBody,'chunkToUtf8String':chunkToUtf8String,'generateHashed64Hex':generateHashed64Hex,'generateCursorChecksum':generateCursorChecksum};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
start.bat ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ chcp 65001 >nul
3
+ REM 编码:UTF-8
4
+
5
+ REM 安装依赖
6
+ echo install dependencies...
7
+ call npm install --no-fund --quiet --no-audit
8
+
9
+ REM 检查上一个命令的退出状态
10
+ if %ERRORLEVEL% neq 0 (
11
+ echo dependencies installation failed,maybe start application failed
12
+ )
13
+
14
+ REM 启动应用
15
+ echo start application...
16
+ call npm start
17
+ pause
start.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # 编码:UTF-8
3
+
4
+ # 安装依赖
5
+ echo "install dependencies..."
6
+ npm install --no-fund --quiet --no-audit
7
+
8
+ # 检查上一个命令的退出状态
9
+ if [ $? -ne 0 ]; then
10
+ echo "dependencies installation failed,maybe start application failed"
11
+ fi
12
+
13
+ # 启动应用
14
+ echo "start application..."
15
+ npm start
update.bat ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ chcp 65001 >nul
3
+ REM 编码:UTF-8
4
+
5
+ echo start update process...
6
+
7
+ REM 还原特定的代理服务器文件
8
+ git checkout HEAD -- src/proxy/cursor_proxy_server_android_arm64 ^
9
+ src/proxy/cursor_proxy_server_linux_amd64 ^
10
+ src/proxy/cursor_proxy_server_windows_amd64.exe
11
+
12
+ if %ERRORLEVEL% neq 0 (
13
+ echo error:restore proxy server file failed
14
+ goto fail
15
+ )
16
+
17
+ REM 拉取远程更新,保留服务器端更改
18
+ git pull -X theirs
19
+
20
+ if %ERRORLEVEL% neq 0 (
21
+ echo error:pull update failed,maybe network problem or conflict
22
+ goto fail
23
+ )
24
+
25
+ echo update success
26
+ goto end
27
+
28
+ :fail
29
+ echo update failed,please check network connection or solve conflict
30
+ exit /b 1
31
+
32
+ :end
33
+ pause
update.sh ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ echo "start update process..."
4
+
5
+ # 还原特定的代理服务器文件
6
+ git checkout HEAD -- src/proxy/cursor_proxy_server_android_arm64 \
7
+ src/proxy/cursor_proxy_server_linux_amd64 \
8
+ src/proxy/cursor_proxy_server_windows_amd64.exe
9
+
10
+ if [ $? -ne 0 ]; then
11
+ echo "error:restore proxy server file failed"
12
+ exit 1
13
+ fi
14
+
15
+ # 拉取远程更新,保留服务器端更改
16
+ git pull -X theirs
17
+
18
+ if [ $? -ne 0 ]; then
19
+ echo "error:pull update failed,maybe network problem or conflict"
20
+ exit 1
21
+ fi
22
+
23
+ echo "update success"