Major refactor to library

This commit is contained in:
2025-12-29 09:51:16 +02:00
parent ae169f81e4
commit 767a9e211f
38 changed files with 1073 additions and 492 deletions

72
pkg/utils/phone.go Normal file
View File

@@ -0,0 +1,72 @@
package utils
import (
"fmt"
"strings"
)
// FormatPhoneToJID converts a phone number to WhatsApp JID format
// If the number already contains @, it returns as-is
// Otherwise, applies formatting rules:
// - If starts with 0, assumes no country code and replaces 0 with country code
// - If starts with +, assumes it already has country code
// - Otherwise adds country code if not present
// - Adds @s.whatsapp.net suffix
func FormatPhoneToJID(phone string, defaultCountryCode string) string {
// If already in JID format, return as-is
if strings.Contains(phone, "@") {
return phone
}
// Remove all non-digit characters
cleaned := strings.Map(func(r rune) rune {
if r >= '0' && r <= '9' {
return r
}
return -1
}, phone)
// If empty after cleaning, return original
if cleaned == "" {
return phone
}
// If number starts with 0, it definitely doesn't have a country code
// Replace the leading 0 with the country code
if strings.HasPrefix(cleaned, "0") && defaultCountryCode != "" {
countryCode := strings.TrimPrefix(defaultCountryCode, "+")
cleaned = countryCode + strings.TrimLeft(cleaned, "0")
return fmt.Sprintf("%s@s.whatsapp.net", cleaned)
}
// Remove all leading zeros
cleaned = strings.TrimLeft(cleaned, "0")
// If original phone started with +, it already has country code
if strings.HasPrefix(phone, "+") {
return fmt.Sprintf("%s@s.whatsapp.net", cleaned)
}
// Add country code if provided and number doesn't start with it
if defaultCountryCode != "" {
countryCode := strings.TrimPrefix(defaultCountryCode, "+")
if !strings.HasPrefix(cleaned, countryCode) {
cleaned = countryCode + cleaned
}
}
return fmt.Sprintf("%s@s.whatsapp.net", cleaned)
}
// IsGroupJID checks if a JID is a group JID
func IsGroupJID(jid string) bool {
return strings.HasSuffix(jid, "@g.us")
}
// IsValidJID checks if a string is a valid WhatsApp JID
func IsValidJID(jid string) bool {
return strings.Contains(jid, "@") &&
(strings.HasSuffix(jid, "@s.whatsapp.net") ||
strings.HasSuffix(jid, "@g.us") ||
strings.HasSuffix(jid, "@broadcast"))
}

200
pkg/utils/phone_test.go Normal file
View File

@@ -0,0 +1,200 @@
package utils
import (
"testing"
)
func TestFormatPhoneToJID(t *testing.T) {
tests := []struct {
name string
phone string
defaultCountryCode string
want string
}{
{
name: "Already in JID format",
phone: "27834606792@s.whatsapp.net",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
{
name: "Plain number with leading zero",
phone: "0834606792",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
{
name: "Number with country code",
phone: "27834606792",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
{
name: "Number with plus sign",
phone: "+27834606792",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
{
name: "Number without country code config",
phone: "0834606792",
defaultCountryCode: "",
want: "834606792@s.whatsapp.net",
},
{
name: "Number with spaces and dashes",
phone: "083-460-6792",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
{
name: "Number with parentheses",
phone: "(083) 460 6792",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
{
name: "US number with leading 1",
phone: "12025551234",
defaultCountryCode: "1",
want: "12025551234@s.whatsapp.net",
},
{
name: "US number with area code",
phone: "202-555-1234",
defaultCountryCode: "1",
want: "12025551234@s.whatsapp.net",
},
{
name: "Group JID unchanged",
phone: "123456789-1234567890@g.us",
defaultCountryCode: "27",
want: "123456789-1234567890@g.us",
},
{
name: "Number with different country code via plus sign",
phone: "+12025551234",
defaultCountryCode: "27",
want: "12025551234@s.whatsapp.net",
},
{
name: "Country code with plus in config",
phone: "0834606792",
defaultCountryCode: "+27",
want: "27834606792@s.whatsapp.net",
},
{
name: "Empty phone number",
phone: "",
defaultCountryCode: "27",
want: "",
},
{
name: "Multiple leading zeros",
phone: "00834606792",
defaultCountryCode: "27",
want: "27834606792@s.whatsapp.net",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := FormatPhoneToJID(tt.phone, tt.defaultCountryCode)
if got != tt.want {
t.Errorf("FormatPhoneToJID(%q, %q) = %q, want %q",
tt.phone, tt.defaultCountryCode, got, tt.want)
}
})
}
}
func TestIsGroupJID(t *testing.T) {
tests := []struct {
name string
jid string
want bool
}{
{
name: "Individual JID",
jid: "27834606792@s.whatsapp.net",
want: false,
},
{
name: "Group JID",
jid: "123456789-1234567890@g.us",
want: true,
},
{
name: "Empty string",
jid: "",
want: false,
},
{
name: "Invalid JID",
jid: "notajid",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := IsGroupJID(tt.jid)
if got != tt.want {
t.Errorf("IsGroupJID(%q) = %v, want %v", tt.jid, got, tt.want)
}
})
}
}
func TestIsValidJID(t *testing.T) {
tests := []struct {
name string
jid string
want bool
}{
{
name: "Valid individual JID",
jid: "27834606792@s.whatsapp.net",
want: true,
},
{
name: "Valid group JID",
jid: "123456789-1234567890@g.us",
want: true,
},
{
name: "Valid broadcast JID",
jid: "123456789@broadcast",
want: true,
},
{
name: "Invalid - no @ symbol",
jid: "27834606792",
want: false,
},
{
name: "Invalid - wrong suffix",
jid: "27834606792@invalid.com",
want: false,
},
{
name: "Empty string",
jid: "",
want: false,
},
{
name: "Just @ symbol",
jid: "@",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := IsValidJID(tt.jid)
if got != tt.want {
t.Errorf("IsValidJID(%q) = %v, want %v", tt.jid, got, tt.want)
}
})
}
}