Files
sing-box-extended/parser/singbox/parser.go

59 lines
1.6 KiB
Go

package singbox
import (
"context"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/sagernet/sing/common/json/badjson"
)
type _SingBoxDocument struct {
Outbounds []option.Outbound `json:"outbounds"`
}
type SingBoxDocument _SingBoxDocument
func (o *SingBoxDocument) UnmarshalJSONContext(ctx context.Context, inputContent []byte) error {
var content badjson.JSONObject
err := content.UnmarshalJSONContext(ctx, inputContent)
if err != nil {
return err
}
outbounds, ok := content.Get("outbounds")
if !ok {
return E.New("missing outbounds in sing-box configuration")
}
var outs badjson.JSONArray
for i, outbound := range outbounds.(badjson.JSONArray) {
typeVal, loaded := outbound.(*badjson.JSONObject).Get("type")
if !loaded {
return E.New("missing type in outbound[", i, "]")
}
switch typeVal.(string) {
case C.TypeDirect, C.TypeBlock, C.TypeDNS, C.TypeSelector, C.TypeURLTest:
continue
default:
outs = append(outs, outbound)
}
}
content.Put("outbounds", outs)
inputContent, err = content.MarshalJSONContext(ctx)
if err != nil {
return err
}
return json.UnmarshalContext(ctx, inputContent, (*_SingBoxDocument)(o))
}
func ParseBoxSubscription(ctx context.Context, content string) ([]option.Outbound, error) {
options, err := json.UnmarshalExtendedContext[SingBoxDocument](ctx, []byte(content))
if err != nil {
return nil, err
}
if len(options.Outbounds) == 0 {
return nil, E.New("no servers found")
}
return options.Outbounds, nil
}