测试代理是否可用

This commit is contained in:
2025-01-09 17:19:44 +08:00
parent fee0c7d845
commit c7124bda81
13 changed files with 3499 additions and 188 deletions

108
common/file.go Normal file
View File

@@ -0,0 +1,108 @@
package common
import (
"bufio"
"fmt"
"net/url"
"os"
"strconv"
"strings"
)
// ReadNodesFile 读取nodes.txt文件并解析所有节点
func ReadNodesFile(filename string) ([]*Node, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var nodes []*Node
nodeSet := make(map[string]bool) // 用于去重
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
// 检查是否已经存在
if _, exists := nodeSet[line]; exists {
continue // 跳过重复的节点
}
node, err := ParseNodeURL(line)
if err != nil {
fmt.Printf("解析节点失败: %v\n", err)
continue // 跳过解析失败的行
}
nodes = append(nodes, node)
nodeSet[line] = true // 标记为已存在
}
if err := scanner.Err(); err != nil {
return nil, err
}
return nodes, nil
}
// ParseNodeURL 解析代理URL字符串为Node结构
func ParseNodeURL(urlStr string) (*Node, error) {
u, err := url.Parse(urlStr)
if err != nil {
return nil, fmt.Errorf("解析URL失败: %v", err)
}
// 获取用户信息
username := ""
password := ""
if u.User != nil {
username = u.User.Username()
if pass, ok := u.User.Password(); ok {
password = pass
}
}
// 解析端口
port := 443 // 默认端口
if u.Port() != "" {
port, err = strconv.Atoi(u.Port())
if err != nil {
return nil, fmt.Errorf("解析端口失败: %v", err)
}
}
return &Node{
Protocol: u.Scheme,
Username: username,
Password: password,
Addr: u.Hostname(),
Port: port,
}, nil
}
// SaveAvailableNodes 保存可用的节点到文件
func SaveAvailableNodes(filename string, nodes []*Node) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
for _, node := range nodes {
// 重新构建URL格式
url := fmt.Sprintf("https://%s:%s@%s:%d\n",
node.Username,
node.Password,
node.Addr,
node.Port)
if _, err := file.WriteString(url); err != nil {
return err
}
}
return nil
}