node-red-contrib-whatsapp-link/whatsapp-utils.js
2025-11-17 13:58:43 +01:00

164 lines
4.3 KiB
JavaScript

// Shared utility functions for WhatsApp nodes
/**
* Format a phone number for WhatsApp Web client (chat)
* Assumes the recipient is a chat (@c.us)
*/
async function formatChatNumber(numb, waClient, nodeLogger) {
// Validate input
if (!numb) {
throw new Error('Number is required');
}
// Convert to string if number
numb = typeof numb === 'number' ? numb.toString() : numb;
// If already formatted, return as-is
if (numb.includes('@')) {
return numb;
}
// Clean: remove everything except digits
numb = numb.replace(/\D/g, '');
// Validate cleaned number
if (!numb || numb.length === 0) {
throw new Error('Invalid number format');
}
// Validate with getNumberId
try {
const numbID = await waClient.getNumberId(numb);
if (numbID) {
return `${numbID.user}@${numbID.server}`;
} else {
// If validation fails, assume it's a chat
nodeLogger.warn(`getNumberId returned null for ${numb}, using @c.us`);
return `${numb}@c.us`;
}
} catch (e) {
// If error, assume it's a chat
nodeLogger.warn(`getNumberId failed for ${numb}, using @c.us: ${e.message}`);
return `${numb}@c.us`;
}
}
/**
* Format a group ID for WhatsApp Web client
* Assumes the recipient is a group (@g.us)
*/
async function formatGroupId(gID, waClient, nodeLogger) {
// Validate input
if (!gID) {
throw new Error('Group ID is required');
}
// Convert to string if number
gID = typeof gID === 'number' ? gID.toString() : gID;
// If already formatted, return as-is
if (gID.includes('@')) {
return gID;
}
// Clean: preserve hyphens (group format: NUMBER-TIMESTAMP)
gID = gID.replace(/[^\d-]/g, '');
// Validate cleaned group ID
if (!gID || gID.length === 0) {
throw new Error('Invalid group ID format');
}
// Groups always use @g.us
return `${gID}@g.us`;
}
/**
* Format a phone number for Socket client (chat)
* Assumes the recipient is a chat
*/
async function formatChatNumberSocket(numb, waClient, nodeLogger) {
// Handle message object with remoteJid
if (numb && numb.remoteJid) {
return numb.remoteJid;
}
// Validate input
if (!numb) {
throw new Error('Number is required');
}
// Convert to string if number
numb = typeof numb === 'number' ? numb.toString() : numb;
// If already formatted, return as-is
if (numb.includes('@')) {
return numb;
}
// Clean: remove everything except digits
numb = numb.replace(/\D/g, '');
// Validate cleaned number
if (!numb || numb.length === 0) {
throw new Error('Invalid number format');
}
// Check if number exists on WhatsApp
try {
const client = await waClient;
const [result] = await client.onWhatsApp(numb);
if (result?.exists) {
return result.jid;
}
// If not found, assume chat
nodeLogger.warn(`onWhatsApp returned no results for ${numb}, using @s.whatsapp.net`);
return `${numb}@s.whatsapp.net`;
} catch (e) {
nodeLogger.warn(`onWhatsApp failed for ${numb}, using @s.whatsapp.net: ${e.message}`);
return `${numb}@s.whatsapp.net`;
}
}
/**
* Format a group ID for Socket client
* Assumes the recipient is a group (@g.us)
*/
async function formatGroupIdSocket(gID, waClient, nodeLogger) {
// Handle message object with remoteJid
if (gID && gID.remoteJid) {
return gID.remoteJid;
}
// Validate input
if (!gID) {
throw new Error('Group ID is required');
}
// Convert to string if number
gID = typeof gID === 'number' ? gID.toString() : gID;
// If already formatted, return as-is
if (gID.includes('@')) {
return gID;
}
// Clean: preserve hyphens (group format: NUMBER-TIMESTAMP)
gID = gID.replace(/[^\d-]/g, '');
// Validate cleaned group ID
if (!gID || gID.length === 0) {
throw new Error('Invalid group ID format');
}
// Groups always use @g.us
return `${gID}@g.us`;
}
module.exports = {
formatChatNumber,
formatGroupId,
formatChatNumberSocket,
formatGroupIdSocket
};