mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-14 00:51:12 +03:00
107 lines
2.2 KiB
Go
107 lines
2.2 KiB
Go
package clash
|
|
|
|
import (
|
|
"context"
|
|
|
|
C "github.com/sagernet/sing-box/constant"
|
|
"github.com/sagernet/sing-box/option"
|
|
"github.com/sagernet/sing/common"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type ClashConfig struct {
|
|
Proxies []ClashProxy `yaml:"proxies"`
|
|
}
|
|
|
|
type _ClashProxy struct {
|
|
Name string `yaml:"name"`
|
|
Type string `yaml:"type"`
|
|
Options Proxy `yaml:"-"`
|
|
|
|
SingType string `yaml:"-"`
|
|
}
|
|
type ClashProxy _ClashProxy
|
|
|
|
type Proxy interface {
|
|
Build() any
|
|
}
|
|
|
|
func (c *ClashProxy) UnmarshalYAML(value *yaml.Node) error {
|
|
err := value.Decode((*_ClashProxy)(c))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var options Proxy
|
|
switch c.Type {
|
|
case "ss":
|
|
c.SingType = C.TypeShadowsocks
|
|
options = &ShadowSocksOption{}
|
|
case "tuic":
|
|
c.SingType = C.TypeTUIC
|
|
options = &TuicOption{}
|
|
case "vmess":
|
|
c.SingType = C.TypeVMess
|
|
options = &VmessOption{}
|
|
case "vless":
|
|
c.SingType = C.TypeVLESS
|
|
options = &VlessOption{}
|
|
case "socks5":
|
|
c.SingType = C.TypeSOCKS
|
|
options = &Socks5Option{}
|
|
case "http":
|
|
c.SingType = C.TypeHTTP
|
|
options = &HttpOption{}
|
|
case "trojan":
|
|
c.SingType = C.TypeTrojan
|
|
options = &TrojanOption{}
|
|
case "hysteria":
|
|
c.SingType = C.TypeHysteria
|
|
options = &HysteriaOption{}
|
|
case "hysteria2":
|
|
c.SingType = C.TypeHysteria2
|
|
options = &Hysteria2Option{}
|
|
case "ssh":
|
|
c.SingType = C.TypeSSH
|
|
options = &SSHOption{}
|
|
case "anytls":
|
|
c.SingType = C.TypeAnyTLS
|
|
options = &AnyTLSOption{}
|
|
default:
|
|
return nil
|
|
}
|
|
err = value.Decode(options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.Options = options
|
|
return nil
|
|
}
|
|
|
|
func (c *ClashProxy) Build() option.Outbound {
|
|
outbound := option.Outbound{
|
|
Tag: c.Name,
|
|
Type: c.SingType,
|
|
}
|
|
if c.Options != nil {
|
|
outbound.Options = c.Options.Build()
|
|
}
|
|
return outbound
|
|
}
|
|
|
|
func ParseClashSubscription(_ context.Context, content string) ([]option.Outbound, error) {
|
|
config := &ClashConfig{}
|
|
err := yaml.Unmarshal([]byte(content), &config)
|
|
if err != nil {
|
|
return nil, E.Cause(err, "parse clash config")
|
|
}
|
|
outbounds := common.FilterIsInstance(config.Proxies, func(proxy ClashProxy) (option.Outbound, bool) {
|
|
if proxy.SingType == "" {
|
|
return option.Outbound{}, false
|
|
}
|
|
return proxy.Build(), true
|
|
})
|
|
return outbounds, nil
|
|
}
|