Skip to content

v2.3.7-lp: linkPreview com hero card + newsletter (canal) resolver#1

Open
ligge wants to merge 4 commits intomainfrom
v2.3.7-lp
Open

v2.3.7-lp: linkPreview com hero card + newsletter (canal) resolver#1
ligge wants to merge 4 commits intomainfrom
v2.3.7-lp

Conversation

@ligge
Copy link
Copy Markdown
Owner

@ligge ligge commented Apr 23, 2026

Escopo

Fork do Evolution API v2.3.7 com 3 patches críticos pro whatsapp-dispatcher do Ligge/Clube BHZ:

  1. linkPreviewOverride — preview de link pré-montado (contorna Baileys com shorteners tipo amzn.to, bit.ly)
  2. Upload real da thumbnail via prepareWAMessageMedia — renderiza como hero card (imagem grande) em vez de thumbnail lateral
  3. Newsletter (canal) support — cherry-pick do PR feat(channel): add support for @newsletter in sendMessage and findChannels EvolutionAPI/evolution-api#2296 upstream + endpoint extra newsletterMetadataFromInvite

Deployado na VM Oracle como evolution-api-lp:v2.3.7.3 (ARM64, build local).


Commits

ab99d39d  feat: newsletter metadata from invite code              ← v2.3.7.3
44518759  cherry-pick PR #2296 (newsletter sendMessage + findChannels) ← v2.3.7.2
62eed894  feat: linkPreview upload via prepareWAMessageMedia      ← v2.3.7.1
1c7dfc05  feat(text): suporte a linkPreviewOverride               ← v2.3.7-lp

1. linkPreviewOverride (1c7dfc05)

Problema: Baileys usa link-preview-js que falha ao seguir redirects de shorteners. URLs tipo amzn.to/XXX chegam no WhatsApp como texto puro sem preview, mesmo com linkPreview: true.

Solução: novo campo linkPreviewOverride no body de POST /message/sendText:

{
  "number": "5531999998888",
  "text": "Confira: https://amzn.to/4tWuwfo",
  "linkPreviewOverride": {
    "title": "Produto na Amazon",
    "description": "...",
    "canonicalUrl": "https://www.amazon.com.br/dp/XXX",
    "jpegThumbnail": "<base64 da imagem>"
  }
}

O fork monta um WAUrlInfo pronto (com matched-text, title, description, jpegThumbnail, canonicalUrl) e entrega direto ao sock.sendMessage — fazendo Baileys renderizar extendedTextMessage com card preview, igual WhatsApp oficial.

A URL original no texto fica intactacanonicalUrl é só metadata do card (não substitui o link exibido). Afiliados e tracking permanecem funcionais.

Arquivos

  • src/api/dto/sendMessage.dto.ts — classe LinkPreviewOverride + campo em Options e Metadata
  • src/api/integrations/channel/whatsapp/whatsapp.baileys.service.tstextMessage monta WAUrlInfo; sendMessageWithTyping prioriza override sobre boolean
  • src/validate/message.schema.ts — propriedade no JSONSchema de sendText

2. Upload real da thumbnail (62eed894)

Problema: v2.3.7.1 aceitava jpegThumbnail como base64, mas Baileys exibia só um thumbnail lateral pequeno (protobuf embed). Queríamos hero card.

Solução: quando linkPreviewOverride.jpegThumbnail ou thumbnailUrl vier, chama prepareWAMessageMedia({ image }, { upload: waUploadToServer, mediaTypeOverride: 'thumbnail-link' }) pra fazer upload real nos servidores do WhatsApp, obtendo highQualityThumbnail completo (directPath, mediaKey, mediaKeyTimestamp, fileSha256, etc).

WhatsApp passa a renderizar como hero card (imagem grande, igual WhatsApp oficial). Fallback pra thumbnail simples se upload falhar.

Arquivos

  • src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts — bloco textMessage reescrito com try/catch de upload

3. Newsletter (canal) support (44518759 + ab99d39d)

3.1 Cherry-pick do upstream (44518759)

