mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-27 04:30:12 +08:00
187 lines
5.1 KiB
Go
187 lines
5.1 KiB
Go
package maxmind
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/Loyalsoldier/geoip/lib"
|
|
"github.com/oschwald/geoip2-golang"
|
|
"github.com/oschwald/maxminddb-golang"
|
|
)
|
|
|
|
var (
|
|
defaultGeoLite2CountryMMDBOutputName = "Country.mmdb"
|
|
|
|
defaultMaxmindOutputDir = filepath.Join("./", "output", "maxmind")
|
|
defaultDBIPOutputDir = filepath.Join("./", "output", "db-ip")
|
|
defaultIPInfoOutputDir = filepath.Join("./", "output", "ipinfo")
|
|
)
|
|
|
|
// Reference: https://ipinfo.io/lite
|
|
type ipInfoLite struct {
|
|
ASN string `maxminddb:"asn"`
|
|
ASName string `maxminddb:"as_name"`
|
|
ASDomain string `maxminddb:"as_domain"`
|
|
Continent string `maxminddb:"continent"`
|
|
ContinentCode string `maxminddb:"continent_code"`
|
|
Country string `maxminddb:"country"`
|
|
CountryCode string `maxminddb:"country_code"`
|
|
}
|
|
|
|
func newGeoLite2CountryMMDBOut(iType string, iDesc string, action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
|
var tmp struct {
|
|
OutputName string `json:"outputName"`
|
|
OutputDir string `json:"outputDir"`
|
|
Want []string `json:"wantedList"`
|
|
Overwrite []string `json:"overwriteList"`
|
|
Exclude []string `json:"excludedList"`
|
|
OnlyIPType lib.IPType `json:"onlyIPType"`
|
|
|
|
SourceMMDBURI string `json:"sourceMMDBURI"`
|
|
}
|
|
|
|
if len(data) > 0 {
|
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if tmp.OutputName == "" {
|
|
tmp.OutputName = defaultGeoLite2CountryMMDBOutputName
|
|
}
|
|
|
|
if tmp.OutputDir == "" {
|
|
switch iType {
|
|
case TypeGeoLite2CountryMMDBOut:
|
|
tmp.OutputDir = defaultMaxmindOutputDir
|
|
|
|
case TypeDBIPCountryMMDBOut:
|
|
tmp.OutputDir = defaultDBIPOutputDir
|
|
|
|
case TypeIPInfoCountryMMDBOut:
|
|
tmp.OutputDir = defaultIPInfoOutputDir
|
|
}
|
|
}
|
|
|
|
return &GeoLite2CountryMMDBOut{
|
|
Type: iType,
|
|
Action: action,
|
|
Description: iDesc,
|
|
OutputName: tmp.OutputName,
|
|
OutputDir: tmp.OutputDir,
|
|
Want: tmp.Want,
|
|
Overwrite: tmp.Overwrite,
|
|
Exclude: tmp.Exclude,
|
|
OnlyIPType: tmp.OnlyIPType,
|
|
|
|
SourceMMDBURI: tmp.SourceMMDBURI,
|
|
}, nil
|
|
}
|
|
|
|
func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
|
|
if strings.TrimSpace(g.SourceMMDBURI) == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
var content []byte
|
|
var err error
|
|
switch {
|
|
case strings.HasPrefix(strings.ToLower(g.SourceMMDBURI), "http://"), strings.HasPrefix(strings.ToLower(g.SourceMMDBURI), "https://"):
|
|
content, err = lib.GetRemoteURLContent(g.SourceMMDBURI)
|
|
default:
|
|
content, err = os.ReadFile(g.SourceMMDBURI)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
db, err := maxminddb.FromBytes(content)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer db.Close()
|
|
|
|
infoList := make(map[string]any)
|
|
networks := db.Networks(maxminddb.SkipAliasedNetworks)
|
|
for networks.Next() {
|
|
switch g.Type {
|
|
case TypeGeoLite2CountryMMDBOut, TypeDBIPCountryMMDBOut:
|
|
var record geoip2.Country
|
|
_, err := networks.Network(&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] = geoip2.Country{
|
|
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] = geoip2.Country{
|
|
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] = 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"`
|
|
}{
|
|
Names: record.RepresentedCountry.Names,
|
|
IsoCode: record.RepresentedCountry.IsoCode,
|
|
GeoNameID: record.RepresentedCountry.GeoNameID,
|
|
IsInEuropeanUnion: record.RepresentedCountry.IsInEuropeanUnion,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
case TypeIPInfoCountryMMDBOut:
|
|
var record ipInfoLite
|
|
_, err := networks.Network(&record)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
countryCode := strings.ToUpper(strings.TrimSpace(record.CountryCode))
|
|
if _, found := infoList[countryCode]; !found {
|
|
record.ASN = ""
|
|
record.ASName = ""
|
|
record.ASDomain = ""
|
|
infoList[countryCode] = record
|
|
}
|
|
|
|
default:
|
|
return nil, lib.ErrNotSupportedFormat
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
return infoList, nil
|
|
}
|