clash-linux commited on
Commit
a37af4b
·
verified ·
1 Parent(s): 79f9c01

Upload 16 files

Browse files
Files changed (2) hide show
  1. src/ProxyServer.js +168 -168
  2. src/lightweight-client.js +37 -19
src/ProxyServer.js CHANGED
@@ -1,169 +1,169 @@
1
- import { spawn } from 'child_process';
2
- import { fileURLToPath } from 'url';
3
- import { dirname, join } from 'path';
4
- import fs from 'fs';
5
- import os from 'os';
6
- import dotenv from 'dotenv';
7
- import chalk from 'chalk';
8
-
9
- // 获取当前文件的目录路径
10
- const __filename = fileURLToPath(import.meta.url);
11
- const __dirname = dirname(__filename);
12
-
13
- // 加载环境变量
14
- dotenv.config({ path: join(dirname(__dirname), '.env') });
15
-
16
- // 日志配置
17
- const logger = {
18
- info: (message) => console.log(chalk.blue(`[ProxyServer] ${message}`)),
19
- error: (message) => console.error(chalk.red(`[ProxyServer] ${message}`)),
20
- warning: (message) => console.warn(chalk.yellow(`[ProxyServer] ${message}`)),
21
- success: (message) => console.log(chalk.green(`[ProxyServer] ${message}`)),
22
- };
23
-
24
- class ProxyServer {
25
- constructor() {
26
- this.proxyProcess = null;
27
- this.platform = process.env.PROXY_SERVER_PLATFORM || 'auto';
28
- this.port = process.env.PROXY_SERVER_PORT || 10655;
29
- this.enabled = process.env.ENABLE_PROXY_SERVER === 'true';
30
- this.proxyAuthToken = process.env.PROXY_AUTH_TOKEN || 'default_token';
31
- }
32
-
33
- // 获取当前系统平台
34
- detectPlatform() {
35
- if (this.platform !== 'auto') {
36
- return this.platform;
37
- }
38
-
39
- const platform = os.platform();
40
- const arch = os.arch();
41
-
42
- if (platform === 'win32') {
43
- return 'windows';
44
- } else if (platform === 'linux') {
45
- if (arch === 'arm64') {
46
- return 'android';
47
- } else {
48
- return 'linux';
49
- }
50
- } else if (platform === 'android') {
51
- return 'android';
52
- } else {
53
- logger.warning(`未知平台: ${platform}, ${arch}, 默认使用linux版本`);
54
- return 'linux';
55
- }
56
- }
57
-
58
- // 获取代理服务器可执行文件路径
59
- getProxyServerPath() {
60
- const platform = this.detectPlatform();
61
- const proxyDir = join(__dirname, 'proxy');
62
-
63
- switch (platform) {
64
- case 'windows':
65
- return join(proxyDir, 'chrome_proxy_server_windows_amd64.exe');
66
- case 'linux':
67
- return join(proxyDir, 'chrome_proxy_server_linux_amd64');
68
- case 'android':
69
- return join(proxyDir, 'chrome_proxy_server_android_arm64');
70
- default:
71
- logger.error(`不支持的平台: ${platform}`);
72
- return null;
73
- }
74
- }
75
-
76
- // 启动代理服务器
77
- async start() {
78
- if (!this.enabled) {
79
- logger.info('代理服务器未启用,跳过启动');
80
- return;
81
- }
82
-
83
- if (this.proxyProcess) {
84
- logger.warning('代理服务器已经在运行中');
85
- return;
86
- }
87
-
88
- const proxyServerPath = this.getProxyServerPath();
89
- if (!proxyServerPath) {
90
- logger.error('无法获取代理服务器路径');
91
- return;
92
- }
93
-
94
- try {
95
- // 启动代理服务器进程
96
- this.proxyProcess = spawn(proxyServerPath, [
97
- '--port', this.port.toString(),
98
- '--token', this.proxyAuthToken
99
- ], {
100
- stdio: ['ignore', 'pipe', 'pipe'], // 使用pipe而不是直接传递流
101
- detached: false
102
- });
103
-
104
- // 将进程的输出重定向到主进程
105
- if (this.proxyProcess.stdout) {
106
- this.proxyProcess.stdout.pipe(process.stdout);
107
- }
108
-
109
- if (this.proxyProcess.stderr) {
110
- this.proxyProcess.stderr.pipe(process.stderr);
111
- }
112
-
113
- // 设置进程事件处理
114
- this.proxyProcess.on('error', (err) => {
115
- logger.error(`代理服务器启动失败: ${err.message}`);
116
- this.proxyProcess = null;
117
- });
118
-
119
- this.proxyProcess.on('exit', (code, signal) => {
120
- logger.info(`代理服务器已退出,退出码: ${code}, 信号: ${signal}`);
121
- this.proxyProcess = null;
122
- });
123
-
124
- // 等待一段时间,确保服务器启动
125
- await new Promise(resolve => setTimeout(resolve, 1000));
126
-
127
- if (this.proxyProcess && this.proxyProcess.exitCode === null) {
128
- logger.success(`代理服务器已启动,端口: ${this.port}`);
129
- return true;
130
- } else {
131
- logger.error('代理服务器启动失败');
132
- return false;
133
- }
134
- } catch (error) {
135
- logger.error(`启动代理服务器时出错: ${error.message}`);
136
- return false;
137
- }
138
- }
139
-
140
- // 停止代理服务器
141
- stop() {
142
- if (!this.proxyProcess) {
143
- //logger.info('代理服务器已关闭');
144
- return;
145
- }
146
-
147
- try {
148
- // 在Windows上使用taskkill确保子进程也被终止
149
- if (this.detectPlatform() === 'windows' && this.proxyProcess.pid) {
150
- spawn('taskkill', ['/pid', this.proxyProcess.pid, '/f', '/t']);
151
- } else {
152
- // 在Linux/Android上使用kill信号
153
- this.proxyProcess.kill('SIGTERM');
154
- }
155
-
156
- logger.success('代理服务器已停止');
157
- } catch (error) {
158
- logger.error(`停止代理服务器时出错: ${error.message}`);
159
- } finally {
160
- this.proxyProcess = null;
161
- }
162
- }
163
- }
164
-
165
- // 创建单例
166
- const proxyServer = new ProxyServer();
167
-
168
- // 导出
169
  export { proxyServer };
 
