package parser import ( "backend/utils" "regexp" "strconv" "strings" "time" ) func parseDispTime(disp string, currConsegna *int) *string { if currConsegna == nil { return nil } var day int var err error if disp != "" { //get only the day part from disp parts := strings.Split(disp, "/") dayStr := strings.TrimSpace(parts[0]) day, err = strconv.Atoi(dayStr) if err != nil || day < 1 || day > 31 { // Invalid day, default to 1 day = 1 } } else { day = 1 } month := *currConsegna currMonth := int(time.Now().Month()) year := time.Now().Year() if month < currMonth { year++ } t := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) if t.Day() != day { // Invalid day for month, default to first day of month t = time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) } formatted := t.Format(time.DateOnly) return &formatted } func ParseDettaglio(dettaglio string, currConsegna *int) (disp_time *string, perm_arr *[]int, persone_arr *[]string, err error) { dettaglio = strings.TrimSpace(dettaglio) disp := getKeyValueUpToXorWhitespace(dettaglio, "disp:", "perm:") perm := getKeyValueUpToXorWhitespace(dettaglio, "perm:", "persone:") persone := getKeyValueUpToXorWhitespace(dettaglio, "persone:", "") disp_time = parseDispTime(disp, currConsegna) if perm != "" { parts := strings.Split(perm, "-") for _, part := range parts { part = strings.TrimSpace(part) if part != "" { num, err := strconv.Atoi(part) if err == nil { if perm_arr == nil { perm_arr = &[]int{} } *perm_arr = append(*perm_arr, num) } } } } if persone != "" { parts := strings.Split(persone, "/") for _, part := range parts { part = strings.TrimSpace(part) if part != "" { if persone_arr == nil { persone_arr = &[]string{} } *persone_arr = append(*persone_arr, part) } } } return } func getKeyValueUpToXorWhitespace(input, key, stopstring string) string { input = strings.TrimSpace(input) i := strings.Index(input, key) if i == -1 { return "" } start := i + len(key) rest := strings.TrimSpace(input[start:]) // Find stopstring, whitespace, or repeated key stop_pos := len(rest) stops := []int{} if stopstring != "" { if j := strings.Index(rest, stopstring); j != -1 { stops = append(stops, j) } } // Find whitespace if ws := strings.IndexAny(rest, " \n\r\t"); ws != -1 { stops = append(stops, ws) } // Find repeated key if k := strings.Index(rest, key); k != -1 { stops = append(stops, k) } // Use the earliest stop for _, s := range stops { if s < stop_pos { stop_pos = s } } val := strings.TrimSpace(rest[:stop_pos]) // Only take the first token before any whitespace or another key if idx := strings.IndexAny(val, " \n\r\t"); idx != -1 { val = val[:idx] } //fmt.Printf("Extracted value for key '%s': '%s'\n", key, val) return val } var mesiMapping = map[int]string{ 1: "Gennaio", 2: "Febbraio", 3: "Marzo", 4: "Aprile", 5: "Maggio", 6: "Giugno", 7: "Luglio", 8: "Agosto", 9: "Settembre", 10: "Ottobre", 11: "Novembre", 12: "Dicembre", } func ParseConsegna(original *string) *int { currentMonth := int(time.Now().Month()) if original == nil { return nil } if *original == "Libero" { return ¤tMonth } else { for k, v := range mesiMapping { if *original == v { return &k } } } return ¤tMonth } func ParsePrezzo(input *string) int { if input == nil || len(*input) == 0 { return 0 } s := *input s = strings.ReplaceAll(s, "€", "") s = strings.ReplaceAll(s, " ", "") s = strings.ReplaceAll(s, ".", "") s = strings.ReplaceAll(s, ",", ".") re := regexp.MustCompile(`\d+(\.\d+)?`) match := re.FindString(s) if match == "" { return 0 } f, err := strconv.ParseFloat(match, 64) if err != nil { return 0 } return int(f * 100) } func ParseTipologia(t1, t2 *string) (tipo *string) { if t1 == nil { return utils.Ptr("Errore") } if *t1 == "V" { return utils.Ptr("Vendita") } if *t1 == "I" { return utils.Ptr("Cessione") } if *t1 == "A" { if t2 != nil { normalized := strings.TrimSpace(*t2) normalized = strings.ToLower(normalized) switch normalized { case "residenziale", "turistico", "stanza": return utils.Ptr("Transitorio") } } return utils.Ptr("Stabile") } return utils.Ptr("Errore") } func ParseEmail(input *string) *string { if input == nil { return nil } email := strings.TrimLeft(*input, " ") if email == "" { return nil } parts := strings.Split(email, " ") if len(parts) > 0 { email = parts[0] } email = strings.TrimSpace(email) if email == "" { return nil } // Basic email validation if !isValidEmail(email) { return nil } return &email } func isValidEmail(email string) bool { // Must contain exactly one @ symbol atCount := strings.Count(email, "@") if atCount != 1 { return false } // Split on @ to get local and domain parts parts := strings.Split(email, "@") if len(parts) != 2 { return false } local := parts[0] domain := parts[1] // Local part cannot be empty if local == "" { return false } // Domain part cannot be empty if domain == "" { return false } // Domain must contain at least one dot if !strings.Contains(domain, ".") { return false } // Domain cannot start or end with dot if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") { return false } // Domain cannot have consecutive dots if strings.Contains(domain, "..") { return false } // Local part cannot start or end with dot if strings.HasPrefix(local, ".") || strings.HasSuffix(local, ".") { return false } // Local part cannot have consecutive dots if strings.Contains(local, "..") { return false } // Basic check for valid characters (this is simplified) // In production, you might want to use a proper regex or email validation library for _, char := range email { if char == ' ' || char == '\t' || char == '\n' || char == '\r' { return false } } return true }