File size: 5,509 Bytes
de9786a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/**
 * 简化的代理池类,支持 HTTP 和 SOCKS5 代理
 */
class ProxyPool {
  constructor() {
    // 从环境变量读取完整的代理URL
    this.proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || '';
    this.isInitialized = false;
    
    // 解析代理URL
    this.parseProxyUrl();
  }
  
  /**
   * 解析代理URL
   */
  parseProxyUrl() {
    if (!this.proxyUrl) {
      console.log('未设置代理URL环境变量 (HTTP_PROXY)');
      return;
    }
    
    try {
      const url = new URL(this.proxyUrl);
      this.proxyInfo = {
        protocol: url.protocol.replace(':', ''),
        host: url.hostname,
        port: parseInt(url.port),
        username: url.username,
        password: url.password,
        full: this.proxyUrl
      };
      
      console.log(`代理配置解析成功: ${this.proxyInfo.protocol}://${this.proxyInfo.host}:${this.proxyInfo.port}`);
    } catch (error) {
      console.error(`代理URL解析失败: ${error.message}`);
      this.proxyInfo = null;
    }
  }
  
  /**
   * 初始化代理池
   */
  async initialize() {
    if (this.isInitialized) return true;
    
    if (!this.proxyUrl) {
      console.log('未配置代理,将使用直连模式');
      this.isInitialized = true;
      return true;
    }
    
    if (!this.proxyInfo) {
      console.error('代理配置无效');
      return false;
    }
    
    // 测试代理连接
    const isValid = await this.testProxyConnection();
    if (isValid) {
      this.isInitialized = true;
      console.log('代理池初始化成功');
      return true;
    } else {
      console.error('代理连接测试失败');
      // 即使测试失败,也标记为已初始化,让实际使用时验证
      this.isInitialized = true;
      console.log('跳过测试失败,继续使用配置的代理');
      return true;
    }
  }
  
  /**
   * 测试代理连接
   */
  async testProxyConnection() {
    if (!this.proxyInfo) return false;
    
    try {
      let agent;
      
      // 根据协议选择不同的代理 Agent
      if (this.proxyUrl.startsWith('socks5://')) {
        const { SocksProxyAgent } = await import('socks-proxy-agent');
        agent = new SocksProxyAgent(this.proxyUrl);
        console.log('使用 SOCKS5 代理进行测试...');
      } else if (this.proxyUrl.startsWith('socks4://')) {
        const { SocksProxyAgent } = await import('socks-proxy-agent');
        agent = new SocksProxyAgent(this.proxyUrl);
        console.log('使用 SOCKS4 代理进行测试...');
      } else {
        const HttpProxyAgent = (await import('http-proxy-agent')).default;
        agent = new HttpProxyAgent(this.proxyUrl);
        console.log('使用 HTTP 代理进行测试...');
      }
      
      const fetch = (await import('node-fetch')).default;
      
      // 尝试多个测试URL
      const testUrls = [
        'http://httpbin.org/ip',
        'https://api.ipify.org?format=json',
        'http://icanhazip.com'
      ];
      
      for (const testUrl of testUrls) {
        try {
          console.log(`测试代理连接到: ${testUrl}`);
          
          const response = await fetch(testUrl, {
            agent,
            timeout: 15000,
            headers: {
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
              'Accept': '*/*',
              'Connection': 'close'
            }
          });
          
          if (response.ok) {
            const data = await response.text();
            let ip = data.trim();
            
            // 尝试解析JSON格式的响应
            try {
              const jsonData = JSON.parse(data);
              ip = jsonData.ip || jsonData.origin || ip;
            } catch (e) {
              // 如果不是JSON,使用原始文本
            }
            
            console.log(`${this.proxyInfo.protocol.toUpperCase()} 代理连接测试成功!`);
            console.log(`测试URL: ${testUrl}`);
            console.log(`出口IP: ${ip}`);
            return true;
          } else {
            console.log(`测试URL ${testUrl} 失败,状态码: ${response.status}`);
          }
        } catch (urlError) {
          console.log(`测试URL ${testUrl} 出错: ${urlError.message}`);
        }
      }
      
      console.error('所有测试URL都失败了');
      return false;
    } catch (error) {
      console.error(`代理连接测试失败: ${error.message}`);
      return false;
    }
  }
  
  /**
   * 获取代理(每次调用返回相同的代理)
   */
  getProxy() {
    if (!this.proxyInfo) {
      return null;
    }
    
    return {
      ip: this.proxyInfo.host,
      port: this.proxyInfo.port,
      protocol: this.proxyInfo.protocol,
      full: this.proxyInfo.full
    };
  }
  
  /**
   * 移除代理(记录错误)
   */
  removeProxy(ip, port) {
    console.log(`记录代理问题: ${ip}:${port}`);
    return true;
  }
  
  /**
   * 获取代理数量
   */
  getValidCount() {
    return this.proxyInfo ? 1 : 0;
  }
  
  /**
   * 获取状态信息
   */
  getStatus() {
    if (!this.proxyInfo) {
      return [];
    }
    
    return [{
      index: 0,
      host: this.proxyInfo.host,
      port: this.proxyInfo.port,
      protocol: this.proxyInfo.protocol,
      active: true
    }];
  }
  
  /**
   * 停止代理池
   */
  stop() {
    console.log('代理池已停止');
  }
}

// 导出
export default ProxyPool;
export const proxyPool = new ProxyPool();