qwen-api-proxy 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -141,6 +141,8 @@ curl http://localhost:3264/api/chat/completions \
141
141
 
142
142
  ## Быстрый старт
143
143
 
144
+ > 🆕 **Новые пользователи?** Начните с [QUICK_START.md](QUICK_START.md) - пошаговое руководство с устранением常见ных ошибок
145
+
144
146
  ### 🌍 Кросс-платформенная поддержка
145
147
 
146
148
  Этот проект полностью поддерживает работу на:
@@ -309,7 +311,7 @@ docker run -d \
309
311
  -v $(pwd)/logs:/app/logs \
310
312
  -v $(pwd)/uploads:/app/uploads \
311
313
  -v $(pwd)/temp:/app/temp \
312
- endykaufman/qwen-api-proxy:1.0.11
314
+ endykaufman/qwen-api-proxy:1.0.13
313
315
 
314
316
  # 3. Смотрим логи
315
317
  docker logs -f qwen-proxy
@@ -318,7 +320,7 @@ docker logs -f qwen-proxy
318
320
  ### Доступные теги
319
321
 
320
322
  - `latest` - последняя стабильная версия
321
- - `1.0.11` - текущая версия
323
+ - `1.0.13` - текущая версия
322
324
  - `1.0.x` - предыдущие версии
323
325
 
324
326
  > **💡 Важно:** Перед первым запуском добавьте аккаунт через `npm run auth` или загрузите сессию через Telegram бота.
@@ -339,7 +341,7 @@ docker logs -f qwen-proxy
339
341
  ```yaml
340
342
  services:
341
343
  qwen-proxy:
342
- image: endykaufman/qwen-api-proxy:1.0.11
344
+ image: endykaufman/qwen-api-proxy:1.0.13
343
345
  container_name: qwen-proxy
344
346
  env_file:
345
347
  - .env
@@ -394,7 +396,7 @@ docker run -d \
394
396
  -v $(pwd)/logs:/app/logs \
395
397
  -v $(pwd)/uploads:/app/uploads \
396
398
  -v $(pwd)/temp:/app/temp \
397
- endykaufman/qwen-api-proxy:1.0.11
399
+ endykaufman/qwen-api-proxy:1.0.13
398
400
  ```
399
401
 
400
402
  Файл `docker-compose.yml`:
@@ -403,7 +405,7 @@ docker run -d \
403
405
  services:
404
406
  qwen-proxy:
405
407
  build: .
406
- image: endykaufman/qwen-api-proxy:1.0.11
408
+ image: endykaufman/qwen-api-proxy:1.0.13
407
409
  container_name: qwen-proxy
408
410
  env_file:
409
411
  - .env # Автоматическая загрузка переменных
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * qwen-api-proxy - CLI entry point for global installation
5
- *
5
+ *
6
6
  * This script:
7
7
  * 1. Sets up the working directory structure in the current location
8
8
  * 2. Creates necessary directories (session, logs, uploads, temp)
@@ -21,7 +21,7 @@ const WORKING_DIR = process.cwd();
21
21
 
22
22
  // Parse command-line arguments early to get custom directory
23
23
  const args = process.argv.slice(2);
24
- const dirFlag = args.find(arg => arg.startsWith('--dir='));
24
+ const dirFlag = args.find((arg) => arg.startsWith('--dir='));
25
25
  const customDir = dirFlag ? dirFlag.split('=')[1] : null;
26
26
 
27
27
  // Use custom directory if specified
@@ -47,8 +47,8 @@ function setupWorkingDirectory(targetDir = EFFECTIVE_DIR) {
47
47
  ];
48
48
 
49
49
  console.log('📁 Setting up working directory...');
