mirror of
https://github.com/nitezs/sub2sing-box.git
synced 2024-12-23 15:04:41 -05:00
⚡️ Improve
This commit is contained in:
parent
5afb06bdce
commit
89bb0d03e0
@ -4,8 +4,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
C "sub2sing-box/constant"
|
C "sub2sing-box/constant"
|
||||||
"sub2sing-box/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type _Outbound struct {
|
type _Outbound struct {
|
||||||
@ -83,17 +83,41 @@ func (h *Outbound) MarshalJSON() ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
result, err := util.MergeAndMarshal(struct {
|
result := make(map[string]any)
|
||||||
Type string `json:"type"`
|
result["type"] = h.Type
|
||||||
Tag string `json:"tag,omitempty"`
|
result["tag"] = h.Tag
|
||||||
}{
|
optsValue := reflect.ValueOf(rawOptions).Elem()
|
||||||
Type: h.Type,
|
optsType := optsValue.Type()
|
||||||
Tag: h.Tag,
|
for i := 0; i < optsType.NumField(); i++ {
|
||||||
}, rawOptions)
|
field := optsValue.Field(i)
|
||||||
if err != nil {
|
fieldType := optsType.Field(i)
|
||||||
return nil, err
|
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 {
|
func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||||
|
@ -9,11 +9,9 @@ type ParseError struct {
|
|||||||
type ParseErrorType string
|
type ParseErrorType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ErrInvalidPrefix ParseErrorType = "invalid url prefix"
|
ErrInvalidPrefix ParseErrorType = "invalid url prefix"
|
||||||
ErrInvalidStruct ParseErrorType = "invalid struct"
|
ErrInvalidStruct ParseErrorType = "invalid struct"
|
||||||
ErrInvalidPort ParseErrorType = "invalid port number"
|
ErrInvalidPort ParseErrorType = "invalid port number"
|
||||||
ErrCannotParseParams ParseErrorType = "cannot parse query parameters"
|
|
||||||
ErrInvalidBase64 ParseErrorType = "invalid base64"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *ParseError) Error() string {
|
func (e *ParseError) Error() string {
|
||||||
|
@ -72,6 +72,8 @@ func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
|||||||
Raw: proxy,
|
Raw: proxy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
method := methodAndPass[0]
|
||||||
|
password := methodAndPass[1]
|
||||||
|
|
||||||
query := link.Query()
|
query := link.Query()
|
||||||
pluginStr := query.Get("plugin")
|
pluginStr := query.Get("plugin")
|
||||||
@ -99,8 +101,8 @@ func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
|||||||
Server: server,
|
Server: server,
|
||||||
ServerPort: port,
|
ServerPort: port,
|
||||||
},
|
},
|
||||||
Method: methodAndPass[0],
|
Method: method,
|
||||||
Password: methodAndPass[1],
|
Password: password,
|
||||||
Plugin: plugin,
|
Plugin: plugin,
|
||||||
PluginOptions: options,
|
PluginOptions: options,
|
||||||
},
|
},
|
||||||
|
@ -78,10 +78,6 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
Insecure: insecureBool,
|
Insecure: insecureBool,
|
||||||
UTLS: &model.OutboundUTLSOptions{
|
|
||||||
Enabled: enableUTLS,
|
|
||||||
Fingerprint: fp,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,10 +89,6 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
Insecure: insecureBool,
|
Insecure: insecureBool,
|
||||||
UTLS: &model.OutboundUTLSOptions{
|
|
||||||
Enabled: enableUTLS,
|
|
||||||
Fingerprint: fp,
|
|
||||||
},
|
|
||||||
Reality: &model.OutboundRealityOptions{
|
Reality: &model.OutboundRealityOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PublicKey: pbk,
|
PublicKey: pbk,
|
||||||
@ -141,7 +133,7 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
hosts, err := url.QueryUnescape(host)
|
hosts, err := url.QueryUnescape(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return model.Outbound{}, &ParseError{
|
return model.Outbound{}, &ParseError{
|
||||||
Type: ErrCannotParseParams,
|
Type: ErrInvalidStruct,
|
||||||
Raw: proxy,
|
Raw: proxy,
|
||||||
Message: err.Error(),
|
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
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ func ParseVmess(proxy string) (model.Outbound, error) {
|
|||||||
proxy = strings.TrimPrefix(proxy, constant.VMessPrefix)
|
proxy = strings.TrimPrefix(proxy, constant.VMessPrefix)
|
||||||
base64, err := util.DecodeBase64(proxy)
|
base64, err := util.DecodeBase64(proxy)
|
||||||
if err != nil {
|
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
|
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