Files
mocksnow/internal/utils/utils.go
Nathan Coad 252bf0a1c8
All checks were successful
continuous-integration/drone/push Build is passing
fix incident view
2025-03-24 17:03:16 +11:00

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