Skip to content

cron/contact-avatars não resolve o nono dígito BR nem consulta wa_lid — avatar fica vazio para contatos cujo wa_id não tem o nono dígito #728

Description

@HigorLira

O que aconteceu?

O job GET /api/v1/cron/contact-avatars marca contatos brasileiros como no_picture mesmo quando o WAHA tem a foto disponível. O avatar nunca aparece no Inbox para esses contatos.

A causa é o chatId que o job monta. Ele usa uma função local que deriva o identificador apenas do telefone gravado:

// app/api/v1/cron/contact-avatars/route.ts:50-54
function chatIdFromIdentity(identity: string): string | null {
  if (identity.startsWith("lid:")) return `${identity.slice(4)}@lid`;
  if (identity.startsWith("phone:")) return `${identity.slice(6).replace(/\D/g, "")}@c.us`;
  return null;
}

E a consulta nem seleciona a coluna wa_lid:

// route.ts:78-79
.select("id, organization_id, wa_identity, avatar_storage_path")
.not("wa_identity", "is", null)

Como wa_identity é gerada a partir do telefone, um contato cujo wa_id real não tem o nono dígito produz um chatId que não existe no WhatsApp. O WAHA responde profilePictureURL: null, e o job classifica isso como "contato sem foto" — o ramo que o próprio código comenta como "estado normal, não erro". O defeito fica invisível: failed: 0.

Por que parece inconsistente com o resto do projeto

O repositório já resolve esse problema em três lugares, e nenhum deles é usado por este cron:

  1. resolveWahaChatId (lib/waha/send.ts:54-62) — a regra canônica. Tenta waLid antes do telefone:

    if (input.waLid) return `${input.waLid}@lid`;
    if (input.waIdentity?.startsWith("lid:")) return `${input.waIdentity.slice(4)}@lid`;
    if (input.phoneNumber) return `${input.phoneNumber.replace(/\D/g, "")}@c.us`;
  2. chatIdOf (lib/agent-engine/edge/crm/session-reconciler.ts:174-180) — mesma ordem, com o comentário que nomeia a causa:

    wa_lid na frente pelo motivo da 0122: wa_identity é GERADA com o telefone antes do lid

  3. resolve-contact-whatsapp-id.ts — descreve o sintoma de forma idêntica ao deste relato:

    No WhatsApp BR o CRM grava +5531998966398 (13 dígitos) mas o wa_id registrado pode ser 553198966398 (12, sem o nono). […] WAHA documenta GET /api/contacts/check-exists para isso; tentamos todas as variantes de busca (phoneLookupVariants) antes de cair no número bruto.

O cron de avatares parece ter ficado de fora dessas correções.

Comportamento esperado

O job deveria resolver o chatId pela mesma regra do resto da base: wa_lid primeiro, e — quando só houver telefone — passar pelas variantes de phoneLookupVariants / check-exists antes de desistir.


Passos para reproduzir

  1. Ter um contato brasileiro cujo wa_id no WhatsApp não tenha o nono dígito (número antigo). O CRM grava phone_number = +55AA9BBBBCCCC (13 dígitos), mas o WhatsApp registra 55AABBBBCCCC (12).
  2. Receber uma mensagem desse contato — a conversa é criada normalmente e as mensagens funcionam (o chatId vem pronto no webhook).
  3. Aguardar (ou disparar) GET /api/v1/cron/contact-avatars.
  4. Observar a resposta: {"scanned":1,"updated":0,"no_picture":1,"failed":0}.
  5. Consultar o banco: avatar_updated_at é preenchido, avatar_storage_path continua NULL.
  6. Consultar o WAHA diretamente com os três identificadores — a foto existe, só não pelo chatId que o cron monta.

Medição na instalação

Mesmo contato, mesma sessão, três identificadores (números mascarados):

contactId enviado ao WAHA Resposta
55AA9BBBBCCCC@c.us — o que o cron monta (13 díg.) {"profilePictureURL": null}
55AABBBBCCCC@c.us — o wa_id real (12 díg.) {"profilePictureURL": "https://pps.whatsapp.net/…"}
<wa_lid>@lid — o LID, já presente em contacts.wa_lid {"profilePictureURL": "https://pps.whatsapp.net/…"}

O próprio WAHA aponta o identificador correto:

GET /api/contacts/check-exists?phone=55AA9BBBBCCCC&session=<sessao>
→ {"numberExists": true, "chatId": "55AABBBBCCCC@c.us"}

Repetir com refresh=true não muda o resultado. A linha do contato já tem o wa_lid preenchido, e ele funciona — o job apenas não o lê.


Ambiente

DeskcommCRM  1.19.0 (imagem ghcr.io/melgarafael/deskcommcrm:stable)
commit       e142504
Instalação   self-host via hostgator-setup-kit/install.sh --yes, em VPS Hostinger
SO           Ubuntu 24.04.4 LTS · Docker 29.7.2 · Compose v5.5.0
Proxy        Caddy (o do kit), HTTPS Let's Encrypt
Banco        Supabase cloud (Postgres 17.6, região sa-east-1, pooler session mode)
WAHA         devlikeapro/waha:latest-2026.7.2 — engine NOWEB, tier CORE

Saída de /api/v1/health:

{"data":{"status":"healthy","version":"1.19.0",
"checks":{"supabase":{"status":"ok","latency_ms":78},
"redis":{"status":"ok","latency_ms":13},
"waha":{"status":"ok","latency_ms":10}}}}

Logs / observações

Resposta do job, depois de limpar avatar_updated_at para forçar o reprocessamento:

$ curl -H "Authorization: Bearer $INTERNAL_CRON_SECRET" \
    http://127.0.0.1:3000/api/v1/cron/contact-avatars

{"data":{"scanned":1,"updated":0,"no_picture":1,"failed":0}}

Estado da linha em contacts (números mascarados):

 nome  |  phone_number   |     wa_identity      |     wa_lid      | avatar_storage_path
-------+-----------------+----------------------+-----------------+---------------------
 ****  | +55AA9BBBBCCCC  | phone:+55AA9BBBBCCCC | <lid presente>  | (NULL)

Sem stack trace: o caminho percorrido é o de "sem foto", não o de erro — por isso failed: 0 e nada nos logs do app. É justamente o que torna o defeito silencioso em produção.

Sugestão de correção

Trocar a chatIdFromIdentity local por resolveWahaChatId (lib/waha/send.ts), incluindo wa_lid no .select() da query. Isso alinha o cron às outras duas implementações e resolve o caso comum sem chamada extra ao WAHA. Para contatos que só tenham telefone, o caminho de resolve-contact-whatsapp-id.ts (check-exists + phoneLookupVariants) cobriria o restante.

Se ajudar, abro um PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions