package helper import ( "context" "crypto/rand" "crypto/tls" "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 string, V any](m map[K]V, fn func(K, V)) { for p, d := range m { fn(p, d) } } func 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(shoudClear bool, runApp func()) { if shoudClear { Clear() } wg := sync.WaitGroup{} ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() defer func() { v := recover() fmt.Println("Recovered:", v) }() runApp() <-ctx.Done() //do stuff after ending wg.Wait() log.Println("AppRunner stopped") os.Exit(0) } func StartTestHTTPServer(port int, name string) { p := strconv.Itoa(port) go func() { fmt.Println("Test server (" + name + "): listening port " + p) // fmt.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, r.Host+"/ OK") }) r.Path("/test1").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, r.Host+"/test1 OK") }) r.Path("/test2").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, r.Host+"/test2 OK") }) err := http.ListenAndServe(":"+p, 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 } func AppendToPointer[T any](slc *[]T, val T) { *slc = append(*slc, val) } func LoadCertificate(certFile, keyFile string) (tls.Certificate, error) { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return tls.Certificate{}, err } return cert, nil } func IsStringEmpty(str string) bool { return str == "" } func IsKeyExistsInMap[V comparable](mp map[string]V, key string) (V, bool, error) { if val, ok := mp[key]; !ok { err := errors.New("Error: missing \"" + key + "\" key") log.Println(err.Error()) return val, ok, err } else { return val, ok, nil } }