fix(call): correct sanitization logic to preserve valid mobile numbers

Addresses GitHub Copilot critical review feedback from PR #149.

## Problem Fixed:

Previous implementation incorrectly removed the last digit from ALL 13-digit
numbers starting with '55', which corrupted valid Brazilian mobile numbers.

### Previous Logic (BROKEN):
```typescript
if (pn.length === 13 && pn.startsWith('55')) {
  return pn.slice(0, -1)  //  Breaks valid mobiles!
}
```

**Impact:**
-  Fixed landlines: 5517380255550 → 551738025555 (correct)
-  BROKE mobiles: 5515991000000 → 551599100000 (wrong!)

## Solution Implemented:

Smart detection using first digit after DDD to distinguish landlines from mobiles.

### Brazilian Phone Format:
- **Mobile**: 55 + DD + 9XXXXXXXX (13 digits)
  - First digit after DDD: 6-9 (mobile indicator)
  - Example: 5515991000000 (55 + 15 + 991000000)
- **Landline**: 55 + DD + XXXXXXXX (12 digits)
  - First digit after DDD: 2-5 (landline indicator)
  - Example: 551541410000 (55 + 15 + 41410000)

### New Logic (CORRECT):
```typescript
const firstDigitAfterDDD = pn.charAt(4)  // Position after 55DD

if (pn.length === 13) {
  if (['2', '3', '4', '5'].includes(firstDigitAfterDDD)) {
    // Landline with 13 digits = ERROR (should be 12)
    if (pn.endsWith('0')) {
      return pn.slice(0, -1)  // Remove buggy trailing zero
    }
  }

  if (['6', '7', '8', '9'].includes(firstDigitAfterDDD)) {
    // Mobile with 13 digits = CORRECT
    return pn  // Don't touch it!
  }
}
```

## Test Cases:

| Input | Type | First Digit | Action | Output | Status |
|-------|------|-------------|--------|--------|--------|
| `5515991000000` | Mobile | 9 | Preserve | `5515991000000` |  Fixed |
| `5511687654321` | Mobile | 6 | Preserve | `5511687654321` |  Fixed |
| `551541410000` | Landline | 4 | Preserve | `551541410000` |  OK |
| `5517380255550` | Landline+bug | 3 | Sanitize | `551738025555` |  OK |
| `5515241410000` | Landline+bug | 2 | Sanitize | `551524141000` |  Fixed |

## Technical Details:

**Position Analysis:**
```
5515991000000
0123456789...
└┬┘└┬┘└─────┘
 │  │    └─ 9 digits (with '9' prefix)
 │  └─ DDD (2 digits)
 └─ Country code (2 digits)

Position 4: First digit after DDD
- 2-5: Landline (should be 12 digits total)
- 6-9: Mobile (should be 13 digits total)
```

**Additional Safety:**
- Only sanitizes if trailing zero present (bug pattern)
- Logs sanitization with type indicator (landline/mobile)
- Preserves non-Brazilian numbers unchanged

## Benefits:

-  Fixes decoder bug for Brazilian landlines
-  Preserves valid mobile numbers (critical fix)
-  More precise detection using first digit rule
-  Better logging for debugging (includes type)
-  Follows official Brazilian numbering plan

## References:

- GitHub Copilot PR #149 review
- Brazilian numbering plan: Digits 2-5 = landline, 6-9 = mobile
- WhatsApp JID format: 55DDD9XXXXXXXX@s.whatsapp.net

https://claude.ai/code/session_01TvSrN9JmHZDdKMZDFWEcUS
This commit is contained in:
Claude
2026-02-11 17:14:13 +00:00
parent f145ab8830
commit b8865e95ac
+49 -14
View File
@@ -1603,12 +1603,21 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
/**
* Sanitizes caller phone number to fix known decoder bugs
*
* Issue: Brazilian landline numbers (12 digits) incorrectly get a trailing zero
* Example: 551738025555 → 5517380255550 (off-by-one error)
* Brazilian Phone Format:
* - Mobile: 55 + DD + 9XXXXXXXX (13 digits total)
* Example: 5515991000000 (55 + 15 + 991000000)
* - Landline: 55 + DD + XXXXXXXX (12 digits total)
* Example: 551541410000 (55 + 15 + 41410000)
*
* This helper removes the trailing zero if:
* - Number is 13 digits (incorrect length)
* - Starts with '55' (Brazil country code)
* Decoder Bug: Landlines incorrectly get trailing zero
* Example: 551738025555 → 5517380255550 (should be 12, not 13)
*
* Detection Logic:
* - Extract first digit after DDD (position 4 in string)
* - If digit is 2-5: It's a LANDLINE
* → 13 digits is ERROR → Remove trailing zero
* - If digit is 6-9: It's a MOBILE
* → 13 digits is CORRECT → Don't touch!
*
* @param pn - Raw phone number from caller_pn attribute
* @returns Sanitized phone number
@@ -1618,15 +1627,41 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
return undefined
}
// Fix Brazilian landline off-by-one bug
// Remove trailing zero if 13 digits and starts with Brazil code
if (pn.length === 13 && pn.startsWith('55')) {
const sanitized = pn.slice(0, -1)
logger.debug(
{ original: pn, sanitized },
'Call: Sanitized Brazilian landline number (removed trailing zero)'
)
return sanitized
// Only process Brazilian numbers (country code 55)
if (!pn.startsWith('55')) {
return pn
}
// Check if it's a 13-digit number (potential landline bug)
if (pn.length === 13) {
// Extract first digit after DDD (position 4)
// Format: 55 DD X...
// 01 23 4...
const firstDigitAfterDDD = pn.charAt(4)
// Landline: first digit is 2-5
// If 13 digits, it's an error (should be 12) - remove trailing zero
if (['2', '3', '4', '5'].includes(firstDigitAfterDDD)) {
// Extra validation: only sanitize if ends with 0 (the bug pattern)
if (pn.endsWith('0')) {
const sanitized = pn.slice(0, -1)
logger.debug(
{ original: pn, sanitized, firstDigit: firstDigitAfterDDD, type: 'landline' },
'Call: Sanitized Brazilian landline number (removed trailing zero)'
)
return sanitized
}
}
// Mobile: first digit is 6-9
// 13 digits is CORRECT for mobile - don't sanitize!
if (['6', '7', '8', '9'].includes(firstDigitAfterDDD)) {
logger.trace(
{ pn, firstDigit: firstDigitAfterDDD, type: 'mobile' },
'Call: Valid Brazilian mobile number (13 digits correct, not sanitizing)'
)
return pn
}
}
return pn