68 lines
1.5 KiB
Go
68 lines
1.5 KiB
Go
package geo
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/oschwald/geoip2-golang"
|
|
)
|
|
|
|
// GeoPoint holds geographic information for an IP address.
|
|
type GeoPoint struct {
|
|
IP string
|
|
Lat float64
|
|
Lon float64
|
|
Country string
|
|
CountryCode string
|
|
Count int
|
|
}
|
|
|
|
// GeoLookup wraps the geoip2 database reader.
|
|
// If no database path is configured, all lookups return nil (no-op).
|
|
type GeoLookup struct {
|
|
db *geoip2.Reader
|
|
}
|
|
|
|
// NewGeoLookup creates a GeoLookup. If path is empty, returns a disabled (no-op) lookup.
|
|
// Returns an error if path is non-empty but the file cannot be opened.
|
|
func NewGeoLookup(path string) (*GeoLookup, error) {
|
|
if path == "" {
|
|
return &GeoLookup{}, nil
|
|
}
|
|
db, err := geoip2.Open(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("geoip2 open %q: %w", path, err)
|
|
}
|
|
return &GeoLookup{db: db}, nil
|
|
}
|
|
|
|
// IsEnabled returns true if a GeoIP2 database is loaded.
|
|
func (g *GeoLookup) IsEnabled() bool {
|
|
return g.db != nil
|
|
}
|
|
|
|
// Close releases the database if open.
|
|
func (g *GeoLookup) Close() {
|
|
if g.db != nil {
|
|
g.db.Close()
|
|
}
|
|
}
|
|
|
|
// Lookup returns a GeoPoint for the given IP, or nil if the database is not loaded
|
|
// or the IP is nil/not found.
|
|
func (g *GeoLookup) Lookup(ip net.IP) *GeoPoint {
|
|
if g.db == nil || ip == nil {
|
|
return nil
|
|
}
|
|
record, err := g.db.City(ip)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return &GeoPoint{
|
|
IP: ip.String(),
|
|
Lat: record.Location.Latitude,
|
|
Lon: record.Location.Longitude,
|
|
Country: record.Country.Names["en"],
|
|
CountryCode: record.Country.IsoCode,
|
|
}
|
|
}
|