From 44aa9c0ccc13ff331b321a0bc8fbe4b6229f47d0 Mon Sep 17 00:00:00 2001 From: Sheikyon Date: Tue, 27 Jan 2026 16:21:01 +0100 Subject: [PATCH 1/2] Use constants for JID suffixes and improve prefix stripping --- src/whatsapp/normalize.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/whatsapp/normalize.ts b/src/whatsapp/normalize.ts index e5ddb0952..1f2d09aa0 100644 --- a/src/whatsapp/normalize.ts +++ b/src/whatsapp/normalize.ts @@ -2,21 +2,21 @@ import { normalizeE164 } from "../utils.js"; const WHATSAPP_USER_JID_RE = /^(\d+)(?::\d+)?@s\.whatsapp\.net$/i; const WHATSAPP_LID_RE = /^(\d+)@lid$/i; +const WHATSAPP_GROUP_SUFFIX = "@g.us"; +/** + * Removes "whatsapp:" prefixes from the string recursively and trims whitespace. + */ function stripWhatsAppTargetPrefixes(value: string): string { - let candidate = value.trim(); - for (;;) { - const before = candidate; - candidate = candidate.replace(/^whatsapp:/i, "").trim(); - if (candidate === before) return candidate; - } + // More efficient than a loop: matches "whatsapp:" followed by optional spaces, one or more times. + return value.trim().replace(/^(whatsapp:\s*)+/i, "").trim(); } export function isWhatsAppGroupJid(value: string): boolean { const candidate = stripWhatsAppTargetPrefixes(value); const lower = candidate.toLowerCase(); - if (!lower.endsWith("@g.us")) return false; - const localPart = candidate.slice(0, candidate.length - "@g.us".length); + if (!lower.endsWith(WHATSAPP_GROUP_SUFFIX)) return false; + const localPart = candidate.slice(0, -WHATSAPP_GROUP_SUFFIX.length); if (!localPart || localPart.includes("@")) return false; return /^[0-9]+(-[0-9]+)*$/.test(localPart); } @@ -30,7 +30,7 @@ export function isWhatsAppUserTarget(value: string): boolean { } /** - * Extract the phone number from a WhatsApp user JID. + * Extract the phone number or ID from a WhatsApp user JID. * "41796666864:0@s.whatsapp.net" -> "41796666864" * "123456@lid" -> "123456" */ @@ -45,20 +45,24 @@ function extractUserJidPhone(jid: string): string | null { export function normalizeWhatsAppTarget(value: string): string | null { const candidate = stripWhatsAppTargetPrefixes(value); if (!candidate) return null; + if (isWhatsAppGroupJid(candidate)) { - const localPart = candidate.slice(0, candidate.length - "@g.us".length); - return `${localPart}@g.us`; + const localPart = candidate.slice(0, -WHATSAPP_GROUP_SUFFIX.length); + return `${localPart}${WHATSAPP_GROUP_SUFFIX}`; } - // Handle user JIDs (e.g. "41796666864:0@s.whatsapp.net") + + // Handle user JIDs (e.g. "41796666864:0@s.whatsapp.net" or "123@lid") if (isWhatsAppUserTarget(candidate)) { const phone = extractUserJidPhone(candidate); if (!phone) return null; const normalized = normalizeE164(phone); return normalized.length > 1 ? normalized : null; } + // If the caller passed a JID-ish string that we don't understand, fail fast. // Otherwise normalizeE164 would happily treat "group:120@g.us" as a phone number. if (candidate.includes("@")) return null; + const normalized = normalizeE164(candidate); return normalized.length > 1 ? normalized : null; } From ecc46c0934f2d296124b3bb609bb572883d5531e Mon Sep 17 00:00:00 2001 From: Sheikyon Date: Tue, 27 Jan 2026 16:38:28 +0100 Subject: [PATCH 2/2] Fix linting and formatting issues --- src/whatsapp/normalize.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/whatsapp/normalize.ts b/src/whatsapp/normalize.ts index 1f2d09aa0..4a70289ae 100644 --- a/src/whatsapp/normalize.ts +++ b/src/whatsapp/normalize.ts @@ -9,7 +9,10 @@ const WHATSAPP_GROUP_SUFFIX = "@g.us"; */ function stripWhatsAppTargetPrefixes(value: string): string { // More efficient than a loop: matches "whatsapp:" followed by optional spaces, one or more times. - return value.trim().replace(/^(whatsapp:\s*)+/i, "").trim(); + return value + .trim() + .replace(/^(whatsapp:\s*)+/i, "") + .trim(); } export function isWhatsAppGroupJid(value: string): boolean {