package internal import ( "encoding/json" "fmt" "log/slog" "math/rand" "os" "path/filepath" "regexp" "strings" "time" ) func ReadConfig(file string, config interface{}) error { file, err := filepath.Abs(file) if err != nil { return err } jsonFile, err := os.ReadFile(file) if err != nil { return err } err = json.Unmarshal(jsonFile, &config) if err != nil { return err } return nil } func Version(appName, appVersion, gitCommit, goVersion string) string { version := appName if appVersion != "" { version += " " + appVersion } if gitCommit != "" { version += "-" + gitCommit } if goVersion != "" { version += " (compiled with " + goVersion + ")" } return version } func ShowVersion(appName, appVersion, gitCommit, goVersion string) { fmt.Print(Version(appName, appVersion, gitCommit, goVersion) + "\n") } const randomChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" func GenerateChars(n int) string { b := make([]byte, n) for i := range b { b[i] = randomChars[rand.Intn(len(randomChars))] } return string(b) } // Encryption key must be URL compatible and strong enough // Requiring only alphanumeric chars with a size between 16 and 256 var encryptionKeyRegexp = regexp.MustCompile("^[a-zA-Z0-9]{16,256}$") func ValidateEncryptionKey(p string) error { if !encryptionKeyRegexp.MatchString(p) { return fmt.Errorf("encryption key doesn't match '%s'", encryptionKeyRegexp) } return nil } // HumanDuration converts number of seconds to a human friendly format // Ex: 3600 -> "1 hour" // Yes it uses rough approximations ¯\_(ツ)_/¯ func HumanDuration(i int) string { var w string if i < 0 { return "" } else if i >= 0 && i < 60 { w = "second" } else if i >= 60 && i < 60*60 { i = i / 60 w = "minute" } else if i >= 60*60 && i < 60*60*24 { w = "hour" i = i / (60 * 60) } else if i >= 60*60*24 && i < 60*60*24*7 { w = "day" i = i / (60 * 60 * 24) } else if i >= 60*60*24*7 && i < 60*60*24*31 { w = "week" i = i / (60 * 60 * 24 * 7) } else if i >= 60*60*24*31 && i < 60*60*24*365 { w = "month" i = i / (60 * 60 * 24 * 31) } else { w = "year" i = i / (60 * 60 * 24 * 365) } if i > 1 { w = w + "s" } return fmt.Sprintf("%d %s", i, w) } // TimeDiff to return the number of seconds between this time and now func TimeDiff(ts time.Time) int { diff := int(time.Since(ts).Seconds()) if diff < 0 { return diff * -1 } return diff } func ReturnError(logger *slog.Logger, message string, err error) int { if err != nil { logger.Error(message, slog.Any("error", err)) } else { logger.Error(message) } return RC_ERROR } func ToLowerStringSlice(src []string) (dst []string) { for _, s := range src { dst = append(dst, strings.ToLower(s)) } return } func InSlice(s []string, elem string) bool { for _, v := range s { if v == elem { return true } } return false }