summaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
authoropenai-code-agent[bot] <[email protected]>2026-04-28 17:44:10 +0000
committerGitHub <[email protected]>2026-04-28 17:44:10 +0000
commit60b366c1682009a246056aad7b4a9d30b2a3fd62 (patch)
treed4c233ca2baad5395159a5d25b704dda58529ea7 /plugin
parent9fc06ad2d090b76132859a61a04a1ff0437cc641 (diff)
refactor(plaintext): use functional options for text/json/clash/surge plugins
Co-authored-by: Loyalsoldier <[email protected]>
Diffstat (limited to 'plugin')
-rw-r--r--plugin/plaintext/clash_in.go4
-rw-r--r--plugin/plaintext/clash_out.go4
-rw-r--r--plugin/plaintext/common_out.go121
-rw-r--r--plugin/plaintext/json_in.go2
-rw-r--r--plugin/plaintext/surge_in.go2
-rw-r--r--plugin/plaintext/surge_out.go2
-rw-r--r--plugin/plaintext/text_in.go147
-rw-r--r--plugin/plaintext/text_out.go2
8 files changed, 213 insertions, 71 deletions
diff --git a/plugin/plaintext/clash_in.go b/plugin/plaintext/clash_in.go
index be77cc62..ae4f9a5b 100644
--- a/plugin/plaintext/clash_in.go
+++ b/plugin/plaintext/clash_in.go
@@ -21,14 +21,14 @@ const (
func init() {
lib.RegisterInputConfigCreator(TypeClashRuleSetClassicalIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
- return newTextIn(TypeClashRuleSetClassicalIn, DescClashRuleSetClassicalIn, action, data)
+ return NewTextInFromBytes(TypeClashRuleSetClassicalIn, DescClashRuleSetClassicalIn, action, data)
})
lib.RegisterInputConverter(TypeClashRuleSetClassicalIn, &TextIn{
Description: DescClashRuleSetClassicalIn,
})
lib.RegisterInputConfigCreator(TypeClashRuleSetIPCIDRIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
- return newTextIn(TypeClashRuleSetIPCIDRIn, DescClashRuleSetIPCIDRIn, action, data)
+ return NewTextInFromBytes(TypeClashRuleSetIPCIDRIn, DescClashRuleSetIPCIDRIn, action, data)
})
lib.RegisterInputConverter(TypeClashRuleSetIPCIDRIn, &TextIn{
Description: DescClashRuleSetIPCIDRIn,
diff --git a/plugin/plaintext/clash_out.go b/plugin/plaintext/clash_out.go
index e7a97f1b..36695cd0 100644
--- a/plugin/plaintext/clash_out.go
+++ b/plugin/plaintext/clash_out.go
@@ -21,14 +21,14 @@ const (
func init() {
lib.RegisterOutputConfigCreator(TypeClashRuleSetClassicalOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
- return newTextOut(TypeClashRuleSetClassicalOut, DescClashRuleSetClassicalOut, action, data)
+ return NewTextOutFromBytes(TypeClashRuleSetClassicalOut, DescClashRuleSetClassicalOut, action, data)
})
lib.RegisterOutputConverter(TypeClashRuleSetClassicalOut, &TextOut{
Description: DescClashRuleSetClassicalOut,
})
lib.RegisterOutputConfigCreator(TypeClashRuleSetIPCIDROut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
- return newTextOut(TypeClashRuleSetIPCIDROut, DescClashRuleSetIPCIDROut, action, data)
+ return NewTextOutFromBytes(TypeClashRuleSetIPCIDROut, DescClashRuleSetIPCIDROut, action, data)
})
lib.RegisterOutputConverter(TypeClashRuleSetIPCIDROut, &TextOut{
Description: DescClashRuleSetIPCIDROut,
diff --git a/plugin/plaintext/common_out.go b/plugin/plaintext/common_out.go
index cc7ba41e..eff912f7 100644
--- a/plugin/plaintext/common_out.go
+++ b/plugin/plaintext/common_out.go
@@ -7,6 +7,7 @@ import (
"net"
"os"
"path/filepath"
+ "strings"
"github.com/Loyalsoldier/geoip/lib"
)
@@ -32,7 +33,83 @@ type TextOut struct {
AddSuffixInLine string
}
-func newTextOut(iType string, iDesc string, action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
+func NewTextOut(iType string, iDesc string, action lib.Action, opts ...lib.OutputOption) lib.OutputConverter {
+ t := &TextOut{
+ Type: iType,
+ Action: action,
+ Description: iDesc,
+ OutputExt: ".txt",
+ }
+
+ switch iType {
+ case TypeTextOut:
+ t.OutputDir = defaultOutputDirForTextOut
+ case TypeClashRuleSetClassicalOut:
+ t.OutputDir = defaultOutputDirForClashRuleSetClassicalOut
+ case TypeClashRuleSetIPCIDROut:
+ t.OutputDir = defaultOutputDirForClashRuleSetIPCIDROut
+ case TypeSurgeRuleSetOut:
+ t.OutputDir = defaultOutputDirForSurgeRuleSetOut
+ }
+
+ for _, opt := range opts {
+ if opt != nil {
+ opt(t)
+ }
+ }
+
+ return t
+}
+
+func WithTextOutOutputDir(dir string) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ dir = strings.TrimSpace(dir)
+ if dir != "" {
+ c.(*TextOut).OutputDir = dir
+ }
+ }
+}
+
+func WithTextOutOutputExt(ext string) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ ext = strings.TrimSpace(ext)
+ if ext != "" {
+ c.(*TextOut).OutputExt = ext
+ }
+ }
+}
+
+func WithTextOutWantedList(lists []string) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ c.(*TextOut).Want = lists
+ }
+}
+
+func WithTextOutExcludedList(lists []string) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ c.(*TextOut).Exclude = lists
+ }
+}
+
+func WithTextOutOnlyIPType(onlyIPType lib.IPType) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ c.(*TextOut).OnlyIPType = onlyIPType
+ }
+}
+
+func WithTextOutAddPrefixInLine(prefix string) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ c.(*TextOut).AddPrefixInLine = prefix
+ }
+}
+
+func WithTextOutAddSuffixInLine(suffix string) lib.OutputOption {
+ return func(c lib.OutputConverter) {
+ c.(*TextOut).AddSuffixInLine = suffix
+ }
+}
+
+func NewTextOutFromBytes(iType string, iDesc string, action lib.Action, data []byte) (lib.OutputConverter, error) {
var tmp struct {
OutputDir string `json:"outputDir"`
OutputExt string `json:"outputExtension"`
@@ -50,36 +127,18 @@ func newTextOut(iType string, iDesc string, action lib.Action, data json.RawMess
}
}
- if tmp.OutputDir == "" {
- switch iType {
- case TypeTextOut:
- tmp.OutputDir = defaultOutputDirForTextOut
- case TypeClashRuleSetClassicalOut:
- tmp.OutputDir = defaultOutputDirForClashRuleSetClassicalOut
- case TypeClashRuleSetIPCIDROut:
- tmp.OutputDir = defaultOutputDirForClashRuleSetIPCIDROut
- case TypeSurgeRuleSetOut:
- tmp.OutputDir = defaultOutputDirForSurgeRuleSetOut
- }
- }
-
- if tmp.OutputExt == "" {
- tmp.OutputExt = ".txt"
- }
-
- return &TextOut{
- Type: iType,
- Action: action,
- Description: iDesc,
- OutputDir: tmp.OutputDir,
- OutputExt: tmp.OutputExt,
- Want: tmp.Want,
- Exclude: tmp.Exclude,
- OnlyIPType: tmp.OnlyIPType,
-
- AddPrefixInLine: tmp.AddPrefixInLine,
- AddSuffixInLine: tmp.AddSuffixInLine,
- }, nil
+ return NewTextOut(
+ iType,
+ iDesc,
+ action,
+ WithTextOutOutputDir(tmp.OutputDir),
+ WithTextOutOutputExt(tmp.OutputExt),
+ WithTextOutWantedList(tmp.Want),
+ WithTextOutExcludedList(tmp.Exclude),
+ WithTextOutOnlyIPType(tmp.OnlyIPType),
+ WithTextOutAddPrefixInLine(tmp.AddPrefixInLine),
+ WithTextOutAddSuffixInLine(tmp.AddSuffixInLine),
+ ), nil
}
func (t *TextOut) marshalBytes(entry *lib.Entry) ([]byte, error) {
diff --git a/plugin/plaintext/json_in.go b/plugin/plaintext/json_in.go
index a4643609..5ee355f9 100644
--- a/plugin/plaintext/json_in.go
+++ b/plugin/plaintext/json_in.go
@@ -13,7 +13,7 @@ const (
func init() {
lib.RegisterInputConfigCreator(TypeJSONIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
- return newTextIn(TypeJSONIn, DescJSONIn, action, data)
+ return NewTextInFromBytes(TypeJSONIn, DescJSONIn, action, data)
})
lib.RegisterInputConverter(TypeJSONIn, &TextIn{
diff --git a/plugin/plaintext/surge_in.go b/plugin/plaintext/surge_in.go
index 7621d0a1..e6250559 100644
--- a/plugin/plaintext/surge_in.go
+++ b/plugin/plaintext/surge_in.go
@@ -18,7 +18,7 @@ const (
func init() {
lib.RegisterInputConfigCreator(TypeSurgeRuleSetIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
- return newTextIn(TypeSurgeRuleSetIn, DescSurgeRuleSetIn, action, data)
+ return NewTextInFromBytes(TypeSurgeRuleSetIn, DescSurgeRuleSetIn, action, data)
})
lib.RegisterInputConverter(TypeSurgeRuleSetIn, &TextIn{
Description: DescSurgeRuleSetIn,
diff --git a/plugin/plaintext/surge_out.go b/plugin/plaintext/surge_out.go
index 8fe62fb4..78d57ae9 100644
--- a/plugin/plaintext/surge_out.go
+++ b/plugin/plaintext/surge_out.go
@@ -18,7 +18,7 @@ const (
func init() {
lib.RegisterOutputConfigCreator(TypeSurgeRuleSetOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
- return newTextOut(TypeSurgeRuleSetOut, DescSurgeRuleSetOut, action, data)
+ return NewTextOutFromBytes(TypeSurgeRuleSetOut, DescSurgeRuleSetOut, action, data)
})
lib.RegisterOutputConverter(TypeSurgeRuleSetOut, &TextOut{
Description: DescSurgeRuleSetOut,
diff --git a/plugin/plaintext/text_in.go b/plugin/plaintext/text_in.go
index a75b1b12..7a7b9c07 100644
--- a/plugin/plaintext/text_in.go
+++ b/plugin/plaintext/text_in.go
@@ -3,6 +3,7 @@ package plaintext
import (
"encoding/json"
"fmt"
+ "log"
"net/http"
"os"
"path/filepath"
@@ -19,14 +20,108 @@ const (
func init() {
lib.RegisterInputConfigCreator(TypeTextIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
- return newTextIn(TypeTextIn, DescTextIn, action, data)
+ return NewTextInFromBytes(TypeTextIn, DescTextIn, action, data)
})
lib.RegisterInputConverter(TypeTextIn, &TextIn{
Description: DescTextIn,
})
}
-func newTextIn(iType string, iDesc string, action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
+func NewTextIn(iType string, iDesc string, action lib.Action, opts ...lib.InputOption) lib.InputConverter {
+ t := &TextIn{
+ Type: iType,
+ Action: action,
+ Description: iDesc,
+ }
+
+ for _, opt := range opts {
+ if opt != nil {
+ opt(t)
+ }
+ }
+
+ return t
+}
+
+func WithTextInNameAndURI(name, uri string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ t := c.(*TextIn)
+ name = strings.TrimSpace(name)
+ uri = strings.TrimSpace(uri)
+ if (name == "" || uri == "") && strings.TrimSpace(t.InputDir) == "" {
+ log.Fatalf("❌ [type %s | action %s] missing inputDir or name", t.Type, t.Action)
+ }
+ t.Name = name
+ t.URI = uri
+ }
+}
+
+func WithTextInInputDir(dir string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ t := c.(*TextIn)
+ dir = strings.TrimSpace(dir)
+ if dir == "" && strings.TrimSpace(t.Name) == "" {
+ log.Fatalf("❌ [type %s | action %s] missing inputDir or name", t.Type, t.Action)
+ }
+ if dir != "" && (strings.TrimSpace(t.Name) != "" || strings.TrimSpace(t.URI) != "" || len(t.IPOrCIDR) > 0) {
+ log.Fatalf("❌ [type %s | action %s] inputDir is not allowed to be used with name or uri or ipOrCIDR", t.Type, t.Action)
+ }
+ t.InputDir = dir
+ }
+}
+
+func WithTextInIPOrCIDR(ipOrCIDR []string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ t := c.(*TextIn)
+ if t.Type != TypeTextIn && len(ipOrCIDR) > 0 {
+ log.Fatalf("❌ [type %s | action %s] ipOrCIDR is invalid for this input format", t.Type, t.Action)
+ }
+ t.IPOrCIDR = ipOrCIDR
+ }
+}
+
+func WithTextInWantedList(lists []string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ t := c.(*TextIn)
+ wantList := make(map[string]bool)
+ for _, want := range lists {
+ if want = strings.ToUpper(strings.TrimSpace(want)); want != "" {
+ wantList[want] = true
+ }
+ }
+ t.Want = wantList
+ }
+}
+
+func WithTextInOnlyIPType(onlyIPType lib.IPType) lib.InputOption {
+ return func(c lib.InputConverter) {
+ c.(*TextIn).OnlyIPType = onlyIPType
+ }
+}
+
+func WithTextInJSONPath(paths []string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ t := c.(*TextIn)
+ if t.Type == TypeJSONIn && len(paths) == 0 {
+ log.Fatalf("❌ [type %s | action %s] missing jsonPath", t.Type, t.Action)
+ }
+ t.JSONPath = paths
+ }
+}
+
+func WithTextInRemovePrefixesInLine(prefixes []string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ c.(*TextIn).RemovePrefixesInLine = prefixes
+ }
+}
+
+func WithTextInRemoveSuffixesInLine(suffixes []string) lib.InputOption {
+ return func(c lib.InputConverter) {
+ c.(*TextIn).RemoveSuffixesInLine = suffixes
+ }
+}
+
+func NewTextInFromBytes(iType string, iDesc string, action lib.Action, data []byte) (lib.InputConverter, error) {
var tmp struct {
Name string `json:"name"`
URI string `json:"uri"`
@@ -50,14 +145,6 @@ func newTextIn(iType string, iDesc string, action lib.Action, data json.RawMessa
}
}
- if iType != TypeTextIn && len(tmp.IPOrCIDR) > 0 {
- return nil, fmt.Errorf("❌ [type %s | action %s] ipOrCIDR is invalid for this input format", iType, action)
- }
-
- if iType == TypeJSONIn && len(tmp.JSONPath) == 0 {
- return nil, fmt.Errorf("❌ [type %s | action %s] missing jsonPath", iType, action)
- }
-
if tmp.InputDir == "" {
if tmp.Name == "" {
return nil, fmt.Errorf("❌ [type %s | action %s] missing inputDir or name", iType, action)
@@ -68,30 +155,26 @@ func newTextIn(iType string, iDesc string, action lib.Action, data json.RawMessa
} else if tmp.Name != "" || tmp.URI != "" || len(tmp.IPOrCIDR) > 0 {
return nil, fmt.Errorf("❌ [type %s | action %s] inputDir is not allowed to be used with name or uri or ipOrCIDR", iType, action)
}
-
- // Filter want list
- wantList := make(map[string]bool)
- for _, want := range tmp.Want {
- if want = strings.ToUpper(strings.TrimSpace(want)); want != "" {
- wantList[want] = true
- }
+ if iType != TypeTextIn && len(tmp.IPOrCIDR) > 0 {
+ return nil, fmt.Errorf("❌ [type %s | action %s] ipOrCIDR is invalid for this input format", iType, action)
+ }
+ if iType == TypeJSONIn && len(tmp.JSONPath) == 0 {
+ return nil, fmt.Errorf("❌ [type %s | action %s] missing jsonPath", iType, action)
}
- return &TextIn{
- Type: iType,
- Action: action,
- Description: iDesc,
- Name: tmp.Name,
- URI: tmp.URI,
- IPOrCIDR: tmp.IPOrCIDR,
- InputDir: tmp.InputDir,
- Want: wantList,
- OnlyIPType: tmp.OnlyIPType,
-
- JSONPath: tmp.JSONPath,
- RemovePrefixesInLine: tmp.RemovePrefixesInLine,
- RemoveSuffixesInLine: tmp.RemoveSuffixesInLine,
- }, nil
+ return NewTextIn(
+ iType,
+ iDesc,
+ action,
+ WithTextInNameAndURI(tmp.Name, tmp.URI),
+ WithTextInIPOrCIDR(tmp.IPOrCIDR),
+ WithTextInInputDir(tmp.InputDir),
+ WithTextInWantedList(tmp.Want),
+ WithTextInOnlyIPType(tmp.OnlyIPType),
+ WithTextInJSONPath(tmp.JSONPath),
+ WithTextInRemovePrefixesInLine(tmp.RemovePrefixesInLine),
+ WithTextInRemoveSuffixesInLine(tmp.RemoveSuffixesInLine),
+ ), nil
}
func (t *TextIn) GetType() string {
diff --git a/plugin/plaintext/text_out.go b/plugin/plaintext/text_out.go
index 06f4df63..a949e07f 100644
--- a/plugin/plaintext/text_out.go
+++ b/plugin/plaintext/text_out.go
@@ -16,7 +16,7 @@ const (
func init() {
lib.RegisterOutputConfigCreator(TypeTextOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
- return newTextOut(TypeTextOut, DescTextOut, action, data)
+ return NewTextOutFromBytes(TypeTextOut, DescTextOut, action, data)
})
lib.RegisterOutputConverter(TypeTextOut, &TextOut{
Description: DescTextOut,