Contact¶
La entidad Contact representa a cualquier usuario de WhatsApp del que tu sesión tenga conocimiento, ya sea que haya iniciado un chat, aparezca en un grupo o haya sido descubierto vía lookups onWhatsApp. Cada contacto incluye una propiedad eager chat apuntando a su instancia Chat 1:1, de modo que puedes saltar de "quién" a "dónde" sin lookups adicionales.
Contact.get(uid) es el único punto de entrada y despacha según la forma del identificador:
- Teléfono plano (solo dígitos, sin
@) → resuelto a través desocket.onWhatsApp(phone). - JID (
<number>@s.whatsapp.net) → buscado en el motor, refrescado desde el socket si falta. - LID (
<number>@lid) → resuelto vía el mapeo persistido LID↔JID.
Importación¶
import { WhatsApp, RedisEngine } from "@arcaelas/whatsapp";
// o
import { WhatsApp, FileSystemEngine } from "@arcaelas/whatsapp";
Usa el constructor vinculado vía wa.Contact. La factory contact(wa) (interna) produce una subclase _Contact vinculada al contexto de WhatsApp: sobre eso operan los delegados estáticos.
Constructor¶
Como Chat, las instancias de Contact no están pensadas para construirse directamente. Provienen de:
wa.Contact.get(uid)— despacho inteligente por teléfono, JID o LID.wa.Contact.list(offset, limit)— lecturas paginadas.chat.members()— participantes de grupos.- Handlers de eventos para
contact:created/contact:updated. msg.author()— el remitente de un mensaje.
import { WhatsApp, RedisEngine } from "@arcaelas/whatsapp";
const wa = new WhatsApp({
engine: new RedisEngine({ url: "redis://127.0.0.1:6379" }),
});
await wa.connect();
// Número de teléfono (solo dígitos)
const byPhone = await wa.Contact.get("5215555555555");
// JID
const byJid = await wa.Contact.get("5215555555555@s.whatsapp.net");
// LID (identificador oculto asignado por WhatsApp)
const byLid = await wa.Contact.get("192837465@lid");
console.log(byPhone?.name, byJid?.phone, byLid?.id);
¿Por qué el despacho inteligente?
WhatsApp expone tres sabores de identificador para el mismo usuario. Contact.get los normaliza a través de un resolver interno más una sonda onWhatsApp en vivo, de modo que tu código solo pasa strings y recibe un Contact normalizado (con un JID válido en .id).
Propiedades¶
Todas las propiedades son getters síncronos sobre la forma interna _raw: IContactRaw, excepto chat, que se hidrata eagerly en la construcción.
| Propiedad | Tipo | Descripción |
|---|---|---|
id | string | JID canónico (p. ej. 5215555555555@s.whatsapp.net). |
jid | string | Alias de id. |
lid | string \| null | Identificador de dispositivo vinculado (@lid) cuando está disponible. |
name | string | Nombre local → push notify → fallback del teléfono. |
phone | string | Dígitos antes del @ en el JID. |
photo | string \| null | URL de foto de perfil (cacheada después del primer refresh/get). |
content | string | Texto de estado/bio. |
me | boolean | true cuando la instancia representa la cuenta autenticada. |
chat | Chat | Chat 1:1 eager vinculado a este contacto. |
IContactRaw¶
export interface IContactRaw {
id: string;
lid?: string | null;
name?: string | null;
notify?: string | null;
verified_name?: string | null;
img_url?: string | null;
status?: string | null;
}
Propiedad eager chat¶
Contact.chat no es una función, es una instancia wa.Chat completamente construida disponible sincrónicamente. Te permite encadenar llamadas como:
const contact = await wa.Contact.get("5215555555555");
if (contact) {
await contact.chat.pin(true);
await contact.chat.typing(true);
await wa.Message.text(contact.chat.id, "Ready to go!");
await contact.chat.typing(false);
}
chat para grupos
Solo los chats 1:1 son descubiertos por Contact.get. Los JIDs de grupo (@g.us) se filtran; usa wa.Chat.get(groupJid) cuando necesites la entidad del grupo.
Métodos¶
rename(name: string)¶
Renombra el contacto localmente (solo libreta de direcciones del dispositivo). No se propaga a los servidores de WhatsApp, pero el nuevo valor es visible inmediatamente a través de .name y se persiste vía el motor.
const contact = await wa.Contact.get("5215555555555");
await contact?.rename("Alice Example");
Devuelve true en caso de éxito, false cuando el contacto no puede ser resuelto.
refresh()¶
Re-hidrata photo y content (bio/estado) desde el socket en vivo y reescribe el documento del motor. Devuelve this en caso de éxito, null si no hay socket activo.
const contact = await wa.Contact.get("5215555555555@s.whatsapp.net");
await contact?.refresh();
console.log(contact?.photo, contact?.content);
Hidratación automática
wa.Contact.get(uid) ya obtiene los datos de perfil la primera vez que se ve un JID. Llama a refresh() solo cuando necesites metadatos frescos (p. ej. el usuario actualizó su avatar).
Estáticos (delegado vía wa.Contact)¶
| Delegado | Signatura | Notas |
|---|---|---|
wa.Contact.get | (uid: string) => Promise<Contact \| null> | Despacho inteligente: teléfono / JID / LID. |
wa.Contact.list | (offset?: number, limit?: number) => Promise<Contact[]> | Contactos persistidos paginados (mtime DESC). Por defecto: 0, 50. Cada resultado tiene chat pre-cargado. |
wa.Contact.rename | (uid: string, name: string) => Promise<boolean> | Delega en la instancia rename. |
wa.Contact.refresh | (uid: string) => Promise<Contact \| null> | Delega en la instancia refresh. |
import { WhatsApp, FileSystemEngine } from "@arcaelas/whatsapp";
const wa = new WhatsApp({
engine: new FileSystemEngine({ path: "./.whatsapp" }),
});
await wa.connect();
// Delegados de una línea
await wa.Contact.rename("5215555555555", "Alice");
await wa.Contact.refresh("5215555555555@s.whatsapp.net");
// Iterar cada contacto
let offset = 0;
while (true) {
const batch = await wa.Contact.list(offset, 100);
if (batch.length === 0) break;
for (const c of batch) {
console.log(c.phone, c.name, c.photo ?? "(no photo)");
}
offset += batch.length;
}
Rutas de persistencia¶
Los registros relacionados con contactos viven bajo las siguientes claves en el motor configurado:
| Ruta | Valor | Escrito por |
|---|---|---|
/contact/{jid} | IContactRaw serializado. | Contact.get, rename, refresh, eventos contact:*. |
/lid/{lid} | String JID serializado — índice inverso para resolución de LID. | Contact.get cuando se descubre un LID; evento lid-mapping.update. |
/chat/{jid} | IChatRaw serializado — el contact.chat eager se carga desde aquí. | Chat.get, persistencia de mensajes, eventos chats.*. |
Consistencia del motor
Cuando autoclean es true (por defecto) y se recibe un loggedOut remoto, todo el motor se borra para forzar una sincronización fresca en el próximo login. Establece autoclean: false en las opciones del constructor de WhatsApp si deseas conservar contactos/chats/mensajes entre reautenticaciones.