Skip to content

Commit

Permalink
自定义 urltest / selector
Browse files Browse the repository at this point in the history
  • Loading branch information
xmdhs committed Nov 17, 2023
1 parent c7fc002 commit 655cdd8
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 7 deletions.
16 changes: 15 additions & 1 deletion frontend.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,22 @@
<br />
<details>
<summary>更多设置</summary>
<br />
<hr />
<details>
<summary>配置文件模板</summary>
<hr />
<span>可通过设置 urltest / selector 的 outbounds,来自定义生成配置文件后其中包含的节点。</span>
<span>类似:</span>
<pre>{
"tag": "selector",
"type": "selector",
"outbounds": [
"include: 新加坡",
"exclude: 香港"
]
}</pre>
<span>均可以使用正则筛选</span>
<br />
<label>
<input type="checkbox" role="switch" v-model="checkbox">
配置文件模板直链
Expand All @@ -63,6 +76,7 @@
</details>
<details>
<summary>自定义 urltest / selector</summary>
<hr />
<div class="grid">
<label>
tag
Expand Down
100 changes: 94 additions & 6 deletions service/arg.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http"
"regexp"
"strconv"
"strings"

"log/slog"

Expand Down Expand Up @@ -70,6 +71,10 @@ func MakeConfig(cxt context.Context, c *http.Client, frontendByte []byte, l *slo
}
b = nb
}
b, err = configUrlTestParser(b)
if err != nil {
return nil, fmt.Errorf("MakeConfig: %w", err)
}
return b, nil
}

Expand All @@ -91,11 +96,7 @@ func customUrlTest(config []byte, u []model.UrlTestArg) ([]byte, error) {
})

for _, v := range u {
nt, err := filter(v.Include, tags, true)
if err != nil {
return nil, fmt.Errorf("customUrlTest: %w", err)
}
nt, err = filter(v.Exclude, nt, false)
nt, err := filterTags(tags, v.Include, v.Exclude)
if err != nil {
return nil, fmt.Errorf("customUrlTest: %w", err)
}
Expand All @@ -122,14 +123,30 @@ func customUrlTest(config []byte, u []model.UrlTestArg) ([]byte, error) {
return nil, fmt.Errorf("customUrlTest: %w", err)
}
}
return jsonFormatting(config), nil
}

func jsonFormatting(config []byte) []byte {
var a any
lo.Must0(json.Unmarshal(config, &a))
bw := bytes.NewBuffer(nil)
jw := json.NewEncoder(bw)
jw.SetEscapeHTML(false)
jw.SetIndent("", " ")
lo.Must0(jw.Encode(a))
return bw.Bytes(), nil
return bw.Bytes()
}

func filterTags(tags []string, include, exclude string) ([]string, error) {
nt, err := filter(include, tags, true)
if err != nil {
return nil, fmt.Errorf("filterTags: %w", err)
}
nt, err = filter(exclude, nt, false)
if err != nil {
return nil, fmt.Errorf("filterTags: %w", err)
}
return nt, nil
}

func filter(reg string, tags []string, need bool) ([]string, error) {
Expand All @@ -146,3 +163,74 @@ func filter(reg string, tags []string, need bool) ([]string, error) {
})
return tag, nil
}

func configUrlTestParser(config []byte) ([]byte, error) {
r := gjson.GetBytes(config, `outbounds.#(outbounds)#`)
if !r.Exists() {
return nil, fmt.Errorf("customUrlTest: %w", ErrJson)
}
setMap := map[string][]string{}

tags := []string{}
gjson.GetBytes(config, `outbounds.#(tag=="urltest").outbounds`).ForEach(func(key, value gjson.Result) bool {
tags = append(tags, value.String())
return true
})

for _, value := range r.Array() {
tl, err := urlTestParser(value, tags)
if err != nil {
return nil, fmt.Errorf("customUrlTest: %w", err)
}
if tl == nil {
continue
}
tagName := value.Get("tag").String()
setMap[tagName] = tl
}

if len(setMap) == 0 {
return config, nil
}

for k, v := range setMap {
b, err := json.Marshal(k)
if err != nil {
return nil, fmt.Errorf("customUrlTest: %w", err)
}
config, err = sjson.SetBytes(config, `outbounds.#(tag==`+string(b)+`).outbounds`, v)
if err != nil {
return nil, fmt.Errorf("customUrlTest: %w", err)
}
}
return jsonFormatting(config), nil
}

func urlTestParser(value gjson.Result, tags []string) ([]string, error) {
out := value.Get("outbounds")
var include, exclude string
extTag := []string{}

out.ForEach(func(key, value gjson.Result) bool {
s := value.String()
if strings.HasPrefix(s, "include: ") {
include = strings.TrimPrefix(s, "include: ")
} else if strings.HasPrefix(s, "exclude: ") {
exclude = strings.TrimPrefix(s, "exclude: ")
} else {
extTag = append(extTag, s)
}
return true
})

if include == "" && exclude == "" {
return nil, nil
}

tags, err := filterTags(tags, include, exclude)
if err != nil {
return nil, fmt.Errorf("urlTestParser: %w", err)
}

return lo.Union(append(tags, extTag...)), nil
}

0 comments on commit 655cdd8

Please sign in to comment.