Traz o PR EvolutionAPI/evolution-api#2296 ("feat(channel): add support for @newsletter in sendMessage and findChannels") que foi merged no branch develop upstream em 11/dez/2025 mas ainda não saiu em release tagueada.

  • POST /chat/findChannels/:instance — lista canais detectados via histórico de envios
  • sendMessage aceita number: <id>@newsletter
  • createJid reconhece sufixo @newsletter

3.2 newsletterMetadataFromInvite (ab99d39d)

O PR upstream não resolve invite code → JID (só lista canais que já tiveram envio). Adicionei endpoint novo pra evitar o chicken-and-egg (sem JID não envia, sem enviar não aparece em findChannels):

POST /chat/newsletterMetadataFromInvite/:instance
Body: { "inviteCode": "0029Vb7OgUv05MUYDGiozv3Y" }
      (aceita também: code, url)

Usa sock.newsletterMetadata('invite', code) do Baileys. Retorna JID + name + subscribers_count + picture. Aceita também URL completa (https://whatsapp.com/channel/XXX).

Arquivos

  • src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts — método newsletterMetadataFromInvite(inviteCode)
  • src/api/controllers/chat.controller.ts — método controller
  • src/api/routes/chat.router.ts — registra rota

Deploy

Build ARM64 nativo na VM Oracle Free Tier (aarch64):

cd /opt/evolution-api-src/fork
git pull
docker build -t evolution-api-lp:v2.3.7.3 .
sed -i 's|evolution-api-lp:v.*|evolution-api-lp:v2.3.7.3|' /opt/evolution-api/docker-compose.yml
docker compose -f /opt/evolution-api/docker-compose.yml up -d

Container roda healthy com mesmo .env do Evolution original — 100% retrocompat.

Testes manuais validados

  • sendText com linkPreviewOverride completo → hero card no WhatsApp (imagem Amazon forno Electrolux + título)
  • ✅ URL canônica no texto continua intacta (amzn.to/4tWuwfo → rastreável)
  • newsletterMetadataFromInvite resolveu 0029Vb7OgUv05MUYDGiozv3Y120363420354363779@newsletter ("DOIDO POR PROMOS")
  • sendText pro canal entrega + hero card renderiza com amzn.to

Notas de manutenção

  • Se subir release upstream > v2.3.7 com newsletter já incluído, dá pra rebase o branch em cima da nova tag. 44518759 vira merge-base zero.
  • linkPreviewOverride é custom nosso — não há PR upstream proposto. Mantém-se no fork.
  • Docker build não usa registry: imagem fica local na VM (evolution-api-lp:vX.Y.Z). Pra distribuir pra outras máquinas, publicar no GHCR/Docker Hub.

ligge and others added 4 commits April 20, 2026 17:07
Contorna a lib de link-preview do Baileys que falha com shorteners
(amzn.to, bit.ly, etc) permitindo o caller pre-montar o preview
(title, description, canonicalUrl, thumbnail).

Se data.linkPreviewOverride vier no body de POST /message/sendText,
textMessage monta um WAUrlInfo pronto e entrega ao sock.sendMessage
como linkPreview objeto (em vez de boolean), fazendo Baileys renderizar
extendedTextMessage com card preview -- igual WhatsApp oficial.

Preserva a URL original do texto (nao altera o que o usuario ve) --
canonicalUrl eh so o campo interno do card do WhatsApp.

Arquivos:
- src/api/dto/sendMessage.dto.ts: LinkPreviewOverride + Metadata
- src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:
  textMessage monta WAUrlInfo; sendMessageWithTyping prioriza override
- src/validate/message.schema.ts: linkPreviewOverride no schema do text

Uso (body POST /message/sendText/:instance):
  {
    "number": "553196018045",
    "text": "Oferta: https://amzn.to/ABC",
    "linkPreviewOverride": {
      "title": "Produto na Amazon",
      "description": "Descricao og:description",
      "canonicalUrl": "https://www.amazon.com.br/dp/XXX",
      "thumbnailUrl": "https://.../og-image.jpg"
    }
  }

Mantem compatibilidade: se linkPreviewOverride ausente, comportamento
original (Baileys decide via linkPreview boolean).
feat(channel): add support for @newsletter in sendMessage and findChannels
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants