refactor: restructure project
This commit is contained in:
parent
1bde2041e1
commit
8215e1f13a
21 changed files with 850 additions and 269 deletions
|
@ -1,50 +0,0 @@
|
|||
package geoloc
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ipCache *Cache
|
||||
|
||||
type Cache struct {
|
||||
store sync.Map
|
||||
}
|
||||
|
||||
func NewCache() *Cache {
|
||||
return &Cache{}
|
||||
}
|
||||
|
||||
func (c *Cache) Set(key, value uint, ttl time.Duration) {
|
||||
c.store.Store(key, value)
|
||||
time.AfterFunc(ttl, func() {
|
||||
c.store.Delete(key)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Cache) Get(key uint) (uint, bool) {
|
||||
output, _ := c.store.Load(key)
|
||||
value, ok := output.(uint)
|
||||
return value, ok
|
||||
}
|
||||
|
||||
func createCache() {
|
||||
ipCache = NewCache()
|
||||
}
|
||||
|
||||
func GetCacheContent(key uint) (uint, bool) {
|
||||
if ipCache == nil {
|
||||
createCache()
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return ipCache.Get(key)
|
||||
}
|
||||
|
||||
func SetCacheContent(key, value uint, ttl time.Duration) {
|
||||
if ipCache == nil {
|
||||
createCache()
|
||||
}
|
||||
|
||||
ipCache.Set(key, value, ttl)
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package geoloc
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func parseCSV(filePath string) ([]IPInfo, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
reader := csv.NewReader(file)
|
||||
|
||||
var data []IPInfo
|
||||
for {
|
||||
record, err := reader.Read()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
ipnumfrom, err := strconv.Atoi(record[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ipnumto, err := strconv.Atoi(record[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if record[2] == "-" {
|
||||
record[2] = ""
|
||||
}
|
||||
if record[3] == "-" {
|
||||
record[3] = ""
|
||||
}
|
||||
if record[4] == "-" {
|
||||
record[4] = ""
|
||||
}
|
||||
if record[5] == "-" {
|
||||
record[5] = ""
|
||||
}
|
||||
latitude, err := strconv.ParseFloat(record[6], 32)
|
||||
if err != nil {
|
||||
latitude = 0
|
||||
}
|
||||
longitude, err := strconv.ParseFloat(record[7], 32)
|
||||
if err != nil {
|
||||
longitude = 0
|
||||
}
|
||||
|
||||
ipinfo := IPInfo{
|
||||
IPNumFrom: uint(ipnumfrom),
|
||||
IPNumTo: uint(ipnumto),
|
||||
Code: record[2],
|
||||
Country: record[3],
|
||||
State: record[4],
|
||||
City: record[5],
|
||||
Latitude: float32(latitude),
|
||||
Longitude: float32(longitude),
|
||||
}
|
||||
|
||||
data = append(data, ipinfo)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func ImportCSV(filePath string) error {
|
||||
ipinfos, err := parseCSV(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = CreateDatabase(ipinfos)
|
||||
return err
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package geoloc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-memdb"
|
||||
)
|
||||
|
||||
var database *memdb.MemDB
|
||||
|
||||
func CreateDatabase(ipinfos []IPInfo) (err error) {
|
||||
schema := &memdb.DBSchema{
|
||||
Tables: map[string]*memdb.TableSchema{
|
||||
"ipinfo": {
|
||||
Name: "ipinfo",
|
||||
Indexes: map[string]*memdb.IndexSchema{
|
||||
"id": {
|
||||
Name: "id",
|
||||
Unique: true,
|
||||
Indexer: &memdb.UintFieldIndex{Field: "IPNumFrom"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
database, err = memdb.NewMemDB(schema)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
txn := database.Txn(true)
|
||||
defer txn.Abort()
|
||||
|
||||
for _, ipinfo := range ipinfos {
|
||||
if err = txn.Insert("ipinfo", ipinfo); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
txn.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
func SearchIPNet(ipnetnum uint) (*IPInfo, error) {
|
||||
txn := database.Txn(false)
|
||||
defer txn.Abort()
|
||||
|
||||
var ipinfo IPInfo
|
||||
for {
|
||||
raw, err := txn.First("ipinfo", "id", ipnetnum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if raw != nil {
|
||||
ipinfo = raw.(IPInfo)
|
||||
break
|
||||
}
|
||||
if ipnetnum == 0 {
|
||||
return nil, fmt.Errorf("SearchIPNet: IP net not found")
|
||||
}
|
||||
ipnetnum = ipnetnum - 256
|
||||
}
|
||||
return &ipinfo, nil
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package geoloc
|
||||
|
||||
const CalculationValue uint = 256
|
||||
|
||||
type IPInfo struct {
|
||||
IPNumFrom uint `json:"ip_num_min"`
|
||||
IPNumTo uint `json:"ip_num_max"`
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
package geoloc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
"github.com/praserx/ipconv"
|
||||
)
|
||||
|
||||
func GetIPInfo(ipaddress string) (uint, error) {
|
||||
var ErrNoValidIP = errors.New("no valid IP address")
|
||||
|
||||
func CalculateIPNum(ipaddress string) (uint, error) {
|
||||
ip := net.ParseIP(ipaddress)
|
||||
if ip == nil {
|
||||
return 0, fmt.Errorf("no valid IP address")
|
||||
return 0, ErrNoValidIP
|
||||
}
|
||||
ipnum, err := ipconv.IPv4ToInt(ip)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ipnumfrom := uint(math.Floor(float64(ipnum)/float64(256))) * 256
|
||||
ipnumfrom := uint(math.Floor(float64(ipnum)/float64(CalculationValue))) * CalculationValue
|
||||
return ipnumfrom, nil
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package geoloc
|
||||
package geoloc_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"git.ar21.de/yolokube/country-geo-locations/pkg/geoloc"
|
||||
)
|
||||
|
||||
func TestGetIPInfo(t *testing.T) {
|
||||
|
@ -18,7 +20,7 @@ func TestGetIPInfo(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got, err := GetIPInfo(tt.args.input); err != nil || !reflect.DeepEqual(got, tt.want) {
|
||||
if got, err := geoloc.CalculateIPNum(tt.args.input); err != nil || !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("GetIPInfo() - %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue