@dianabots/baileys
v0.1.20
Published
Uma biblioteca WebSockets para interagir com o WhatsApp Web — dianabots.
Readme
📋 Índice Geral
Para facilitar a navegação por esta extensa documentação, os tópicos estão organizados por categorias. Clique nas seções para expandi-las:
- 📦 Instalação do Pacote
- 📱 Conexão padrão via QR Code
- 🔑 Conexão via Pairing Code (Sem QR)
- 🌐 Customizando a Identidade do Navegador
- ⚙️ Visão Geral das Opções de Conexão
- 💬 Mensagens de Texto e Menções
- 🖼️ Imagens (URL, Buffer e Local)
- 🎬 Vídeos e Notas de Vídeo (Bubbles)
- 🎙️ Áudios Simples e Notas de Voz (Gravações)
- 📄 Arquivos e Documentos Anexos
- 🎴 Envio de Figurinhas estáticas
- 📍 Localizações geográficas
- 👤 Envio de VCards de Contatos
- ❤️ Reagir e remover reações a mensagens
- 📊 Criação de Enquetes e Quizzes
- 📈 Manipulação de Resultados de Enquetes
- 🔄 Atualização de Enquetes em tempo real
- ↗️ Encaminhamento de Mensagens
- 🗑️ Revogação e Exclusão de Mensagens
- ✏️ Edição de Mensagens enviadas
- 📌 Fixação e Desafixação de Mensagens no Chat
- 🗂️ Álbuns de Mídia combinados
- 📅 Criação de Eventos integrados
- 📖 Envio de Status / Stories para Grupos
- 🏷️ Menções Ocultas em Status
- 📡 Postagens em Canais (Newsletter)
- 🔁 Respostas estruturadas de Fluxo (Flow)
- 🔘 Respostas de Clique de Botão
- 📎 Fixação Permanente no Chat (Keep)
- 📞 Agendamento de Chamadas de Voz/Vídeo
- 🔗 Convites de Grupo em formato card
- 🛍️ Compartilhamento de Produtos
- 👁️ Mensagens de Visualização Única (Foto/Vídeo)
- 👁️ Visualização Única V2 e Extensão
- ⏳ Ativação de Chats Efêmeros
- 🙈 Mensagens Ocultas com Spoilers
- 🎭 Wrap Automático de Status de Grupo
- 🎞️ Suporte a Figurinhas Lottie dinâmicas
- 🤖 Marcação de Resposta Gerada por IA
- 🔒 Exibição da Etiqueta de Serviço Oficial Meta
- 📍 Botões acoplados a Localização
- 🎛️ Quick Replies e Seções em botões
- 📋 Estruturas de Mensagens de Lista
- 🗃️ Botões de Modelo (Template Buttons)
- 🌊 Estruturas avançadas com Native Flow
- 🎠 Carrossel Interativo com Multi-Cards
- 📃 Envio de respostas de seleção de Lista
- 🎴 Upload de Pacotes Completos de Figurinhas
- 📢 Respostas com Anúncios Externos (Ad Cards)
- 💳 Solicitação de Transferência de Valores
- 🧾 Envio de Faturas detalhadas (Invoices)
- 📦 Envio de Confirmações de Pedidos (Orders)
- 💨 Controle de Mensagens Temporárias por tempo
- ⚡ Envio de Mensagens Brutas (Raw Proto)
- ✍️ Blocos textuais ricos (addText)
- 💻 Blocos de códigos estruturados (addCode)
- 📊 Tabelas dinâmicas ricas (addTable)
- 🖼️ Imagens e Grades de Imagens (addImage)
- 🎬 Vídeos e listas de vídeo estruturadas (addVideo)
- 🔗 Links de referências bibliográficas (addSource)
- 🎥 HScroll de Vídeos curtos (addReels)
- 🛍️ Cards de produtos interativos (addProduct)
- 📝 Postagens de redes sociais no chat (addPost)
- 💡 Dicas e observações rápidas (addTip)
- 🔮 Pílulas de sugestões rápidas (addSuggest)
- Mapa, LaTeX, Grids e Animações complexas
- Recebimento e Decodificação de Mensagens Ricas
🔌 Conexão & Inicialização
Nesta seção, você aprenderá a instalar e inicializar a biblioteca @dianabots/baileys de diferentes maneiras.
📦 Instalação
Adicione a biblioteca ao seu projeto Node.js usando o gerenciador de pacotes de sua preferência:
npm install @dianabots/baileys
# ou usando yarn
yarn add @dianabots/baileys📱 Conexão QR Code
Exemplo básico de inicialização com geração de QR Code no terminal e salvamento automático das credenciais:
// Importação no padrão CommonJS ou ESM
const {
default: makeWASocket,
useMultiFileAuthState,
DisconnectReason,
fetchLatestBaileysVersion
} = require('@dianabots/baileys')
async function start() {
// Define a pasta onde os arquivos de autenticação serão salvos
const { state, saveCreds } = await useMultiFileAuthState('auth_info')
const { version } = await fetchLatestBaileysVersion()
const sock = makeWASocket({
version,
auth: state,
printQRInTerminal: true // Exibe o QR Code diretamente no terminal
})
// Escuta atualizações de credenciais para salvar o estado da sessão
sock.ev.on('creds.update', saveCreds)
// Monitora alterações na conexão (reconecta automaticamente caso caia)
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'close') {
const code = lastDisconnect?.error?.output?.statusCode
if (code !== DisconnectReason.loggedOut) {
start() // Reconectar
}
} else if (connection === 'open') {
console.log('Bot Conectado com sucesso!')
}
})
}
start()🔑 Conexão Pairing Code
Ideal para servidores VPS ou ambientes onde não há visualização do terminal para leitura do QR Code. O código de 8 dígitos é retornado diretamente:
const sock = makeWASocket({ version, auth: state, printQRInTerminal: false })
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'close') {
if (lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut) start()
}
})
// Solicitar código de pareamento passando o número de telefone (DDI + DDD + Número)
if (!sock.authState.creds.registered) {
const code = await sock.requestPairingCode('5511999999999')
console.log('Seu código de pareamento é:', code)
}
// Também é possível forçar um código específico de 8 caracteres
const customCode = await sock.requestPairingCode('5511999999999', 'BOTDIANA')🌐 Identidade do Navegador
Você pode configurar como o seu bot é identificado nas sessões ativas do WhatsApp no celular (configuração browser):
const { Browsers } = require('@dianabots/baileys')
makeWASocket({
// Opções pré-definidas da biblioteca:
browser: Browsers.macOS('Chrome'), // MacOS rodando Chrome
browser: Browsers.windows('Chrome'), // Windows rodando Chrome
browser: Browsers.ubuntu('Chrome'), // Ubuntu rodando Chrome
browser: Browsers.baileys('Chrome'), // Padrão Baileys
// Ou defina uma identidade totalmente personalizada:
browser: ['Minha Empresa', 'Safari', '2.0.0']
})⚙️ Opções de Conexão
Lista das principais configurações disponíveis ao instanciar o socket do bot:
makeWASocket({
version,
auth: state,
printQRInTerminal: true,
browser: Browsers.macOS('Chrome'),
connectTimeoutMs: 20000, // Timeout de conexão
keepAliveIntervalMs: 30000, // Envio de PING para manter conexão ativa
markOnlineOnConnect: true, // Exibir bot como "Online"
syncFullHistory: false, // Desative para economizar consumo de RAM
generateHighQualityLinkPreview: false,// Pré-visualizações de links em alta resolução
emitOwnEvents: true, // Emitir eventos disparados pelo próprio bot
getMessage: async key => {
// Retorna mensagens salvas do banco de dados (ajuda em funções de quoted e decodificação)
return store?.messages?.[key.remoteJid]?.get(key.id)?.message
}
})📨 Eventos & Gerenciamento de Chats
📬 Receber Mensagens
Acompanhe a chegada de novas mensagens por meio do monitoramento do evento messages.upsert:
sock.ev.on('messages.upsert', async ({ messages, type }) => {
// Apenas processa mensagens recebidas em tempo real
if (type !== 'notify') return
for (const m of messages) {
if (!m.message) continue
if (m.key.fromMe) continue // Ignora mensagens enviadas pelo próprio bot
const jid = m.key.remoteJid
const isGroup = jid.endsWith('@g.us')
const sender = isGroup ? m.key.participant : jid
// Extrai o conteúdo textual independente do tipo de mensagem
const text =
m.message.conversation ||
m.message.extendedTextMessage?.text ||
m.message.imageMessage?.caption ||
m.message.videoMessage?.caption || ''
console.log(`Mensagem de ${sender}: ${text}`)
// Marca a mensagem recebida como lida (visualizada)
await sock.readMessages([m.key])
// Envia o estado de "digitando..." para a conversa
await sock.sendPresenceUpdate('composing', jid)
}
})👥 Manipulação de Grupos
Métodos para gerenciar membros, títulos, descrições e obter informações gerais sobre grupos:
// Escutar quando participantes entram, saem, são promovidos ou rebaixados
sock.ev.on('group-participants.update', ({ id, participants, action }) => {
console.log(`Grupo: ${id} | Membros: ${participants} | Ação: ${action}`)
// action pode ser: 'add' (entrou) | 'remove' (saiu) | 'promote' (adm) | 'demote' (rebaixado)
})
// Obter dados completos de um grupo (Nome, Descrição, Participantes, etc)
const meta = await sock.groupMetadata('[email protected]')
console.log(`Nome do Grupo: ${meta.subject}`)
// Listar todos os grupos em que o bot está inserido
const groups = await sock.groupFetchAllParticipating()
// Adicionar, remover, promover ou rebaixar membros
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'add')
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'remove')
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'promote')
await sock.groupParticipantsUpdate(groupJid, ['[email protected]'], 'demote')
// Alterar as propriedades do grupo
await sock.groupUpdateSubject(groupJid, 'Novo Nome do Grupo')
await sock.groupUpdateDescription(groupJid, 'Nova descrição detalhada do grupo')
// Bloquear ou liberar o envio de mensagens para apenas administradores
await sock.groupSettingUpdate(groupJid, 'announcement') // Apenas ADMs enviam
await sock.groupSettingUpdate(groupJid, 'not_announcement') // Todos enviam
// Mencionar todos os membros do grupo de uma vez
const groupMeta = await sock.groupMetadata(groupJid)
const members = groupMeta.participants.map(p => p.id)
await sock.sendMessage(groupJid, {
text: members.map(m => `@${m.split('@')[0]}`).join(' '),
mentions: members
})📤 Envio de Mensagens Básicas & Mídias
Exemplos de como enviar texto, fotos, vídeos, áudios, figurinhas, contatos e localizações.
💬 Texto
// Mensagem de texto simples
await sock.sendMessage(jid, { text: 'Olá, esta é uma mensagem!' })
// Mensagem marcando usuários específicos (menção) respondendo a outra mensagem (quoted)
await sock.sendMessage(jid, {
text: 'Olá @5511999999999!',
mentions: ['[email protected]']
}, { quoted: m })🖼️ Imagem
// Envio informando uma URL externa
await sock.sendMessage(jid, {
image: { url: 'https://example.com/foto.jpg' },
caption: 'Esta é a legenda da imagem'
})
// Envio de imagem através de um arquivo Buffer ou arquivo local
await sock.sendMessage(jid, {
image: fs.readFileSync('foto.jpg'),
caption: 'Enviada através de buffer'
})🎬 Vídeo
// Vídeo tradicional com legenda
await sock.sendMessage(jid, {
video: { url: 'https://example.com/video.mp4' },
caption: 'Legenda do vídeo',
gifPlayback: false // Se true, o vídeo será enviado em loop infinito sem áudio
})
// Nota de Vídeo Circular (Mensagem de vídeo bubble / PTV)
await sock.sendMessage(jid, {
video: fs.readFileSync('video.mp4'),
ptv: true // Ativa o formato circular
})🎙️ Áudio & Notas de Voz
// Enviar arquivo de áudio clássico (exibe player de duração)
await sock.sendMessage(jid, {
audio: { url: 'https://example.com/musica.mp3' },
mimetype: 'audio/mpeg'
})
// Enviar nota de voz (exibe gravação com microfone azul - PTT)
await sock.sendMessage(jid, {
audio: fs.readFileSync('gravacao.ogg'),
mimetype: 'audio/ogg; codecs=opus',
ptt: true // Ativa a nota de voz
})📄 Documento
await sock.sendMessage(jid, {
document: fs.readFileSync('relatorio.pdf'),
mimetype: 'application/pdf',
fileName: 'Relatorio_Anual.pdf',
caption: 'Legenda explicativa opcional'
})🎴 Figurinha
// Envia arquivo WebP como figurinha estática
await sock.sendMessage(jid, { sticker: fs.readFileSync('figurinha.webp') })📍 Localização
await sock.sendMessage(jid, {
location: {
degreesLatitude: -23.55052,
degreesLongitude: -46.633308,
name: 'Praça da Sé',
address: 'São Paulo, Brasil'
}
})👤 Contato
await sock.sendMessage(jid, {
contacts: {
displayName: 'Diana Suporte',
contacts: [{
vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:Diana Suporte\nTEL;type=CELL;type=VOICE;waid=5511999999999:+55 11 99999-9999\nEND:VCARD'
}]
}
})💬 Recursos de Interação & Enquetes
❤️ Reação
// Reagir com um emoji a uma mensagem específica utilizando a chave (key) dela
await sock.sendMessage(jid, { react: { text: '👍', key: m.key } })
// Para remover a reação, basta enviar o texto vazio
await sock.sendMessage(jid, { react: { text: '', key: m.key } })📊 Enquete
// Enquete básica de escolha única
await sock.sendMessage(jid, {
poll: {
name: 'Qual seu tema preferido?',
values: ['Modo Claro', 'Modo Escuro', 'Sistema'],
selectableCount: 1 // 1 = escolha única. 0 = multipla escolha
}
})
// Enquete avançada com parâmetros adicionais
await sock.sendMessage(jid, {
poll: {
name: 'Escolha de Cores',
values: ['Vermelho', 'Azul'],
selectableCount: 1,
endDate: new Date('2025-12-31'),
hideVoter: true, // Oculta quem votou em qual opção
canAddOption: false,
toAnnouncementGroup: false
}
})
// Quiz (Enquete estruturada contendo uma resposta certa)
await sock.sendMessage(jid, {
poll: {
name: 'Quem descobriu a gravidade?',
values: ['Tesla', 'Newton', 'Einstein'],
selectableCount: 1,
pollType: 1, // 1 representa QUIZ
correctAnswer: 'Newton'
}
})📈 Resultado da Enquete
Envio manual de um gráfico/card contendo o consolidado dos votos de uma enquete:
await sock.sendMessage(jid, {
pollResult: {
name: 'Resultado da Votação',
votes: [
{ name: 'Opção A', voteCount: 15 },
{ name: 'Opção B', voteCount: 8 }
],
pollType: 0 // 0 = ENQUETE, 1 = QUIZ
}
})🔄 Atualização da Enquete
Usado para sincronizar ou enviar um voto computado a uma enquete ativa:
await sock.sendMessage(jid, {
pollUpdate: {
key: pollMessage.key, // Chave da mensagem da enquete original
vote: encryptedVotePayload, // Payload do voto criptografado
metadata: optionalMetadata
}
})↗️ Encaminhar
await sock.sendMessage(jid, {
forward: messageToForward,
force: true // Força a exibição do rótulo "Mensagem Encaminhada"
})🗑️ Apagar Mensagem
Apaga mensagens para todos no chat:
await sock.sendMessage(jid, { delete: messageToDelete.key })✏️ Editar Mensagem
Edita o conteúdo textual de uma mensagem enviada anteriormente:
await sock.sendMessage(jid, {
text: 'Este texto foi corrigido via edição',
edit: messageToEdit.key
})📌 Fixar Mensagem
Fixa ou desafixa mensagens no topo da conversa:
// Fixar por 24 horas (tempo em segundos)
await sock.sendMessage(jid, {
pin: m.key,
type: 1, // 1 = Fixar
time: 86400 // 86400 = 1 dia | 604800 = 7 dias | 2592000 = 30 dias
})
// Desafixar mensagem
await sock.sendMessage(jid, { pin: m.key, type: 2 })✨ Elementos Avançados & Wrappers
🗂️ Álbum
Permite o envio agrupado de mídias (fotos e vídeos) em uma única mensagem de grade:
await sock.sendMessage(jid, {
album: [
{ image: { url: 'https://example.com/foto1.jpg' }, caption: 'Legenda do item 1' },
{ image: { url: 'https://example.com/foto2.jpg' }, caption: 'Legenda do item 2' },
{ video: { url: 'https://example.com/video.mp4' }, caption: 'Vídeo do álbum' }
]
})📅 Evento
Cria convites de eventos integrados à agenda dos participantes:
await sock.sendMessage(jid, {
event: {
name: 'Lançamento Oficial Diana',
description: 'Apresentação dos novos recursos do bot',
startDate: new Date('2025-12-01T10:00:00'),
endDate: new Date('2025-12-01T12:00:00'),
location: {
degreesLatitude: -23.55052,
degreesLongitude: -46.633308,
name: 'Auditório Principal'
},
extraGuestsAllowed: true // Permite acompanhantes
}
})
// Evento acoplado a um agendamento de chamada nativa
await sock.sendMessage(jid, {
event: {
name: 'Chamada de Alinhamento',
startDate: new Date('2025-12-01T10:00:00'),
call: 'audio', // 'audio' ou 'video'
isScheduleCall: true
}
})📖 Status / Story de Grupo
Publique um status ou story visível para todos os integrantes de um grupo específico:
// Enviar status textual
await sock.sendMessage(groupJid, {
groupStatusMessage: { text: 'Aviso importante para o grupo!' }
})
// Enviar status de imagem
await sock.sendMessage(groupJid, {
groupStatusMessage: {
image: { url: 'https://example.com/status.jpg' },
caption: 'Legenda explicativa'
}
})
// Enviar status de áudio gravado (nota de voz)
await sock.sendMessage(groupJid, {
groupStatusMessage: {
audio: fs.readFileSync('status_voz.ogg'),
mimetype: 'audio/ogg; codecs=opus',
ptt: true
}
})🏷️ Menção no Status
Permite marcar usuários de forma oculta ao publicar um status (eles receberão notificações):
// Marcando múltiplos JIDs de contatos ou grupos
await sock.sendMessage(['[email protected]', '[email protected]'], {
text: 'Status especial para vocês',
backgroundColor: '#ff6b9d'
})📡 Canal (Newsletter)
Melhoria v0.1.16: O envio de mídias para canais foi corrigido. Resolvidos os bugs de ausência do atributo
mediatypee da falta de miniaturas.
Para postagens em canais onde o bot é administrador (JIDs terminados em @newsletter). Canais não possuem encriptação de ponta a ponta:
const channelJid = '120363425154682710@newsletter'
// Texto simples
await sock.sendMessage(channelJid, { text: 'Olá inscritos!' })
// Imagens (URL, arquivo local ou Buffer)
await sock.sendMessage(channelJid, {
image: { url: 'https://example.com/post.jpg' },
caption: 'Capa do dia'
})
// Vídeos e Áudios
await sock.sendMessage(channelJid, {
video: { url: 'https://example.com/tutorial.mp4' },
caption: 'Assista agora!'
})
// Enquete em Canal
await sock.sendMessage(channelJid, {
poll: {
name: 'O que prefere no bot?',
values: ['Facilidade', 'Recursos', 'Suporte'],
selectableCount: 1
}
})🔁 Resposta de Fluxo (Flow)
Permite enviar respostas estruturadas simulando interações nativas do tipo Flow:
await sock.sendMessage(jid, {
flowReply: {
name: 'quick_reply',
paramsJson: '{"id":"botao_1"}',
text: 'Ação executada',
format: 1,
version: 1
}
})🔘 Resposta de Botão
Simula e envia o evento de clique em um botão interativo:
// Simular clique em botão de template
await sock.sendMessage(jid, {
buttonReply: { displayText: 'Confirmar Cadastro', id: 'confirm_btn', index: 0 },
type: 'template'
})
// Simular clique em botão simples (Plain)
await sock.sendMessage(jid, {
buttonReply: { displayText: 'Não, obrigado', id: 'cancel_btn' },
type: 'plain'
})📎 Manter no Chat (Keep)
Evita que uma mensagem de chat temporário seja apagada:
await sock.sendMessage(jid, {
keep: m.key,
keepType: 1 // 1 = Manter mensagem, 2 = Remover proteção (unkeep)
})📞 Chamada Agendada
await sock.sendMessage(jid, {
call: {
time: Date.now() + 3600000, // Agendado para daqui a 1 hora
type: 1, // 1 = Áudio, 2 = Vídeo
title: 'Reunião de Escopo'
}
})🔗 Convite de Grupo
Cria e envia um card estruturado contendo o convite para um grupo:
await sock.sendMessage(jid, {
groupInvite: {
jid: '[email protected]',
inviteCode: 'código_de_entrada',
inviteExpiration: Date.now() + 86400000, // Expiração (24 horas)
subject: 'Grupo de Clientes VIP',
text: 'Junte-se à nossa comunidade exclusiva!'
}
})🛍️ Produto
await sock.sendMessage(jid, {
product: {
productImage: fs.readFileSync('celular.jpg'),
productId: 'prod_99',
title: 'Smartphone Diana S25',
description: 'O celular mais moderno do mercado',
currencyCode: 'BRL',
priceAmount1000: 2999000, // R$ 2.999,00 (Valor em milésimos)
retailerId: 'sku_diana_s25',
url: 'https://loja.dianabots.com/s25'
},
businessOwnerJid: '[email protected]' // JID comercial obrigatório
})👁️ Visualização Única
Envia imagens ou vídeos configurados para serem visualizados apenas uma vez:
await sock.sendMessage(jid, {
image: { url: 'https://example.com/secreta.jpg' },
viewOnce: true // Ativa visualização única
})👁️ Visualização Única V2
// Utilizando a estrutura V2 do WhatsApp
await sock.sendMessage(jid, {
image: { url: 'https://example.com/secreta.jpg' },
viewOnceV2: true
})
// Com suporte estendido
await sock.sendMessage(jid, {
image: { url: 'https://example.com/secreta.jpg' },
viewOnceV2Extension: true
})⏳ Efêmero
// Ativa o envio de uma mensagem temporária avulsa no chat
await sock.sendMessage(jid, {
text: 'Esta mensagem desaparecerá no tempo configurado no chat',
ephemeral: true
})🙈 Spoiler
Envia imagens ocultando a legenda com filtro de spoiler:
await sock.sendMessage(jid, {
image: { url: 'https://example.com/revelacao.jpg' },
caption: 'Este é o grande final da temporada!',
spoiler: true // Oculta legenda
})🎭 Wrap de Status de Grupo
Wrapper automático para enviar mídias encapsuladas como status de grupo:
await sock.sendMessage(jid, {
text: 'Status enviado via automação',
groupStatus: true // Encapsula a mensagem automaticamente
})🎞️ Figurinha Lottie
// Envia animação lottie como figurinha dinâmica
await sock.sendMessage(jid, {
sticker: fs.readFileSync('animacao.webp'),
isLottie: true
})🤖 Ícone de IA
Exibe no cabeçalho ou nas informações da mensagem o selo oficial de "Mensagem Gerada por IA". Suportado apenas em chats privados:
await sock.sendMessage(jid, { text: 'Esta é uma resposta gerada por IA', ai: true })🔒 Etiqueta Secure Meta Service
Envia mensagens de texto contendo a etiqueta azul de canal ou serviço oficial Meta verificado:
await sock.sendMessage(jid, {
text: 'Serviço de Atendimento Autorizado',
secureMetaServiceLabel: true
})🎛️ Mensagens Interativas & Botões
📍 Botões com Cabeçalho de Localização
Permite criar botões estruturados contendo dados de localização no topo (Header do Tipo 6):
await sock.sendMessage(jid, {
buttonsMessage: {
locationMessage: {
degreesLatitude: -23.55052,
degreesLongitude: -46.633308,
name: 'Minha Empresa',
address: 'Endereço Comercial',
jpegThumbnail: './img/fachada.jpg' // Aceita arquivo local, URL ou Buffer
},
contentText: 'Confirme sua visita no botão abaixo',
footerText: 'Powered by @dianabots/baileys',
buttons: [
{ buttonId: 'confirm_visit', buttonText: { displayText: 'Confirmar Agendamento' }, type: 1 }
],
headerType: 6 // 6 indica cabeçalho de Localização
}
})Tipos suportados para headerType:
| ID | Formato do Cabeçalho |
|:--:|----------------------|
| 1 | Texto simples |
| 2 | Imagem |
| 3 | Vídeo |
| 4 | Documento |
| 6 | Localização geográfica |
🎛️ Botões
// Botões simples de resposta rápida (Quick Reply)
await sock.sendMessage(jid, {
text: 'Selecione sua categoria de interesse',
footer: 'Menu de Seleção',
buttons: [
{ id: 'cat_tech', text: 'Tecnologia' },
{ id: 'cat_arts', text: 'Artes' }
]
})
// Shorthand prático: Criar menu de lista integrado a um único botão
await sock.sendMessage(jid, {
text: 'Selecione abaixo',
buttons: [{
text: 'Ver Seções',
sections: [{
title: 'Principais Serviços',
rows: [
{ id: 'serv_1', title: 'Consultoria', description: 'Atendimento especializado' },
{ id: 'serv_2', title: 'Suporte', description: 'Correção de erros' }
]
}]
}]
})📋 Mensagem de Lista
await sock.sendMessage(jid, {
text: 'Por favor, escolha uma opção abaixo', // Mapeado para description
title: 'Central de Serviços', // Mapeado para title
buttonText: 'Ver Categorias', // Rótulo do botão disparador da lista
footer: 'Selecione apenas uma opção',
sections: [
{
title: 'Desenvolvimento',
rows: [
{ id: 'dev_web', title: 'Websites', description: 'Desenvolvimento frontend/backend' },
{ id: 'dev_app', title: 'Aplicativos', description: 'Mobile nativo iOS/Android' }
]
},
{
title: 'Design',
rows: [
{ id: 'design_logo', title: 'Logotipo & Branding' }
]
}
]
})🗃️ Botões de Modelo (Template Buttons)
Neste formato, você pode mesclar links web, chamadas telefônicas e respostas rápidas:
await sock.sendMessage(jid, {
text: 'Central de Informações Diana',
footer: 'Clique em uma das opções',
templateButtons: [
{ id: 'quick_rep_1', text: 'Falar com Atendente' },
{ url: 'https://dianabots.com', text: 'Acessar Site Oficial' },
{ call: '+5511999999999', text: 'Ligar para a Central' }
]
})🌊 Fluxo Nativo (Native Flow)
Permite construir interações nativas sofisticadas diretamente de acordo com as chaves inseridas:
// Botões automatizados via Native Flow
await sock.sendMessage(jid, {
text: 'Painel Interativo',
nativeFlow: [
{ id: 'op_1', text: 'Opção Rápida 1' },
{ url: 'https://example.com', text: 'Abrir Site' },
{ copy: 'CUPOMDIANA', text: 'Copiar Cupom' },
{ call: '+5511999999999', text: 'Iniciar Chamada' }
]
})
// Banner de Oferta por tempo limitado (offerText)
await sock.sendMessage(jid, {
text: 'Super Desconto!',
offerText: '50% de Desconto',
offerUrl: 'https://example.com/desconto',
offerCode: 'DIANA50',
offerExpiration: 1800000000,
nativeFlow: [{ id: 'claim_now', text: 'Garantir Cupom' }]
})Detecção Automática de Tipos: A biblioteca converte automaticamente as chaves inseridas para as chamadas correspondentes do WhatsApp (
id->quick_reply,url->cta_url,copy->cta_copy,call->cta_call,sections->single_select).
🎠 Carrossel
Permite exibir múltiplos cartões com rolagem horizontal contendo mídias e botões independentes:
await sock.sendMessage(jid, {
text: 'Portfólio de Produtos',
footer: 'Navegue pelo carrossel',
cards: [
{
image: { url: 'https://example.com/card1.jpg' },
title: 'Plano Básico',
caption: 'Ideal para iniciar sua jornada',
footer: 'R$ 49/mês',
nativeFlow: [{ name: 'quick_reply', paramsJson: '{"id":"choose_basic"}', text: 'Assinar Plano' }]
},
{
image: { url: 'https://example.com/card2.jpg' },
title: 'Plano Premium',
caption: 'Acesso total aos nossos recursos',
footer: 'R$ 99/mês',
nativeFlow: [{ name: 'quick_reply', paramsJson: '{"id":"choose_premium"}', text: 'Assinar Plano' }]
}
]
})🔧 Recursos Especializados & Outros
📃 Resposta de Lista
Envia uma confirmação programática de resposta contendo o ID e os detalhes do item selecionado:
await sock.sendMessage(jid, {
listReply: {
title: 'Confirmação de Seleção',
description: 'Você escolheu o Serviço A',
id: 'serv_1' // ID correspondente ao item selecionado
}
})🎴 Pacote de Figurinhas
Carrega um arquivo contendo múltiplas figurinhas empacotadas de uma só vez. A biblioteca processa e ajusta os formatos necessários:
await sock.sendMessage(jid, {
cover: fs.readFileSync('capa_pack.webp'), // Imagem de capa obrigatória
name: 'Diana Pack',
publisher: 'dianabots',
description: 'Pacote oficial de figurinhas',
stickers: [
{ data: fs.readFileSync('stk1.webp'), emojis: ['👍'], accessibilityLabel: 'Joinha' },
{ data: { url: 'https://example.com/stk2.webp' }, emojis: ['❤️'] }
]
})📢 Resposta de Anúncio Externo
Cria balões enriquecidos exibindo banners, links externos e descrições detalhadas (Ad Cards):
await sock.sendMessage(jid, {
text: 'Confira as novidades no blog',
externalAdReply: {
title: 'Artigo Especial Diana',
body: 'Como utilizar bots para alavancar seu negócio',
thumbnail: fs.readFileSync('capa_artigo.jpg'), // Buffer obrigatório
url: 'https://dianabots.com/blog/bot-whatsapp',
mediaType: 1,
largeThumbnail: true // Exibe miniatura ampliada
}
})💳 Solicitar Pagamento
Gera um card solicitando transferência monetária através do WhatsApp Pay:
await sock.sendMessage(jid, {
text: 'Pagamento referente à contratação',
requestPaymentFrom: '[email protected]',
amount1000: 50000000, // R$ 50.000,00 (Valor em milésimos)
currencyCodeIso4217: 'BRL',
expiryTimestamp: Date.now() + 86400000 // Expiração em 24h
})🧾 Fatura (Invoice)
// Envio acoplado a um arquivo PDF
await sock.sendMessage(jid, {
document: fs.readFileSync('fatura.pdf'),
mimetype: 'application/pdf',
fileName: 'Fatura_Servico.pdf',
invoiceNote: 'Fatura digital detalhada para pagamento'
})📦 Pedido (Order)
Cria e envia um card contendo os dados organizados de uma compra/pedido comercial:
await sock.sendMessage(jid, {
order: {
orderId: 'ped_29910',
thumbnail: fs.readFileSync('produto.jpg'),
itemCount: 3,
status: 'PAYMENT_PENDING',
surface: 'CATALOG',
message: 'Seu pedido foi recebido com sucesso!',
orderTitle: 'Pedido #29910',
sellerJid: '[email protected]',
token: 'token_de_seguranca_unico',
totalAmount1000: 150000000, // R$ 150.000,00 (Em milésimos)
totalCurrencyCode: 'BRL'
}
})💨 Mensagens Temporárias
Ative ou desative as mensagens temporárias em chats de grupos especificando o tempo de duração:
// Ativar (Duração padrão de 24 horas - 86400 segundos)
await sock.sendMessage(groupJid, { disappearingMessagesInChat: true })
// Desativar mensagens temporárias
await sock.sendMessage(groupJid, { disappearingMessagesInChat: false })
// Configurar tempo de expiração customizado (Exemplo: 7 dias)
await sock.sendMessage(groupJid, { disappearingMessagesInChat: 604800 })Aviso: Suportado exclusivamente em chats de grupos (
@g.us).
⚡ Mensagem Bruta (Raw)
Caso queira contornar as validações da biblioteca e enviar uma mensagem formatada diretamente nas especificações do WAProto:
await sock.sendMessage(jid, {
raw: true, // Ignora o pré-processador da biblioteca
extendedTextMessage: {
text: 'Minha mensagem enviada no padrão proto cru do WhatsApp'
}
})🤖 Formatação Avançada de Respostas Ricas (IA)
As Mensagens Ricas (AIRichResponseMessage) são balões de formatação avançada criados para se assemelharem às interações estruturadas de Inteligência Artificial nativas do WhatsApp.
⚠️ Atenção: Os parâmetros
contentText,headerText,footerTextedisclaimerTextnão atuam como chaves de disparo. O envio isolado desses campos gerará uma falha do tipo Error: Invalid media type. Certifique-se de sempre inserir ao menos uma mídia rica disparadora (code,table,richImage,richResponse, etc).
✍️ addText
// ✅ Forma correta de enviar blocos textuais ricos usando o array richResponse
await sock.sendMessage(jid, {
richResponse: [
{ text: 'Este é um bloco textual gerado via IA contendo formatações de *itálico* e **negrito**.' }
],
headerText: 'Título Informativo',
footerText: 'Informações Finais',
disclaimerText: 'Mensagem gerada por Inteligência Artificial'
})💻 addCode
Insere trechos de códigos com destaque e formatação estruturada na conversa:
await sock.sendMessage(jid, {
code: 'const soma = (a, b) => a + b;\nconsole.log(soma(5, 10));',
language: 'javascript', // Linguagem para formatação do código
headerText: 'Exemplo prático de JavaScript:',
footerText: 'Fim do trecho de código'
})Lista de chaves de linguagens suportadas pela biblioteca:
| Linguagem | Chaves Suportadas |
|---|---|
| JavaScript | javascript, js |
| TypeScript | typescript, ts |
| Python | python, py |
| Go | go, golang |
| C++ | cpp, c++ |
| Rust | rust, rs |
| Java | java |
| PHP | php |
| Ruby | ruby, rb |
| Kotlin | kotlin, kt |
| Swift | swift |
| C | c |
| SQL / Banco de Dados | sql, mysql, postgresql, sqlite |
| Bash / Shell | bash, sh, shell |
| HTML / CSS | html, css |
| JSON / YAML | json, yaml, yml |
📊 addTable
await sock.sendMessage(jid, {
table: [
['Produto', 'Quantidade', 'Preço'], // Primeira linha define os cabeçalhos
['Celular', '10', 'R$ 2999'],
['Notebook', '5', 'R$ 4500']
],
title: 'Inventário de Estoque',
headerText: 'Confira as tabelas atualizadas',
footerText: 'Dados de Dezembro de 2025'
})
// Tabela sem cabeçalho (utilizando a chave noHeading)
await sock.sendMessage(jid, {
table: [
['Taxa de Entrega', 'R$ 15,00'],
['Desconto Aplicado', '-R$ 10,00']
],
noHeading: true,
title: 'Detalhamento Financeiro'
})🖼️ addImage
// Envio de imagem rica unitária
await sock.sendMessage(jid, {
richImage: 'https://example.com/banner.jpg',
headerText: 'Capa da Campanha'
})
// Envio de múltiplas imagens em formato grade rica (Grid)
await sock.sendMessage(jid, {
richImage: [
'https://example.com/imagem1.jpg',
'https://example.com/imagem2.jpg',
'https://example.com/imagem3.jpg'
],
headerText: 'Grade de fotos do evento'
})🎬 addVideo
// Envio de vídeo rico com definição opcional de duração (sintaxe: 'url|segundos')
await sock.sendMessage(jid, {
richVideo: 'https://example.com/video.mp4|60', // 60 segundos
headerText: 'Apresentação Institucional'
})
// Lista contendo múltiplos vídeos ricos em sequência
await sock.sendMessage(jid, {
richVideo: [
'https://example.com/video1.mp4|30',
'https://example.com/video2.mp4|45'
],
headerText: 'Lista de reprodução de tutoriais'
})🔗 addSource
Permite indexar fontes de referências externas contendo ícones e links:
await sock.sendMessage(jid, {
source: [
{
url: 'https://wikipedia.org',
title: 'Artigo Principal Wikipedia',
display_name: 'Wikipedia',
subtitle: 'Enciclopédia Livre',
favicon: 'https://wikipedia.org/favicon.ico'
}
],
headerText: 'Fontes consultadas'
})🎥 addReels
Cria uma listagem com rolagem horizontal contendo vídeos curtos (Reels):
await sock.sendMessage(jid, {
reels: [
{
username: 'criador_tech',
videoUrl: 'https://example.com/video.mp4',
thumbnailUrl: 'https://example.com/capa.jpg',
profileIconUrl: 'https://example.com/avatar.jpg',
reels_title: 'Como automatizar chats',
likes_count: 5200,
view_count: 90000,
reel_source: 'IG',
is_verified: true
}
],
headerText: 'Destaques em vídeos curtos'
})🛍️ addProduct
// Produto único rico (Layout Single)
await sock.sendMessage(jid, {
richProduct: {
title: 'Camiseta Premium',
brand: 'Diana Vestuário',
price: 'R$ 79,90',
product_url: 'https://loja.dianabots.com/camiseta',
image_url: 'https://example.com/camiseta.jpg'
},
headerText: 'Sugestão de Compra'
})
// Múltiplos produtos ricos (Layout HScroll com rolagem)
await sock.sendMessage(jid, {
richProduct: [
{ title: 'Item A', price: 'R$ 29', product_url: 'https://loja.com/a', image_url: 'https://loja.com/a.jpg' },
{ title: 'Item B', price: 'R$ 39', product_url: 'https://loja.com/b', image_url: 'https://loja.com/b.jpg' }
],
headerText: 'Confira as promoções do dia'
})📝 addPost
Publicações ricas simulando redes sociais:
await sock.sendMessage(jid, {
richPost: {
username: 'dianabots_oficial',
profile_picture_url: 'https://example.com/avatar.jpg',
is_verified: true,
thumbnail_url: 'https://example.com/post_capa.jpg',
post_caption: 'Acabamos de lançar as respostas ricas para o bot!',
likes_count: 4500,
post_url: 'https://instagram.com/p/post_id',
source_app: 'INSTAGRAM',
orientation: 'LANDSCAPE'
},
headerText: 'Publicação Recente'
})💡 addTip
Adiciona blocos explicativos de dicas no rodapé ou cabeçalho das respostas ricas:
await sock.sendMessage(jid, {
tip: 'Dica: Você pode encadear múltiplas tabelas e blocos utilizando o array richResponse.',
headerText: 'Dica de Uso'
})🔮 addSuggest
Exibe pílulas horizontais contendo botões de sugestões rápidas para facilitar a resposta dos usuários:
await sock.sendMessage(jid, {
contentText: 'O que você deseja fazer agora?',
suggest: [
'Ver exemplo de código',
'Acessar tabelas',
'Falar com suporte'
]
})🗺️ Mapa Rico, LaTeX, Grades & Animações
// LaTeX (Expressões matemáticas formatações ricas)
await sock.sendMessage(jid, {
latex: {
text: 'Equação de Einstein:',
expressions: [
{ expression: 'E = mc^2', width: 120, height: 40 }
]
},
headerText: 'Física Teórica'
})
// Mapa Rico integrado com marcadores
await sock.sendMessage(jid, {
map: {
centerLatitude: -23.55052,
centerLongitude: -46.633308,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
showInfoList: true,
annotations: [
{ number: 1, latitude: -23.55052, longitude: -46.633308, title: 'São Paulo', body: 'Cidade Central' }
]
},
headerText: 'Coordenadas Geográficas'
})📥 Receber & Decodificar Mensagem Rica
Para capturar e decodificar mensagens ricas recebidas pelo bot, utilize a seguinte estrutura no escutador messages.upsert:
const { normalizeMessageContent, parseRichMessage } = require('@dianabots/baileys')
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
const inner = normalizeMessageContent(msg.message)
const parsed = parseRichMessage(inner?.richResponseMessage)
if (!parsed) continue
for (const sub of parsed.submessages) {
switch (sub.type) {
case 'text': console.log('Teks:', sub.text); break
case 'code': console.log('Código:', sub.language, sub.raw); break
case 'table': console.log('Tabela:', sub.title, sub.rows); break
case 'gridImage': console.log('Grid Image:', sub.gridImageUrl); break
case 'inlineImage': console.log('Inline Image:', sub.imageUrl); break
case 'dynamic': console.log('Dynamic:', sub.url); break
case 'map': console.log('Map:', sub.centerLatitude, sub.centerLongitude); break
case 'latex': console.log('LaTeX:', sub.expressions); break
case 'contentItems': console.log('Content Items:', sub.items); break
}
}
}
})🏛️ Licença
Este projeto é distribuído sob os termos da licença MIT. Veja o arquivo LICENSE para mais informações.
