package utils import ( "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() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) _, _ = saveFailedRequest("non_200", url, req.Header, resp.Header, resp.StatusCode, body, "status error") return result, fmt.Errorf("Failed to fetch url %s: status error: %d", url, resp.StatusCode) } // handle gzip decompression if server used it var raw []byte if strings.Contains(resp.Header.Get("Content-Encoding"), "gzip") { gz, gerr := gzip.NewReader(resp.Body) if gerr != nil { body, _ := io.ReadAll(resp.Body) // best-effort _, _ = saveFailedRequest("gzip_error", url, req.Header, resp.Header, resp.StatusCode, body, gerr.Error()) return result, fmt.Errorf("gzip new reader: %w", gerr) } defer gz.Close() raw, err = io.ReadAll(gz) } else { 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) } // 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, " ", "") } func CommaToDot(str *string) *string { if str != nil { result := strings.ReplaceAll(*str, ",", ".") return &result } return nil }