All checks were successful
continuous-integration/drone/push Build is passing
178 lines
4.3 KiB
Go
178 lines
4.3 KiB
Go
package utils
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"log"
|
|
"log/slog"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"time"
|
|
)
|
|
|
|
const rsaBits = 4096
|
|
|
|
func GetFilePath(path string) string {
|
|
// Check for empty filename
|
|
if len(path) == 0 {
|
|
return ""
|
|
}
|
|
|
|
// check if filename exists
|
|
if _, err := os.Stat(path); os.IsNotExist((err)) {
|
|
slog.Info("File not found, searching in same directory as binary", "filename", path)
|
|
// if not, check that it exists in the same directory as the currently executing binary
|
|
ex, err2 := os.Executable()
|
|
if err2 != nil {
|
|
slog.Error("Error determining binary path", "error", err)
|
|
return ""
|
|
}
|
|
binaryPath := filepath.Dir(ex)
|
|
path = filepath.Join(binaryPath, path)
|
|
slog.Info("Found file", "path", path)
|
|
}
|
|
return path
|
|
}
|
|
|
|
// Get preferred outbound ip of this machine
|
|
// @see https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go
|
|
func GetOutboundIP() net.IP {
|
|
conn, err := net.Dial("udp", "8.8.8.8:80")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
|
|
|
return localAddr.IP
|
|
}
|
|
|
|
// Check if a file exists from https://stackoverflow.com/questions/12518876/how-to-check-if-a-file-exists-in-go
|
|
func FileExists(filename string) bool {
|
|
info, err := os.Stat(filename)
|
|
if os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
return !info.IsDir()
|
|
}
|
|
|
|
func SleepWithContext(ctx context.Context, d time.Duration) {
|
|
timer := time.NewTimer(d)
|
|
select {
|
|
case <-ctx.Done():
|
|
if !timer.Stop() {
|
|
<-timer.C
|
|
}
|
|
case <-timer.C:
|
|
}
|
|
}
|
|
|
|
// Generic converter using reflection for all sqlc/sqlite types
|
|
func ConvertStruct(src interface{}, dst interface{}) {
|
|
srcVal := reflect.ValueOf(src)
|
|
srcType := reflect.TypeOf(src)
|
|
dstVal := reflect.ValueOf(dst).Elem()
|
|
|
|
for i := 0; i < srcVal.NumField(); i++ {
|
|
srcField := srcVal.Field(i)
|
|
srcFieldType := srcField.Type()
|
|
dstField := dstVal.FieldByName(srcType.Field(i).Name)
|
|
|
|
//slog.Info("Source field", "name", srcType.Field(i).Name)
|
|
|
|
if !dstField.IsValid() || !dstField.CanSet() {
|
|
continue
|
|
}
|
|
|
|
switch srcFieldType {
|
|
case reflect.TypeOf(sql.NullString{}):
|
|
//slog.Info("Sourcefield is string")
|
|
if srcField.FieldByName("Valid").Bool() {
|
|
dstField.SetString(srcField.FieldByName("String").String())
|
|
} else {
|
|
dstField.SetString("")
|
|
}
|
|
|
|
case reflect.TypeOf(sql.NullInt64{}):
|
|
//slog.Info("Sourcefield is int64")
|
|
if srcField.FieldByName("Valid").Bool() {
|
|
val := srcField.FieldByName("Int64").Int()
|
|
if dstField.Kind() == reflect.String {
|
|
dstField.SetString(fmt.Sprintf("%d", val))
|
|
} else {
|
|
dstField.SetInt(val)
|
|
}
|
|
} else {
|
|
if dstField.Kind() == reflect.String {
|
|
dstField.SetString("")
|
|
} else {
|
|
dstField.SetInt(0)
|
|
}
|
|
}
|
|
|
|
case reflect.TypeOf(sql.NullFloat64{}):
|
|
if srcField.FieldByName("Valid").Bool() {
|
|
val := srcField.FieldByName("Float64").Float()
|
|
if dstField.Kind() == reflect.String {
|
|
dstField.SetString(fmt.Sprintf("%f", val))
|
|
} else {
|
|
dstField.SetFloat(val)
|
|
}
|
|
} else {
|
|
if dstField.Kind() == reflect.String {
|
|
dstField.SetString("")
|
|
} else {
|
|
dstField.SetFloat(0)
|
|
}
|
|
}
|
|
|
|
case reflect.TypeOf(sql.NullBool{}):
|
|
if srcField.FieldByName("Valid").Bool() {
|
|
val := srcField.FieldByName("Bool").Bool()
|
|
if dstField.Kind() == reflect.String {
|
|
dstField.SetString(fmt.Sprintf("%t", val))
|
|
} else {
|
|
dstField.SetBool(val)
|
|
}
|
|
} else {
|
|
if dstField.Kind() == reflect.String {
|
|
dstField.SetString("")
|
|
} else {
|
|
dstField.SetBool(false)
|
|
}
|
|
}
|
|
|
|
case reflect.TypeOf(sql.NullTime{}):
|
|
//slog.Info("Sourcefield is time")
|
|
if srcField.FieldByName("Valid").Bool() {
|
|
t := srcField.FieldByName("Time").Interface().(time.Time)
|
|
dstField.SetString(t.Format("2006-01-02 15:04:05"))
|
|
} else {
|
|
slog.Info("value is not valid")
|
|
dstField.SetString("")
|
|
}
|
|
|
|
default:
|
|
// Handle []byte (often from BLOB fields)
|
|
if srcField.Kind() == reflect.Slice && srcField.Type().Elem().Kind() == reflect.Uint8 {
|
|
if !srcField.IsNil() {
|
|
encoded := base64.StdEncoding.EncodeToString(srcField.Bytes())
|
|
dstField.SetString(encoded)
|
|
} else {
|
|
dstField.SetString("")
|
|
}
|
|
}
|
|
|
|
// Fallback: copy if types are directly assignable
|
|
if srcField.Type().AssignableTo(dstField.Type()) {
|
|
dstField.Set(srcField)
|
|
}
|
|
}
|
|
}
|
|
}
|