190 lines
4.9 KiB
Go
190 lines
4.9 KiB
Go
package mmdb
|
|
|
|
import (
|
|
"errors"
|
|
"net/netip"
|
|
|
|
"git.kor-elf.net/kor-elf-shield/geoip2"
|
|
"git.kor-elf.net/kor-elf-shield/geoip2/internal/pkg"
|
|
"git.kor-elf.net/kor-elf-shield/geoip2/internal/service/maxmind/mmdb"
|
|
|
|
oschwaldGeoip2 "github.com/oschwald/geoip2-golang/v2"
|
|
)
|
|
|
|
const (
|
|
DownloadURLCityLite = "https://download.maxmind.com/geoip/databases/GeoLite2-City/download?suffix=tar.gz"
|
|
NameDirNameCityLite = "GeoLite2-City"
|
|
)
|
|
|
|
// City is a structure that contains information about the IP address.
|
|
type City struct {
|
|
// lang is a language.
|
|
lang language
|
|
}
|
|
|
|
// NewCity creates a new City instance.
|
|
// @param download - an interface for downloading MaxMind GeoIP2 database
|
|
// @param logger - a logger
|
|
// @param dir - a directory for storing MaxMind GeoIP2 database
|
|
// @return geoip2.RefreshableGeoIP2 - a MaxMind GeoIP2 database service
|
|
func NewCity(download *Download, logger geoip2.Logger, dir string, language language) geoip2.RefreshableGeoIP2 {
|
|
city := &City{
|
|
lang: language,
|
|
}
|
|
|
|
newDir := pkg.NewDir(dir, NameDirNameCityLite)
|
|
return mmdb.NewMMDB(download, city.infoCity, logger, newDir)
|
|
}
|
|
|
|
// infoCity returns information about the IP address.
|
|
// @param ip - IP address
|
|
// @param reader - MaxMind GeoIP2 database reader
|
|
// @return geoip2.Info - information about the IP address
|
|
// @return error - an error if the IP address could not be found
|
|
func (c *City) infoCity(ip netip.Addr, reader *oschwaldGeoip2.Reader) (geoip2.Info, error) {
|
|
record, err := reader.City(ip)
|
|
if err != nil {
|
|
return geoip2.Info{}, err
|
|
}
|
|
if !record.HasData() {
|
|
return geoip2.Info{}, errors.New(geoip2.ErrNotFound)
|
|
}
|
|
|
|
var timeZone string
|
|
if record.Location.HasData() {
|
|
timeZone = record.Location.TimeZone
|
|
}
|
|
|
|
return geoip2.Info{
|
|
IP: ip,
|
|
ISOCode: record.Country.ISOCode,
|
|
Country: c.country(record.Country),
|
|
City: c.city(record.City),
|
|
CitySubdivisions: c.subdivisions(record.Subdivisions),
|
|
TimeZone: timeZone,
|
|
Continent: c.continent(record.Continent),
|
|
}, nil
|
|
}
|
|
|
|
func (c *City) continent(continent oschwaldGeoip2.Continent) string {
|
|
if !continent.HasData() {
|
|
return ""
|
|
}
|
|
|
|
switch c.lang {
|
|
case LanguageRussian:
|
|
return continent.Names.Russian
|
|
case LanguageEnglish:
|
|
return continent.Names.English
|
|
case LanguageBrazilianPortuguese:
|
|
return continent.Names.BrazilianPortuguese
|
|
case LanguageSimplifiedChinese:
|
|
return continent.Names.SimplifiedChinese
|
|
case LanguageJapanese:
|
|
return continent.Names.Japanese
|
|
case LanguageGerman:
|
|
return continent.Names.German
|
|
case LanguageFrench:
|
|
return continent.Names.French
|
|
case LanguageSpanish:
|
|
return continent.Names.Spanish
|
|
default:
|
|
return continent.Names.English
|
|
}
|
|
}
|
|
|
|
func (c *City) country(country oschwaldGeoip2.CountryRecord) string {
|
|
if !country.HasData() {
|
|
return ""
|
|
}
|
|
|
|
switch c.lang {
|
|
case LanguageRussian:
|
|
return country.Names.Russian
|
|
case LanguageEnglish:
|
|
return country.Names.English
|
|
case LanguageBrazilianPortuguese:
|
|
return country.Names.BrazilianPortuguese
|
|
case LanguageSimplifiedChinese:
|
|
return country.Names.SimplifiedChinese
|
|
case LanguageJapanese:
|
|
return country.Names.Japanese
|
|
case LanguageGerman:
|
|
return country.Names.German
|
|
case LanguageFrench:
|
|
return country.Names.French
|
|
case LanguageSpanish:
|
|
return country.Names.Spanish
|
|
default:
|
|
return country.Names.English
|
|
}
|
|
}
|
|
|
|
func (c *City) city(city oschwaldGeoip2.CityRecord) string {
|
|
if !city.HasData() {
|
|
return ""
|
|
}
|
|
|
|
switch c.lang {
|
|
case LanguageRussian:
|
|
return city.Names.Russian
|
|
case LanguageEnglish:
|
|
return city.Names.English
|
|
case LanguageBrazilianPortuguese:
|
|
return city.Names.BrazilianPortuguese
|
|
case LanguageSimplifiedChinese:
|
|
return city.Names.SimplifiedChinese
|
|
case LanguageJapanese:
|
|
return city.Names.Japanese
|
|
case LanguageGerman:
|
|
return city.Names.German
|
|
case LanguageFrench:
|
|
return city.Names.French
|
|
case LanguageSpanish:
|
|
return city.Names.Spanish
|
|
default:
|
|
return city.Names.English
|
|
}
|
|
}
|
|
|
|
func (c *City) subdivisions(subdivisions []oschwaldGeoip2.CitySubdivision) []string {
|
|
var citySubdivisions []string
|
|
|
|
if len(subdivisions) == 0 {
|
|
return citySubdivisions
|
|
}
|
|
|
|
for _, subdivision := range subdivisions {
|
|
citySubdivisions = append(citySubdivisions, c.subdivision(subdivision))
|
|
}
|
|
|
|
return citySubdivisions
|
|
}
|
|
|
|
func (c *City) subdivision(subdivision oschwaldGeoip2.CitySubdivision) string {
|
|
if !subdivision.HasData() {
|
|
return ""
|
|
}
|
|
|
|
switch c.lang {
|
|
case LanguageRussian:
|
|
return subdivision.Names.Russian
|
|
case LanguageEnglish:
|
|
return subdivision.Names.English
|
|
case LanguageBrazilianPortuguese:
|
|
return subdivision.Names.BrazilianPortuguese
|
|
case LanguageSimplifiedChinese:
|
|
return subdivision.Names.SimplifiedChinese
|
|
case LanguageJapanese:
|
|
return subdivision.Names.Japanese
|
|
case LanguageGerman:
|
|
return subdivision.Names.German
|
|
case LanguageFrench:
|
|
return subdivision.Names.French
|
|
case LanguageSpanish:
|
|
return subdivision.Names.Spanish
|
|
default:
|
|
return subdivision.Names.English
|
|
}
|
|
}
|