1
+ import { spawn } from 'child_process';
2
+ import { fileURLToPath } from 'url';
3
+ import { dirname, join } from 'path';
4
+ import fs from 'fs';
5
+ import os from 'os';
6
+ import dotenv from 'dotenv';
7
+ import chalk from 'chalk';
8
+
9
+ // 获取当前文件的目录路径
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ // 加载环境变量
14
+ dotenv.config({ path: join(dirname(__dirname), '.env') });
15
+
16
+ // 日志配置
17
+ const logger = {
18
+ info: (message) => console.log(chalk.blue(`[ProxyServer] ${message}`)),
19
+ error: (message) => console.error(chalk.red(`[ProxyServer] ${message}`)),
20
+ warning: (message) => console.warn(chalk.yellow(`[ProxyServer] ${message}`)),
21
+ success: (message) => console.log(chalk.green(`[ProxyServer] ${message}`)),
22
+ };
23
+
24
+ class ProxyServer {
25
+ constructor() {
26
+ this.proxyProcess = null;
27
+ this.platform = process.env.PROXY_SERVER_PLATFORM || 'auto';
28
+ this.port = process.env.PROXY_SERVER_PORT || 10655;
29
+ this.enabled = process.env.ENABLE_PROXY_SERVER === 'true';
30
+ this.proxyAuthToken = process.env.PROXY_AUTH_TOKEN || 'default_token';
31
+ }
32
+
33
+ // 获取当前系统平台
34
+ detectPlatform() {
35
+ if (this.platform !== 'auto') {
36
+ return this.platform;
37
+ }
38
+
39
+ const platform = os.platform();
40
+ const arch = os.arch();
41
+
42
+ if (platform === 'win32') {
43
+ return 'windows';
44
+ } else if (platform === 'linux') {
45
+ if (arch === 'arm64') {
46
+ return 'android';
47
+ } else {
48
+ return 'linux';
49
+ }
50
+ } else if (platform === 'android') {
51
+ return 'android';
52
+ } else {
53
+ logger.warning(`未知平台: ${platform}, ${arch}, 默认使用linux版本`);
54
+ return 'linux';
55
+ }
56
+ }
57
+
58
+ // 获取代理服务器可执行文件路径
59
+ getProxyServerPath() {
60
+ const platform = this.detectPlatform();
61
+ const proxyDir = join(__dirname, 'proxy');
62
+
63
+ switch (platform) {
64
+ case 'windows':
65
+ return join(proxyDir, 'chrome_proxy_server_windows_amd64.exe');
66
+ case 'linux':
67
+ return join(proxyDir, 'chrome_proxy_server_linux_amd64');
68
+ case 'android':
69
+ return join(proxyDir, 'chrome_proxy_server_android_arm64');
70
+ default:
71
+ logger.error(`不支持的平台: ${platform}`);
72
+ return null;
73
+ }
74
+ }
75
+
76
+ // 启动代理服务器
77
+ async start() {
78
+ if (!this.enabled) {
79
+ logger.info('代理服务器未启用,跳过启动');
80
+ return;
81
+ }
82
+
83
+ if (this.proxyProcess) {
84
+ logger.warning('代理服务器已经在运行中');
85
+ return;
86
+ }
87
+
88
+ const proxyServerPath = this.getProxyServerPath();
89
+ if (!proxyServerPath) {
90
+ logger.error('无法获取代理服务器路径');
91
+ return;
92
+ }
93
+
94
+ try {
95
+ // 启动代理服务器进程
96
+ this.proxyProcess = spawn(proxyServerPath, [
97
+ '--port', this.port.toString(),
98
+ '--token', this.proxyAuthToken
99
+ ], {
100
+ stdio: ['ignore', 'pipe', 'pipe'], // 使用pipe而不是直接传递流
101
+ detached: false
102
+ });
103
+
104
+ // 将进程的输出重定向到主进程
105
+ if (this.proxyProcess.stdout) {
106
+ this.proxyProcess.stdout.pipe(process.stdout);
107
+ }
108
+
109
+ if (this.proxyProcess.stderr) {
110
+ this.proxyProcess.stderr.pipe(process.stderr);
111
+ }
112
+
113
+ // 设置进程事件处理
114
+ this.proxyProcess.on('error', (err) => {
115
+ logger.error(`代理服务器启动失败: ${err.message}`);
116
+ this.proxyProcess = null;
117
+ });
118
+
119
+ this.proxyProcess.on('exit', (code, signal) => {
120
+ logger.info(`代理服务器已退出,退出码: ${code}, 信号: ${signal}`);
121
+ this.proxyProcess = null;
122
+ });
123
+
124
+ // 等待一段时间,确保服务器启动
125
+ await new Promise(resolve => setTimeout(resolve, 1000));
126
+
127
+ if (this.proxyProcess && this.proxyProcess.exitCode === null) {
128
+ logger.success(`代理服务器已启动,端口: ${this.port}`);
129
+ return true;
130
+ } else {
131
+ logger.error('代理服务器启动失败');
132
+ return false;
133
+ }
134
+ } catch (error) {
135
+ logger.error(`启动代理服务器时出错: ${error.message}`);
136
+ return false;
137
+ }
138
+ }
139
+
140
+ // 停止代理服务器
141
+ stop() {
142
+ if (!this.proxyProcess) {
143
+ //logger.info('代理服务器已关闭');
144
+ return;
145
+ }
146
+
147
+ try {
148
+ // 在Windows上使用taskkill确保子进程也被终止
149
+ if (this.detectPlatform() === 'windows' && this.proxyProcess.pid) {
150
+ spawn('taskkill', ['/pid', this.proxyProcess.pid, '/f', '/t']);
151
+ } else {
152
+ // 在Linux/Android上使用kill信号
153
+ this.proxyProcess.kill('SIGTERM');
154
+ }
155
+
156
+ logger.success('代理服务器已停止');
157
+ } catch (error) {
158
+ logger.error(`停止代理服务器时出错: ${error.message}`);
159
+ } finally {
160
+ this.proxyProcess = null;
161
+ }
162
+ }
163
+ }
164
+
165
+ // 创建单例
166
+ const proxyServer = new ProxyServer();
167
+
168
+ // 导出
169
  export { proxyServer };
