diff --git a/.gitignore b/.gitignore index 55d9fff..4ea5a84 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,7 @@ subs logs data .env -.vscode/settings.json \ No newline at end of file +.vscode/settings.json +config.yaml +config.yml +config.json \ No newline at end of file diff --git a/common/sub.go b/common/sub.go index 80b1113..7e0b7c5 100644 --- a/common/sub.go +++ b/common/sub.go @@ -154,7 +154,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, return nil, NewRegexInvalidError("prefix", err) } if reg.Match(data) { - p, err := parser.ParseProxies(strings.Split(string(data), "\n")...) + p, err := parser.ParseProxies(parser.ParseConfig{UseUDP: query.UseUDP}, strings.Split(string(data), "\n")...) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, ) return nil, NewSubscriptionParseError(err) } - p, err := parser.ParseProxies(strings.Split(base64, "\n")...) + p, err := parser.ParseProxies(parser.ParseConfig{UseUDP: query.UseUDP}, strings.Split(base64, "\n")...) if err != nil { return nil, err } @@ -187,7 +187,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, } if len(query.Proxy) != 0 { - p, err := parser.ParseProxies(query.Proxies...) + p, err := parser.ParseProxies(parser.ParseConfig{UseUDP: query.UseUDP}, query.Proxies...) if err != nil { return nil, err } @@ -200,6 +200,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, } } + // 去重 proxies := make(map[string]*P.Proxy) newProxies := make([]P.Proxy, 0, len(proxyList)) for i := range proxyList { @@ -216,6 +217,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, } proxyList = newProxies + // 移除 if strings.TrimSpace(query.Remove) != "" { newProxyList := make([]P.Proxy, 0, len(proxyList)) for i := range proxyList { @@ -233,8 +235,8 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, proxyList = newProxyList } + // 替换 if len(query.ReplaceKeys) != 0 { - replaceRegs := make([]*regexp.Regexp, 0, len(query.ReplaceKeys)) for _, v := range query.ReplaceKeys { replaceReg, err := regexp.Compile(v) @@ -256,6 +258,7 @@ func BuildSub(clashType model.ClashType, query model.SubConfig, template string, } } + // 重命名有相同名称的节点 names := make(map[string]int) for i := range proxyList { if _, exist := names[proxyList[i].Name]; exist { diff --git a/model/sub_config.go b/model/sub_config.go index f221729..b8d965d 100644 --- a/model/sub_config.go +++ b/model/sub_config.go @@ -32,6 +32,7 @@ type SubConfig struct { NodeListMode bool `form:"nodeList,default=false" binding:""` IgnoreCountryGrooup bool `form:"ignoreCountryGroup,default=false" binding:""` UserAgent string `form:"userAgent" binding:""` + UseUDP bool `form:"useUDP,default=false" binding:""` } type RuleProviderStruct struct { diff --git a/parser/anytls.go b/parser/anytls.go index c6e909d..76d1653 100644 --- a/parser/anytls.go +++ b/parser/anytls.go @@ -26,7 +26,7 @@ func (p *AnytlsParser) GetType() string { return "anytls" } -func (p *AnytlsParser) Parse(proxy string) (P.Proxy, error) { +func (p *AnytlsParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } @@ -72,6 +72,7 @@ func (p *AnytlsParser) Parse(proxy string) (P.Proxy, error) { Password: password, SNI: sni, SkipCertVerify: insecureBool, + UDP: config.UseUDP, }, } return result, nil diff --git a/parser/common.go b/parser/common.go index ebbaf8e..cc80f14 100644 --- a/parser/common.go +++ b/parser/common.go @@ -77,14 +77,18 @@ func DecodeBase64(s string) (string, error) { return string(decodeStr), nil } -func ParseProxies(proxies ...string) ([]P.Proxy, error) { +type ParseConfig struct { + UseUDP bool +} + +func ParseProxies(config ParseConfig, proxies ...string) ([]P.Proxy, error) { var result []P.Proxy for _, proxy := range proxies { if proxy != "" { var proxyItem P.Proxy var err error - proxyItem, err = ParseProxyWithRegistry(proxy) + proxyItem, err = ParseProxyWithRegistry(config, proxy) if err != nil { return nil, err } diff --git a/parser/hysteria.go b/parser/hysteria.go index 40a8632..e39d800 100644 --- a/parser/hysteria.go +++ b/parser/hysteria.go @@ -27,7 +27,7 @@ func (p *HysteriaParser) GetType() string { return "hysteria" } -func (p *HysteriaParser) Parse(proxy string) (P.Proxy, error) { +func (p *HysteriaParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } diff --git a/parser/hysteria2.go b/parser/hysteria2.go index 10df50f..f11ccc3 100644 --- a/parser/hysteria2.go +++ b/parser/hysteria2.go @@ -26,7 +26,7 @@ func (p *Hysteria2Parser) GetType() string { return "hysteria2" } -func (p *Hysteria2Parser) Parse(proxy string) (P.Proxy, error) { +func (p *Hysteria2Parser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } diff --git a/parser/registry.go b/parser/registry.go index fb7e09e..f8dfde7 100644 --- a/parser/registry.go +++ b/parser/registry.go @@ -9,7 +9,7 @@ import ( ) type ProxyParser interface { - Parse(proxy string) (P.Proxy, error) + Parse(config ParseConfig, proxy string) (P.Proxy, error) GetPrefixes() []string GetType() string SupportClash() bool @@ -64,7 +64,7 @@ func GetAllPrefixes() []string { return prefixes } -func ParseProxyWithRegistry(proxy string) (P.Proxy, error) { +func ParseProxyWithRegistry(config ParseConfig, proxy string) (P.Proxy, error) { proxy = strings.TrimSpace(proxy) if proxy == "" { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidStruct, "empty proxy string") @@ -72,7 +72,7 @@ func ParseProxyWithRegistry(proxy string) (P.Proxy, error) { for prefix, parser := range registry.parsers { if strings.HasPrefix(proxy, prefix) { - return parser.Parse(proxy) + return parser.Parse(config, proxy) } } diff --git a/parser/shadowsocks.go b/parser/shadowsocks.go index e32823c..8906ced 100644 --- a/parser/shadowsocks.go +++ b/parser/shadowsocks.go @@ -30,7 +30,7 @@ func (p *ShadowsocksParser) GetType() string { } // Parse 解析Shadowsocks代理 -func (p *ShadowsocksParser) Parse(proxy string) (P.Proxy, error) { +func (p *ShadowsocksParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } @@ -108,9 +108,9 @@ func (p *ShadowsocksParser) Parse(proxy string) (P.Proxy, error) { Password: password, Server: server, Port: port, + UDP: config.UseUDP, }, } - return result, nil } diff --git a/parser/shadowsocksr.go b/parser/shadowsocksr.go index 3bf52bc..557a1bf 100644 --- a/parser/shadowsocksr.go +++ b/parser/shadowsocksr.go @@ -27,7 +27,7 @@ func (p *ShadowsocksRParser) GetType() string { return "ssr" } -func (p *ShadowsocksRParser) Parse(proxy string) (P.Proxy, error) { +func (p *ShadowsocksRParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } @@ -100,9 +100,9 @@ func (p *ShadowsocksRParser) Parse(proxy string) (P.Proxy, error) { Password: password, ObfsParam: obfsParam, ProtocolParam: protoParam, + UDP: config.UseUDP, }, } - return result, nil } diff --git a/parser/socks.go b/parser/socks.go index 081ef41..6efc36b 100644 --- a/parser/socks.go +++ b/parser/socks.go @@ -25,7 +25,7 @@ func (p *SocksParser) GetType() string { return "socks5" } -func (p *SocksParser) Parse(proxy string) (P.Proxy, error) { +func (p *SocksParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } diff --git a/parser/trojan.go b/parser/trojan.go index ae0e059..bc8cf31 100644 --- a/parser/trojan.go +++ b/parser/trojan.go @@ -26,7 +26,7 @@ func (p *TrojanParser) GetType() string { return "trojan" } -func (p *TrojanParser) Parse(proxy string) (P.Proxy, error) { +func (p *TrojanParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } diff --git a/parser/vless.go b/parser/vless.go index 86feba6..ad51c33 100644 --- a/parser/vless.go +++ b/parser/vless.go @@ -26,7 +26,7 @@ func (p *VlessParser) GetType() string { return "vless" } -func (p *VlessParser) Parse(proxy string) (P.Proxy, error) { +func (p *VlessParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } diff --git a/parser/vmess.go b/parser/vmess.go index 6756e52..8132f3f 100644 --- a/parser/vmess.go +++ b/parser/vmess.go @@ -46,7 +46,7 @@ func (p *VmessParser) GetType() string { return "vmess" } -func (p *VmessParser) Parse(proxy string) (P.Proxy, error) { +func (p *VmessParser) Parse(config ParseConfig, proxy string) (P.Proxy, error) { if !hasPrefix(proxy, p.GetPrefixes()) { return P.Proxy{}, fmt.Errorf("%w: %s", ErrInvalidPrefix, proxy) } @@ -112,6 +112,7 @@ func (p *VmessParser) Parse(proxy string) (P.Proxy, error) { UUID: vmess.Id, AlterID: aid, Cipher: vmess.Scy, + UDP: config.UseUDP, } if len(alpn) > 0 { diff --git a/server/static/index.html b/server/static/index.html index 36ca44a..8c70247 100644 --- a/server/static/index.html +++ b/server/static/index.html @@ -1,5 +1,5 @@ - + @@ -28,10 +28,38 @@ height: 25px; width: 25px; } + + /* 主题切换按钮样式 */ + .theme-toggle { + position: fixed; + top: 20px; + right: 20px; + z-index: 1000; + border: none; + border-radius: 50%; + width: 50px; + height: 50px; + font-size: 20px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + } + + .theme-toggle:hover { + transform: scale(1.1); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + } - + + + +

sub2clash

@@ -104,6 +132,11 @@
+ +
+ + +
@@ -145,7 +178,7 @@
-
-