50
-
51
- dirs.forEach(dir => {
50
+
51
+ dirs.forEach((dir) => {
52
52
  const dirPath = path.join(targetDir, dir);
53
53
  if (!fs.existsSync(dirPath)) {
54
54
  fs.mkdirSync(dirPath, { recursive: true });
@@ -71,16 +71,16 @@ function setupWorkingDirectory(targetDir = EFFECTIVE_DIR) {
71
71
  function setupEnvFile(targetDir = EFFECTIVE_DIR) {
72
72
  const envPath = path.join(targetDir, '.env');
73
73
  const envExamplePath = path.join(targetDir, '.env.example');
74
-
74
+
75
75
  if (!fs.existsSync(envPath)) {
76
76
  // Copy .env.example from package if it exists in working dir, otherwise create basic
77
77
  const packageEnvExample = path.join(PACKAGE_ROOT, '.env.example');
78
-
78
+
79
79
  if (fs.existsSync(packageEnvExample)) {
80
80
  fs.copyFileSync(packageEnvExample, envExamplePath);
81
81
  console.log(' ✓ Created .env.example');
82
82
  }
83
-
83
+
84
84
  // Create empty .env if not exists
85
85
  if (!fs.existsSync(envPath)) {
86
86
  fs.writeFileSync(envPath, '# Qwen API Proxy Configuration\n# See .env.example for available options\n\n');
@@ -105,12 +105,12 @@ function setupGitignore(targetDir = EFFECTIVE_DIR) {
105
105
  'session_backup_*'
106
106
  ];
107
107
  const missingEntries = [];
108
-
108
+
109
109
  // Check which entries are missing from .gitignore
110
110
  if (fs.existsSync(gitignorePath)) {
111
111
  const content = fs.readFileSync(gitignorePath, 'utf8');
112
- const lines = content.split('\n').map(line => line.trim());
113
- requiredEntries.forEach(entry => {
112
+ const lines = content.split('\n').map((line) => line.trim());
113
+ requiredEntries.forEach((entry) => {
114
114
  if (!lines.includes(entry)) {
115
115
  missingEntries.push(entry);
116
116
  }
@@ -146,7 +146,7 @@ npm-debug.log*
146
146
  fs.writeFileSync(gitignorePath, gitignoreContent);
147
147
  console.log(' ✓ Created .gitignore');
148
148
  }
149
-
149
+
150
150
  return missingEntries;
151
151
  }
152
152
 
@@ -155,7 +155,7 @@ npm-debug.log*
155
155
  */
156
156
  function checkDependencies() {
157
157
  const isWindows = process.platform === 'win32';
158
-
158
+
159
159
  try {
160
160
  // On Windows, check for zip.exe or 7z.exe
161
161
  if (isWindows) {
@@ -195,25 +195,36 @@ function setup() {
195
195
  console.log('\n╔══════════════════════════════════════════════════════════╗');
196
196
  console.log('║ Qwen API Proxy - Working Directory Setup ║');
197
197
  console.log('╚══════════════════════════════════════════════════════════╝\n');
198
-
198
+
199
199
  console.log(`📍 Working directory: ${EFFECTIVE_DIR}\n`);
200
-
200
+
201
201
  setupWorkingDirectory();
202
202
  console.log();
203
203
  setupEnvFile();
204
204
  console.log();
205
-
205
+
206
206
  const missingGitignoreDirs = setupGitignore();
207
207
  console.log();
208
-
208
+
209
209
  checkDependencies();
210
-
210
+
211
211
  console.log('\n✅ Working directory setup complete!\n');
212
-
212
+ console.log('📝 Next steps for first-time users:');
213
+ console.log(' 1. Add an account: qwen-api-proxy (or npx qwen-api-proxy)');
214
+ console.log(' - Select "1 - Add new account"');
215
+ console.log(' - Browser will open for authentication');
216
+ console.log(' - Login to Qwen and press ENTER in console');
217
+ console.log(' 2. Create archive: qwen-api-proxy archive');
218
+ console.log(' 3. Start server: qwen-api-proxy');
219
+ console.log('\n💡 Alternative: Use Telegram bot to upload session files');
220
+ console.log(' - Configure TELEGRAM_BOT_TOKEN in .env file');
221
+ console.log(' - Send session archive to the bot');
222
+ console.log('\n');
223
+
213
224
  // Show warnings for missing .gitignore entries
214
225
  if (missingGitignoreDirs.length > 0) {
215
226
  console.warn('⚠️ WARNING: The following entries are not in .gitignore:');
216
- missingGitignoreDirs.forEach(entry => {
227
+ missingGitignoreDirs.forEach((entry) => {
217
228
  console.warn(` - ${entry}`);
218
229
  });
219
230
  console.warn('\n Add them to .gitignore to prevent committing sensitive data!\n');
@@ -224,41 +235,41 @@ function setup() {
224
235
  const needsSetup = args.includes('--setup') || !fs.existsSync(path.join(EFFECTIVE_DIR, 'session'));
225
236
 
226
237
  // Parse command from arguments (already defined args above)
227
- const command = args.find(arg => !arg.startsWith('-'));
238
+ const command = args.find((arg) => !arg.startsWith('-'));
228
239
 
229
240
  // Handle 'init' command - manual setup only
230
241
  if (command === 'init') {
231
242
  console.log('\n╔══════════════════════════════════════════════════════════╗');
232
243
  console.log('║ Qwen API Proxy - Initialize Working Directory ║');
233
244
  console.log('╚══════════════════════════════════════════════════════════╝\n');
234
-
245
+
235
246
  console.log(`📍 Working directory: ${EFFECTIVE_DIR}\n`);
236
-
247
+
237
248
  setupWorkingDirectory(EFFECTIVE_DIR);
238
249
  console.log();
239
250
  setupEnvFile(EFFECTIVE_DIR);
240
251
  console.log();
241
-
252
+
242
253
  const missingGitignoreDirs = setupGitignore(EFFECTIVE_DIR);
243
254
  console.log();
244
-
255
+
245
256
  checkDependencies();
246
-
257
+
247
258
  console.log('\n✅ Working directory initialized successfully!\n');
248
259
  console.log('📝 Next steps:');
249
260
  console.log(' 1. Edit .env file with your configuration');
250
261
  console.log(' 2. Run: qwen-api-proxy');
251
262
  console.log('\n');
252
-
263
+
253
264
  // Show warnings for missing .gitignore entries
254
265
  if (missingGitignoreDirs.length > 0) {
255
266
  console.warn('⚠️ WARNING: The following entries are not in .gitignore:');
256
- missingGitignoreDirs.forEach(entry => {
267
+ missingGitignoreDirs.forEach((entry) => {
257
268
  console.warn(` - ${entry}`);
258
269
  });
259
270
  console.warn('\n Add them to .gitignore to prevent committing sensitive data!\n');
260
271
  }
261
-
272
+
262
273
  process.exit(0);
263
274
  }
264
275
 
@@ -267,11 +278,11 @@ if (command === 'doctor') {
267
278
  console.log('\n╔══════════════════════════════════════════════════════════╗');
268
279
  console.log('║ Qwen API Proxy - System Health Check ║');
269
280
  console.log('╚══════════════════════════════════════════════════════════╝\n');
270
-
281
+
271
282
  const issues = [];
272
283
  const warnings = [];
273
284
  const ok = [];
274
-
285
+
275
286
  // Check Node.js version
276
287
  const nodeVersion = process.version;
277
288
  const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
@@ -280,7 +291,7 @@ if (command === 'doctor') {
280
291
  } else {
281
292
  issues.push(`Node.js ${nodeVersion} (✗ requires >= 18)`);
282
293
  }
283
-
294
+
284
295
  // Check zip command (cross-platform)
285
296
  const isWindows = process.platform === 'win32';
286
297
  let zipAvailable = false;
@@ -304,16 +315,16 @@ if (command === 'doctor') {
304
315
  } catch (error) {
305
316
  // zip not available
306
317
  }
307
-
318
+
308
319
  if (zipAvailable) {
309
320
  ok.push('zip/7z command available');
310
321
  } else {
311
322
  warnings.push('zip/7z command not found (required for archive command)');
312
323
  }
313
-
324
+
314
325
  // Check working directory structure
315
326
  const requiredDirs = ['session', 'session/accounts', 'session/history', 'logs', 'uploads', 'temp'];
316
- requiredDirs.forEach(dir => {
327
+ requiredDirs.forEach((dir) => {
317
328
  const dirPath = path.join(EFFECTIVE_DIR, dir);
318
329
  if (fs.existsSync(dirPath)) {
319
330
  ok.push(`${dir}/ directory exists`);
@@ -321,12 +332,12 @@ if (command === 'doctor') {
321
332
  warnings.push(`${dir}/ directory missing`);
322
333
  }
323
334
  });
324
-
335
+
325
336
  // Check .env file
326
337
  const envPath = path.join(EFFECTIVE_DIR, '.env');
327
338
  if (fs.existsSync(envPath)) {
328
339
  ok.push('.env file exists');
329
-
340
+
330
341
  // Check for common configurations
331
342
  const envContent = fs.readFileSync(envPath, 'utf8');
332
343
  if (envContent.includes('TELEGRAM_BOT_TOKEN=') && !envContent.includes('TELEGRAM_BOT_TOKEN=your_bot_token_here')) {
@@ -337,7 +348,7 @@ if (command === 'doctor') {
337
348
  } else {
338
349
  warnings.push('.env file not found (run "qwen-api-proxy init" to create)');
339
350
  }
340
-
351
+
341
352
  // Check .gitignore file
342
353
  const gitignorePath = path.join(EFFECTIVE_DIR, '.gitignore');
343
354
  const requiredGitignoreEntries = [
@@ -349,16 +360,16 @@ if (command === 'doctor') {
349
360
  'session_backup_*'
350
361
  ];
351
362
  const missingGitignoreEntries = [];
352
-
363
+
353
364
  if (fs.existsSync(gitignorePath)) {
354
365
  const content = fs.readFileSync(gitignorePath, 'utf8');
355
- const lines = content.split('\n').map(line => line.trim());
356
- requiredGitignoreEntries.forEach(entry => {
366
+ const lines = content.split('\n').map((line) => line.trim());
367
+ requiredGitignoreEntries.forEach((entry) => {
357
368
  if (!lines.includes(entry)) {
358
369
  missingGitignoreEntries.push(entry);
359
370
  }
360
371
  });
361
-
372
+
362
373
  if (missingGitignoreEntries.length === 0) {
363
374
  ok.push('.gitignore properly configured');
364
375
  } else {
@@ -367,11 +378,11 @@ if (command === 'doctor') {
367
378
  } else {
368
379
  warnings.push('.gitignore not found (run "qwen-api-proxy init" to create)');
369
380
  }
370
-
381
+
371
382
  // Check permissions
372
383
  const testDirs = ['session', 'logs', 'uploads'];
373
384
  let permissionsOk = true;
374
- testDirs.forEach(dir => {
385
+ testDirs.forEach((dir) => {
375
386
  const dirPath = path.join(EFFECTIVE_DIR, dir);
376
387
  if (fs.existsSync(dirPath)) {
377
388
  try {
@@ -387,7 +398,7 @@ if (command === 'doctor') {
387
398
  if (permissionsOk) {
388
399
  ok.push('Directory permissions OK');
389
400
  }
390
-
401
+
391
402
  // Check session data
392
403
  const tokensPath = path.join(EFFECTIVE_DIR, 'session', 'tokens.json');
393
404
  if (fs.existsSync(tokensPath)) {
@@ -404,7 +415,7 @@ if (command === 'doctor') {
404
415
  } else {
405
416
  warnings.push('No accounts configured yet');
406
417
  }
407
-
418
+
408
419
  // Check disk space (cross-platform)
409
420
  try {
410
421
  if (isWindows) {
@@ -456,21 +467,21 @@ if (command === 'doctor') {
456
467
  } catch (error) {
457
468
  // df/wmic not available, skip
458
469
  }
459
-
470
+
460
471
  // Print results
461
472
  console.log('✅ OK:');
462
- ok.forEach(msg => console.log(` ✓ ${msg}`));
463
-
473
+ ok.forEach((msg) => console.log(` ✓ ${msg}`));
474
+
464
475
  if (warnings.length > 0) {
465
476
  console.log('\n⚠️ Warnings:');
466
- warnings.forEach(msg => console.log(` ⚠ ${msg}`));
477
+ warnings.forEach((msg) => console.log(` ⚠ ${msg}`));
467
478
  }
468
-
479
+
469
480
  if (issues.length > 0) {
470
481
  console.log('\n❌ Issues:');
471
- issues.forEach(msg => console.log(` ✗ ${msg}`));
482
+ issues.forEach((msg) => console.log(` ✗ ${msg}`));
472
483
  }
473
-
484
+
474
485
  console.log('\n' + '='.repeat(60));
475
486
  if (issues.length === 0 && warnings.length === 0) {
476
487
  console.log('🎉 All checks passed! System is healthy.');
@@ -480,7 +491,7 @@ if (command === 'doctor') {
480
491
  console.log(`✗ ${issues.length} issue(s) found - please fix before running`);
481
492
  }
482
493
  console.log('='.repeat(60) + '\n');
483
-
494
+
484
495
  process.exit(issues.length > 0 ? 1 : 0);
485
496
  }
486
497
 
package/index.js CHANGED
@@ -15,7 +15,7 @@ import { checkPermissions } from './src/utils/permissionChecker.js';
15
15
  import fs from 'fs';
16
16
  import path from 'path';
17
17
  import { execSync } from 'child_process';
18
- import { SESSION_DIR } from './src/config.js';
18
+ import { SESSION_DIR, ACCOUNTS_DIR } from './src/config.js';
19
19
 
20
20
  const app = express();
21
21
 
@@ -27,7 +27,7 @@ if (Number.isNaN(port) || port <= 0 || port > 65535) {
27
27
  }
28
28
 
29
29
  function toBoolean(value) {
30
- if (typeof value !== 'string') return false;
30
+ if (typeof value !== 'string') {return false;}
31
31
  return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase());
32
32
  }
33
33
 
@@ -42,7 +42,7 @@ function ensureNonInteractiveTokens() {
42
42
  return false;
43
43
  }
44
44
  const now = Date.now();
45
- const validTokens = tokens.filter(t => (!t.resetAt || new Date(t.resetAt).getTime() <= now) && !t.invalid);
45
+ const validTokens = tokens.filter((t) => (!t.resetAt || new Date(t.resetAt).getTime() <= now) && !t.invalid);
46
46
  if (!validTokens.length) {
47
47
  logWarn('⚠️ Все аккаунты недоступны. Сервер работает в режиме Telegram бота.');
48
48
  logWarn('📦 Отправьте архив с сессиями через Telegram бот для обновления аккаунтов.');
@@ -75,7 +75,7 @@ app.use((req, res, next) => {
75
75
  res.header('Access-Control-Allow-Origin', '*');
76
76
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
77
77
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
78
- if (req.method === 'OPTIONS') return res.sendStatus(200);
78
+ if (req.method === 'OPTIONS') {return res.sendStatus(200);}
79
79
  next();
80
80
  });
81
81
 
@@ -133,6 +133,30 @@ function createSessionArchive() {
133
133
  throw new Error('Папка сессии пуста. Сначала выполните авторизацию.');
134
134
  }
135
135
 
136
+ // Проверяем, есть ли реальные данные (accounts, tokens.json, и т.д.)
137
+ const hasAccounts = fs.existsSync(path.join(sessionPath, 'accounts')) &&
138
+ fs.readdirSync(path.join(sessionPath, 'accounts')).length > 0;
139
+ const hasTokens = fs.existsSync(path.join(sessionPath, 'tokens.json'));
140
+
141
+ if (!hasAccounts && !hasTokens) {
142
+ throw new Error('Папка сессии не содержит данных аккаунтов.');
143
+ }
144
+
145
+ // Показываем статистику
146
+ console.log('\n📊 Найденные данные:');
147
+ if (hasAccounts) {
148
+ const accounts = fs.readdirSync(path.join(sessionPath, 'accounts'));
149
+ console.log(` ✓ Аккаунты: ${accounts.length} (${accounts.join(', ')})`);
150
+ }
151
+ if (hasTokens) {
152
+ try {
153
+ const tokens = JSON.parse(fs.readFileSync(path.join(sessionPath, 'tokens.json'), 'utf8'));
154
+ console.log(` ✓ Токены: ${Array.isArray(tokens) ? tokens.length : 0} записей`);
155
+ } catch (e) {
156
+ console.log(' ⚠ tokens.json не удалось прочитать');
157
+ }
158
+ }
159
+
136
160
  // Создаем ZIP архив (cross-platform)
137
161
  let command;
138
162
  if (isWindows) {
@@ -188,29 +212,29 @@ function validateGitignore() {
188
212
  'session_backup',
189
213
  'session_backup_*'
190
214
  ];
191
-
215
+
192
216
  if (!fs.existsSync(gitignorePath)) {
193
217
  logWarn('⚠️ Файл .gitignore не найден в корневой директории');
194
218
  logWarn(' Рекомендуется создать .gitignore для защиты чувствительных данных');
195
219
  return false;
196
220
  }
197
-
221
+
198
222
  const content = fs.readFileSync(gitignorePath, 'utf8');
199
- const lines = content.split('\n').map(line => line.trim());
223
+ const lines = content.split('\n').map((line) => line.trim());
200
224
  const missingEntries = [];
201
-
202
- requiredEntries.forEach(entry => {
225
+
226
+ requiredEntries.forEach((entry) => {
203
227
  if (!lines.includes(entry)) {
204
228
  missingEntries.push(entry);
205
229
  }
206
230
  });
207
-
231
+
208
232
  if (missingEntries.length > 0) {
209
233
  logWarn(`⚠️ .gitignore отсутствует: ${missingEntries.join(', ')}`);
210
234
  logWarn(' Добавьте эти записи в .gitignore для защиты данных');
211
235
  return false;
212
236
  }
213
-
237
+
214
238
  logInfo('✅ .gitignore проверен - все записи на месте');
215
239
  return true;
216
240
  }
@@ -234,6 +258,68 @@ async function handleCLICommand() {
234
258
  console.log('╚══════════════════════════════════════════════════════════╝\n');
235
259
 
236
260
  try {
261
+ // Проверяем, есть ли уже аккаунты
262
+ const tokensPath = path.join(process.cwd(), SESSION_DIR, 'tokens.json');
263
+ const accountsPath = path.join(process.cwd(), SESSION_DIR, ACCOUNTS_DIR);
264
+
265
+ let hasAccounts = false;
266
+
267
+ if (fs.existsSync(tokensPath)) {
268
+ try {
269
+ const tokens = JSON.parse(fs.readFileSync(tokensPath, 'utf8'));
270
+ if (Array.isArray(tokens) && tokens.length > 0) {
271
+ hasAccounts = true;
272
+ }
273
+ } catch (e) {
274
+ // tokens.json corrupted
275
+ }
276
+ }
277
+
278
+ if (!hasAccounts && fs.existsSync(accountsPath)) {
279
+ const accounts = fs.readdirSync(accountsPath);
280
+ if (accounts.length > 0) {
281
+ hasAccounts = true;
282
+ }
283
+ }
284
+
285
+ // Если аккаунтов нет, предлагаем добавить
286
+ if (!hasAccounts) {
287
+ console.log('📝 Аккаунты не найдены. Необходимо добавить аккаунт перед созданием архива.\n');
288
+ console.log('🔹 Вариант 1: Добавить аккаунт сейчас (откроется браузер)');
289
+ console.log('🔹 Вариант 2: Отправить файл сессии через Telegram бота');
290
+ console.log('🔹 Вариант 3: Выйти и запустить вручную: npx qwen-api-proxy\n');
291
+
292
+ const { prompt } = await import('./src/utils/prompt.js');
293
+ const choice = await prompt('Ваш выбор (1/2/3, Enter = 1): ');
294
+
295
+ if (choice === '2') {
296
+ console.log('\n💡 Для использования Telegram бота:');
297
+ console.log(' 1. Добавьте TELEGRAM_BOT_TOKEN в .env файл');
298
+ console.log(' 2. Запустите: npx qwen-api-proxy');
299
+ console.log(' 3. Отправьте файл сессии боту\n');
300
+ process.exit(0);
301
+ } else if (choice === '3') {
302
+ console.log('\n👋 Выход. Запустите "npx qwen-api-proxy" для добавления аккаунта.\n');
303
+ process.exit(0);
304
+ }
305
+
306
+ // choice === '1' или Enter - добавляем аккаунт
307
+ console.log('\n🔐 Запуск браузера для добавления аккаунта...\n');
308
+
309
+ const { addAccountInteractive } = await import('./src/utils/accountSetup.js');
310
+ const accountId = await addAccountInteractive();
311
+
312
+ if (!accountId) {
313
+ console.log('\n❌ Аккаунт не был добавлен. Архив не создан.\n');
314
+ process.exit(1);
315
+ }
316
+
317
+ console.log(`\n✅ Аккаунт ${accountId} успешно добавлен!\n`);
318
+ } else {
319
+ console.log('✅ Найден существующий аккаунт\n');
320
+ }
321
+
322
+ // Теперь создаем архив
237
323
  const archivePath = createSessionArchive();
238
324
  console.log('\n🎉 ГОТОВО!');
239
325
  console.log(`📄 Архив: ${archivePath}`);
@@ -320,7 +406,7 @@ async function startServer() {
320
406
  console.log('4 - Удалить аккаунт');
321
407
 
322
408
  let choice = await prompt('Ваш выбор (Enter = 3): ');
323
- if (!choice) choice = '3';
409
+ if (!choice) {choice = '3';}
324
410
 
325
411
  if (choice === '1') {
326
412
  await addAccountInteractive();
@@ -328,9 +414,9 @@ async function startServer() {
328
414
  const { reloginAccountInteractive } = await import('./src/utils/accountSetup.js');
329
415
  await reloginAccountInteractive();
330
416
  } else if (choice === '3') {
331
- const hasValidToken = tokens.some(t => {
332
- if (t.invalid) return false;
333
- if (!t.resetAt) return true;
417
+ const hasValidToken = tokens.some((t) => {
418
+ if (t.invalid) {return false;}
419
+ if (!t.resetAt) {return true;}
334
420
  return new Date(t.resetAt).getTime() <= Date.now();
335
421
  });
336
422
  if (!tokens.length || !hasValidToken) {
@@ -422,7 +508,7 @@ async function startServer() {
422
508
  logInfo('🔍 Начинаем загрузку списка моделей...');
423
509
  const apiModels = await fetchModelsFromAPI();
424
510
  logDebug(`fetchModelsFromAPI вернул: ${apiModels ? apiModels.length + ' моделей' : 'null'}`);
425
-
511
+
426
512
  if (apiModels && apiModels.length > 0) {
427
513
  logInfo(`✅ Загружено ${apiModels.length} моделей с Qwen API`);
428
514
  logDebug(`Первые 5 моделей: ${apiModels.slice(0, 5).join(', ')}`);
@@ -433,11 +519,11 @@ async function startServer() {
433
519
  const fileModels = getAvailableModelsFromFile();
434
520
  logDebug(`getAvailableModelsFromFile вернул: ${fileModels ? fileModels.length + ' моделей' : 'null'}`);
435
521
  }
436
-
522
+
437
523
  const defaultModel = getDefaultModel();
438
524
  logInfo(`🎯 Модель по умолчанию: ${defaultModel}`);
439
525
  logDebug(`getDefaultModel() вернул: ${defaultModel}`);
440
-
526
+
441
527
  getApiKeys();
442
528
  });
443
529
  } catch (err) {
@@ -451,10 +537,10 @@ async function startServer() {
451
537
  }
452
538
 
453
539
  // Проверяем CLI команды перед запуском сервера
454
- handleCLICommand().then(hasCommand => {
540
+ handleCLICommand().then((hasCommand) => {
455
541
  if (!hasCommand) {
456
542
  // Нет команды CLI, запускаем сервер как обычно
457
- startServer().catch(async error => {
543
+ startServer().catch(async (error) => {
458
544
  logError('Ошибка при запуске сервера', error);
459
545
  await shutdownBrowser();
460
546
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwen-api-proxy",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Proxy server for accessing Qwen API through browser emulation with OpenAI-compatible API and Telegram bot",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -44,6 +44,8 @@
44
44
  "scripts": {
45
45
  "start": "node index.js",
46
46
  "archive": "node index.js archive",
47
+ "lint": "eslint .",
48
+ "lint:fix": "eslint . --fix",
47
49
  "test": "echo \"Error: no test specified\" && exit 1",
48
50
  "test:cross-platform": "node test-cross-platform.js",
49
51
  "check-permissions": "node scripts/checkPermissions.js",
@@ -82,5 +84,9 @@
82
84
  "puppeteer-extra-plugin-stealth": "^2.11.2",
83
85
  "undici": "^6.21.1",
84
86
  "winston": "^3.17.0"
87
+ },
88
+ "devDependencies": {
89
+ "eslint": "^9.39.4",
90
+ "eslint-plugin-import": "^2.32.0"
85
91
  }
86
- }
92
+ }