qwen-api-proxy 1.0.12 → 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.
@@ -22,10 +22,10 @@ function hasFileChanged() {
22
22
  if (!fs.existsSync(SETTINGS_FILE)) {
23
23
  return true; // Файл не существует, нужно перечитать
24
24
  }
25
-
25
+
26
26
  const stats = fs.statSync(SETTINGS_FILE);
27
27
  const currentMTime = stats.mtimeMs;
28
-
28
+
29
29
  // Если кэш пуст или время изменения отличается - файл изменился
30
30
  return !settingsCacheMTime || currentMTime !== settingsCacheMTime;
31
31
  } catch (error) {
@@ -52,20 +52,20 @@ export function loadBotSettings() {
52
52
  settingsCacheMTime = null;
53
53
  return defaultSettings;
54
54
  }
55
-
55
+
56
56
  // Проверяем изменился ли файл
57
57
  if (!hasFileChanged() && settingsCache) {
58
58
  // Файл не изменился, возвращаем кэш
59
59
  return settingsCache;
60
60
  }
61
-
61
+
62
62
  // Файл изменился или кэш пуст - читаем файл
63
63
  const stats = fs.statSync(SETTINGS_FILE);
64
64
  settingsCacheMTime = stats.mtimeMs;
65
-
65
+
66
66
  const settings = JSON.parse(fs.readFileSync(SETTINGS_FILE, 'utf8'));
67
67
  settingsCache = settings;
68
-
68
+
69
69
  logInfo(`✅ Настройки бота загружены из файла: модель=${settings.activeModel || 'default'}, LLM=${settings.llmChatEnabled}`);
70
70
  return settings;
71
71
  } catch (error) {
@@ -95,15 +95,15 @@ export function saveBotSettings(settings) {
95
95
  }
96
96
 
97
97
  settings.lastUpdated = new Date().toISOString();
98
-
98
+
99
99
  fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2), 'utf8');
100
-
100
+
101
101
  // Обновляем кэш
102
102
  settingsCache = settings;
103
103
  // Обновляем время модификации
104
104
  const stats = fs.statSync(SETTINGS_FILE);
105
105
  settingsCacheMTime = stats.mtimeMs;
106
-
106
+
107
107
  logInfo(`💾 Настройки бота сохранены: модель=${settings.activeModel || 'default'}, LLM=${settings.llmChatEnabled}`);
108
108
  return true;
