mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
channel: master
version: 1.2.0
source-ref: D:\code\open_source\ant-chrome master
source-commit: f3d7ec5
merged-public-base: 3d264eb
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package proxy
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func parseClashNode(src string) (map[string]interface{}, string, error) {
|
|
data := strings.TrimSpace(src)
|
|
if strings.HasPrefix(strings.ToLower(data), "clash://") {
|
|
raw := strings.TrimPrefix(data, "clash://")
|
|
raw, _ = url.QueryUnescape(raw)
|
|
decoded, err := decodeBase64String(raw)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
data = string(decoded)
|
|
}
|
|
var payload interface{}
|
|
if err := yaml.Unmarshal([]byte(data), &payload); err != nil {
|
|
return nil, "", err
|
|
}
|
|
nodeMap := pickClashNode(payload)
|
|
if nodeMap == nil {
|
|
return nil, "", fmt.Errorf("clash 节点解析失败")
|
|
}
|
|
nodeType := strings.ToLower(getMapString(nodeMap, "type"))
|
|
switch nodeType {
|
|
case "socks5", "http", "https":
|
|
return nil, buildStandardProxyFromClash(nodeMap, nodeType), nil
|
|
case "vmess":
|
|
return buildOutboundFromClashVmess(nodeMap)
|
|
case "vless":
|
|
return buildOutboundFromClashVless(nodeMap)
|
|
case "trojan":
|
|
return buildOutboundFromClashTrojan(nodeMap)
|
|
case "ss", "shadowsocks":
|
|
return buildOutboundFromClashSS(nodeMap)
|
|
case "ssr":
|
|
return nil, "", fmt.Errorf("不支持 ShadowsocksR 协议,Xray 不支持 SSR,请使用 SS/vmess/vless/trojan")
|
|
case "hysteria2", "hysteria":
|
|
return buildOutboundFromClashHysteria2(nodeMap)
|
|
}
|
|
return nil, "", fmt.Errorf("不支持的节点类型")
|
|
}
|
|
|
|
func pickClashNode(payload interface{}) map[string]interface{} {
|
|
if m := toStringMap(payload); m != nil {
|
|
if proxies, ok := m["proxies"]; ok {
|
|
if arr, ok := proxies.([]interface{}); ok && len(arr) > 0 {
|
|
return toStringMap(arr[0])
|
|
}
|
|
}
|
|
if proxyItem, ok := m["proxy"]; ok {
|
|
if node := toStringMap(proxyItem); node != nil {
|
|
return node
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
if arr, ok := payload.([]interface{}); ok && len(arr) > 0 {
|
|
return toStringMap(arr[0])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func buildStandardProxyFromClash(node map[string]interface{}, scheme string) string {
|
|
host := getMapString(node, "server")
|
|
port := getMapInt(node, "port")
|
|
username := getMapString(node, "username")
|
|
password := getMapString(node, "password")
|
|
if host == "" || port == 0 {
|
|
return ""
|
|
}
|
|
address := fmt.Sprintf("%s:%d", host, port)
|
|
if username != "" {
|
|
user := url.UserPassword(username, password)
|
|
return fmt.Sprintf("%s://%s@%s", scheme, user.String(), address)
|
|
}
|
|
return fmt.Sprintf("%s://%s", scheme, address)
|
|
}
|