66 lines
1.1 KiB
Go
66 lines
1.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
_ "embed"
|
|
"io"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/oschwald/maxminddb-golang"
|
|
)
|
|
|
|
//go:embed assets/world.json
|
|
var trafficWorld []byte
|
|
|
|
//go:embed assets/dbip-country-lite-2026-10.mmdb.gz
|
|
var trafficGeoCompressed []byte
|
|
|
|
const trafficGeoDate = "2026-10"
|
|
|
|
var trafficGeo struct {
|
|
sync.Once
|
|
db *maxminddb.Reader
|
|
}
|
|
|
|
func trafficGeoReady() bool {
|
|
trafficGeo.Do(func() {
|
|
r, err := gzip.NewReader(bytes.NewReader(trafficGeoCompressed))
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer r.Close()
|
|
data, err := io.ReadAll(io.LimitReader(r, 32<<20))
|
|
if err != nil {
|
|
return
|
|
}
|
|
trafficGeo.db, _ = maxminddb.FromBytes(data)
|
|
})
|
|
return trafficGeo.db != nil
|
|
}
|
|
func lookupTrafficCountry(ipText string) string {
|
|
ip := net.ParseIP(ipText)
|
|
if ip == nil {
|
|
return ""
|
|
}
|
|
if ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast() {
|
|
return "LAN"
|
|
}
|
|
if !ip.IsGlobalUnicast() {
|
|
return ""
|
|
}
|
|
if !trafficGeoReady() {
|
|
return ""
|
|
}
|
|
var record struct {
|
|
Country struct {
|
|
Code string `maxminddb:"iso_code"`
|
|
} `maxminddb:"country"`
|
|
}
|
|
if trafficGeo.db.Lookup(ip, &record) != nil {
|
|
return ""
|
|
}
|
|
return record.Country.Code
|
|
}
|