summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--config-example.json8
-rw-r--r--config.json14
-rw-r--r--plugin/maxmind/mmdb.go85
4 files changed, 85 insertions, 28 deletions
diff --git a/README.md b/README.md
index 795cde93..0b54cc06 100644
--- a/README.md
+++ b/README.md
@@ -167,6 +167,12 @@ These two concepts are notable: `input` and `output`. The `input` is the data so
- **clashRuleSet**:[ipcidr 类型的 Clash RuleSet](https://github.com/Dreamacro/clash/wiki/premium-core-features#ipcidr)
- **surgeRuleSet**:[Surge RuleSet](https://manual.nssurge.com/rule/ruleset.html)
+### 注意事项
+
+由于 MaxMind mmdb 文件格式的限制,当不同列表的 IP 或 CIDR 数据有交集或重复项时,后写入的列表的 IP 或 CIDR 数据会覆盖(overwrite)之前已写入的列表的数据。譬如,IP `1.1.1.1` 同属于列表 `AU` 和列表 `Cloudflare`。如果 `Cloudflare` 在 `AU` 之后写入,则 IP `1.1.1.1` 归属于列表 `Cloudflare`。
+
+为了确保某些指定的列表、被修改的列表一定囊括属于它的所有 IP 或 CIDR 数据,可在 `output` 输出格式为 `maxmindMMDB` 的配置中增加选项 `overwriteList`,该选项中指定的列表会在最后逐一写入,列表中最后一项优先级最高。若已设置选项 `wantedList`,则无需设置 `overwriteList`。`wantedList` 中指定的列表会在最后逐一写入,列表中最后一项优先级最高。
+
## CLI 功能展示
可通过 `go install -v github.com/Loyalsoldier/geoip@latest` 直接安装 CLI。
diff --git a/config-example.json b/config-example.json
index f2a1363b..0396feae 100644
--- a/config-example.json
+++ b/config-example.json
@@ -113,6 +113,14 @@
"type": "maxmindMMDB",
"action": "output",
"args": {
+ "outputName": "Country.mmdb",
+ "overwriteList": ["cn", "private"]
+ }
+ },
+ {
+ "type": "maxmindMMDB",
+ "action": "output",
+ "args": {
"outputName": "country-only-cn-private.mmdb",
"wantedList": ["cn", "private"]
}
diff --git a/config.json b/config.json
index 860a80c8..68bff450 100644
--- a/config.json
+++ b/config.json
@@ -83,7 +83,19 @@
"type": "maxmindMMDB",
"action": "output",
"args": {
- "outputName": "Country.mmdb"
+ "outputName": "Country.mmdb",
+ "overwriteList": [
+ "cn",
+ "private",
+ "cloudflare",
+ "cloudfront",
+ "facebook",
+ "fastly",
+ "google",
+ "netflix",
+ "telegram",
+ "twitter"
+ ]
}
},
{
diff --git a/plugin/maxmind/mmdb.go b/plugin/maxmind/mmdb.go
index 4e0ec242..26440101 100644
--- a/plugin/maxmind/mmdb.go
+++ b/plugin/maxmind/mmdb.go
@@ -38,6 +38,7 @@ func newMMDB(action lib.Action, data json.RawMessage) (lib.OutputConverter, erro
OutputName string `json:"outputName"`
OutputDir string `json:"outputDir"`
Want []string `json:"wantedList"`
+ Overwrite []string `json:"overwriteList"`
OnlyIPType lib.IPType `json:"onlyIPType"`
}
@@ -62,6 +63,7 @@ func newMMDB(action lib.Action, data json.RawMessage) (lib.OutputConverter, erro
OutputName: tmp.OutputName,
OutputDir: tmp.OutputDir,
Want: tmp.Want,
+ Overwrite: tmp.Overwrite,
OnlyIPType: tmp.OnlyIPType,
}, nil
}
@@ -73,6 +75,7 @@ type mmdb struct {
OutputName string
OutputDir string
Want []string
+ Overwrite []string
OnlyIPType lib.IPType
}
@@ -89,14 +92,6 @@ func (m *mmdb) GetDescription() string {
}
func (m *mmdb) Output(container lib.Container) error {
- // Filter want list
- wantList := make(map[string]bool)
- for _, want := range m.Want {
- if want = strings.ToUpper(strings.TrimSpace(want)); want != "" {
- wantList[want] = true
- }
- }
-
writer, err := mmdbwriter.New(
mmdbwriter.Options{
DatabaseType: "GeoLite2-Country",
@@ -110,27 +105,16 @@ func (m *mmdb) Output(container lib.Container) error {
}
updated := false
- switch len(wantList) {
- case 0:
- for entry := range container.Loop() {
- if err := m.marshalData(writer, entry); err != nil {
- return err
- }
- updated = true
+ for _, name := range m.getEntryNameListInOrder(container) {
+ entry, found := container.GetEntry(name)
+ if !found {
+ log.Printf("❌ entry %s not found", name)
+ continue
}
-
- default:
- for name := range wantList {
- entry, found := container.GetEntry(name)
- if !found {
- log.Printf("❌ entry %s not found", name)
- continue
- }
- if err := m.marshalData(writer, entry); err != nil {
- return err
- }
- updated = true
+ if err := m.marshalData(writer, entry); err != nil {
+ return err
}
+ updated = true
}
if updated {
@@ -144,6 +128,53 @@ func (m *mmdb) Output(container lib.Container) error {
return nil
}
+func (m *mmdb) getEntryNameListInOrder(container lib.Container) []string {
+ /*
+ Note: The IPs and/or CIDRs of the latter list will overwrite those of the former one
+ when duplicated data found due to MaxMind mmdb file format constraint.
+
+ Be sure to place the name of the most important list at last
+ when writing wantedList and overwriteList in config file.
+
+ The order of names in wantedList has a higher priority than which of the overwriteList.
+ */
+
+ wantList := make([]string, 0, 200)
+ for _, want := range m.Want {
+ if want = strings.ToUpper(strings.TrimSpace(want)); want != "" {
+ wantList = append(wantList, want)
+ }
+ }
+
+ if len(wantList) > 0 {
+ return wantList
+ }
+
+ overwriteList := make([]string, 0, 200)
+ overwriteMap := make(map[string]bool)
+ for _, overwrite := range m.Overwrite {
+ if overwrite = strings.ToUpper(strings.TrimSpace(overwrite)); overwrite != "" {
+ overwriteList = append(overwriteList, overwrite)
+ overwriteMap[overwrite] = true
+ }
+ }
+
+ list := make([]string, 0, 200)
+ for entry := range container.Loop() {
+ name := entry.GetName()
+ _, found := overwriteMap[name]
+ if found {
+ continue
+ }
+ list = append(list, name)
+ }
+
+ // Make sure the names in overwriteList are written at last
+ list = append(list, overwriteList...)
+
+ return list
+}
+
func (m *mmdb) marshalData(writer *mmdbwriter.Tree, entry *lib.Entry) error {
var entryCidr []string
var err error