mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package proxy
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func proxyConfigToMapping(src string) (map[string]any, error) {
|
|
src = strings.TrimSpace(src)
|
|
l := strings.ToLower(src)
|
|
|
|
if strings.HasPrefix(l, "http://") || strings.HasPrefix(l, "https://") {
|
|
return parseStandardProxy(src, "http")
|
|
}
|
|
if strings.HasPrefix(l, "socks5://") {
|
|
return parseStandardProxy(src, "socks5")
|
|
}
|
|
if strings.HasPrefix(l, "ss://") {
|
|
return parseSSURIToMapping(src)
|
|
}
|
|
|
|
if strings.Contains(l, "://") && !strings.Contains(l, "type:") {
|
|
return nil, fmt.Errorf("URI 格式暂不支持: %s", l[:min(30, len(l))])
|
|
}
|
|
|
|
return parseClashYAMLToMapping(src)
|
|
}
|
|
|
|
func parseStandardProxy(src string, proxyType string) (map[string]any, error) {
|
|
parsed, err := url.Parse(src)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("代理地址解析失败: %w", err)
|
|
}
|
|
host := strings.TrimSpace(parsed.Hostname())
|
|
port, err := strconv.Atoi(parsed.Port())
|
|
if err != nil {
|
|
port = 0
|
|
}
|
|
if host == "" || port == 0 {
|
|
return nil, fmt.Errorf("无法解析地址: %s", src)
|
|
}
|
|
username := ""
|
|
password := ""
|
|
if parsed.User != nil {
|
|
username = parsed.User.Username()
|
|
password, _ = parsed.User.Password()
|
|
}
|
|
|
|
mapping := map[string]any{
|
|
"name": "speedtest-proxy",
|
|
"type": proxyType,
|
|
"server": host,
|
|
"port": port,
|
|
}
|
|
if username != "" {
|
|
mapping["username"] = username
|
|
mapping["password"] = password
|
|
}
|
|
return mapping, nil
|
|
}
|
|
|
|
func parseSSURIToMapping(src string) (map[string]any, error) {
|
|
outbound, err := buildOutboundSS(src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
settings, ok := outbound["settings"].(map[string]interface{})
|
|
if !ok {
|
|
return nil, fmt.Errorf("ss 节点缺少 settings")
|
|
}
|
|
server, err := firstShadowsocksServer(settings)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mapping := map[string]any{
|
|
"name": "speedtest-proxy",
|
|
"type": "ss",
|
|
"server": server["address"],
|
|
"port": server["port"],
|
|
"cipher": server["method"],
|
|
"password": server["password"],
|
|
}
|
|
return mapping, nil
|
|
}
|
|
|
|
func firstShadowsocksServer(settings map[string]interface{}) (map[string]interface{}, error) {
|
|
servers, ok := settings["servers"].([]interface{})
|
|
if !ok || len(servers) == 0 {
|
|
return nil, fmt.Errorf("ss 节点缺少 servers")
|
|
}
|
|
server, ok := servers[0].(map[string]interface{})
|
|
if !ok || server == nil {
|
|
return nil, fmt.Errorf("ss server 格式无效")
|
|
}
|
|
return server, nil
|
|
}
|
|
|
|
func parseClashYAMLToMapping(src string) (map[string]any, error) {
|
|
var payload interface{}
|
|
if err := yaml.Unmarshal([]byte(src), &payload); err != nil {
|
|
return nil, fmt.Errorf("YAML 解析失败: %v", err)
|
|
}
|
|
|
|
node := pickClashNode(payload)
|
|
if node == nil {
|
|
return nil, fmt.Errorf("无法提取 Clash 节点")
|
|
}
|
|
|
|
if _, ok := node["name"]; !ok {
|
|
node["name"] = "speedtest-proxy"
|
|
}
|
|
|
|
return node, nil
|
|
}
|
|
|
|
func min(a, b int) int {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|