summaryrefslogtreecommitdiff
path: root/plugin/maxmind/common_out.go
diff options
context:
space:
mode:
authorLoyalsoldier <[email protected]>2026-01-22 11:37:11 +0800
committerLoyalsoldier <[email protected]>2026-01-22 11:37:11 +0800
commitac53325ec76e43fb981c694cb44badf9cbb07e8d (patch)
tree12bd44c19206cbdb06eab8acefc362fbf5dfdb7d /plugin/maxmind/common_out.go
parent77e5f4a2c24fb87f79e73c05729562138df8279e (diff)
Diffstat (limited to 'plugin/maxmind/common_out.go')
-rw-r--r--plugin/maxmind/common_out.go152
1 files changed, 127 insertions, 25 deletions
diff --git a/plugin/maxmind/common_out.go b/plugin/maxmind/common_out.go
index 01f10fc0..21063faa 100644
--- a/plugin/maxmind/common_out.go
+++ b/plugin/maxmind/common_out.go
@@ -8,8 +8,8 @@ import (
"strings"
"github.com/Loyalsoldier/geoip/lib"
- "github.com/oschwald/geoip2-golang"
- "github.com/oschwald/maxminddb-golang"
+ "github.com/oschwald/geoip2-golang/v2"
+ "github.com/oschwald/maxminddb-golang/v2"
)
var (
@@ -20,6 +20,15 @@ var (
defaultIPInfoOutputDir = filepath.Join("./", "output", "ipinfo")
)
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+var (
+ zeroDBIPLanguageNames dbipLanguageNames
+ zeroDBIPContinent dbipContinent
+ zeroDBIPCountryRecord dbipCountryRecord
+ zeroDBIPRepresentedCountry dbipRepresentedCountry
+ zeroDBIPCountry dbipCountry
+)
+
// Reference: https://ipinfo.io/lite
type ipInfoLite struct {
ASN string `maxminddb:"asn"`
@@ -31,6 +40,66 @@ type ipInfoLite struct {
CountryCode string `maxminddb:"country_code"`
}
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipLanguageNames struct {
+ geoip2.Names
+
+ // Persian localized name
+ Persian string `json:"fa,omitzero" maxminddb:"fa"`
+ // Korean localized name
+ Korean string `json:"ko,omitzero" maxminddb:"ko"`
+}
+
+func (d dbipLanguageNames) HasData() bool {
+ return d != zeroDBIPLanguageNames
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipContinent struct {
+ geoip2.Continent
+
+ Names dbipLanguageNames `json:"names,omitzero" maxminddb:"names"`
+}
+
+func (d dbipContinent) HasData() bool {
+ return d != zeroDBIPContinent
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipCountryRecord struct {
+ geoip2.CountryRecord
+
+ Names dbipLanguageNames `json:"names,omitzero" maxminddb:"names"`
+}
+
+func (d dbipCountryRecord) HasData() bool {
+ return d != zeroDBIPCountryRecord
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipRepresentedCountry struct {
+ geoip2.RepresentedCountry
+
+ Names dbipLanguageNames `json:"names,omitzero" maxminddb:"names"`
+}
+
+func (d dbipRepresentedCountry) HasData() bool {
+ return d != zeroDBIPRepresentedCountry
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipCountry struct {
+ Traits geoip2.CountryTraits `json:"traits,omitzero" maxminddb:"traits"`
+ Continent dbipContinent `json:"continent,omitzero" maxminddb:"continent"`
+ RepresentedCountry dbipRepresentedCountry `json:"represented_country,omitzero" maxminddb:"represented_country"`
+ Country dbipCountryRecord `json:"country,omitzero" maxminddb:"country"`
+ RegisteredCountry dbipCountryRecord `json:"registered_country,omitzero" maxminddb:"registered_country"`
+}
+
+func (d dbipCountry) HasData() bool {
+ return d != zeroDBIPCountry
+}
+
func newGeoLite2CountryMMDBOut(iType string, iDesc string, action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
var tmp struct {
OutputName string `json:"outputName"`
@@ -98,26 +167,25 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
return nil, err
}
- db, err := maxminddb.FromBytes(content)
+ db, err := maxminddb.OpenBytes(content)
if err != nil {
return nil, err
}
defer db.Close()
infoList := make(map[string]any)
- networks := db.Networks(maxminddb.SkipAliasedNetworks)
- for networks.Next() {
+ for network := range db.Networks() {
switch g.Type {
- case TypeGeoLite2CountryMMDBOut, TypeDBIPCountryMMDBOut:
+ case TypeGeoLite2CountryMMDBOut:
var record geoip2.Country
- _, err := networks.Network(&record)
+ err := network.Decode(&record)
if err != nil {
return nil, err
}
switch {
- case strings.TrimSpace(record.Country.IsoCode) != "":
- countryCode := strings.ToUpper(strings.TrimSpace(record.Country.IsoCode))
+ case strings.TrimSpace(record.Country.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.Country.ISOCode))
if _, found := infoList[countryCode]; !found {
infoList[countryCode] = geoip2.Country{
Continent: record.Continent,
@@ -125,8 +193,8 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
}
- case strings.TrimSpace(record.RegisteredCountry.IsoCode) != "":
- countryCode := strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.IsoCode))
+ case strings.TrimSpace(record.RegisteredCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.ISOCode))
if _, found := infoList[countryCode]; !found {
infoList[countryCode] = geoip2.Country{
Continent: record.Continent,
@@ -134,19 +202,14 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
}
- case strings.TrimSpace(record.RepresentedCountry.IsoCode) != "":
- countryCode := strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.IsoCode))
+ case strings.TrimSpace(record.RepresentedCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.ISOCode))
if _, found := infoList[countryCode]; !found {
infoList[countryCode] = geoip2.Country{
Continent: record.Continent,
- Country: struct {
- Names map[string]string `maxminddb:"names"`
- IsoCode string `maxminddb:"iso_code"`
- GeoNameID uint `maxminddb:"geoname_id"`
- IsInEuropeanUnion bool `maxminddb:"is_in_european_union"`
- }{
+ Country: geoip2.CountryRecord{
Names: record.RepresentedCountry.Names,
- IsoCode: record.RepresentedCountry.IsoCode,
+ ISOCode: record.RepresentedCountry.ISOCode,
GeoNameID: record.RepresentedCountry.GeoNameID,
IsInEuropeanUnion: record.RepresentedCountry.IsInEuropeanUnion,
},
@@ -154,9 +217,52 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
}
+ case TypeDBIPCountryMMDBOut:
+ var record dbipCountry
+ err := network.Decode(&record)
+ if err != nil {
+ return nil, err
+ }
+
+ switch {
+ case strings.TrimSpace(record.Country.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.Country.ISOCode))
+ if _, found := infoList[countryCode]; !found {
+ infoList[countryCode] = dbipCountry{
+ Continent: record.Continent,
+ Country: record.Country,
+ }
+ }
+
+ case strings.TrimSpace(record.RegisteredCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.ISOCode))
+ if _, found := infoList[countryCode]; !found {
+ infoList[countryCode] = dbipCountry{
+ Continent: record.Continent,
+ Country: record.RegisteredCountry,
+ }
+ }
+
+ case strings.TrimSpace(record.RepresentedCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.ISOCode))
+ if _, found := infoList[countryCode]; !found {
+ infoList[countryCode] = dbipCountry{
+ Continent: record.Continent,
+ Country: dbipCountryRecord{
+ CountryRecord: geoip2.CountryRecord{
+ ISOCode: record.RepresentedCountry.ISOCode,
+ GeoNameID: record.RepresentedCountry.GeoNameID,
+ IsInEuropeanUnion: record.RepresentedCountry.IsInEuropeanUnion,
+ },
+ Names: record.RepresentedCountry.Names,
+ },
+ }
+ }
+ }
+
case TypeIPInfoCountryMMDBOut:
var record ipInfoLite
- _, err := networks.Network(&record)
+ err := network.Decode(&record)
if err != nil {
return nil, err
}
@@ -174,10 +280,6 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
- if networks.Err() != nil {
- return nil, networks.Err()
- }
-
if len(infoList) == 0 {
return nil, fmt.Errorf("❌ [type %s | action %s] no extra info found in the source MMDB file: %s", g.Type, g.Action, g.SourceMMDBURI)
}