qwen-api-proxy 1.0.12 → 1.0.14
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 +5 -5
- package/bin/qwen-api-proxy.js +53 -53
- package/index.js +33 -33
- package/package.json +8 -2
- package/src/api/chat.js +71 -71
- package/src/api/chatHistory.js +19 -19
- package/src/api/fileUpload.js +23 -23
- package/src/api/imageGeneration.js +23 -23
- package/src/api/modelMapping.js +145 -153
- package/src/api/routes.js +148 -148
- package/src/api/tokenManager.js +93 -93
- package/src/browser/auth.js +13 -13
- package/src/browser/browser.js +9 -9
- package/src/browser/session.js +3 -3
- package/src/config.js +4 -4
- package/src/utils/accountSetup.js +14 -14
- package/src/utils/botSettings.js +14 -14
- package/src/utils/permissionChecker.js +157 -157
- package/src/utils/prompt.js +1 -1
- package/src/utils/proxy.js +11 -11
- package/src/utils/telegramBot.js +692 -664
- package/src/utils/telegramNotifier.js +7 -7
package/src/utils/botSettings.js
CHANGED
|
@@ -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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
}
|
package/src/utils/prompt.js
CHANGED
|
@@ -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
|
}
|
package/src/utils/proxy.js
CHANGED
|
@@ -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(
|
|
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,
|