mirror of
https://github.com/bestnite/sub2clash.git
synced 2025-10-26 09:11:01 +00:00
Refactor subscription handling by removing SubConfig model, updating BuildSub function to use ConvertConfig, and enhancing Base64 decoding across parsers. Update routes and frontend to support new configuration format.
This commit is contained in:
@@ -13,11 +13,12 @@ func GetSupportProxyTypes(clashType ClashType) map[string]bool {
|
||||
supportProxyTypes := make(map[string]bool)
|
||||
|
||||
for _, parser := range parser.GetAllParsers() {
|
||||
if clashType == Clash {
|
||||
switch clashType {
|
||||
case Clash:
|
||||
if parser.SupportClash() {
|
||||
supportProxyTypes[parser.GetType()] = true
|
||||
}
|
||||
} else if clashType == ClashMeta {
|
||||
case ClashMeta:
|
||||
if parser.SupportMeta() {
|
||||
supportProxyTypes[parser.GetType()] = true
|
||||
}
|
||||
|
||||
92
model/convert_config.go
Normal file
92
model/convert_config.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/bestnite/sub2clash/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ConvertConfig struct {
|
||||
ClashType ClashType `json:"clashType" binding:"required"`
|
||||
Subs []string `json:"subscriptions" binding:""`
|
||||
Proxies []string `json:"proxies" binding:""`
|
||||
Refresh bool `json:"refresh" binding:""`
|
||||
Template string `json:"template" binding:""`
|
||||
RuleProviders []RuleProviderStruct `json:"ruleProviders" binding:""`
|
||||
Rules []RuleStruct `json:"rules" binding:""`
|
||||
AutoTest bool `json:"autoTest" binding:""`
|
||||
Lazy bool `json:"lazy" binding:""`
|
||||
Sort string `json:"sort" binding:""`
|
||||
Remove string `json:"remove" binding:""`
|
||||
Replace map[string]string `json:"replace" binding:""`
|
||||
NodeListMode bool `json:"nodeList" binding:""`
|
||||
IgnoreCountryGrooup bool `json:"ignoreCountryGroup" binding:""`
|
||||
UserAgent string `json:"userAgent" binding:""`
|
||||
UseUDP bool `json:"useUDP" binding:""`
|
||||
}
|
||||
|
||||
type RuleProviderStruct struct {
|
||||
Behavior string `json:"behavior" binding:""`
|
||||
Url string `json:"url" binding:""`
|
||||
Group string `json:"group" binding:""`
|
||||
Prepend bool `json:"prepend" binding:""`
|
||||
Name string `json:"name" binding:""`
|
||||
}
|
||||
|
||||
type RuleStruct struct {
|
||||
Rule string `json:"rule" binding:""`
|
||||
Prepend bool `json:"prepend" binding:""`
|
||||
}
|
||||
|
||||
func ParseConvertQuery(c *gin.Context) (ConvertConfig, error) {
|
||||
config := c.Param("config")
|
||||
queryBytes, err := utils.DecodeBase64(config, true)
|
||||
if err != nil {
|
||||
return ConvertConfig{}, errors.New("参数错误: " + err.Error())
|
||||
}
|
||||
var query ConvertConfig
|
||||
err = json.Unmarshal([]byte(queryBytes), &query)
|
||||
if err != nil {
|
||||
return ConvertConfig{}, errors.New("参数错误: " + err.Error())
|
||||
}
|
||||
if len(query.Subs) == 0 && len(query.Proxies) == 0 {
|
||||
return ConvertConfig{}, errors.New("参数错误: sub 和 proxy 不能同时为空")
|
||||
}
|
||||
if len(query.Subs) > 0 {
|
||||
for i := range query.Subs {
|
||||
if !strings.HasPrefix(query.Subs[i], "http") {
|
||||
return ConvertConfig{}, errors.New("参数错误: sub 格式错误")
|
||||
}
|
||||
if _, err := url.ParseRequestURI(query.Subs[i]); err != nil {
|
||||
return ConvertConfig{}, errors.New("参数错误: " + err.Error())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
query.Subs = nil
|
||||
}
|
||||
if query.Template != "" {
|
||||
if strings.HasPrefix(query.Template, "http") {
|
||||
uri, err := url.ParseRequestURI(query.Template)
|
||||
if err != nil {
|
||||
return ConvertConfig{}, err
|
||||
}
|
||||
query.Template = uri.String()
|
||||
}
|
||||
}
|
||||
if len(query.RuleProviders) > 0 {
|
||||
names := make(map[string]bool)
|
||||
for _, ruleProvider := range query.RuleProviders {
|
||||
if _, ok := names[ruleProvider.Name]; ok {
|
||||
return ConvertConfig{}, errors.New("参数错误: Rule-Provider 名称重复")
|
||||
}
|
||||
names[ruleProvider.Name] = true
|
||||
}
|
||||
} else {
|
||||
query.RuleProviders = nil
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type SubConfig struct {
|
||||
Sub string `form:"sub" binding:""`
|
||||
Subs []string `form:"-" binding:""`
|
||||
Proxy string `form:"proxy" binding:""`
|
||||
Proxies []string `form:"-" binding:""`
|
||||
Refresh bool `form:"refresh,default=false" binding:""`
|
||||
Template string `form:"template" binding:""`
|
||||
RuleProvider string `form:"ruleProvider" binding:""`
|
||||
RuleProviders []RuleProviderStruct `form:"-" binding:""`
|
||||
Rule string `form:"rule" binding:""`
|
||||
Rules []RuleStruct `form:"-" binding:""`
|
||||
AutoTest bool `form:"autoTest,default=false" binding:""`
|
||||
Lazy bool `form:"lazy,default=false" binding:""`
|
||||
Sort string `form:"sort" binding:""`
|
||||
Remove string `form:"remove" binding:""`
|
||||
Replace string `form:"replace" binding:""`
|
||||
ReplaceKeys []string `form:"-" binding:""`
|
||||
ReplaceTo []string `form:"-" binding:""`
|
||||
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 {
|
||||
Behavior string
|
||||
Url string
|
||||
Group string
|
||||
Prepend bool
|
||||
Name string
|
||||
}
|
||||
|
||||
type RuleStruct struct {
|
||||
Rule string
|
||||
Prepend bool
|
||||
}
|
||||
|
||||
func ParseSubQuery(c *gin.Context) (SubConfig, error) {
|
||||
var query SubConfig
|
||||
if err := c.ShouldBind(&query); err != nil {
|
||||
return SubConfig{}, errors.New("参数错误: " + err.Error())
|
||||
}
|
||||
if query.Sub == "" && query.Proxy == "" {
|
||||
return SubConfig{}, errors.New("参数错误: sub 和 proxy 不能同时为空")
|
||||
}
|
||||
if query.Sub != "" {
|
||||
query.Subs = strings.Split(query.Sub, ",")
|
||||
for i := range query.Subs {
|
||||
if !strings.HasPrefix(query.Subs[i], "http") {
|
||||
return SubConfig{}, errors.New("参数错误: sub 格式错误")
|
||||
}
|
||||
if _, err := url.ParseRequestURI(query.Subs[i]); err != nil {
|
||||
return SubConfig{}, errors.New("参数错误: " + err.Error())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
query.Subs = nil
|
||||
}
|
||||
if query.Proxy != "" {
|
||||
query.Proxies = strings.Split(query.Proxy, ",")
|
||||
} else {
|
||||
query.Proxies = nil
|
||||
}
|
||||
if query.Template != "" {
|
||||
if strings.HasPrefix(query.Template, "http") {
|
||||
uri, err := url.ParseRequestURI(query.Template)
|
||||
if err != nil {
|
||||
return SubConfig{}, err
|
||||
}
|
||||
query.Template = uri.String()
|
||||
}
|
||||
}
|
||||
if query.RuleProvider != "" {
|
||||
reg := regexp.MustCompile(`\[(.*?)\]`)
|
||||
ruleProviders := reg.FindAllStringSubmatch(query.RuleProvider, -1)
|
||||
for i := range ruleProviders {
|
||||
length := len(ruleProviders)
|
||||
parts := strings.Split(ruleProviders[length-i-1][1], ",")
|
||||
if len(parts) < 4 {
|
||||
return SubConfig{}, errors.New("参数错误: ruleProvider 格式错误")
|
||||
}
|
||||
u := parts[1]
|
||||
uri, err := url.ParseRequestURI(u)
|
||||
if err != nil {
|
||||
return SubConfig{}, errors.New("参数错误: " + err.Error())
|
||||
}
|
||||
u = uri.String()
|
||||
if len(parts) == 4 {
|
||||
hash := sha256.Sum224([]byte(u))
|
||||
parts = append(parts, hex.EncodeToString(hash[:]))
|
||||
}
|
||||
query.RuleProviders = append(
|
||||
query.RuleProviders, RuleProviderStruct{
|
||||
Behavior: parts[0],
|
||||
Url: u,
|
||||
Group: parts[2],
|
||||
Prepend: parts[3] == "true",
|
||||
Name: parts[4],
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
names := make(map[string]bool)
|
||||
for _, ruleProvider := range query.RuleProviders {
|
||||
if _, ok := names[ruleProvider.Name]; ok {
|
||||
return SubConfig{}, errors.New("参数错误: Rule-Provider 名称重复")
|
||||
}
|
||||
names[ruleProvider.Name] = true
|
||||
}
|
||||
} else {
|
||||
query.RuleProviders = nil
|
||||
}
|
||||
if query.Rule != "" {
|
||||
reg := regexp.MustCompile(`\[(.*?)\]`)
|
||||
rules := reg.FindAllStringSubmatch(query.Rule, -1)
|
||||
for i := range rules {
|
||||
length := len(rules)
|
||||
r := rules[length-1-i][1]
|
||||
strings.LastIndex(r, ",")
|
||||
parts := [2]string{}
|
||||
parts[0] = r[:strings.LastIndex(r, ",")]
|
||||
parts[1] = r[strings.LastIndex(r, ",")+1:]
|
||||
query.Rules = append(
|
||||
query.Rules, RuleStruct{
|
||||
Rule: parts[0],
|
||||
Prepend: parts[1] == "true",
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
query.Rules = nil
|
||||
}
|
||||
if strings.TrimSpace(query.Replace) != "" {
|
||||
reg := regexp.MustCompile(`\[<(.*?)>,<(.*?)>\]`)
|
||||
replaces := reg.FindAllStringSubmatch(query.Replace, -1)
|
||||
for i := range replaces {
|
||||
length := len(replaces[i])
|
||||
if length != 3 {
|
||||
return SubConfig{}, errors.New("参数错误: replace 格式错误")
|
||||
}
|
||||
query.ReplaceKeys = append(query.ReplaceKeys, replaces[i][1])
|
||||
query.ReplaceTo = append(query.ReplaceTo, replaces[i][2])
|
||||
}
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
Reference in New Issue
Block a user