package utils import ( "bytes" "compress/gzip" "encoding/xml" "fmt" "io" "net/http" "os" "reflect" "strings" "time" ) func Ptr[T any](v T) *T { return &v } func MakeUppercase(s string) string { if s != "" && reflect.TypeOf(s).Kind() == reflect.String && len(s) > 0 { return strings.ToUpper(string(s[0])) + s[1:] } return "" } // func fetchXML(url string) ([]byte, error) { // resp, err := http.Get(url) // if err != nil { // return []byte{}, fmt.Errorf("GET error: %v", err) // } // defer resp.Body.Close() // if resp.StatusCode != http.StatusOK { // return []byte{}, fmt.Errorf("status error: %v", resp.StatusCode) // } // data, err := io.ReadAll(resp.Body) // if err != nil { // return []byte{}, fmt.Errorf("read body: %v", err) // } // return data, nil // } func GetXMLFromFile[T any](filePath string) (T, error) { var result T xmlFile, err := os.Open(filePath) if err != nil { return result, fmt.Errorf("failed to open file: %w", err) } defer xmlFile.Close() byteValue, err := io.ReadAll(xmlFile) if err != nil { return result, fmt.Errorf("failed to read file: %w", err) } err = xml.Unmarshal(byteValue, &result) if err != nil { return result, fmt.Errorf("failed to unmarshal XML: %w", err) } return result, nil } func GetDataXML[T any](url string) (T, error) { var result T client := &http.Client{ Timeout: 30 * time.Second, } req, err := http.NewRequest("GET", url, nil) if err != nil { return result, fmt.Errorf("failed to create request: %w", err) } // Add browser-like headers to avoid 403 req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)") req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") req.Header.Set("Accept-Language", "en-US,en;q=0.9,it;q=0.8") req.Header.Set("Accept-Encoding", "gzip, deflate") req.Header.Set("Connection", "keep-alive") req.Header.Set("Referer", "https://www.miogest.com/") resp, err := client.Do(req) if err != nil { return result, fmt.Errorf("Failed to fetch url %s: %w", url, err) } defer resp.Body.Close() raw, err := io.ReadAll(resp.Body) if err != nil { _, _ = saveFailedRequest("read_error", url, req.Header, resp.Header, resp.StatusCode, raw, err.Error()) return result, fmt.Errorf("failed to read response: %w", err) } if resp.StatusCode != http.StatusOK { _, _ = saveFailedRequest("non_200", url, req.Header, resp.Header, resp.StatusCode, raw, "status error") return result, fmt.Errorf("Failed to fetch url %s: status error: %d", url, resp.StatusCode) } // handle gzip decompression if server used it isGzipHeader := strings.Contains(strings.ToLower(resp.Header.Get("Content-Encoding")), "gzip") isGzipMagic := len(raw) > 2 && raw[0] == 0x1f && raw[1] == 0x8b if isGzipHeader || isGzipMagic { gz, gerr := gzip.NewReader(bytes.NewReader(raw)) if gerr != nil { _, _ = saveFailedRequest("gzip_error", url, req.Header, resp.Header, resp.StatusCode, raw, gerr.Error()) return result, fmt.Errorf("gzip new reader: %w", gerr) } defer gz.Close() decompressed, err := io.ReadAll(gz) if err != nil { _, _ = saveFailedRequest("gzip_read_error", url, req.Header, resp.Header, resp.StatusCode, raw, err.Error()) return result, fmt.Errorf("gzip read: %w", err) } raw = decompressed } // attempt to unmarshal if err := xml.Unmarshal(raw, &result); err != nil { _, _ = saveFailedRequest("unmarshal_error", url, req.Header, resp.Header, resp.StatusCode, raw, err.Error()) return result, fmt.Errorf("failed to unmarshal XML: %w", err) } return result, nil } func SafeRemoveAll(path string) error { err := os.RemoveAll(path) if err != nil { if os.IsNotExist(err) { return nil } return err } return nil } func GetStringValue(strPtr *string) string { if strPtr != nil { return *strPtr } return "" } func RemoveWhitespace(str string) string { return strings.ReplaceAll(str, " ", "") }