summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoyalsoldier <[email protected]>2024-08-31 11:03:59 +0800
committerLoyalsoldier <[email protected]>2024-08-31 11:03:59 +0800
commitdeff06ac0f59751bb9857bc7d645b756b6133ddf (patch)
tree318880aad86a2223ed0cddfbc4f4283929861102
parentfca10e64304b331c56dafe307f4eddfb7614fbb2 (diff)
Feat: support to specify IP or CIDR in config file for text input format
-rw-r--r--configuration.md43
-rw-r--r--plugin/plaintext/common_in.go1
-rw-r--r--plugin/plaintext/text_in.go50
3 files changed, 84 insertions, 10 deletions
diff --git a/configuration.md b/configuration.md
index 2b225dd8..b25bf45d 100644
--- a/configuration.md
+++ b/configuration.md
@@ -570,10 +570,11 @@
- **type**:(必须)输入格式的名称
- **action**:(必须)操作类型,值为 `add`(添加 IP 地址)或 `remove`(移除 IP 地址)
- **args**:(必须)
- - **name**:类别名称。(不能与 `inputDir` 同时使用;需要与 `uri` 同时使用)
- - **uri**:纯文本 txt 文件路径,可为本地文件路径或远程 `http`、`https` 文件 URL。(不能与 `inputDir` 同时使用;需要与 `name` 同时使用)
- - **inputDir**:需要遍历的输入目录(不遍历子目录)。(遍历的文件名作为类别名称;不能与 `name` 和 `uri` 同时使用)
- - **wantedList**:(可选,数组)指定需要的类别/文件。(与 `inputDir` 同时使用)
+ - **name**:(可选)类别名称。(不能与 `inputDir` 同时使用;需要与 `uri` 或 `ipOrCIDR` 同时使用)
+ - **uri**:(可选)纯文本 txt 文件路径,可为本地文件路径或远程 `http`、`https` 文件 URL。(不能与 `inputDir` 同时使用;需要与 `name` 同时使用;可与 `ipOrCIDR` 同时使用)
+ - **ipOrCIDR**:(可选,数组)纯文本 IP 地址或 CIDR。(不能与 `inputDir` 同时使用;需要与 `name` 同时使用;可与 `uri` 同时使用)
+ - **inputDir**:(可选)需要遍历的输入目录(不遍历子目录)。(遍历的文件名作为类别名称;不能与 `name`、`uri` 和 `ipOrCIDR` 同时使用)
+ - **wantedList**:(可选,数组)指定需要的文件。(与 `inputDir` 同时使用)
- **onlyIPType**:(可选)只处理的 IP 地址类型,值为 `ipv4` 或 `ipv6`
- **removePrefixesInLine**:(可选,数组)每一行需要移除的字符串前缀
- **removeSuffixesInLine**:(可选,数组)每一行需要移除的字符串后缀
@@ -594,6 +595,40 @@
```jsonc
{
"type": "text",
+ "action": "add", // 添加 IP 地址
+ "args": {
+ "name": "cn",
+ "ipOrCIDR": ["1.0.0.1", "1.0.0.1/24"] // 添加 IP 或 CIDR 到 cn 类别
+ }
+}
+```
+
+```jsonc
+{
+ "type": "text",
+ "action": "remove", // 移除 IP 地址
+ "args": {
+ "name": "cn",
+ "ipOrCIDR": ["1.0.0.1", "1.0.0.1/24"] // 从 cn 类别移除 IP 或 CIDR
+ }
+}
+```
+
+```jsonc
+{
+ "type": "text",
+ "action": "add", // 添加 IP 地址
+ "args": {
+ "name": "cn",
+ "uri": "./cn.txt", // 读取本地文件 cn.txt 的 IPv4 和 IPv6 地址,并添加到 cn 类别中
+ "ipOrCIDR": ["1.0.0.1", "1.0.0.1/24"] // 添加 IP 或 CIDR 到 cn 类别
+ }
+}
+```
+
+```jsonc
+{
+ "type": "text",
"action": "add", // 添加 IP 地址
"args": {
"inputDir": "./text", // 遍历 ./text 目录内的所有文件(不遍历子目录)
diff --git a/plugin/plaintext/common_in.go b/plugin/plaintext/common_in.go
index bf678e37..fbaf21ff 100644
--- a/plugin/plaintext/common_in.go
+++ b/plugin/plaintext/common_in.go
@@ -17,6 +17,7 @@ type textIn struct {
Description string
Name string
URI string
+ IPOrCIDR []string
InputDir string
Want map[string]bool
OnlyIPType lib.IPType
diff --git a/plugin/plaintext/text_in.go b/plugin/plaintext/text_in.go
index 037271c1..9bc0d73f 100644
--- a/plugin/plaintext/text_in.go
+++ b/plugin/plaintext/text_in.go
@@ -30,6 +30,7 @@ func newTextIn(iType string, action lib.Action, data json.RawMessage) (lib.Input
var tmp struct {
Name string `json:"name"`
URI string `json:"uri"`
+ IPOrCIDR []string `json:"ipOrCIDR"`
InputDir string `json:"inputDir"`
Want []string `json:"wantedList"`
OnlyIPType lib.IPType `json:"onlyIPType"`
@@ -49,16 +50,23 @@ func newTextIn(iType string, action lib.Action, data json.RawMessage) (lib.Input
}
}
- if tmp.Name == "" && tmp.URI == "" && tmp.InputDir == "" {
- return nil, fmt.Errorf("type %s | action %s missing inputdir or name or uri", typeTextIn, action)
+ 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 (tmp.Name != "" && tmp.URI == "") || (tmp.Name == "" && tmp.URI != "") {
- return nil, fmt.Errorf("type %s | action %s name & uri must be specified together", typeTextIn, action)
+ if iType == typeJSONIn && len(tmp.JSONPath) == 0 {
+ return nil, fmt.Errorf("❌ [type %s | action %s] missing jsonPath", typeJSONIn, action)
}
- if iType == typeJSONIn && len(tmp.JSONPath) == 0 {
- return nil, fmt.Errorf("type %s | action %s missing jsonPath", typeJSONIn, action)
+ if tmp.InputDir == "" {
+ if tmp.Name == "" {
+ return nil, fmt.Errorf("❌ [type %s | action %s] missing inputDir or name", iType, action)
+ }
+ if tmp.URI == "" && len(tmp.IPOrCIDR) == 0 {
+ return nil, fmt.Errorf("❌ [type %s | action %s] missing uri or ipOrCIDR", iType, action)
+ }
+ } 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
@@ -75,6 +83,7 @@ func newTextIn(iType string, action lib.Action, data json.RawMessage) (lib.Input
Description: descTextIn,
Name: tmp.Name,
URI: tmp.URI,
+ IPOrCIDR: tmp.IPOrCIDR,
InputDir: tmp.InputDir,
Want: wantList,
OnlyIPType: tmp.OnlyIPType,
@@ -104,6 +113,7 @@ func (t *textIn) Input(container lib.Container) (lib.Container, error) {
switch {
case t.InputDir != "":
err = t.walkDir(t.InputDir, entries)
+
case t.Name != "" && t.URI != "":
switch {
case strings.HasPrefix(strings.ToLower(t.URI), "http://"), strings.HasPrefix(strings.ToLower(t.URI), "https://"):
@@ -111,6 +121,15 @@ func (t *textIn) Input(container lib.Container) (lib.Container, error) {
default:
err = t.walkLocalFile(t.URI, t.Name, entries)
}
+ if err != nil {
+ return nil, err
+ }
+
+ fallthrough
+
+ case t.Name != "" && len(t.IPOrCIDR) > 0:
+ err = t.appendIPOrCIDR(t.IPOrCIDR, t.Name, entries)
+
default:
return nil, fmt.Errorf("config missing argument inputDir or name or uri")
}
@@ -238,3 +257,22 @@ func (t *textIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry)
return nil
}
+
+func (t *textIn) appendIPOrCIDR(ipOrCIDR []string, name string, entries map[string]*lib.Entry) error {
+ name = strings.ToUpper(name)
+
+ entry, found := entries[name]
+ if !found {
+ entry = lib.NewEntry(name)
+ }
+
+ for _, cidr := range ipOrCIDR {
+ if err := entry.AddPrefix(strings.TrimSpace(cidr)); err != nil {
+ return err
+ }
+ }
+
+ entries[name] = entry
+
+ return nil
+}