109
109
  } catch (error) {
@@ -144,23 +144,23 @@ export function clearSettingsCache() {
144
144
  export function getActiveModel() {
145
145
  try {
146
146
  const settings = loadBotSettings();
147
-
147
+
148
148
  // Если есть activeModel в настройках бота - используем его
149
149
  if (settings && settings.activeModel) {
150
150
  return settings.activeModel;
151
151
  }
152
-
152
+
153
153
  // Иначе используем DEFAULT_MODEL из .env
154
154
  if (DEFAULT_MODEL) {
155
155
  return DEFAULT_MODEL;
156
156
  }
157
-
157
+
158
158
  // Fallback: первая модель из списка доступных
159
159
  try {
160
160
  const modelsFile = path.join(process.cwd(), 'src', 'AvailableModels.txt');
161
161
  if (fs.existsSync(modelsFile)) {
162
162
  const modelsContent = fs.readFileSync(modelsFile, 'utf8');
163
- const models = modelsContent.split('\n').map(m => m.trim()).filter(m => m && !m.startsWith('#'));
163
+ const models = modelsContent.split('\n').map((m) => m.trim()).filter((m) => m && !m.startsWith('#'));
164
164
  if (models.length > 0) {
165
165
  return models[0];
166
166
  }
@@ -168,7 +168,7 @@ export function getActiveModel() {
168
168
  } catch (e) {
169
169
  // Если не удалось загрузить список моделей
170
170
  }
171
-
171
+
172
172
  // Последний fallback
173
173
  return 'qwen3.5-plus';
174
174
  } catch (error) {
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * Permission Checker
5
- *
5
+ *
6
6
  * Checks write permissions for all project directories and files at startup.
7
7
  * Provides helpful commands to fix any permission issues.
8
8
  */
@@ -20,186 +20,186 @@ const ROOT_DIR = path.resolve(__dirname, '../..');
20
20
  * Define all directories and files that need write access
21
21
  */
22
22
  const PATHS_TO_CHECK = [
23
- // Main directories
24
- { path: SESSION_DIR, type: 'directory', recursive: true },
25
- { path: path.join(SESSION_DIR, 'accounts'), type: 'directory', recursive: true },
26
- { path: path.join(SESSION_DIR, 'history'), type: 'directory', recursive: true },
27
- { path: UPLOADS_DIR, type: 'directory', recursive: false },
28
- { path: LOGS_DIR, type: 'directory', recursive: false },
29
- { path: 'temp', type: 'directory', recursive: false },
30
- { path: 'session_backup', type: 'directory', recursive: false },
31
-
32
- // Important files
33
- { path: path.join(SESSION_DIR, 'tokens.json'), type: 'file', optional: true },
34
- { path: path.join(SESSION_DIR, 'auth_token.txt'), type: 'file', optional: true },
35
- { path: path.join(SESSION_DIR, 'bot_settings.json'), type: 'file', optional: true },
36
- { path: '.env', type: 'file', optional: true },
23
+ // Main directories
24
+ { path: SESSION_DIR, type: 'directory', recursive: true },
25
+ { path: path.join(SESSION_DIR, 'accounts'), type: 'directory', recursive: true },
26
+ { path: path.join(SESSION_DIR, 'history'), type: 'directory', recursive: true },
27
+ { path: UPLOADS_DIR, type: 'directory', recursive: false },
28
+ { path: LOGS_DIR, type: 'directory', recursive: false },
29
+ { path: 'temp', type: 'directory', recursive: false },
30
+ { path: 'session_backup', type: 'directory', recursive: false },
31
+
32
+ // Important files
33
+ { path: path.join(SESSION_DIR, 'tokens.json'), type: 'file', optional: true },
34
+ { path: path.join(SESSION_DIR, 'auth_token.txt'), type: 'file', optional: true },
35
+ { path: path.join(SESSION_DIR, 'bot_settings.json'), type: 'file', optional: true },
36
+ { path: '.env', type: 'file', optional: true }
37
37
  ];
38
38
 
39
39
  /**
40
40
  * Test if a path is writable
41
41
  */
42
42
  function testWritePermission(testPath, type) {
43
- try {
44
- if (type === 'directory') {
45
- // Test directory writability by checking if we can create/delete a temp file
46
- const tempFile = path.join(testPath, '.write_test_' + Date.now());
47
- fs.writeFileSync(tempFile, 'test');
48
- fs.unlinkSync(tempFile);
49
- return { writable: true, error: null };
50
- } else if (type === 'file') {
51
- // For files, test if parent directory is writable
52
- const parentDir = path.dirname(testPath);
53
- if (!fs.existsSync(parentDir)) {
54
- return { writable: false, error: `Parent directory does not exist: ${parentDir}` };
55
- }
56
- // Try to read if file exists
57
- if (fs.existsSync(testPath)) {
58
- fs.accessSync(testPath, fs.constants.R_OK | fs.constants.W_OK);
59
- }
60
- return { writable: true, error: null };
43
+ try {
44
+ if (type === 'directory') {
45
+ // Test directory writability by checking if we can create/delete a temp file
46
+ const tempFile = path.join(testPath, '.write_test_' + Date.now());
47
+ fs.writeFileSync(tempFile, 'test');
48
+ fs.unlinkSync(tempFile);
49
+ return { writable: true, error: null };
50
+ } else if (type === 'file') {
51
+ // For files, test if parent directory is writable
52
+ const parentDir = path.dirname(testPath);
53
+ if (!fs.existsSync(parentDir)) {
54
+ return { writable: false, error: `Parent directory does not exist: ${parentDir}` };
55
+ }
56
+ // Try to read if file exists
57
+ if (fs.existsSync(testPath)) {
58
+ fs.accessSync(testPath, fs.constants.R_OK | fs.constants.W_OK);
59
+ }
60
+ return { writable: true, error: null };
61
+ }
62
+ } catch (error) {
63
+ return { writable: false, error: error.message };
61
64
  }
62
- } catch (error) {
63
- return { writable: false, error: error.message };
64
- }
65
65
  }
66
66
 
67
67
  /**
68
68
  * Generate fix commands for a path
69
69
  */
70
70
  function generateFixCommands(testPath, type) {
71
- const absolutePath = path.isAbsolute(testPath) ? testPath : path.join(ROOT_DIR, testPath);
72
- const commands = [];
73
-
74
- if (type === 'directory' || (type === 'file' && fs.existsSync(testPath))) {
71
+ const absolutePath = path.isAbsolute(testPath) ? testPath : path.join(ROOT_DIR, testPath);
72
+ const commands = [];
73
+
74
+ if (type === 'directory' || (type === 'file' && fs.existsSync(testPath))) {
75
75
  // Fix ownership
76
- commands.push(`sudo chown -R $USER:$USER "${absolutePath}"`);
77
- // Fix permissions
78
- if (type === 'directory') {
79
- commands.push(`sudo chmod -R 755 "${absolutePath}"`);
80
- } else {
81
- commands.push(`sudo chmod 644 "${absolutePath}"`);
82
- }
83
- } else if (type === 'file' && !fs.existsSync(testPath)) {
76
+ commands.push(`sudo chown -R $USER:$USER "${absolutePath}"`);
77
+ // Fix permissions
78
+ if (type === 'directory') {
79
+ commands.push(`sudo chmod -R 755 "${absolutePath}"`);
80
+ } else {
81
+ commands.push(`sudo chmod 644 "${absolutePath}"`);
82
+ }
83
+ } else if (type === 'file' && !fs.existsSync(testPath)) {
84
84
  // File doesn't exist, fix parent directory
85
- const parentDir = path.dirname(absolutePath);
86
- commands.push(`sudo chown -R $USER:$USER "${parentDir}"`);
87
- commands.push(`sudo chmod -R 755 "${parentDir}"`);
88
- }
89
-
90
- return commands;
85
+ const parentDir = path.dirname(absolutePath);
86
+ commands.push(`sudo chown -R $USER:$USER "${parentDir}"`);
87
+ commands.push(`sudo chmod -R 755 "${parentDir}"`);
88
+ }
89
+
90
+ return commands;
91
91
  }
92
92
 
93
93
  /**
94
94
  * Check all paths and report issues
95
95
  */
96
96
  export async function checkPermissions() {
97
- logInfo('🔍 Проверка прав доступа к директориям и файлам...');
98
-
99
- const issues = [];
100
- const allCommands = new Set();
101
-
102
- for (const { path: relativePath, type, optional, recursive } of PATHS_TO_CHECK) {
103
- const absolutePath = path.isAbsolute(relativePath) ? relativePath : path.join(ROOT_DIR, relativePath);
104
-
105
- // Skip optional paths that don't exist
106
- if (optional && !fs.existsSync(absolutePath)) {
107
- continue;
108
- }
109
-
110
- // For directories, check if they exist
111
- if (type === 'directory' && !fs.existsSync(absolutePath)) {
112
- // Try to create it
113
- try {
114
- fs.mkdirSync(absolutePath, { recursive: true });
115
- logInfo(` ✅ Создана директория: ${relativePath}`);
116
- } catch (error) {
117
- issues.push({
118
- path: relativePath,
119
- absolutePath,
120
- type,
121
- error: `Cannot create directory: ${error.message}`,
122
- commands: generateFixCommands(path.dirname(absolutePath), 'directory')
123
- });
124
- }
125
- continue;
126
- }
127
-
128
- // Test write permission
129
- const result = testWritePermission(absolutePath, type);
130
-
131
- if (!result.writable) {
132
- issues.push({
133
- path: relativePath,
134
- absolutePath,
135
- type,
136
- error: result.error,
137
- commands: generateFixCommands(absolutePath, type)
138
- });
97
+ logInfo('🔍 Проверка прав доступа к директориям и файлам...');
98
+
99
+ const issues = [];
100
+ const allCommands = new Set();
101
+
102
+ for (const { path: relativePath, type, optional, recursive } of PATHS_TO_CHECK) {
103
+ const absolutePath = path.isAbsolute(relativePath) ? relativePath : path.join(ROOT_DIR, relativePath);
104
+
105
+ // Skip optional paths that don't exist
106
+ if (optional && !fs.existsSync(absolutePath)) {
107
+ continue;
108
+ }
109
+
110
+ // For directories, check if they exist
111
+ if (type === 'directory' && !fs.existsSync(absolutePath)) {
112
+ // Try to create it
113
+ try {
114
+ fs.mkdirSync(absolutePath, { recursive: true });
115
+ logInfo(` ✅ Создана директория: ${relativePath}`);
116
+ } catch (error) {
117
+ issues.push({
118
+ path: relativePath,
119
+ absolutePath,
120
+ type,
121
+ error: `Cannot create directory: ${error.message}`,
122
+ commands: generateFixCommands(path.dirname(absolutePath), 'directory')
123
+ });
124
+ }
125
+ continue;
126
+ }
127
+
128
+ // Test write permission
129
+ const result = testWritePermission(absolutePath, type);
130
+
131
+ if (!result.writable) {
132
+ issues.push({
133
+ path: relativePath,
134
+ absolutePath,
135
+ type,
136
+ error: result.error,
137
+ commands: generateFixCommands(absolutePath, type)
138
+ });
139
+ }
139
140
  }
140
- }
141
-
142
- // Report results
143
- if (issues.length === 0) {
144
- logInfo('✅ Все директории и файлы доступны для записи');
145
- return true;
146
- }
147
-
148
- // Report issues
149
- logError(`❌ Обнаружены проблемы с правами доступа (${issues.length}):`);
150
- console.error('');
151
-
152
- for (const issue of issues) {
153
- logError(` 📁 ${issue.path} (${issue.type})`);
154
- logError(` Ошибка: ${issue.error}`);
155
- logError(` Решение:`);
156
- for (const cmd of issue.commands) {
157
- console.error(` ${cmd}`);
158
- allCommands.add(cmd);
141
+
142
+ // Report results
143
+ if (issues.length === 0) {
144
+ logInfo('✅ Все директории и файлы доступны для записи');
145
+ return true;
159
146
  }
147
+
148
+ // Report issues
149
+ logError(`❌ Обнаружены проблемы с правами доступа (${issues.length}):`);
160
150
  console.error('');
161
- }
162
-
163
- // Show combined fix command
164
- if (allCommands.size > 0) {
165
- console.error('═'.repeat(70));
166
- console.error('🔧 Быстрое решение (скопируйте и выполните в терминале):');
167
- console.error('═'.repeat(70));
168
- console.error('');
169
- console.error(' ⚡ ОДНОЙ СТРОКОЙ (рекомендуется):');
170
- console.error(' ' + '─'.repeat(68));
171
-
172
- // Group by parent directory for cleaner output
173
- const dirsToFix = new Set();
151
+
174
152
  for (const issue of issues) {
175
- if (issue.type === 'directory') {
176
- dirsToFix.add(issue.absolutePath);
177
- } else {
178
- dirsToFix.add(path.dirname(issue.absolutePath));
179
- }
153
+ logError(` 📁 ${issue.path} (${issue.type})`);
154
+ logError(` Ошибка: ${issue.error}`);
155
+ logError(' Решение:');
156
+ for (const cmd of issue.commands) {
157
+ console.error(` ${cmd}`);
158
+ allCommands.add(cmd);
159
+ }
160
+ console.error('');
180
161
  }
181
-
182
- const allPaths = Array.from(dirsToFix).join(' ');
183
- console.error('');
184
- console.error(` sudo chown -R $USER:$USER ${allPaths}`);
185
- console.error(` sudo chmod -R 755 ${allPaths}`);
186
- console.error('');
187
-
188
- console.error(' 📦 ИЛИ исправить все основные директории проекта:');
189
- console.error(' ' + '─'.repeat(68));
190
- const mainDirs = [
191
- path.join(ROOT_DIR, SESSION_DIR),
192
- path.join(ROOT_DIR, UPLOADS_DIR),
193
- path.join(ROOT_DIR, LOGS_DIR),
194
- path.join(ROOT_DIR, 'temp'),
195
- path.join(ROOT_DIR, 'session_backup')
196
- ].join(' ');
197
- console.error(` sudo chown -R $USER:$USER ${mainDirs}`);
198
- console.error(` sudo chmod -R 755 ${mainDirs}`);
199
- console.error('');
200
- console.error('═'.repeat(70));
201
- console.error('');
202
- }
203
-
204
- return false;
162
+
163
+ // Show combined fix command
164
+ if (allCommands.size > 0) {
165
+ console.error('═'.repeat(70));
166
+ console.error('🔧 Быстрое решение (скопируйте и выполните в терминале):');
167
+ console.error(''.repeat(70));
168
+ console.error('');
169
+ console.error(' ОДНОЙ СТРОКОЙ (рекомендуется):');
170
+ console.error(' ' + '─'.repeat(68));
171
+
172
+ // Group by parent directory for cleaner output
173
+ const dirsToFix = new Set();
174
+ for (const issue of issues) {
175
+ if (issue.type === 'directory') {
176
+ dirsToFix.add(issue.absolutePath);
177
+ } else {
178
+ dirsToFix.add(path.dirname(issue.absolutePath));
179
+ }
180
+ }
181
+
182
+ const allPaths = Array.from(dirsToFix).join(' ');
183
+ console.error('');
184
+ console.error(` sudo chown -R $USER:$USER ${allPaths}`);
185
+ console.error(` sudo chmod -R 755 ${allPaths}`);
186
+ console.error('');
187
+
188
+ console.error(' 📦 ИЛИ исправить все основные директории проекта:');
189
+ console.error(' ' + '─'.repeat(68));
190
+ const mainDirs = [
191
+ path.join(ROOT_DIR, SESSION_DIR),
192
+ path.join(ROOT_DIR, UPLOADS_DIR),
193
+ path.join(ROOT_DIR, LOGS_DIR),
194
+ path.join(ROOT_DIR, 'temp'),
195
+ path.join(ROOT_DIR, 'session_backup')
196
+ ].join(' ');
197
+ console.error(` sudo chown -R $USER:$USER ${mainDirs}`);
198
+ console.error(` sudo chmod -R 755 ${mainDirs}`);
199
+ console.error('');
200
+ console.error('═'.repeat(70));
201
+ console.error('');
202
+ }
203
+
204
+ return false;
205
205
  }
@@ -7,5 +7,5 @@ import readline from 'readline';
7
7
  */
8
8
  export function prompt(question) {
9
9
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
10
- return new Promise(resolve => rl.question(question, ans => { rl.close(); resolve(ans.trim()); }));
10
+ return new Promise((resolve) => rl.question(question, (ans) => { rl.close(); resolve(ans.trim()); }));
11
11
  }
@@ -1,6 +1,6 @@
1
1
  import { ProxyAgent } from 'proxy-agent';
2
2
  import { TELEGRAM_PROXY, QWEN_PROXY, FILE_DOWNLOAD_PROXY } from '../config.js';
3
- import { logInfo, logWarn, logDebug } from '../logger/index.js';
3
+ import { logInfo, logWarn, logDebug, logError } from '../logger/index.js';
4
4
 
5
5
  // Кэш прокси агентов (создаются один раз)
6
6
  let telegramProxyAgent = null;
@@ -95,7 +95,7 @@ export function getFileDownloadProxyAgent() {
95
95
  logInfo('✅ Прокси для скачивания файлов успешно инициализирован');
96
96
  return fileDownloadProxyAgent;
97
97
  } catch (error) {
98
- logError(`❌ Ошибка инициализации прокси для скачивания файлов`, error);
98
+ logError('❌ Ошибка инициализации прокси для скачивания файлов', error);
99
99
  fileDownloadProxyInitialized = true;
100
100
  fileDownloadProxyAgent = null;
101
101
  return null;
@@ -108,7 +108,7 @@ export function getFileDownloadProxyAgent() {
108
108
  * @returns {string} - Замаскированный URL
109
109
  */
110
110
  function maskProxyUrl(url) {
111
- if (!url) return 'none';
111
+ if (!url) {return 'none';}
112
112
  try {
113
113
  const parsed = new URL(url);
114
114
  if (parsed.username || parsed.password) {
@@ -128,7 +128,7 @@ function maskProxyUrl(url) {
128
128
  */
129
129
  export async function fetchWithTelegramProxy(url, options = {}) {
130
130
  const proxyAgent = getTelegramProxyAgent();
131
-
131
+
132
132
  // Если прокси не настроен, используем обычный fetch
133
133
  if (!proxyAgent) {
134
134
  return fetch(url, options);
@@ -136,9 +136,9 @@ export async function fetchWithTelegramProxy(url, options = {}) {
136
136
 
137
137
  // Используем node-fetch с agent опцией
138
138
  const { default: nodeFetch } = await import('node-fetch');
139
-
139
+
140
140
  logDebug(`📱 Запрос к Telegram через прокси: ${url}`);
141
-
141
+
142
142
  return nodeFetch(url, {
143
143
  ...options,
144
144
  agent: proxyAgent
@@ -153,7 +153,7 @@ export async function fetchWithTelegramProxy(url, options = {}) {
153
153
  */
154
154
  export async function fetchWithQwenProxy(url, options = {}) {
155
155
  const proxyAgent = getQwenProxyAgent();
156
-
156
+
157
157
  // Если прокси не настроен, используем обычный fetch
158
158
  if (!proxyAgent) {
159
159
  return fetch(url, options);
@@ -161,9 +161,9 @@ export async function fetchWithQwenProxy(url, options = {}) {
161
161
 
162
162
  // Используем node-fetch с agent опцией
163
163
  const { default: nodeFetch } = await import('node-fetch');
164
-
164
+
165
165
  logDebug(`🧠 Запрос к Qwen LLM через прокси: ${url}`);
166
-
166
+
167
167
  return nodeFetch(url, {
168
168
  ...options,
169
169
  agent: proxyAgent
@@ -186,7 +186,7 @@ export async function checkTelegramProxyAvailability() {
186
186
  }
187
187
 
188
188
  const { default: nodeFetch } = await import('node-fetch');
189
-
189
+
190
190
  // Тестовый запрос к Telegram API
191
191
  const response = await nodeFetch('https://api.telegram.org/bot', {
192
192
  agent: proxyAgent,
@@ -216,7 +216,7 @@ export async function checkQwenProxyAvailability() {
216
216
  }
217
217
 
218
218
  const { default: nodeFetch } = await import('node-fetch');
219
-
219
+
220
220
  // Тестовый запрос к Qwen API
221
221
  const response = await nodeFetch('https://chat.qwen.ai', {
222
222
  agent: proxyAgent,