forked from mirror/serenity
Append subscription groups to other groups
This commit is contained in:
parent
774257d003
commit
646e6b13ac
@ -203,5 +203,5 @@ func closeMonitor(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
log.Fatal("sing-box did not close!")
|
log.Fatal("serenity did not close!")
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package template
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
M "github.com/sagernet/serenity/common/metadata"
|
M "github.com/sagernet/serenity/common/metadata"
|
||||||
@ -129,95 +130,128 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio
|
|||||||
subscriptionGroups = make(map[string][]boxOption.Outbound)
|
subscriptionGroups = make(map[string][]boxOption.Outbound)
|
||||||
)
|
)
|
||||||
for _, extraGroup := range t.groups {
|
for _, extraGroup := range t.groups {
|
||||||
myFilter := func(outboundTag string) bool {
|
|
||||||
if len(extraGroup.filter) > 0 {
|
|
||||||
if !common.Any(extraGroup.filter, func(it *regexp.Regexp) bool {
|
|
||||||
return it.MatchString(outboundTag)
|
|
||||||
}) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(extraGroup.exclude) > 0 {
|
|
||||||
if common.Any(extraGroup.exclude, func(it *regexp.Regexp) bool {
|
|
||||||
return it.MatchString(outboundTag)
|
|
||||||
}) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if extraGroup.Target != option.ExtraGroupTargetSubscription {
|
if extraGroup.Target != option.ExtraGroupTargetSubscription {
|
||||||
extraTags := common.Filter(common.FlatMap(subscriptions, func(it *subscription.Subscription) []string {
|
continue
|
||||||
return common.Map(it.Servers, outboundToString)
|
}
|
||||||
}), myFilter)
|
tmpl := template.New("tag")
|
||||||
if len(extraTags) == 0 {
|
if extraGroup.TagPerSubscription != "" {
|
||||||
continue
|
_, err := tmpl.Parse(extraGroup.TagPerSubscription)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "parse `tag_per_subscription`: ", extraGroup.TagPerSubscription)
|
||||||
}
|
}
|
||||||
groupOutbound := boxOption.Outbound{
|
} else {
|
||||||
Tag: extraGroup.Tag,
|
common.Must1(tmpl.Parse("{{ .tag }} ({{ .subscription_name }})"))
|
||||||
|
}
|
||||||
|
var outboundTags []string
|
||||||
|
for _, it := range subscriptions {
|
||||||
|
subscriptionTags := common.Filter(common.Map(it.Servers, outboundToString), func(outboundTag string) bool {
|
||||||
|
if len(extraGroup.filter) > 0 {
|
||||||
|
if !common.Any(extraGroup.filter, func(it *regexp.Regexp) bool {
|
||||||
|
return it.MatchString(outboundTag)
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(extraGroup.exclude) > 0 {
|
||||||
|
if common.Any(extraGroup.exclude, func(it *regexp.Regexp) bool {
|
||||||
|
return it.MatchString(outboundTag)
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
var tagPerSubscription string
|
||||||
|
if len(outboundTags) == 0 && len(subscriptions) == 1 {
|
||||||
|
tagPerSubscription = extraGroup.Tag
|
||||||
|
} else {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
err := tmpl.Execute(&buffer, map[string]interface{}{
|
||||||
|
"tag": extraGroup.Tag,
|
||||||
|
"subscription_name": it.Name,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "generate tag for extra group: tag=", extraGroup.Tag, ", subscription=", it.Name)
|
||||||
|
}
|
||||||
|
tagPerSubscription = buffer.String()
|
||||||
|
}
|
||||||
|
groupOutboundPerSubscription := boxOption.Outbound{
|
||||||
|
Tag: tagPerSubscription,
|
||||||
Type: extraGroup.Type,
|
Type: extraGroup.Type,
|
||||||
}
|
}
|
||||||
switch extraGroup.Type {
|
switch extraGroup.Type {
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
selectorOptions := common.PtrValueOrDefault(extraGroup.CustomSelector)
|
selectorOptions := common.PtrValueOrDefault(extraGroup.CustomSelector)
|
||||||
groupOutbound.Options = &selectorOptions
|
groupOutboundPerSubscription.Options = &selectorOptions
|
||||||
selectorOptions.Outbounds = append(selectorOptions.Outbounds, extraTags...)
|
selectorOptions.Outbounds = common.Uniq(append(selectorOptions.Outbounds, subscriptionTags...))
|
||||||
case C.TypeURLTest:
|
if len(selectorOptions.Outbounds) == 0 {
|
||||||
urltestOptions := common.PtrValueOrDefault(extraGroup.CustomURLTest)
|
|
||||||
groupOutbound.Options = &urltestOptions
|
|
||||||
urltestOptions.Outbounds = append(urltestOptions.Outbounds, extraTags...)
|
|
||||||
}
|
|
||||||
if extraGroup.Target == option.ExtraGroupTargetDefault {
|
|
||||||
defaultGroups = append(defaultGroups, groupOutbound)
|
|
||||||
} else {
|
|
||||||
globalGroups = append(globalGroups, groupOutbound)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tmpl := template.New("tag")
|
|
||||||
if extraGroup.TagPerSubscription != "" {
|
|
||||||
_, err := tmpl.Parse(extraGroup.TagPerSubscription)
|
|
||||||
if err != nil {
|
|
||||||
return E.Cause(err, "parse `tag_per_subscription`: ", extraGroup.TagPerSubscription)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
common.Must1(tmpl.Parse("{{ .tag }} ({{ .subscription_name }})"))
|
|
||||||
}
|
|
||||||
var outboundTags []string
|
|
||||||
for _, it := range subscriptions {
|
|
||||||
subscriptionTags := common.Filter(common.Map(it.Servers, outboundToString), myFilter)
|
|
||||||
if len(subscriptionTags) == 0 {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var tagPerSubscription string
|
case C.TypeURLTest:
|
||||||
if len(outboundTags) == 0 && len(subscriptions) == 1 {
|
urltestOptions := common.PtrValueOrDefault(extraGroup.CustomURLTest)
|
||||||
tagPerSubscription = extraGroup.Tag
|
groupOutboundPerSubscription.Options = &urltestOptions
|
||||||
} else {
|
urltestOptions.Outbounds = common.Uniq(append(urltestOptions.Outbounds, subscriptionTags...))
|
||||||
var buffer bytes.Buffer
|
if len(urltestOptions.Outbounds) == 0 {
|
||||||
err := tmpl.Execute(&buffer, map[string]interface{}{
|
continue
|
||||||
"tag": extraGroup.Tag,
|
|
||||||
"subscription_name": it.Name,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return E.Cause(err, "generate tag for extra group: tag=", extraGroup.Tag, ", subscription=", it.Name)
|
|
||||||
}
|
|
||||||
tagPerSubscription = buffer.String()
|
|
||||||
}
|
}
|
||||||
groupOutboundPerSubscription := boxOption.Outbound{
|
|
||||||
Tag: tagPerSubscription,
|
|
||||||
Type: extraGroup.Type,
|
|
||||||
}
|
|
||||||
switch extraGroup.Type {
|
|
||||||
case C.TypeSelector:
|
|
||||||
selectorOptions := common.PtrValueOrDefault(extraGroup.CustomSelector)
|
|
||||||
groupOutboundPerSubscription.Options = &selectorOptions
|
|
||||||
selectorOptions.Outbounds = append(selectorOptions.Outbounds, subscriptionTags...)
|
|
||||||
case C.TypeURLTest:
|
|
||||||
urltestOptions := common.PtrValueOrDefault(extraGroup.CustomURLTest)
|
|
||||||
groupOutboundPerSubscription.Options = &urltestOptions
|
|
||||||
urltestOptions.Outbounds = append(urltestOptions.Outbounds, subscriptionTags...)
|
|
||||||
}
|
|
||||||
subscriptionGroups[it.Name] = append(subscriptionGroups[it.Name], groupOutboundPerSubscription)
|
|
||||||
}
|
}
|
||||||
|
subscriptionGroups[it.Name] = append(subscriptionGroups[it.Name], groupOutboundPerSubscription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, extraGroup := range t.groups {
|
||||||
|
if extraGroup.Target == option.ExtraGroupTargetSubscription {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
extraTags := groupTags
|
||||||
|
for _, group := range subscriptionGroups {
|
||||||
|
extraTags = append(extraTags, common.Map(group, outboundToString)...)
|
||||||
|
}
|
||||||
|
sort.Strings(extraTags)
|
||||||
|
if len(extraTags) == 0 || extraGroup.filter != nil || extraGroup.exclude != nil {
|
||||||
|
extraTags = append(extraTags, common.Filter(common.FlatMap(subscriptions, func(it *subscription.Subscription) []string {
|
||||||
|
return common.Map(it.Servers, outboundToString)
|
||||||
|
}), func(outboundTag string) bool {
|
||||||
|
if len(extraGroup.filter) > 0 {
|
||||||
|
if !common.Any(extraGroup.filter, func(it *regexp.Regexp) bool {
|
||||||
|
return it.MatchString(outboundTag)
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(extraGroup.exclude) > 0 {
|
||||||
|
if common.Any(extraGroup.exclude, func(it *regexp.Regexp) bool {
|
||||||
|
return it.MatchString(outboundTag)
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})...)
|
||||||
|
}
|
||||||
|
groupOutbound := boxOption.Outbound{
|
||||||
|
Tag: extraGroup.Tag,
|
||||||
|
Type: extraGroup.Type,
|
||||||
|
}
|
||||||
|
switch extraGroup.Type {
|
||||||
|
case C.TypeSelector:
|
||||||
|
selectorOptions := common.PtrValueOrDefault(extraGroup.CustomSelector)
|
||||||
|
groupOutbound.Options = &selectorOptions
|
||||||
|
selectorOptions.Outbounds = common.Uniq(append(selectorOptions.Outbounds, extraTags...))
|
||||||
|
if len(selectorOptions.Outbounds) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case C.TypeURLTest:
|
||||||
|
urltestOptions := common.PtrValueOrDefault(extraGroup.CustomURLTest)
|
||||||
|
groupOutbound.Options = &urltestOptions
|
||||||
|
urltestOptions.Outbounds = common.Uniq(append(urltestOptions.Outbounds, extraTags...))
|
||||||
|
if len(urltestOptions.Outbounds) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if extraGroup.Target == option.ExtraGroupTargetDefault {
|
||||||
|
defaultGroups = append(defaultGroups, groupOutbound)
|
||||||
|
} else {
|
||||||
|
globalGroups = append(globalGroups, groupOutbound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +272,6 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio
|
|||||||
}
|
}
|
||||||
options.Outbounds = groupJoin(options.Outbounds, defaultTag, false, groupTags...)
|
options.Outbounds = groupJoin(options.Outbounds, defaultTag, false, groupTags...)
|
||||||
options.Outbounds = groupJoin(options.Outbounds, defaultTag, false, globalOutboundTags...)
|
options.Outbounds = groupJoin(options.Outbounds, defaultTag, false, globalOutboundTags...)
|
||||||
|
|
||||||
options.Outbounds = append(options.Outbounds, allGroupOutbounds...)
|
options.Outbounds = append(options.Outbounds, allGroupOutbounds...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user