Skip to content

Commit

Permalink
feat: support ipinfo location
Browse files Browse the repository at this point in the history
  • Loading branch information
lanthora committed Oct 29, 2024
1 parent 08e0798 commit ce6c941
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 46 deletions.
101 changes: 101 additions & 0 deletions candy/location.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package candy

import (
"crypto/tls"
"net"
"net/http"
"os"
"path"

"github.com/ipinfo/go/v2/ipinfo"
"github.com/ipinfo/go/v2/ipinfo/cache"
"github.com/lanthora/cacao/argp"
"github.com/lanthora/cacao/logger"
"github.com/oschwald/geoip2-golang"
)

func GetLocation(ip net.IP) (country, region string) {
if !ip.IsPrivate() {
ok := false
if country, region, ok = ipinfoLocation(ip); !ok {
country, region, _ = mmdbLocation(ip)
}
}
return
}

type dummyCacheEngine struct {
cache map[string]interface{}
}

var dummyCache = ipinfo.NewCache(newDummyCacheEngine())
var httpClient = &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}

func newDummyCacheEngine() *dummyCacheEngine {
return &dummyCacheEngine{
cache: make(map[string]interface{}),
}
}

func (c *dummyCacheEngine) Get(key string) (interface{}, error) {
if v, ok := c.cache[key]; ok {
return v, nil
}
return nil, cache.ErrNotFound
}

func (c *dummyCacheEngine) Set(key string, value interface{}) error {
c.cache[key] = value
return nil
}

func ipinfoLocation(ip net.IP) (country, region string, ok bool) {
client := ipinfo.NewClient(httpClient, dummyCache, "")
if info, err := client.GetIPInfo(ip); err == nil {
country = info.Country
region = info.Region
ok = true
}
return
}

func findFileByExtFromDir(dir string, ext string) (string, error) {
files, err := os.ReadDir(dir)
if err != nil {
return "", err
}
for _, file := range files {
if path.Ext(file.Name()) == ext {
return file.Name(), nil
}
}
return "", os.ErrNotExist
}

func mmdbLocation(ip net.IP) (country, region string, ok bool) {
storageDir := argp.Get("storage", ".")
filename, err := findFileByExtFromDir(storageDir, ".mmdb")
if err != nil {
logger.Debug("cannot found mmdb file: %v", err)
return
}
db, err := geoip2.Open(path.Join(storageDir, filename))
if err != nil {
logger.Debug("open mmdb failed: %v", err)
return
}
defer db.Close()
record, err := db.City(ip)
if err != nil {
logger.Debug("get location failed: %v", err)
return
}

country = record.Country.IsoCode

if len(record.Subdivisions) > 0 {
region = record.Subdivisions[0].Names["en"]
}
ok = true
return
}
4 changes: 2 additions & 2 deletions candy/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func (ws *candysocket) handleAuthMessage(buffer []byte) error {
db.Where(ws.dev.model).First(ws.dev.model)
ws.dev.model.IP = uint32ToStrIp(message.IP)
ws.dev.model.Online = true
ws.dev.model.Country, ws.dev.model.Region = storage.GetLocation(net.ParseIP(ws.ctx.ClientIP()))
ws.dev.model.Country, ws.dev.model.Region = GetLocation(net.ParseIP(ws.ctx.ClientIP()))
ws.dev.model.Save()

ws.updateSystemRoute()
Expand Down Expand Up @@ -357,7 +357,7 @@ func (ws *candysocket) handlePeerConnMessage(buffer []byte) error {

ip := make(net.IP, 4)
binary.BigEndian.PutUint32(ip, message.IP)
ws.dev.model.Country, ws.dev.model.Region = storage.GetLocation(ip)
ws.dev.model.Country, ws.dev.model.Region = GetLocation(ip)
ws.dev.model.Save()

return nil
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ module github.com/lanthora/cacao
go 1.22.5

require (
github.com/deckarep/golang-set/v2 v2.6.0
github.com/gin-gonic/gin v1.10.0
github.com/glebarez/sqlite v1.11.0
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/ipinfo/go/v2 v2.10.0
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/oschwald/geoip2-golang v1.11.0
github.com/sirupsen/logrus v1.9.3
Expand All @@ -18,7 +20,6 @@ require (
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/deckarep/golang-set/v2 v2.6.0
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
Expand All @@ -36,13 +37,15 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/oschwald/maxminddb-golang v1.13.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/ipinfo/go/v2 v2.10.0 h1:v9sFjaxnVVD+JVgpWpjgwols18Tuu4SgBDaHHaw0IXo=
github.com/ipinfo/go/v2 v2.10.0/go.mod h1:tRDkYfM20b1XzNqorn1Q1O6Xtg7uzw3Wn3I2R0SyJh4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
Expand All @@ -67,6 +69,8 @@ github.com/oschwald/geoip2-golang v1.11.0 h1:hNENhCn1Uyzhf9PTmquXENiWS6AlxAEnBII
github.com/oschwald/geoip2-golang v1.11.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
github.com/oschwald/maxminddb-golang v1.13.0 h1:R8xBorY71s84yO06NgTmQvqvTvlS/bnYZrrWX1MElnU=
github.com/oschwald/maxminddb-golang v1.13.0/go.mod h1:BU0z8BfFVhi1LQaonTwwGQlsHUEu9pWNdMfmq4ztm0o=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down Expand Up @@ -99,6 +103,9 @@ golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
43 changes: 0 additions & 43 deletions storage/storage.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package storage

import (
"net"
"os"
"path"

"github.com/glebarez/sqlite"
"github.com/lanthora/cacao/argp"
"github.com/lanthora/cacao/logger"
"github.com/oschwald/geoip2-golang"
"gorm.io/gorm"
gormlogger "gorm.io/gorm/logger"
)
Expand All @@ -34,44 +32,3 @@ var db *gorm.DB
func Get() *gorm.DB {
return db
}

func findFileByExtFromDir(dir string, ext string) (string, error) {
files, err := os.ReadDir(dir)
if err != nil {
return "", err
}
for _, file := range files {
if path.Ext(file.Name()) == ext {
return file.Name(), nil
}
}
return "", os.ErrNotExist
}

func GetLocation(ip net.IP) (country, region string) {
storageDir := argp.Get("storage", ".")
filename, err := findFileByExtFromDir(storageDir, ".mmdb")
if err != nil {
logger.Debug("cannot found mmdb file: %v", err)
return
}
db, err := geoip2.Open(path.Join(storageDir, filename))
if err != nil {
logger.Debug("open mmdb failed: %v", err)
return
}
defer db.Close()
record, err := db.City(ip)
if err != nil {
logger.Debug("get location failed: %v", err)
return
}

country = record.Country.IsoCode

if len(record.Subdivisions) > 0 {
region = record.Subdivisions[0].Names["en"]
}

return
}

0 comments on commit ce6c941

Please sign in to comment.