mirror of
https://github.com/nitezs/sub2sing-box.git
synced 2024-12-23 11:24:43 -05:00
⚡️ Improve
This commit is contained in:
parent
5afb06bdce
commit
89bb0d03e0
@ -4,8 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
C "sub2sing-box/constant"
|
||||
"sub2sing-box/util"
|
||||
)
|
||||
|
||||
type _Outbound struct {
|
||||
@ -83,17 +83,41 @@ func (h *Outbound) MarshalJSON() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := util.MergeAndMarshal(struct {
|
||||
Type string `json:"type"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
}{
|
||||
Type: h.Type,
|
||||
Tag: h.Tag,
|
||||
}, rawOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
result := make(map[string]any)
|
||||
result["type"] = h.Type
|
||||
result["tag"] = h.Tag
|
||||
optsValue := reflect.ValueOf(rawOptions).Elem()
|
||||
optsType := optsValue.Type()
|
||||
for i := 0; i < optsType.NumField(); i++ {
|
||||
field := optsValue.Field(i)
|
||||
fieldType := optsType.Field(i)
|
||||
if fieldType.Anonymous {
|
||||
embeddedFields := reflect.ValueOf(field.Interface())
|
||||
if field.Kind() == reflect.Struct {
|
||||
for j := 0; j < embeddedFields.NumField(); j++ {
|
||||
embeddedField := embeddedFields.Field(j)
|
||||
embeddedFieldType := embeddedFields.Type().Field(j)
|
||||
processField(embeddedField, embeddedFieldType, result)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
processField(field, fieldType, result)
|
||||
}
|
||||
}
|
||||
return []byte(result), nil
|
||||
return json.Marshal(result)
|
||||
}
|
||||
|
||||
func processField(field reflect.Value, fieldType reflect.StructField, result map[string]any) {
|
||||
jsonTag := fieldType.Tag.Get("json")
|
||||
if jsonTag == "-" {
|
||||
return
|
||||
}
|
||||
tagParts := strings.Split(jsonTag, ",")
|
||||
tagName := tagParts[0]
|
||||
if len(tagParts) > 1 && tagParts[1] == "omitempty" && field.IsZero() {
|
||||
return
|
||||
}
|
||||
result[tagName] = field.Interface()
|
||||
}
|
||||
|
||||
func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||
|
@ -9,11 +9,9 @@ type ParseError struct {
|
||||
type ParseErrorType string
|
||||
|
||||
const (
|
||||
ErrInvalidPrefix ParseErrorType = "invalid url prefix"
|
||||
ErrInvalidStruct ParseErrorType = "invalid struct"
|
||||
ErrInvalidPort ParseErrorType = "invalid port number"
|
||||
ErrCannotParseParams ParseErrorType = "cannot parse query parameters"
|
||||
ErrInvalidBase64 ParseErrorType = "invalid base64"
|
||||
ErrInvalidPrefix ParseErrorType = "invalid url prefix"
|
||||
ErrInvalidStruct ParseErrorType = "invalid struct"
|
||||
ErrInvalidPort ParseErrorType = "invalid port number"
|
||||
)
|
||||
|
||||
func (e *ParseError) Error() string {
|
||||
|
@ -72,6 +72,8 @@ func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
||||
Raw: proxy,
|
||||
}
|
||||
}
|
||||
method := methodAndPass[0]
|
||||
password := methodAndPass[1]
|
||||
|
||||
query := link.Query()
|
||||
pluginStr := query.Get("plugin")
|
||||
@ -99,8 +101,8 @@ func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
||||
Server: server,
|
||||
ServerPort: port,
|
||||
},
|
||||
Method: methodAndPass[0],
|
||||
Password: methodAndPass[1],
|
||||
Method: method,
|
||||
Password: password,
|
||||
Plugin: plugin,
|
||||
PluginOptions: options,
|
||||
},
|
||||
|
@ -78,10 +78,6 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
||||
ALPN: alpn,
|
||||
ServerName: sni,
|
||||
Insecure: insecureBool,
|
||||
UTLS: &model.OutboundUTLSOptions{
|
||||
Enabled: enableUTLS,
|
||||
Fingerprint: fp,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -93,10 +89,6 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
||||
ALPN: alpn,
|
||||
ServerName: sni,
|
||||
Insecure: insecureBool,
|
||||
UTLS: &model.OutboundUTLSOptions{
|
||||
Enabled: enableUTLS,
|
||||
Fingerprint: fp,
|
||||
},
|
||||
Reality: &model.OutboundRealityOptions{
|
||||
Enabled: true,
|
||||
PublicKey: pbk,
|
||||
@ -141,7 +133,7 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
||||
hosts, err := url.QueryUnescape(host)
|
||||
if err != nil {
|
||||
return model.Outbound{}, &ParseError{
|
||||
Type: ErrCannotParseParams,
|
||||
Type: ErrInvalidStruct,
|
||||
Raw: proxy,
|
||||
Message: err.Error(),
|
||||
}
|
||||
@ -153,5 +145,13 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if enableUTLS {
|
||||
result.VLESSOptions.OutboundTLSOptionsContainer.TLS.UTLS = &model.OutboundUTLSOptions{
|
||||
Enabled: enableUTLS,
|
||||
Fingerprint: fp,
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func ParseVmess(proxy string) (model.Outbound, error) {
|
||||
proxy = strings.TrimPrefix(proxy, constant.VMessPrefix)
|
||||
base64, err := util.DecodeBase64(proxy)
|
||||
if err != nil {
|
||||
return model.Outbound{}, &ParseError{Type: ErrInvalidBase64, Raw: proxy, Message: err.Error()}
|
||||
return model.Outbound{}, &ParseError{Type: ErrInvalidStruct, Raw: proxy, Message: err.Error()}
|
||||
}
|
||||
|
||||
var vmess model.VmessJson
|
||||
|
@ -1,78 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func MergeAndMarshal(s1, s2 any) (string, error) {
|
||||
merged, err := mergeStructs(s1, s2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
jsonBytes, err := json.Marshal(merged)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonBytes), nil
|
||||
}
|
||||
|
||||
func mergeStructs(s1, s2 any) (any, error) {
|
||||
v1 := reflect.ValueOf(s1)
|
||||
v2 := reflect.ValueOf(s2)
|
||||
|
||||
if v1.Kind() == reflect.Pointer {
|
||||
v1 = v1.Elem()
|
||||
}
|
||||
if v2.Kind() == reflect.Pointer {
|
||||
v2 = v2.Elem()
|
||||
}
|
||||
|
||||
if v1.Kind() != reflect.Struct || v2.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("both arguments must be structs")
|
||||
}
|
||||
|
||||
t1 := v1.Type()
|
||||
t2 := v2.Type()
|
||||
|
||||
var fields []reflect.StructField
|
||||
var fieldsSet = make(map[string]reflect.Type)
|
||||
for i := 0; i < t1.NumField(); i++ {
|
||||
field := t1.Field(i)
|
||||
fields = append(fields, field)
|
||||
fieldsSet[field.Name] = field.Type
|
||||
}
|
||||
|
||||
for i := 0; i < t2.NumField(); i++ {
|
||||
field := t2.Field(i)
|
||||
if existingType, ok := fieldsSet[field.Name]; ok {
|
||||
if existingType != field.Type {
|
||||
return nil, fmt.Errorf("field %s has conflicting types: %s and %s", field.Name, existingType, field.Type)
|
||||
}
|
||||
} else {
|
||||
fields = append(fields, field)
|
||||
fieldsSet[field.Name] = field.Type
|
||||
}
|
||||
}
|
||||
|
||||
newType := reflect.StructOf(fields)
|
||||
|
||||
newValue := reflect.New(newType).Elem()
|
||||
|
||||
for i := 0; i < t1.NumField(); i++ {
|
||||
valueField := newValue.FieldByName(t1.Field(i).Name)
|
||||
if valueField.IsValid() {
|
||||
valueField.Set(v1.Field(i))
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < t2.NumField(); i++ {
|
||||
valueField := newValue.FieldByName(t2.Field(i).Name)
|
||||
if valueField.IsValid() {
|
||||
valueField.Set(v2.Field(i))
|
||||
}
|
||||
}
|
||||
|
||||
return newValue.Interface(), nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user