initial commit

This commit is contained in:
mr0xb 2026-08-24 14:44:54 -04:00
commit 885e7d6e02
22 changed files with 3001 additions and 0 deletions

68
internal/geo/geo.go Normal file
View file

@ -0,0 +1,68 @@
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,
}
}