infoalloggi-monorepo/apps/backend/parser/parser.go

298 lines
5.9 KiB
Go

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 &currentMonth
} else {
for k, v := range mesiMapping {
if *original == v {
return &k
}
}
}
return &currentMonth
}
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
}