summaryrefslogtreecommitdiff
path: root/plugin/plaintext/common_out.go
diff options
context:
space:
mode:
authorloyalsoldier <[email protected]>2021-08-27 18:27:16 +0800
committerloyalsoldier <[email protected]>2021-08-29 20:09:57 +0800
commit85a343aca99d864c517f13cd3169ebcc910ec0d8 (patch)
treeeccfd3680d9dc6e22f265a9525dccac85902c2ab /plugin/plaintext/common_out.go
parent2b32e8845d9e55b6c23ebb41bd0f382100094386 (diff)
Refactor: use plugin architecture to support multiple I/O formats
Diffstat (limited to 'plugin/plaintext/common_out.go')
-rw-r--r--plugin/plaintext/common_out.go170
1 files changed, 170 insertions, 0 deletions
diff --git a/plugin/plaintext/common_out.go b/plugin/plaintext/common_out.go
new file mode 100644
index 00000000..ff4ab63b
--- /dev/null
+++ b/plugin/plaintext/common_out.go
@@ -0,0 +1,170 @@
+package plaintext
+
+import (
+ "bytes"
+ "encoding/json"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+
+ "github.com/Loyalsoldier/geoip/lib"
+)
+
+var (
+ defaultOutputDirForTextOut = filepath.Join("./", "output", "text")
+ defaultOutputDirForClashRuleSetClassicalOut = filepath.Join("./", "output", "clash", "classical")
+ defaultOutputDirForClashRuleSetIPCIDROut = filepath.Join("./", "output", "clash", "ipcidr")
+ defaultOutputDirForSurgeRuleSetOut = filepath.Join("./", "output", "surge")
+)
+
+type textOut struct {
+ Type string
+ Action lib.Action
+ Description string
+ OutputDir string
+ Want []string
+ OnlyIPType lib.IPType
+}
+
+func newTextOut(iType string, action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
+ var tmp struct {
+ OutputDir string `json:"outputDir"`
+ Want []string `json:"wantedList"`
+ OnlyIPType lib.IPType `json:"onlyIPType"`
+ }
+
+ if len(data) > 0 {
+ if err := json.Unmarshal(data, &tmp); err != nil {
+ return nil, err
+ }
+ }
+
+ 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
+ }
+ }
+
+ return &textOut{
+ Type: iType,
+ Action: action,
+ Description: descTextOut,
+ OutputDir: tmp.OutputDir,
+ Want: tmp.Want,
+ OnlyIPType: tmp.OnlyIPType,
+ }, nil
+}
+
+func (t *textOut) marshalBytes(entry *lib.Entry) ([]byte, error) {
+ var err error
+
+ var entryCidr []string
+ switch t.OnlyIPType {
+ case lib.IPv4:
+ entryCidr, err = entry.MarshalText(lib.IgnoreIPv6)
+ case lib.IPv6:
+ entryCidr, err = entry.MarshalText(lib.IgnoreIPv4)
+ default:
+ entryCidr, err = entry.MarshalText()
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ var buf bytes.Buffer
+ switch t.Type {
+ case typeTextOut:
+ err = t.marshalBytesForTextOut(&buf, entryCidr)
+ case typeClashRuleSetClassicalOut:
+ err = t.marshalBytesForClashRuleSetClassicalOut(&buf, entryCidr)
+ case typeClashRuleSetIPCIDROut:
+ err = t.marshalBytesForClashRuleSetIPCIDROut(&buf, entryCidr)
+ case typeSurgeRuleSetOut:
+ err = t.marshalBytesForSurgeRuleSetOut(&buf, entryCidr)
+ default:
+ return nil, lib.ErrNotSupportedFormat
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+func (t *textOut) marshalBytesForTextOut(buf *bytes.Buffer, entryCidr []string) error {
+ for _, cidr := range entryCidr {
+ buf.WriteString(cidr)
+ buf.WriteString("\n")
+ }
+ return nil
+}
+
+func (t *textOut) marshalBytesForClashRuleSetClassicalOut(buf *bytes.Buffer, entryCidr []string) error {
+ buf.WriteString("payload:\n")
+ for _, cidr := range entryCidr {
+ ip, _, err := net.ParseCIDR(cidr)
+ if err != nil {
+ return err
+ }
+ if ip.To4() != nil {
+ buf.WriteString(" - IP-CIDR,")
+ } else {
+ buf.WriteString(" - IP-CIDR6,")
+ }
+ buf.WriteString(cidr)
+ buf.WriteString("\n")
+ }
+
+ return nil
+}
+
+func (t *textOut) marshalBytesForClashRuleSetIPCIDROut(buf *bytes.Buffer, entryCidr []string) error {
+ buf.WriteString("payload:\n")
+ for _, cidr := range entryCidr {
+ buf.WriteString(" - '")
+ buf.WriteString(cidr)
+ buf.WriteString("'\n")
+ }
+
+ return nil
+}
+
+func (t *textOut) marshalBytesForSurgeRuleSetOut(buf *bytes.Buffer, entryCidr []string) error {
+ for _, cidr := range entryCidr {
+ ip, _, err := net.ParseCIDR(cidr)
+ if err != nil {
+ return err
+ }
+ if ip.To4() != nil {
+ buf.WriteString("IP-CIDR,")
+ } else {
+ buf.WriteString("IP-CIDR6,")
+ }
+ buf.WriteString(cidr)
+ buf.WriteString("\n")
+ }
+
+ return nil
+}
+
+func (t *textOut) writeFile(filename string, data []byte) error {
+ if err := os.MkdirAll(t.OutputDir, 0755); err != nil {
+ return err
+ }
+
+ if err := os.WriteFile(filepath.Join(t.OutputDir, filename), data, 0644); err != nil {
+ return err
+ }
+
+ log.Printf("✅ [%s] %s --> %s", t.Type, filename, t.OutputDir)
+
+ return nil
+}