src/lightweight-client.js CHANGED
@@ -14,6 +14,8 @@ import {
14
  import { proxyPool } from './ProxyPool.js';
15
  import { proxyServer } from './ProxyServer.js';
16
  import { cookieManager } from './CookieManager.js';
 
 
17
 
18
  // 获取当前文件的目录路径
19
  const __filename = fileURLToPath(import.meta.url);
@@ -380,34 +382,50 @@ async function fetchNotionResponse(chunkQueue, notionRequestBody, headers, notio
380
  // 创建fetch选项
381
  const fetchOptions = {
382
  method: 'POST',
383
- headers: {
384
- ...headers,
385
- 'user-agent': window.navigator.userAgent,
386
- 'Cookie': notionCookie
387
- },
388
  body: JSON.stringify(notionRequestBody),
 
389
  };
390
 
391
- // 添加代理配置(如果有)
392
  if (USE_NATIVE_PROXY_POOL && ENABLE_PROXY_SERVER && !PROXY_URL) {
393
- proxy = proxyPool.getProxy();
394
- if (proxy !== null)
395
- {
396
- logger.info(`使用代理: ${proxy.full}`);
397
- }
398
- else{
399
- logger.warning(`没有可用代理`);
400
  }
401
  } else if(USE_NATIVE_PROXY_POOL&&!PROXY_URL&&!ENABLE_PROXY_SERVER) {
402
- const { HttpsProxyAgent } = await import('https-proxy-agent');
403
- proxy = proxyPool.getProxy();
404
- fetchOptions.agent = new HttpsProxyAgent(proxy.full);
405
- logger.info(`使用代理: ${proxy.full}`);
 
 
 
406
  }else if(PROXY_URL){
407
- const { HttpsProxyAgent } = await import('https-proxy-agent');
408
- fetchOptions.agent = new HttpsProxyAgent(PROXY_URL);
 
 
 
 
 
 
 
 
 
 
 
 
409
  logger.info(`使用代理: ${PROXY_URL}`);
410
  }
 
 
 
 
 
411
  let response = null;
412
  // 发送请求
413
  if (ENABLE_PROXY_SERVER && USE_NATIVE_PROXY_POOL){
 
14
  import { proxyPool } from './ProxyPool.js';
15
  import { proxyServer } from './ProxyServer.js';
16
  import { cookieManager } from './CookieManager.js';
17
+ import { HttpsProxyAgent } from 'https-proxy-agent';
18
+ import dns from 'dns';
19
 
20
  // 获取当前文件的目录路径
21
  const __filename = fileURLToPath(import.meta.url);
 
382
  // 创建fetch选项
383
  const fetchOptions = {
384
  method: 'POST',
385
+ headers: headers,
 
 
 
 
386
  body: JSON.stringify(notionRequestBody),
387
+ timeout: 120000 // 120s
388
  };
389
 
390
+ // 根据条件添加代理
391
  if (USE_NATIVE_PROXY_POOL && ENABLE_PROXY_SERVER && !PROXY_URL) {
392
+ const proxy = await proxyPool.getProxy();
393
+ if (proxy) {
394
+ fetchOptions.agent = new HttpsProxyAgent(proxy.url);
395
+ logger.info(`使用原生代理池: ${proxy.url} (来自 ${proxy.source})`);
396
+ } else {
397
+ logger.warning("原生代理池已启用但没有可用的代理,将不使用代理");
 
398
  }
399
  } else if(USE_NATIVE_PROXY_POOL&&!PROXY_URL&&!ENABLE_PROXY_SERVER) {
400
+ const proxy = await proxyPool.getProxy();
401
+ if (proxy) {
402
+ fetchOptions.agent = new HttpsProxyAgent(proxy.url);
403
+ logger.info(`使用原生代理池: ${proxy.url} (来自 ${proxy.source})`);
404
+ } else {
405
+ logger.warning("原生代理池已启用但没有可用的代理,将不使用代理");
406
+ }
407
  }else if(PROXY_URL){
408
+ // IPv6 优先
409
+ const customLookup = (hostname, options, callback) => {
410
+ dns.lookup(hostname, { family: 6 }, (err, address, family) => {
411
+ if (err) {
412
+ // 如果 IPv6 查询失败,则回退到 IPv4
413
+ dns.lookup(hostname, { family: 4 }, (err, address, family) => {
414
+ callback(err, address, family);
415
+ });
416
+ } else {
417
+ callback(err, address, family);
418
+ }
419
+ });
420
+ };
421
+ fetchOptions.agent = new HttpsProxyAgent(PROXY_URL, { lookup: customLookup });
422
  logger.info(`使用代理: ${PROXY_URL}`);
423
  }
424
+ else if (ENABLE_PROXY_SERVER && !USE_NATIVE_PROXY_POOL && !PROXY_URL){
425
+ const proxy = await proxyPool.getProxy();
426
+ fetchOptions.agent = new HttpsProxyAgent(proxy.url);
427
+ logger.info(`使用代理: ${proxy.url} (来自 ${proxy.source})`);
428
+ }
429
  let response = null;
430
  // 发送请求
431
  if (ENABLE_PROXY_SERVER && USE_NATIVE_PROXY_POOL){