go-zprox/pkg/helper/helper.go
Zeev Diukman fbaf9393ea first
2025-03-02 16:14:03 +00:00

512 lines
12 KiB
Go

package helper
import (
"context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"os/exec"
"os/signal"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"time"
"unicode"
"github.com/gookit/goutil/dump"
"github.com/gorilla/mux"
)
// const (
// COLOR_Reset = "\033[0m"
// COLOR_Red = "\033[31m"
// COLOR_Green = "\033[32m"
// COLOR_Yellow = "\033[33m"
// COLOR_Blue = "\033[34m"
// COLOR_Purple = "\033[35m"
// COLOR_Cyan = "\033[36m"
// COLOR_Gray = "\033[37m"
// COLOR_White = "\033[97m" // Brighter white
// )
// func Log(msg string) {
// log.New(os.Stdout, msg, log.Ldate|log.Ltime)
// }
// func Colorize(colorCode string, message string) string {
// return colorCode + message + COLOR_Reset
// }
type IsStruct struct{}
var (
Is IsStruct
h = New()
)
type Helper struct {
Convert Convert
Struct Struct
Screen Screen
Error Error
If If
Log Log
}
type Convert struct {
}
type Struct struct {
}
type Screen struct {
}
type Error struct {
Val error
}
type If struct {
Error Error
}
type Log struct {
Error Error
}
func (h *Helper) P(val any) {
dump.Println(val)
}
// InsertStringValueIntoField inserts a string value into a specified field of a struct.
//
// structPtr must be a pointer to a struct.
// fieldName is the name of the field (case-sensitive).
// stringValue is the string value to be inserted.
//
// Returns an error if:
// - structPtr is not a pointer to a struct.
// - The fieldName is not found in the struct.
// - The field is not settable (e.g., unexported).
// - The field is not of type string.
func New() *Helper {
return &Helper{}
}
func (e *Error) Log() {
if e.Val != nil {
log.Println(e.Val.Error())
}
}
func (e *Error) In(err error) *Error {
e.Val = err
return e
}
func (conv *Struct) Insert(structPtr interface{}, param ...any) {
// func (conv *Struct) Insert(structPtr interface{}, fieldName string, stringValue string, sep string) string {
rawFieldName := param[0].(string)
fieldValue := param[1]
sep := ""
if len(param) > 2 {
sep = param[2].(string)
} else {
sep = "_"
}
// if len(param[2].(string)) > 0 {
// sep = param[2].(string)
// }
seperatorRune := []rune(sep)[0]
field := CapitalizeAfterChar(rawFieldName, seperatorRune)
field = CapitalizeFirstLetter(field)
field = strings.ReplaceAll(field, sep, "")
err := InsertAnyValueIntoField(structPtr, field, fieldValue)
h.Error.Val = err
h.If.Error.Log()
}
func (conv *Struct) ToStructField(str string, seperator string) string {
seperatorRune := []rune(seperator)[0]
field := CapitalizeAfterChar(str, seperatorRune)
field = CapitalizeFirstLetter(field)
field = strings.ReplaceAll(field, seperator, "")
return field
}
func InsertStringValueIntoField(structPtr interface{}, fieldName string, stringValue string) error {
if structPtr == nil {
return errors.New("structPtr cannot be nil")
}
val := reflect.ValueOf(structPtr)
if val.Kind() != reflect.Ptr {
return errors.New("structPtr must be a pointer to a struct")
}
elem := val.Elem()
if elem.Kind() != reflect.Struct {
return errors.New("structPtr must be a pointer to a struct")
}
fieldVal := elem.FieldByName(fieldName)
if !fieldVal.IsValid() {
return fmt.Errorf("field '%s' not found in struct", fieldName)
}
if !fieldVal.CanSet() {
return fmt.Errorf("field '%s' is not settable (unexported or embedded without being exported)", fieldName)
}
if fieldVal.Kind() != reflect.String {
return fmt.Errorf("field '%s' is not a string type", fieldName)
}
fieldVal.SetString(stringValue)
return nil
}
func InsertAnyValueIntoField(structPtr interface{}, fieldName string, anyValue any) error {
if structPtr == nil {
return errors.New("structPtr cannot be nil")
}
val := reflect.ValueOf(structPtr)
if val.Kind() != reflect.Ptr {
return errors.New("structPtr must be a pointer to a struct")
}
elem := val.Elem()
if elem.Kind() != reflect.Struct {
return errors.New("structPtr must be a pointer to a struct")
}
fieldVal := elem.FieldByName(fieldName)
if !fieldVal.IsValid() {
return fmt.Errorf("field '%s' not found in struct", fieldName)
}
if !fieldVal.CanSet() {
return fmt.Errorf("field '%s' is not settable (unexported or embedded without being exported)", fieldName)
}
switch v := anyValue.(type) {
case string:
{
if fieldVal.Kind() != reflect.String {
return fmt.Errorf("field '%s' is not a string type", fieldName)
}
fieldVal.SetString(v)
return nil
}
case bool:
{
if fieldVal.Kind() != reflect.Bool {
return fmt.Errorf("field '%s' is not a string type", fieldName)
}
fieldVal.SetBool(v)
return nil
}
}
return fmt.Errorf("value of field '%s' is unknown type", fieldName)
}
// CapitalizeAfterChar capitalizes the first letter immediately following each occurrence of a specific character in a string.
//
// For example:
// CapitalizeAfterChar("hello_world", '_') == "hello_World"
// CapitalizeAfterChar("this-is-a-test", '-') == "this-Is-A-Test"
// CapitalizeAfterChar(" leading spaces and_underscores", '_') == " leading spaces and_Underscores"
func CapitalizeAfterChar(input string, char rune) string {
var result strings.Builder
capitalizeNext := false // Flag to indicate if the next letter should be capitalized
for _, r := range input {
if capitalizeNext {
result.WriteRune(unicode.ToUpper(r)) // Capitalize the current rune
capitalizeNext = false // Reset the flag
} else {
result.WriteRune(r) // Write the rune as is
}
if r == char {
capitalizeNext = true // Set the flag to capitalize the next letter
}
}
return result.String()
}
func CapitalizeAfterCharMulti(input string, char rune) string {
var result strings.Builder
capitalizeNext := false // Flag to indicate if the next letter should be capitalized
for _, r := range input {
if capitalizeNext {
result.WriteRune(unicode.ToUpper(r)) // Capitalize the current rune
capitalizeNext = false // Reset the flag
} else {
result.WriteRune(r) // Write the rune as is
}
if r == char {
capitalizeNext = true // Set the flag to capitalize the next letter
}
}
return result.String()
}
func CapitalizeFirstLetter(input string) string {
if input == "" {
return input // Return empty string if input is empty
}
runes := []rune(input) // Convert string to rune slice for Unicode support
firstRune := runes[0]
if !unicode.IsLetter(firstRune) {
return input // Return original string if first char is not a letter
}
capitalizedFirstRune := unicode.ToUpper(firstRune)
runes[0] = capitalizedFirstRune
return string(runes) // Convert rune slice back to string
}
func MapIter[K comparable, V comparable](m map[K]V, fn func(K, V)) {
for p, d := range m {
fn(p, d)
}
}
func (*Screen) Clear() {
if runtime.GOOS == "windows" {
cmd := exec.Command("cmd", "/c", "cls")
cmd.Stdout = os.Stdout
cmd.Run()
} else {
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
cmd.Run()
}
}
func RandStringByBits(nBits int) string {
b := make([]byte, nBits/8)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return err.Error()
}
return base64.RawURLEncoding.EncodeToString(b)
}
func StructToMap(obj interface{}) map[string]any {
val := reflect.ValueOf(obj)
typ := reflect.TypeOf(obj)
result := make(map[string]any)
for i := 0; i < val.NumField(); i++ {
field := typ.Field(i)
result[field.Name] = val.Field(i).Interface()
}
return result
}
func FetchGetJson(u string) (map[string]any, error) {
resp, err := http.Get(u)
if err != nil {
return nil, err
}
respByes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
data := map[string]any{}
json.Unmarshal(respByes, &data)
return data, nil
}
func GetLastChar(str string) string {
return str[len(str)-1:]
}
func IsLastChar(str string, chr string) bool {
if l := GetLastChar(str); l == chr {
return true
}
return false
}
func IsLastCharDo(str string, chr string, f func(r bool)) bool {
result := IsLastChar(str, chr)
func(bool) {
f(result)
}(result)
return result
}
func IsFetchOK[V any](u string, funcName string, f func(string) (*http.Response, error)) *http.Response {
// errCntr := 0
errCntrTotal := 0
var (
a V
resp *http.Response
err error
)
for {
resp, err = f(u)
if err == nil && resp.StatusCode == 200 {
// ClearScreen()
break
} else {
// errCntr++
// errCntrTotal++
// if errCntr == 10 {
// errCntr = 0
// ClearScreen()
// }
// if errCntr == 1 {
// ClearScreen()
// }
errCntrTotalStr := strconv.Itoa(errCntrTotal)
pkg := reflect.TypeOf(a).PkgPath()
dt := time.Now()
dateTime := dt.Format("02-01-2006 15:04:05")
fmt.Println("ERROR: " + dateTime + ">---------<" + errCntrTotalStr + ">")
fmt.Println(" :")
fmt.Println(" Package name: " + pkg)
fmt.Println("Function name: " + funcName)
fmt.Println(" URL: " + u)
fmt.Println("Error message: " + err.Error())
fmt.Println("--------------------------------------")
time.Sleep(5 * time.Second)
}
}
return resp
}
func IsSliceContains[T comparable](sliceVals []T, valueToSearch T) bool {
for _, v := range sliceVals {
if v == valueToSearch {
return true
}
}
return false
}
func AddDotBetween(k ...string) string {
constructedKey := ""
for i, key := range k {
constructedKey += key
if i < len(k)-1 {
constructedKey += "."
}
}
return constructedKey
}
func RemoveSliceDuplicates(elements []string) []string {
encountered := map[string]bool{}
result := []string{}
for v := range elements {
if encountered[elements[v]] {
// Do not add duplicate.
} else {
// Record this element as an encountered element.
encountered[elements[v]] = true
// Append to result slice.
result = append(result, elements[v])
}
}
// Return the new slice.
return result
}
func IfLast[T any](counter int, someVar map[string]T, fn func()) {
counter++
if len(someVar) == counter {
fn()
}
}
func (s *IsStruct) Pointer(v any) bool {
valueOfP := reflect.ValueOf(v)
if valueOfP.Kind() == reflect.Ptr {
return true
} else {
return false
}
}
func AppRunner(runApp func()) {
wg := sync.WaitGroup{}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
runApp()
<-ctx.Done()
//do stuff after ending
wg.Wait()
fmt.Println("BYE BYE!")
os.Exit(0)
}
func StartTestHTTPServer(port int) {
p := strconv.Itoa(port)
go func() {
log.Println("Test server is running at http://" + GetIP() + ":" + p)
r := mux.NewRouter()
r.Path("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "/ OK")
})
r.Path("/test1").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "/test1 OK")
})
r.Path("/test2").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "/test2 OK")
})
err := http.ListenAndServe(":3000", r)
if err != nil {
log.Println(err.Error())
}
}()
}
func GetIP(prefix ...string) string {
prfx := "192.168."
if len(prefix) > 0 {
prfx = prefix[0]
}
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Println("Error getting interface addresses:", err)
return ""
}
for _, addr := range addrs {
// Check if the address is an IP address
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
a := strings.HasPrefix(ipnet.IP.String(), prfx)
c := ipnet.IP.To4() != nil
if c && a { //check for ipv4
prfx = ipnet.IP.String()
break
}
// } else if ipnet.IP.To16() != nil { //check for ipv6
// fmt.Println("Local IPv6 address:", ipnet.IP.String())
// }
}
}
return prfx
}