first commit
Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped
Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped
This commit is contained in:
254
internal/parser/manager.go
Normal file
254
internal/parser/manager.go
Normal file
@@ -0,0 +1,254 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/subconverter-go/internal/config"
|
||||
"github.com/subconverter-go/internal/logging"
|
||||
)
|
||||
|
||||
// Parser 解析器接口
|
||||
// 定义了所有代理协议解析器必须实现的方法
|
||||
type Parser interface {
|
||||
// Parse 解析代理配置
|
||||
// input: 输入的代理配置字符串
|
||||
// 返回解析后的代理配置和错误信息
|
||||
Parse(input string) (*ProxyConfig, error)
|
||||
|
||||
// Validate 验证代理配置
|
||||
// config: 需要验证的代理配置
|
||||
// 返回验证结果和错误信息
|
||||
Validate(config *ProxyConfig) error
|
||||
|
||||
// GetSupportedProtocols 获取支持的协议
|
||||
// 返回该解析器支持的协议列表
|
||||
GetSupportedProtocols() []string
|
||||
}
|
||||
|
||||
// ProxyConfig 代理配置结构体
|
||||
// 包含所有代理协议的通用配置信息
|
||||
type ProxyConfig struct {
|
||||
// 基本信息
|
||||
Name string `json:"name"` // 代理名称
|
||||
Server string `json:"server"` // 服务器地址
|
||||
Port int `json:"port"` // 服务器端口
|
||||
Type string `json:"type"` // 代理类型
|
||||
|
||||
// 协议特定配置
|
||||
Protocol string `json:"protocol"` // 协议类型 (ss, ssr, vmess, trojan, http, socks5)
|
||||
Settings map[string]interface{} `json:"settings"` // 协议特定设置
|
||||
|
||||
// 扩展信息
|
||||
Remarks string `json:"remarks"` // 备注信息
|
||||
Group string `json:"group"` // 分组名称
|
||||
Location string `json:"location"` // 地理位置
|
||||
UDP bool `json:"udp"` // 是否支持UDP
|
||||
|
||||
// 性能和质量指标
|
||||
Latency int `json:"latency"` // 延迟 (ms)
|
||||
Score int `json:"score"` // 质量评分
|
||||
}
|
||||
|
||||
// ParserManager 解析器管理器
|
||||
// 管理所有代理协议解析器,提供统一的解析接口
|
||||
type ParserManager struct {
|
||||
logger *logging.Logger
|
||||
configMgr *config.ConfigManager
|
||||
parsers map[string]Parser // 协议名称到解析器的映射
|
||||
}
|
||||
|
||||
// NewParserManager 创建新的解析器管理器
|
||||
// 返回初始化好的ParserManager实例
|
||||
func NewParserManager(logger *logging.Logger, configMgr *config.ConfigManager) *ParserManager {
|
||||
pm := &ParserManager{
|
||||
logger: logger,
|
||||
configMgr: configMgr,
|
||||
parsers: make(map[string]Parser),
|
||||
}
|
||||
|
||||
// 注册所有解析器
|
||||
pm.registerParsers()
|
||||
|
||||
return pm
|
||||
}
|
||||
|
||||
// registerParsers 注册所有解析器
|
||||
// 将各种代理协议解析器注册到管理器中
|
||||
func (pm *ParserManager) registerParsers() {
|
||||
// 注册Shadowsocks解析器
|
||||
pm.parsers["ss"] = NewShadowsocksParser(pm.logger)
|
||||
|
||||
// 注册ShadowsocksR解析器
|
||||
pm.parsers["ssr"] = NewShadowsocksRParser(pm.logger)
|
||||
|
||||
// 注册VMess解析器
|
||||
pm.parsers["vmess"] = NewVMessParser(pm.logger)
|
||||
|
||||
// 注册Trojan解析器
|
||||
pm.parsers["trojan"] = NewTrojanParser(pm.logger)
|
||||
|
||||
// 注册HTTP解析器
|
||||
pm.parsers["http"] = NewHTTPParser(pm.logger)
|
||||
|
||||
// 注册Socks5解析器
|
||||
pm.parsers["socks5"] = NewSocks5Parser(pm.logger)
|
||||
|
||||
pm.logger.Info("Registered parsers: ss, ssr, vmess, trojan, http, socks5")
|
||||
}
|
||||
|
||||
// Parse 解析代理配置
|
||||
// 自动识别协议并调用相应的解析器
|
||||
func (pm *ParserManager) Parse(input string) (*ProxyConfig, error) {
|
||||
pm.logger.Debugf("Parsing proxy configuration: %s", input[:min(len(input), 50)]+"...")
|
||||
|
||||
// 尝试自动检测协议
|
||||
protocol, err := pm.detectProtocol(input)
|
||||
if err != nil {
|
||||
pm.logger.WithError(err).Error("Failed to detect protocol")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取对应的解析器
|
||||
parser, exists := pm.parsers[protocol]
|
||||
if !exists {
|
||||
pm.logger.Errorf("No parser found for protocol: %s", protocol)
|
||||
return nil, fmt.Errorf("unsupported protocol: %s", protocol)
|
||||
}
|
||||
|
||||
// 调用解析器进行解析
|
||||
config, err := parser.Parse(input)
|
||||
if err != nil {
|
||||
pm.logger.WithError(err).Errorf("Failed to parse %s configuration", protocol)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置协议类型
|
||||
config.Protocol = protocol
|
||||
|
||||
pm.logger.Infof("Successfully parsed %s configuration for server: %s:%d", protocol, config.Server, config.Port)
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// detectProtocol 检测输入字符串的协议类型
|
||||
// 通过前缀和格式识别代理协议
|
||||
func (pm *ParserManager) detectProtocol(input string) (string, error) {
|
||||
// 去除前后空格
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
lower := strings.ToLower(input)
|
||||
|
||||
// 检查URL格式
|
||||
switch {
|
||||
case strings.HasPrefix(lower, "ss://"):
|
||||
return "ss", nil
|
||||
case strings.HasPrefix(lower, "ssr://"):
|
||||
return "ssr", nil
|
||||
case strings.HasPrefix(lower, "vmess://"), strings.HasPrefix(lower, "vmess1://"):
|
||||
return "vmess", nil
|
||||
case strings.HasPrefix(lower, "trojan://"):
|
||||
return "trojan", nil
|
||||
case strings.HasPrefix(lower, "socks5://"), strings.HasPrefix(lower, "socks://"), strings.HasPrefix(lower, "https://t.me/socks"), strings.HasPrefix(lower, "tg://socks"):
|
||||
return "socks5", nil
|
||||
case strings.HasPrefix(lower, "http://"), strings.HasPrefix(lower, "https://"), strings.HasPrefix(lower, "tg://http"), strings.HasPrefix(lower, "https://t.me/http"):
|
||||
return "http", nil
|
||||
}
|
||||
|
||||
// 如果没有明确的协议前缀,尝试从内容推断
|
||||
if strings.Contains(lower, "ssr://") {
|
||||
return "ssr", nil
|
||||
}
|
||||
if strings.Contains(lower, "vmess://") || strings.Contains(lower, "vmess1://") {
|
||||
return "vmess", nil
|
||||
}
|
||||
if strings.Contains(lower, "ss://") {
|
||||
return "ss", nil
|
||||
}
|
||||
if strings.Contains(lower, "trojan://") {
|
||||
return "trojan", nil
|
||||
}
|
||||
if strings.Contains(lower, "socks5://") || strings.Contains(lower, "socks://") {
|
||||
return "socks5", nil
|
||||
}
|
||||
if strings.Contains(lower, "http://") || strings.Contains(lower, "https://") {
|
||||
return "http", nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unknown protocol for input: %s", input)
|
||||
}
|
||||
|
||||
// GetSupportedProtocols 获取所有支持的协议
|
||||
// 返回管理器支持的所有代理协议列表
|
||||
func (pm *ParserManager) GetSupportedProtocols() []string {
|
||||
protocols := make([]string, 0, len(pm.parsers))
|
||||
for protocol := range pm.parsers {
|
||||
protocols = append(protocols, protocol)
|
||||
}
|
||||
|
||||
// 按字母顺序排序
|
||||
sort.Strings(protocols)
|
||||
return protocols
|
||||
}
|
||||
|
||||
// GetParser 获取指定协议的解析器
|
||||
// 返回对应协议的解析器实例
|
||||
func (pm *ParserManager) GetParser(protocol string) (Parser, error) {
|
||||
parser, exists := pm.parsers[protocol]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("parser not found for protocol: %s", protocol)
|
||||
}
|
||||
return parser, nil
|
||||
}
|
||||
|
||||
// Validate 验证代理配置
|
||||
// 使用对应的解析器验证配置的有效性
|
||||
func (pm *ParserManager) Validate(config *ProxyConfig) error {
|
||||
parser, err := pm.GetParser(config.Protocol)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return parser.Validate(config)
|
||||
}
|
||||
|
||||
// ParseBatch 批量解析代理配置
|
||||
// 支持从包含多个代理配置的字符串中解析所有配置
|
||||
func (pm *ParserManager) ParseBatch(input string) ([]*ProxyConfig, error) {
|
||||
pm.logger.Debugf("Parsing batch proxy configuration")
|
||||
|
||||
// 按行分割输入
|
||||
lines := strings.Split(input, "\n")
|
||||
var configs []*ProxyConfig
|
||||
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 尝试解析每一行
|
||||
config, err := pm.Parse(line)
|
||||
if err != nil {
|
||||
pm.logger.WithError(err).Warnf("Failed to parse line: %s", line)
|
||||
continue
|
||||
}
|
||||
|
||||
configs = append(configs, config)
|
||||
}
|
||||
|
||||
if len(configs) == 0 {
|
||||
return nil, fmt.Errorf("no valid proxy configurations found")
|
||||
}
|
||||
|
||||
pm.logger.Infof("Successfully parsed %d proxy configurations", len(configs))
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
// 辅助函数
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in New Issue
Block a user