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
CountryPhoneCodeAG = 54
CountryPhoneCodeMX = 52
// CountryPhoneCodeMXWA For Whatsapp.
CountryPhoneCodeMXWA = 521
CountryPhoneCodeUS = "1443"
CountryPhoneCodePS = 970
CountryPhoneCodeUZ = 998
@ -30,11 +28,13 @@ var (
ErrPhoneTooShort = errors.New("phone is too short - must be at least 5 symbols")
ErrCannotDetermineCountry = errors.New("cannot determine phone country code")
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
func FormatNumberForWA(number string, format pn.PhoneNumberFormat) (string, error) {
// FormatNumberForWA forms in the format according to the rules https://faq.whatsapp.com/1294841057948784
func FormatNumberForWA(number string) (string, error) {
parsedPhone, err := ParsePhone(number)
if err != nil {
@ -46,7 +46,7 @@ func FormatNumberForWA(number string, format pn.PhoneNumberFormat) (string, erro
case CountryPhoneCodeAG:
formattedPhoneNumber = Add9AGIFNeed(parsedPhone)
default:
formattedPhoneNumber = pn.Format(parsedPhone, format)
formattedPhoneNumber = pn.Format(parsedPhone, pn.E164)
}
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).
// But for argentine numbers there is no automatic addition 9 to the country code.
func ParsePhone(phoneNumber string) (*pn.PhoneNumber, error) {
trimmedPhone := regexp.MustCompile(`\D+`).ReplaceAllString(phoneNumber, "")
trimmedPhone := TrimmedPhoneRegexp.ReplaceAllString(phoneNumber, "")
if len(trimmedPhone) < MinPhoneSymbolCount {
return nil, ErrPhoneTooShort
}
@ -89,9 +89,13 @@ func ParsePhone(phoneNumber string) (*pn.PhoneNumber, error) {
parsedPhone.NationalNumber = &number
}
if IsMexicoNumber(trimmedPhone, parsedPhone) {
c := int32(CountryPhoneCodeMXWA)
parsedPhone.CountryCode = &c
if IsMexicoNumber(parsedPhone) {
number, err := getMexicanNationalNumber(parsedPhone)
if err != nil {
return nil, err
}
parsedPhone.NationalNumber = &number
}
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"
}
func IsMexicoNumber(phone string, parsed *pn.PhoneNumber) bool {
phoneNumber := regexp.MustCompile(`\D+`).ReplaceAllString(phone, "")
return len(phoneNumber) == 13 &&
parsed.GetCountryCode() == CountryPhoneCodeMX &&
strings.HasPrefix(phoneNumber, "521")
func IsMexicoNumber(parsed *pn.PhoneNumber) bool {
return parsed.GetCountryCode() == CountryPhoneCodeMX
}
func IsUSNumber(phone string) bool {
return slices.Contains(undefinedUSCodes, phone[:4]) &&
return slices.Contains(UndefinedUSCodes, phone[:4]) &&
phoneiso3166.E164.LookupString(CountryPhoneCodeUS+phone[4:]) == "US"
}
@ -177,6 +178,20 @@ func getUzbekistanNationalNumber(phone string, parsedPhone *pn.PhoneNumber) (uin
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 {
countryCode := phoneiso3166.E164.LookupString(phone)

View File

@ -54,14 +54,20 @@ func TestParsePhone(t *testing.T) {
n := "5219982418333"
pn, err := ParsePhone(n)
require.NoError(t, err)
assert.Equal(t, uint64(9982418333), pn.GetNationalNumber())
assert.Equal(t, int32(CountryPhoneCodeMXWA), pn.GetCountryCode())
assert.Equal(t, uint64(19982418333), pn.GetNationalNumber())
assert.Equal(t, int32(CountryPhoneCodeMX), pn.GetCountryCode())
n = "+521 (998) 241 83 33"
pn, err = ParsePhone(n)
require.NoError(t, err)
assert.Equal(t, uint64(9982418333), pn.GetNationalNumber())
assert.Equal(t, int32(CountryPhoneCodeMXWA), pn.GetCountryCode())
assert.Equal(t, uint64(19982418333), pn.GetNationalNumber())
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) {
@ -88,3 +94,32 @@ func TestParsePhone(t *testing.T) {
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)
}
}