fix parsing

This commit is contained in:
Руслан 2024-12-23 15:49:05 +03:00
parent f25059448b
commit 61618bc7f8
2 changed files with 75 additions and 25 deletions

View File

@ -17,8 +17,6 @@ const (
CountryPhoneCodeDE = 49 CountryPhoneCodeDE = 49
CountryPhoneCodeAG = 54 CountryPhoneCodeAG = 54
CountryPhoneCodeMX = 52 CountryPhoneCodeMX = 52
// CountryPhoneCodeMXWA For Whatsapp.
CountryPhoneCodeMXWA = 521
CountryPhoneCodeUS = "1443" CountryPhoneCodeUS = "1443"
CountryPhoneCodePS = 970 CountryPhoneCodePS = 970
CountryPhoneCodeUZ = 998 CountryPhoneCodeUZ = 998
@ -30,11 +28,13 @@ var (
ErrPhoneTooShort = errors.New("phone is too short - must be at least 5 symbols") ErrPhoneTooShort = errors.New("phone is too short - must be at least 5 symbols")
ErrCannotDetermineCountry = errors.New("cannot determine phone country code") ErrCannotDetermineCountry = errors.New("cannot determine phone country code")
ErrCannotParsePhone = errors.New("cannot parse phone number") ErrCannotParsePhone = errors.New("cannot parse phone number")
undefinedUSCodes = []string{"1445", "1945", "1840", "1448", "1279", "1839"}
TrimmedPhoneRegexp = regexp.MustCompile(`\D+`)
UndefinedUSCodes = []string{"1445", "1945", "1840", "1448", "1279", "1839"}
) )
// FormatNumberForWA forms in the specified format according to the rules https://faq.whatsapp.com/1294841057948784 // FormatNumberForWA forms in the format according to the rules https://faq.whatsapp.com/1294841057948784
func FormatNumberForWA(number string, format pn.PhoneNumberFormat) (string, error) { func FormatNumberForWA(number string) (string, error) {
parsedPhone, err := ParsePhone(number) parsedPhone, err := ParsePhone(number)
if err != nil { if err != nil {
@ -46,7 +46,7 @@ func FormatNumberForWA(number string, format pn.PhoneNumberFormat) (string, erro
case CountryPhoneCodeAG: case CountryPhoneCodeAG:
formattedPhoneNumber = Add9AGIFNeed(parsedPhone) formattedPhoneNumber = Add9AGIFNeed(parsedPhone)
default: default:
formattedPhoneNumber = pn.Format(parsedPhone, format) formattedPhoneNumber = pn.Format(parsedPhone, pn.E164)
} }
return formattedPhoneNumber, nil return formattedPhoneNumber, nil
@ -56,7 +56,7 @@ func FormatNumberForWA(number string, format pn.PhoneNumberFormat) (string, erro
// For mexican numbers automatic add 1 after to the country code (521). // For mexican numbers automatic add 1 after to the country code (521).
// But for argentine numbers there is no automatic addition 9 to the country code. // But for argentine numbers there is no automatic addition 9 to the country code.
func ParsePhone(phoneNumber string) (*pn.PhoneNumber, error) { func ParsePhone(phoneNumber string) (*pn.PhoneNumber, error) {
trimmedPhone := regexp.MustCompile(`\D+`).ReplaceAllString(phoneNumber, "") trimmedPhone := TrimmedPhoneRegexp.ReplaceAllString(phoneNumber, "")
if len(trimmedPhone) < MinPhoneSymbolCount { if len(trimmedPhone) < MinPhoneSymbolCount {
return nil, ErrPhoneTooShort return nil, ErrPhoneTooShort
} }
@ -89,9 +89,13 @@ func ParsePhone(phoneNumber string) (*pn.PhoneNumber, error) {
parsedPhone.NationalNumber = &number parsedPhone.NationalNumber = &number
} }
if IsMexicoNumber(trimmedPhone, parsedPhone) { if IsMexicoNumber(parsedPhone) {
c := int32(CountryPhoneCodeMXWA) number, err := getMexicanNationalNumber(parsedPhone)
parsedPhone.CountryCode = &c if err != nil {
return nil, err
}
parsedPhone.NationalNumber = &number
} }
return parsedPhone, err return parsedPhone, err
@ -101,15 +105,12 @@ func IsRussianNumberWith8Prefix(phone string) bool {
return strings.HasPrefix(phone, "8") && len(phone) == 11 && phoneiso3166.E164.LookupString("7"+phone[1:]) == "RU" return strings.HasPrefix(phone, "8") && len(phone) == 11 && phoneiso3166.E164.LookupString("7"+phone[1:]) == "RU"
} }
func IsMexicoNumber(phone string, parsed *pn.PhoneNumber) bool { func IsMexicoNumber(parsed *pn.PhoneNumber) bool {
phoneNumber := regexp.MustCompile(`\D+`).ReplaceAllString(phone, "") return parsed.GetCountryCode() == CountryPhoneCodeMX
return len(phoneNumber) == 13 &&
parsed.GetCountryCode() == CountryPhoneCodeMX &&
strings.HasPrefix(phoneNumber, "521")
} }
func IsUSNumber(phone string) bool { func IsUSNumber(phone string) bool {
return slices.Contains(undefinedUSCodes, phone[:4]) && return slices.Contains(UndefinedUSCodes, phone[:4]) &&
phoneiso3166.E164.LookupString(CountryPhoneCodeUS+phone[4:]) == "US" phoneiso3166.E164.LookupString(CountryPhoneCodeUS+phone[4:]) == "US"
} }
@ -177,6 +178,20 @@ func getUzbekistanNationalNumber(phone string, parsedPhone *pn.PhoneNumber) (uin
return result, nil return result, nil
} }
func getMexicanNationalNumber(parsedPhone *pn.PhoneNumber) (uint64, error) {
result := parsedPhone.GetNationalNumber()
phoneWithDigit := fmt.Sprintf("1%d", parsedPhone.GetNationalNumber())
num, err := strconv.Atoi(phoneWithDigit)
if err != nil {
return 0, err
}
result = uint64(num)
return result, nil
}
func getCountryCode(phone string) string { func getCountryCode(phone string) string {
countryCode := phoneiso3166.E164.LookupString(phone) countryCode := phoneiso3166.E164.LookupString(phone)

View File

@ -54,14 +54,20 @@ func TestParsePhone(t *testing.T) {
n := "5219982418333" n := "5219982418333"
pn, err := ParsePhone(n) pn, err := ParsePhone(n)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, uint64(9982418333), pn.GetNationalNumber()) assert.Equal(t, uint64(19982418333), pn.GetNationalNumber())
assert.Equal(t, int32(CountryPhoneCodeMXWA), pn.GetCountryCode()) assert.Equal(t, int32(CountryPhoneCodeMX), pn.GetCountryCode())
n = "+521 (998) 241 83 33" n = "+521 (998) 241 83 33"
pn, err = ParsePhone(n) pn, err = ParsePhone(n)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, uint64(9982418333), pn.GetNationalNumber()) assert.Equal(t, uint64(19982418333), pn.GetNationalNumber())
assert.Equal(t, int32(CountryPhoneCodeMXWA), pn.GetCountryCode()) assert.Equal(t, int32(CountryPhoneCodeMX), pn.GetCountryCode())
n = "529982418333"
pn, err = ParsePhone(n)
require.NoError(t, err)
assert.Equal(t, uint64(19982418333), pn.GetNationalNumber())
assert.Equal(t, int32(CountryPhoneCodeMX), pn.GetCountryCode())
}) })
t.Run("palestine number", func(t *testing.T) { t.Run("palestine number", func(t *testing.T) {
@ -88,3 +94,32 @@ func TestParsePhone(t *testing.T) {
assert.Equal(t, int32(CountryPhoneCodeUZ), pn.GetCountryCode()) assert.Equal(t, int32(CountryPhoneCodeUZ), pn.GetCountryCode())
}) })
} }
func TestFormatNumberForWA(t *testing.T) {
numbers := map[string]string{
"79040000000": "+79040000000",
"491736276098": "+491736276098",
"89185553535": "+79185553535",
"4915229457499": "+4915229457499",
"5491131157821": "+5491131157821",
"541131157821": "+5491131157821",
"5219982418333": "+5219982418333",
"529982418333": "+5219982418333",
"14452385043": "+14452385043",
"19452090748": "+19452090748",
"19453003681": "+19453003681",
"19452141217": "+19452141217",
"18407778097": "+18407778097",
"14482074337": "+14482074337",
"18406665259": "+18406665259",
"19455009160": "+19455009160",
"19452381431": "+19452381431",
"12793006305": "+12793006305",
}
for orig, expected := range numbers {
actual, err := FormatNumberForWA(orig)
assert.NoError(t, err)
assert.Equal(t, expected, actual)
}
}