refactor: restructure project
All checks were successful
ci/woodpecker/push/lint Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful

This commit is contained in:
Tom Neuber 2024-11-26 13:35:54 +01:00
parent 1bde2041e1
commit 8215e1f13a
Signed by: tom
GPG key ID: F17EFE4272D89FF6
21 changed files with 850 additions and 269 deletions

View file

@ -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)
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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"`

View file

@ -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
}

View file

@ -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)
}
})