diff options
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | config-example.json | 8 | ||||
| -rw-r--r-- | config.json | 14 | ||||
| -rw-r--r-- | plugin/maxmind/mmdb.go | 85 |
4 files changed, 85 insertions, 28 deletions
@@ -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 |
