// Package parser provides message text parsing utilities for the CRM. // It extracts structured lead information from raw WhatsApp message text. package parser import ( "regexp" "strings" "unicode" "golang.org/x/text/unicode/norm" ) // ExtractService scans msg for any keyword in the mapping (case-insensitive, // accent-insensitive) and returns the corresponding service name. // If no keyword matches, it returns "Não especificou". // // mapping is a map[keyword]serviceName loaded from the service_keywords table. func ExtractService(msg string, mapping map[string]string) string { normalized := normalizeText(msg) // Sort by keyword length descending so longer phrases match before shorter ones. // We iterate the map which has no order, so we do two passes: // first collect all matches, then pick the longest keyword match. type match struct { keyword string service string } var best match for kw, svc := range mapping { normKW := normalizeText(kw) if strings.Contains(normalized, normKW) { if len(kw) > len(best.keyword) { best = match{keyword: kw, service: svc} } } } if best.service != "" { return best.service } return "Não especificou" } // NormalizePhone converts a raw WhatsApp phone string to E.164 format (+countrycode...). // It strips the @s.whatsapp.net suffix, removes non-digit characters, and prepends "+". func NormalizePhone(raw string) string { // Strip WhatsApp JID suffix. if idx := strings.Index(raw, "@"); idx != -1 { raw = raw[:idx] } // Keep only digits. digits := regexp.MustCompile(`\D`).ReplaceAllString(raw, "") if digits == "" { return raw } return "+" + digits } // normalizeText lowercases and removes accents from s for fuzzy comparison. func normalizeText(s string) string { // NFD decomposition splits accented characters into base + combining marks. t := norm.NFD.String(strings.ToLower(s)) // Remove combining marks (Unicode category Mn). var b strings.Builder for _, r := range t { if unicode.Is(unicode.Mn, r) { continue } b.WriteRune(r) } return b.String() }