npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@areumtecnologia/wasockets

v2.0.0

Published

WhatsApp API Modification By areumtecnologia

Readme

WaSockets - API do WhatsApp Web em TypeScript/JavaScript


⚠️ Nota Importante e Licença

Esta biblioteca é uma modificação independente e não é de forma alguma afiliada, endossada ou associada ao WhatsApp ou à Meta Inc. O uso desta ferramenta é de sua inteira responsabilidade. Desencorajamos fortemente o uso para spam, envio em massa não solicitado ou qualquer prática que viole os Termos de Serviço do WhatsApp.

O projeto é licenciado sob a licença MIT e incorpora componentes sob a licença GPL-3.0 (devido ao uso de criptografia do libsignal).


🚀 Diferenciais e Correções da Áreum Tecnologia

O WaSockets foi criado para resolver problemas crônicos de estabilidade e adicionar recursos ausentes na versão original do Baileys. Abaixo estão as principais melhorias implementadas:

| Categoria | Recurso / Correção | Descrição | | :--- | :--- | :--- | | Criptografia & Sessão | Correção de descriptografia em grupos (pn/lid mismatch) | Corrige a falha crítica que impedia a descriptografia correta de mensagens quando a identidade de um participante alternava entre o número de telefone (PN) e o ID interno (LID). | | Criptografia & Sessão | Descriptografia robusta de Enquetes/Eventos | Resolve o erro AES-GCM Unsupported state or unable to authenticate data garantindo que o autor original seja extraído do objeto de mensagem persistido. | | Estabilidade | Versão Web Estabilizada | Integração com o protocolo Web v2.3000.1038819500 e restauração da função fetchLatestWaWebVersion para buscar sempre a versão de compatibilidade mais recente e funcional do WhatsApp. | | Eventos | Buffer de Eventos Corrigido | Adicionada a propriedade shouldIncrementChatUnread no buffer de eventos para garantir um controle preciso e confiável de mensagens não lidas no chat. | | Segurança | Sessões de Autenticação Seguras | Remoção de adaptadores de autenticação inseguros/obsoletos (arquivo único ou MongoDB que causavam corrupção de estado), unificando e otimizando o uso do useMultiFileAuthState. | | Comunidades | Suporte a Comunidades | Implementação nativa para escutar e processar comentários em canais de comunidades (handle comment message) e reações em comunidades. | | Eventos do WhatsApp | Manipulação de Eventos e Respostas | Suporte a reações de edição de eventos (handle event edit) e decodificação das respostas de presença em eventos (getAggregateResponsesInEventMessage). | | Mídia | Correções de Miniaturas e Status | Correção de falhas na extração de miniaturas (extractImageThumb), na geração de previews de links, no envio de mídias em álbuns/vídeos e na publicação de mídias em status de grupos. | | Newsletters (Canais) | Consulta de Canais Inscritos | Adicionado o método exclusivo newsletterSubscribed que lista todos os canais de transmissão (Newsletters) aos quais o usuário está inscrito. | | Mensagens de Negócios | Botões Interativos & PIX | Suporte avançado para layouts de botões interativos, botões Cards (com imagem/vídeo), suporte para botões PIX estáticos e fluxos completos de checkout e pagamento (review_and_pay). | | Recursos Web (v1.1.6) | Fixação com Duração | Fixação de mensagens com durações configuráveis (24h, 7d, 30d) usando pinInChatMessage e messageAddOnDurationInSecs. | | Recursos Web (v1.1.6) | Reação a Status | Método nativo reactToStatus para curtir e reagir diretamente a publicações de Status. | | Recursos Web (v1.1.6) | Eventos & RSVP | Criação, cancelamento (cancelEvent) e confirmação de presença (sendEventResponse) em eventos de grupo. | | Recursos Web (v1.1.6) | Favoritos & Notas de Contato | Sincronização via App State de chats favoritos (updateFavorite) e anotações internas de contatos (updateChatNote). | | Recursos Web (v1.1.6) | Chamadas Web (Web Calling) | Sinalização completa de chamadas no navegador (offerCall, acceptCall, terminateCall, rejectCall). | | Recursos Web (v1.1.6) | Resolução Reversa de LID | Consulta reversa USync para obter o número de telefone a partir de um identificador @lid (getPnUser). | | Transição LID (Pilar 2) | Store Unificado (LID & PN) | store.getContact(jid) e store.getChat(jid) com indexação cruzada e resolução automática de apelidos LID/PN. | | Transição LID (Pilar 2) | Roteamento & Resolução JID | Métodos sock.toPn(), sock.toLid(), sock.resolveJid() e auto-aprendizado de chaves no cache do Signal. | | Multimídia & Canais (Pilar 3) | Álbum Nativo & Waveforms | Envio de álbuns (sendAlbumMessage), ordenação indexada e suporte a waveforms PTT customizadas. | | Multimídia & Canais (Pilar 3) | Newsletters (Canais) v2 | Consulta de reações (newsletterFetchReactions), mensagens individuais (newsletterFetchMessage) e lista parseada. |


📌 Índice


📦 Instalação

Adicione o pacote ao seu projeto via Yarn ou NPM:

Versão Estável (Recomendado):

yarn add @areumtecnologia/wasockets
# ou
npm install @areumtecnologia/wasockets

Versão de Desenvolvimento (Edge):

yarn add github:areumtecnologia/WaSockets

🔑 Conectando a Conta

O WhatsApp fornece uma API multi-dispositivo que permite ao WaSockets se autenticar como um segundo cliente web. Isso pode ser feito via QR Code ou Código de Emparelhamento.

Conexão via QR Code

const { default: makeWASocket, Browsers } = require('@areumtecnologia/wasockets')

const sock = makeWASocket({
    // Configurações do navegador exibidas no WhatsApp do celular
    browser: Browsers.ubuntu('Chrome'),
    printQRInTerminal: true
})

Conexão via Código de Emparelhamento (Pairing Code)

Ideal para servidores sem interface gráfica ou fluxos onde você não deseja escanear o QR Code, usando apenas o número do telefone. O número deve conter o código do país (ex: 55 para Brasil) e DDD, apenas com números.

const { default: makeWASocket } = require('@areumtecnologia/wasockets')

const sock = makeWASocket({
    printQRInTerminal: false // Deve ser false
})

if (!sock.authState.creds.registered) {
    const numeroTelefone = '5511999999999' // Insira o número completo
    const codigo = await sock.requestPairingCode(numeroTelefone)
    console.log(`Digite este código no seu WhatsApp: ${codigo}`)
}

Recebendo Histórico Completo

Por padrão, a conexão emula um cliente leve. Para receber um histórico maior de mensagens anteriores, configure o navegador para emular um Desktop (macOS ou Windows) e ative a sincronização:

const sock = makeWASocket({
    browser: Browsers.macOS('Desktop'),
    syncFullHistory: true
})

💾 Salvando e Restaurando Sessões

Para evitar a necessidade de escanear o QR Code a cada reinicialização, utilize a função useMultiFileAuthState para salvar as chaves de criptografia e credenciais em uma pasta local.

const { default: makeWASocket, useMultiFileAuthState } = require('@areumtecnologia/wasockets')

async function iniciar() {
    // Carrega o estado da pasta especificada
    const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')

    const sock = makeWASocket({
        auth: state
    })

    // Salva as credenciais sempre que forem atualizadas
    sock.ev.on('creds.update', saveCreds)
}
iniciar()

[!IMPORTANT] Quando mensagens são enviadas ou recebidas, as chaves de criptografia são atualizadas para segurança. É crucial que o evento creds.update chame a função saveCreds para persistir o novo estado. Caso contrário, a sessão será desconectada e as mensagens falharão.


⚙️ Configurações Importantes do Socket

1. Cache de Metadados de Grupo (Altamente Recomendado)

Se a sua aplicação gerencia grupos, buscar metadados diretamente no WhatsApp para cada mensagem recebida causa lentidão e risco de banimento por limite de requisições. Implemente um cache temporário:

const NodeCache = require('@cacheable/node-cache') // ou similar
const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })

const sock = makeWASocket({
    cachedGroupMetadata: async (jid) => groupCache.get(jid)
})

sock.ev.on('groups.update', async ([event]) => {
    const metadata = await sock.groupMetadata(event.id)
    groupCache.set(event.id, metadata)
})

sock.ev.on('group-participants.update', async (event) => {
    const metadata = await sock.groupMetadata(event.id)
    groupCache.set(event.id, metadata)
})

2. Recuperação de Mensagens e Enquetes

Para descriptografar respostas de enquetes antigas ou gerenciar tentativas de reenvio automáticas do WhatsApp, configure a função getMessage:

const sock = makeWASocket({
    getMessage: async (key) => {
        // Busque a mensagem salva no seu banco de dados ou store local
        return await buscarMensagemSalva(key.id)
    }
})

3. Fila Inteligente de Mensagens Durante Quedas Transitórias

Quando a conexão com o WhatsApp cai momentaneamente, o WaSockets armazena mensagens em buffer de espera e as envia automaticamente assim que a conexão se restabelece:

const sock = makeWASocket({
    enableMessageQueue: true, // Ativado por padrão (evita perda de mensagens durante reconexão)
    messageQueueTtlMs: 5 * 60 * 1000 // TTL de expiração na fila (padrão: 5 minutos)
})

4. Auto-Reparo de Sessão E2E / Signal (repairSession)

Se uma conversa específica apresentar erros de chave ou falhas de descriptografia (Bad MAC ou Session Corrupted), não é mais necessário deletar a pasta inteira de autenticação. Use o método repairSession:

// Remove a sessão danificada e força a renegociação de chaves E2E com o contato
await sock.repairSession('[email protected]')

🚀 Exemplo Prático Inicial (Bootstrap)

Aqui está um arquivo funcional completo em JavaScript (CommonJS) para iniciar a sua integração:

const { default: makeWASocket, DisconnectReason, useMultiFileAuthState, makeReconnectManager, shouldReconnect } = require('@areumtecnologia/wasockets')
const { Boom } = require('@hapi/boom')

async function connectToWhatsApp() {
    // 1. Inicializa o estado de autenticação baseado em arquivos
    const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
    
    // 2. Cria o Socket de Conexão com fila de mensagens inteligente ativada por padrão
    const sock = makeWASocket({
        auth: state,
        printQRInTerminal: true,
        enableMessageQueue: true // Fila de envio automático durante reconexões transitórias
    })

    // Gerenciador de reconexão adaptativa com Backoff Exponencial e Full Jitter (evita banimentos)
    const reconnectManager = makeReconnectManager({
        onReconnect: async (attempt) => {
            console.log(`Reconectando ao WhatsApp (tentativa #${attempt})...`)
            await connectToWhatsApp()
        }
    })

    // 3. Monitora o status da conexão
    sock.ev.on('connection.update', async (update) => {
        const { connection, lastDisconnect } = update
        
        if (connection === 'close') {
            await reconnectManager.handleDisconnect(lastDisconnect?.error)
        } else if (connection === 'open') {
            reconnectManager.reset()
            console.log('Conexão com o WhatsApp estabelecida com sucesso!')
        }
    })

    // 4. Salva credenciais atualizadas
    sock.ev.on('creds.update', saveCreds)

    // 5. Escuta e responde a novas mensagens recebidas
    sock.ev.on('messages.upsert', async (event) => {
        for (const m of event.messages) {
            // Ignora mensagens que não sejam do tipo padrão ou geradas pelo próprio bot
            if (!m.message || m.key.fromMe) continue

            console.log('Mensagem recebida de:', m.key.remoteJid)
            console.log('Conteúdo:', JSON.stringify(m, null, 2))

            // Responde à mensagem
            await sock.sendMessage(m.key.remoteJid, { text: 'Olá! Recebi sua mensagem com sucesso.' })
        }
    })
}

// Inicia o processo
connectToWhatsApp()

📡 Tratamento de Eventos e Mídia

O WaSockets utiliza um sistema de eventos tipado baseado no EventEmitter.

sock.ev.on('messages.upsert', ({ messages, type }) => {
    // type pode ser 'notify' (nova notificação) ou 'append' (carregamento histórico)
    console.log('Novas mensagens recebidas:', messages)
})

Download de Mídias Recebidas

Para baixar mídias (fotos, vídeos, áudios, documentos ou stickers) recebidas no evento messages.upsert, utilize a função utilitária downloadMediaMessage:

const { downloadMediaMessage } = require('@areumtecnologia/wasockets')
const fs = require('fs')

sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const msg of messages) {
        if (!msg.message || msg.key.fromMe) continue

        const isMedia = msg.message.imageMessage || 
                        msg.message.videoMessage || 
                        msg.message.audioMessage || 
                        msg.message.documentMessage || 
                        msg.message.stickerMessage

        if (isMedia) {
            // Baixa o arquivo diretamente em formato Buffer
            const buffer = await downloadMediaMessage(msg, 'buffer', {})
            
            // Exemplo: Salvar no disco
            const ext = msg.message.imageMessage ? 'jpg' : msg.message.audioMessage ? 'ogg' : 'bin'
            fs.writeFileSync(`./download_${msg.key.id}.${ext}`, buffer)
            console.log(`Mídia baixada com sucesso (${buffer.length} bytes)!`)

            // Ou baixar como stream de leitura para processamento em tempo real:
            // const stream = await downloadMediaMessage(msg, 'stream', {})
        }
    }
})

Decifrar Votos de Enquetes

Os votos em enquetes chegam como mensagens criptografadas no evento messages.update. É preciso usar o helper getAggregateVotesInPollMessage passando a mensagem original da enquete.

const { getAggregateVotesInPollMessage } = require('@areumtecnologia/wasockets')

sock.ev.on('messages.update', async (updates) => {
    for (const { key, update } of updates) {
        if (update.pollUpdates) {
            // 1. Busca a mensagem original da enquete que foi criada anteriormente
            const pollCreationMessage = await obterMensagemSalva(key)
            if (pollCreationMessage) {
                // 2. Agrega os votos
                const pollVotes = await getAggregateVotesInPollMessage({
                    message: pollCreationMessage,
                    pollUpdates: update.pollUpdates
                })
                
                // 3. Exibe as opções votadas e os respectivos eleitores
                console.log('Resultado da Enquete Atualizado:', pollVotes)
            }
        }
    }
})

Decifrar Respostas de Eventos

A mesma lógica se aplica a eventos criados no chat (como convites de reuniões). O WaSockets fornece o helper getAggregateResponsesInEventMessage para analisar as presenças.

const { getAggregateResponsesInEventMessage } = require('@areumtecnologia/wasockets')

sock.ev.on('messages.update', async (updates) => {
    for (const { key, update } of updates) {
        if (update.eventResponses) {
            const eventCreationMessage = await obterMensagemSalva(key)
            if (eventCreationMessage) {
                const responses = await getAggregateResponsesInEventMessage({
                    message: eventCreationMessage,
                    eventResponses: update.eventResponses
                })
                console.log('Respostas ao evento atualizadas:', responses)
            }
        }
    }
})

🔍 Verificação de Contatos e Presença

Verificação de Números no WhatsApp (onWhatsApp)

Valide se um ou vários números de telefone possuem contas ativas registradas no WhatsApp antes de disparar mensagens:

// Aceita um ou vários números (com DDI e DDD)
const resultados = await sock.onWhatsApp('5511999999999', '5511888888888', '5521977777777')

for (const { jid, exists } of resultados) {
    if (exists) {
        console.log(`O número ${jid} está ativo no WhatsApp!`)
    } else {
        console.log(`O número ${jid} NÃO possui conta no WhatsApp.`)
    }
}

Presença e Digitando / Gravando Áudio

Simule atividade humana enviando estados de presença ou monitore o status de contatos:

// 1. Indicar que está digitando...
await sock.sendPresenceUpdate('composing', jid)

// 2. Indicar que está gravando áudio...
await sock.sendPresenceUpdate('recording', jid)

// 3. Pausar status de digitação/gravação
await sock.sendPresenceUpdate('paused', jid)

// 4. Alterar presença geral da conta ('available' = Online, 'unavailable' = Offline)
await sock.sendPresenceUpdate('available')

// 5. Inscrever-se para escutar presença de um contato específico
await sock.presenceSubscribe(jid)

// 6. Monitorar atualizações de presença recebidas
sock.ev.on('presence.update', ({ id, presences }) => {
    console.log(`Atualização de presença de ${id}:`, presences)
})

✉️ Enviando Mensagens

Mensagens de Texto e Menções

// Mensagem de texto simples
await sock.sendMessage(jid, { text: 'Olá Mundo!' })

// Mensagem citando (respondendo a) outra mensagem
await sock.sendMessage(jid, { text: 'Esta é uma resposta.' }, { quoted: mensagemOriginal })

// Mensagem mencionando contatos no grupo
await sock.sendMessage(jid, {
    text: 'Olá @5511999999999 e @5511888888888!',
    mentions: ['[email protected]', '[email protected]']
})

Mensagens de Mídia

É possível passar caminhos de arquivos locais (url), links da internet (url), buffers ou streams de leitura.

const fs = require('fs')

// Imagem com legenda
await sock.sendMessage(jid, {
    image: { url: './foto.jpg' }, // ou { url: 'https://example.com/foto.jpg' } ou Buffer
    caption: 'Minha foto legal!'
})

// Álbum de mídias (Múltiplas fotos/vídeos no mesmo bloco)
await sock.sendMessage(jid, {
    album: [
        { image: { url: './foto1.jpg' }, caption: 'Foto 1' },
        { image: { url: './foto2.jpg' }, caption: 'Foto 2' },
        { video: { url: './video.mp4' }, caption: 'Vídeo do Álbum' }
    ]
})

// GIF (vídeo mp4 simulado como reprodução contínua)
await sock.sendMessage(jid, {
    video: fs.readFileSync('./video-gif.mp4'),
    gifPlayback: true,
    caption: 'Olha esse gif!'
})

// Áudio Gravado (Simula o gravador de voz do WhatsApp - PTT)
await sock.sendMessage(jid, {
    audio: { url: './audio.ogg' },
    mimetype: 'audio/mp4', // obrigatório
    ptt: true // Define como mensagem de voz
})

// Mensagem de Visualização Única (View Once)
await sock.sendMessage(jid, {
    image: { url: './foto.jpg' },
    viewOnce: true,
    caption: 'Esta foto desaparecerá após ser aberta!'
})

[!TIP] Para mensagens de áudio funcionarem perfeitamente em todos os dispositivos móveis e web, converta o áudio original para o formato OGG Opus (codec libopus) usando a ferramenta FFMpeg: ffmpeg -i input.mp3 -c:a libopus -ac 1 -avoid_negative_ts make_zero output.ogg


Documentos e Arquivos

Envie qualquer formato de arquivo (PDF, planilhas, arquivos compactados) informando o mimetype e o fileName para exibição correta no aplicativo:

await sock.sendMessage(jid, {
    document: { url: './fatura_setembro.pdf' }, // ou Buffer ou { url: 'https://exemplo.com/doc.pdf' }
    mimetype: 'application/pdf',
    fileName: 'Fatura_Setembro_2026.pdf'
})

Figurinhas (Stickers)

Envie figurinhas estáticas ou animadas no formato WebP:

await sock.sendMessage(jid, {
    sticker: fs.readFileSync('./minha_figurinha.webp') // aceita Buffer ou { url: './figurinha.webp' }
})

Localização Fixa e em Tempo Real

Envie pontos no mapa ou compartilhe localização em tempo real com latitude e longitude:

// Localização Fixa
await sock.sendMessage(jid, {
    location: {
        degreesLatitude: -23.55052,
        degreesLongitude: -46.633308,
        name: 'Sede da Áreum Tecnologia',
        address: 'Av. Paulista, 1000 - Bela Vista, São Paulo - SP'
    }
})

// Localização em Tempo Real (Live Location)
await sock.sendMessage(jid, {
    location: {
        degreesLatitude: -23.55052,
        degreesLongitude: -46.633308
    },
    live: true
})

Contatos e Cartões vCard

Envie um ou múltiplos contatos com cartão vCard formatado:

const vcard = 'BEGIN:VCARD\n'
            + 'VERSION:3.0\n' 
            + 'FN:Suporte Técnico Áreum\n'
            + 'ORG:Áreum Tecnologia;\n'
            + 'TEL;type=CELL;type=VOICE;waid=5511999999999:+55 11 99999-9999\n'
            + 'END:VCARD'

await sock.sendMessage(jid, {
    contacts: {
        displayName: 'Suporte Técnico Áreum',
        contacts: [{ vcard }]
    }
})

Reações a Mensagens

Reaja com emojis a qualquer mensagem enviada ou recebida (ou remova a reação enviando string vazia ''):

// Reagir à mensagem com um emoji
await sock.sendMessage(jid, {
    react: {
        text: '🔥', // Emoji da reação
        key: msg.key // Chave da mensagem original que receberá a reação
    }
})

// Remover reação anterior
await sock.sendMessage(jid, {
    react: {
        text: '',
        key: msg.key
    }
})

Criação de Enquetes

Crie enquetes interativas com contagem configurável de seleção (voto único ou múltiplo):

await sock.sendMessage(jid, {
    poll: {
        name: 'Qual o melhor diferencial do WaSockets?',
        values: [
            'Resolução Transparente de LID',
            'Envio Nativo de Álbuns',
            'Newsletters v2 e Canais',
            'Fila Inteligente de Reconexão'
        ],
        selectableCount: 1 // 1 para escolha única; > 1 para permitir múltiplas escolhas
    }
})

Listas Interativas de Opções (Sections)

Envie menus organizados por categorias e linhas para navegação intuitiva:

await sock.sendMessage(jid, {
    text: 'Selecione o setor desejado para atendimento:',
    footer: 'Áreum Tecnologia • Atendimento Automatizado',
    title: 'Central de Relacionamento',
    buttonText: 'Ver Departamentos',
    sections: [
        {
            title: 'Atendimento Comercial',
            rows: [
                { title: 'Novas Contratações', rowId: 'row_vendas', description: 'Conheça nossos planos e soluções' },
                { title: 'Upgrade de Plano', rowId: 'row_upgrade', description: 'Amplie os limites da sua conta' }
            ]
        },
        {
            title: 'Suporte & Operações',
            rows: [
                { title: 'Suporte Técnico', rowId: 'row_suporte', description: 'Dúvidas de integração e bugs' },
                { title: 'Financeiro', rowId: 'row_financeiro', description: '2ª via de boleto e notas fiscais' }
            ]
        }
    ]
})

Botões Interativos

Os botões nativos do WhatsApp são suportados através da propriedade interactiveButtons.

await sock.sendMessage(jid, {
    text: 'Olá! Escolha uma das opções abaixo:',
    title: 'Painel Interativo',
    subtitle: 'Selecione com um clique',
    footer: 'Áreum Tecnologia',
    interactiveButtons: [
        {
            name: 'quick_reply',
            buttonParamsJson: JSON.stringify({
                display_text: 'Suporte Técnico',
                id: 'btn_suporte'
            })
        },
        {
            name: 'cta_url',
            buttonParamsJson: JSON.stringify({
                display_text: 'Acessar Site',
                url: 'https://areum.com.br',
                merchant_url: 'https://areum.com.br'
            })
        },
        {
            name: 'cta_call',
            buttonParamsJson: JSON.stringify({
                display_text: 'Ligar Agora',
                phone_number: '5511999999999'
            })
        }
    ]
})

Botão de Pagamento PIX

O WaSockets permite o envio de chaves estáticas de PIX diretamente integradas na interface de pagamento nativa do WhatsApp pelo botão payment_info.

await sock.sendMessage(jid, {
    text: 'Efetue o pagamento do pedido abaixo clicando em Pagar:',
    interactiveButtons: [
        {
            name: 'payment_info',
            buttonParamsJson: JSON.stringify({
                payment_settings: [{
                    type: 'pix_static_code',
                    pix_static_code: {
                        merchant_name: 'Áreum Tecnologia LTDA',
                        key: '[email protected]', // Chave PIX (E-mail, CPF/CNPJ, Telefone ou EVP)
                        key_type: 'EMAIL' // Tipos suportados: PHONE, EMAIL, CPF, EVP
                    }
                }]
            })
        }
    ]
})

Fluxos de Checkout (PAY)

É possível enviar solicitações de checkout com itens detalhados de faturamento para pagamentos eletrônicos integrados no aplicativo através da ação review_and_pay.

await sock.sendMessage(jid, {
    text: 'Fatura gerada com sucesso!',
    interactiveButtons: [
        {
            name: 'review_and_pay',
            buttonParamsJson: JSON.stringify({
                currency: 'BRL',
                payment_type: 'physical-goods',
                total_amount: {
                    value: '15000', // R$ 150,00 (representado sem decimais, multiplicado pelo offset)
                    offset: '100'
                },
                reference_id: 'REF_PEDIDO_12345',
                payment_method: 'confirm',
                payment_status: 'captured',
                payment_timestamp: Math.floor(Date.now() / 1000),
                order: {
                    status: 'completed',
                    order_type: 'PAYMENT_REQUEST',
                    subtotal: { value: '15000', offset: '100' },
                    items: [{
                        retailer_id: 'item_01',
                        name: 'Licença Anual WaSockets',
                        amount: { value: '15000', offset: '100' },
                        quantity: '1'
                    }]
                },
                additional_note: 'Agradecemos a sua preferência!'
            })
        }
    ]
})

Menção em Status

Permite publicar status (stories) e marcar diretamente contatos/grupos específicos (máximo de 5 menções por status).

const contatosParaMencionar = [
    '[email protected]',
    '[email protected]'
]

// Envia um status em formato de texto mencionando os contatos acima
await sock.sendStatusMentions(
    {
        text: 'Novidade incrível para vocês! 🚀',
        backgroundColor: '#1c1c1c',
        textColor: '#ffffff'
    },
    contatosParaMencionar
)

// Curtir / Reagir diretamente a uma publicação de Status (Stories)
await sock.reactToStatus(statusMsgKey, '❤️')

Comentários em Canais e Comunidades

Envie respostas e comentários estruturados em postagens de canais (Newsletters) ou mensagens de aviso em comunidades:

await sock.sendMessage(jid, {
    comment: {
        targetMessageKey: mensagemOriginal.key,
        message: { text: 'Excelente atualização! 👏' }
    }
})

Envio Nativo de Álbuns de Fotos e Vídeos (Pilar 3)

Envie múltiplos arquivos de imagem e vídeo agrupados nativamente em um container de álbum (layout de grade no WhatsApp Web e Celular) com ordenação indexada e suporte a legendas:

// Método direto e simplificado
await sock.sendAlbumMessage(jid, [
    { image: { url: 'https://exemplo.com/foto1.jpg' }, caption: 'Foto 1 do produto' },
    { image: { url: 'https://exemplo.com/foto2.jpg' }, caption: 'Foto 2 em outro ângulo' },
    { video: { url: 'https://exemplo.com/demonstracao.mp4' }, caption: 'Vídeo explicativo' }
])

// Ou através de sendMessage com a propriedade album:
await sock.sendMessage(jid, {
    album: [
        { image: { url: './local/foto1.jpg' } },
        { image: { url: './local/foto2.jpg' } }
    ]
})

Mensagens de Áudio PTT com Waveform Customizada (Pilar 3)

Você pode enviar notas de voz (Push-To-Talk) com geração automática de ondas sonoras ou fornecer uma forma de onda predefinida (array ou Buffer):

// Áudio PTT com waveform automática gerada a partir do arquivo
await sock.sendMessage(jid, {
    audio: { url: './audio.mp3' },
    mimetype: 'audio/ogg; codecs=opus',
    ptt: true
})

// Áudio PTT com waveform predefinida (evita decodificação intensiva de CPU)
await sock.sendMessage(jid, {
    audio: { url: './audio.mp3' },
    mimetype: 'audio/ogg; codecs=opus',
    ptt: true,
    waveform: [0, 15, 30, 75, 100, 80, 45, 20, 10, 0] // 64 barras de amplitude
})

Encaminhamento de Mensagens

Encaminhe mensagens para outros chats preservando ou forçando o status de encaminhado:

// Encaminhar uma mensagem recebida para outro destinatário
await sock.sendMessage(outroJid, {
    forward: mensagemOriginal,
    force: true // Exibe o selo de mensagem encaminhada
})

📝 Modificando Mensagens e Chats

// Apagar uma mensagem para todos
const msg = await sock.sendMessage(jid, { text: 'Mensagem enviada com erro!' })
await sock.sendMessage(jid, { delete: msg.key })

// Editar uma mensagem enviada
await sock.sendMessage(jid, {
    text: 'Esta é a mensagem com o texto corrigido.',
    edit: msg.key
})

// Arquivar um chat
await sock.chatModify({ archive: true, lastMessages: [msg] }, jid)

// Silenciar um chat por 8 horas
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)

// Remover silenciamento de um chat
await sock.chatModify({ mute: null }, jid)

// Marcar chat como Não Lido
await sock.chatModify({ markRead: false, lastMessages: [msg] }, jid)

// Fixar chat na lista de conversas
await sock.chatModify({ pin: true }, jid)

Confirmação de Leitura (readMessages)

Envie confirmações de leitura explícitas para exibir os ticks azuis ao remetente:

// Marca uma ou mais mensagens recebidas como lidas
await sock.readMessages([msg.key])

Mensagens com Estrela (star)

Marque mensagens importantes com estrela (favoritas) na conversa:

// Adicionar estrela à mensagem
await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], true)

// Remover estrela da mensagem
await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], false)

Fixação de Mensagens com Duração

Fixe mensagens em conversas individuais ou grupos escolhendo a duração desejada:

// Fixar mensagem por 7 dias (604800 segundos)
// Durações padrão: 86400 (24h), 604800 (7 dias), 2592000 (30 dias)
await sock.sendMessage(jid, {
    pin: {
        key: msg.key,
        type: 1, // 1: Fixar, 2: Desafixar
        time: 604800
    }
})

// Desafixar mensagem
await sock.sendMessage(jid, {
    pin: {
        key: msg.key,
        type: 2
    }
})

Favoritos e Anotações de Contato

Organize suas conversas sincronizando com o WhatsApp Web e celular:

// Marcar conversa como Favorita
await sock.updateFavorite(jid, true)

// Desmarcar conversa como Favorita
await sock.updateFavorite(jid, false)

// Adicionar ou atualizar nota interna no contato (Chat Note)
await sock.updateChatNote(jid, 'Cliente solicitou proposta para 50 atendentes.')

// Remover nota interna do contato
await sock.removeChatNote(jid)

👤 Perfil do Usuário e Foto

Gerencie fotos de perfil, recados e nome de exibição (PushName) diretamente pelo socket:

// 1. Obter a URL da foto de perfil de um contato ou grupo
const pfpUrl = await sock.profilePictureUrl(jid, 'image') // ou 'preview' para miniatura
console.log('Foto de Perfil:', pfpUrl)

// 2. Atualizar a sua própria foto de perfil (ou a foto de um grupo do qual você é admin)
await sock.updateProfilePicture(jid, { url: './nova_foto.jpg' }) // Aceita caminho, URL ou Buffer

// 3. Remover a foto de perfil
await sock.removeProfilePicture(jid)

// 4. Consultar o recado / About (Status) de um contato
const statusInfo = await sock.fetchStatus(jid)
console.log(`Recado de ${jid}: ${statusInfo?.status} (Definido em: ${statusInfo?.setAt})`)

// 5. Atualizar o seu próprio recado / About
await sock.updateProfileStatus('Disponível apenas para atendimentos prioritários 🚀')

// 6. Atualizar o seu nome público de exibição (PushName)
await sock.updateProfileName('Áreum Tecnologia - Suporte Oficial')

📅 Eventos em Grupos e RSVP

Crie eventos colaborativos, responda confirmações de presença e cancele eventos:

// 1. Criar um novo evento no grupo
const evento = await sock.sendMessage(grupoJid, {
    event: {
        name: 'Reunião de Planejamento de Sprints',
        description: 'Alinhamento estratégico dos projetos da Áreum Tecnologia.',
        startTime: Math.floor(Date.now() / 1000) + 86400, // Amanhã
        extraGuestsAllowed: true
    }
})

// 2. Responder ao Evento (RSVP)
// Tipos de resposta: 'GOING' (1), 'NOT_GOING' (2), 'MAYBE' (3)
await sock.sendEventResponse(grupoJid, evento.key, 'GOING', 1 /* +1 convidado extra */)

// 3. Cancelar o Evento
await sock.cancelEvent(grupoJid, evento.key)

📞 Chamadas Web (Web Calling)

Gerencie o ciclo completo de sinalização de chamadas de voz e vídeo:

// Iniciar uma chamada (áudio ou vídeo)
const chamada = await sock.offerCall('[email protected]', false /* isVideo */)
console.log('ID da chamada:', chamada.id)

// Atender uma chamada recebida
await sock.acceptCall(callId, callerJid)

// Encerrar uma chamada em andamento
await sock.terminateCall(callId, callerJid)

// Rejeitar uma chamada recebida
await sock.rejectCall(callId, callerJid)

🔍 Resolução de Usuários & Transição LID (Pilar 2)

Com a evolução da privacidade no WhatsApp, participantes de grupos e canais frequentemente utilizam identificadores @lid. O WaSockets oferece um conjunto completo de ferramentas de alto desempenho com cache automático em memória e no banco de chaves Signal:

Métodos de Resolução Transparente no Socket

// 1. Converter LID para número de telefone (PN) com busca em cache/DB
const pnJid = await sock.toPn('12345678901234@lid')
console.log('JID com número real:', pnJid) // '[email protected]'

// Caso não esteja em cache local, pode passar true para consultar o servidor via USync:
const pnJidFromNetwork = await sock.toPn('12345678901234@lid', true)

// 2. Converter número de telefone (PN) para LID
const lidJid = await sock.toLid('[email protected]')
console.log('LID correspondente:', lidJid) // '12345678901234@lid'

// 3. Resolução completa e unificada (retorna ambos)
const resolved = await sock.resolveJid(authorJid)
console.log(resolved) // { pn: '[email protected]', lid: '12345678901234@lid', jid: ... }

// 4. Registrar manualmente um mapeamento conhecido
await sock.storeLidPnMapping('[email protected]', '12345678901234@lid')

// 5. Consultas diretas via protocolo USync (baixo nível)
const [lidUser] = await sock.getLidUser('[email protected]')
const [pnUser] = await sock.getPnUser('12345678901234@lid')

Store Unificado de Contatos e Conversas (makeInMemoryStore)

Tradicionalmente, quando o WhatsApp chaveia as mensagens para @lid, chamadas como store.contacts[jid] ou store.messages[jid] falhavam por incompatibilidade de identificadores. O WaSockets resolve isso unificando o catálogo em tempo de execução:

import { makeInMemoryStore } from '@areumtecnologia/wasockets'

const store = makeInMemoryStore({})
store.bind(sock.ev)

// Busca unificada: localiza o contato quer você passe o número (@s.whatsapp.net), o @lid ou apenas os dígitos
const contact = store.getContact('12345678901234@lid') 
// Retorna o contato completo contendo .id, .lid, .phoneNumber, .name, etc.

// Busca unificada de chat: localiza a conversa mesmo se foi iniciada com PN ou com LID
const chat = store.getChat('12345678901234@lid')

// Carregamento de mensagens com fallback cruzado automático entre LID e PN
const messages = await store.loadMessages('12345678901234@lid', 25)

🏷️ Etiquetas de Negócio (Labels - WhatsApp Business)

O WaSockets permite que você gerencie etiquetas e organize contatos ou mensagens diretamente pelo aplicativo WhatsApp Business.

Criando, Editando e Deletando Etiquetas (CRUD de Sistema)

Você pode criar, editar e excluir as etiquetas globais da sua conta:

// Criar uma nova etiqueta com cor específica
// Cores suportadas: de 0 a 19 correspondentes à paleta do WhatsApp Business
const novaLabel = await sock.createLabel('Lead Qualificado', 5)

// Atualizar o nome e a cor de uma etiqueta existente
await sock.updateLabel('label_id_123', 'Pagamento Aprovado', 2)

// Deletar uma etiqueta definitivamente da conta
await sock.deleteLabel('label_id_123')

Associando Etiquetas a Conversas e Mensagens

Para categorizar chats específicos ou marcar mensagens individuais dentro de uma conversa:

// Associar etiqueta a uma conversa (JID)
await sock.addChatLabel(jid, 'label_id_123')

// Remover etiqueta de uma conversa (JID)
await sock.removeChatLabel(jid, 'label_id_123')

// Associar etiqueta a uma mensagem específica
await sock.addMessageLabel(jid, 'mensagem_id_456', 'label_id_123')

// Remover etiqueta de uma mensagem específica
await sock.removeMessageLabel(jid, 'mensagem_id_456', 'label_id_123')

Respostas Rápidas (Quick Replies)

Para contas WhatsApp Business, gerencie respostas rápidas acessíveis via atalhos:

// Criar ou atualizar resposta rápida
await sock.addOrEditQuickReply({
    id: 'qr_ola',
    shortcut: '/ola',
    message: 'Olá! Seja muito bem-vindo à Áreum Tecnologia. Como podemos te ajudar hoje?',
    keywords: ['ola', 'ajuda', 'suporte', 'inicio']
})

// Remover resposta rápida pelo ID
await sock.removeQuickReply('qr_ola')

👥 Gerenciamento de Grupos

As operações de alteração estrutural em grupos requerem que a conta conectada seja administradora do grupo correspondente.

// Criar um novo grupo
const grupo = await sock.groupCreate('Equipe de Suporte Áreum', ['[email protected]'])
console.log('Grupo criado com ID:', grupo.id)

// Adicionar/Remover/Promover participantes
// Parâmetros de ação: 'add' | 'remove' | 'promote' | 'demote'
await sock.groupParticipantsUpdate(grupo.id, ['[email protected]'], 'add')

// Obter dados/metadados de um grupo ANTES de entrar usando o código de convite
const infoConvite = await sock.groupGetInviteInfo('ABcdEFghIJklMnOpQrStUv')
console.log(`Nome do grupo no convite: ${infoConvite.subject}`)

// Obter o código/link de convite do grupo
const codigoConvite = await sock.groupInviteCode(grupo.id)
console.log(`Link: https://chat.whatsapp.com/${codigoConvite}`)

// Revogar link de convite anterior e gerar um novo
const novoCodigo = await sock.groupRevokeInvite(grupo.id)

// Entrar em um grupo usando um código de convite (apenas o código, sem o domínio completo)
const resposta = await sock.groupAcceptInvite('ABcdEFghIJklMnOpQrStUv')

// Alterar o assunto (título) do grupo
await sock.groupUpdateSubject(grupo.id, 'Novo Nome do Grupo')

// Alterar a descrição do grupo
await sock.groupUpdateDescription(grupo.id, 'Regras do grupo e links importantes.')

// Sair do grupo
await sock.groupLeave(grupo.id)

// Obter a lista de pessoas aguardando aprovação para entrar no grupo
const solicitacoes = await sock.groupRequestParticipantsList(grupo.id)
console.log(solicitacoes)

// Aprovar entrada pendente
await sock.groupRequestParticipantsUpdate(grupo.id, ['[email protected]'], 'approve') // ou 'reject'

// Obter metadados do grupo (participantes, título, regras, descrição)
const metadados = await sock.groupMetadata(grupo.id)
console.log(`Título: ${metadados.subject}, Membros: ${metadados.participants.length}`)

👥 Etiquetas de Membro (Member Tags) em Grupos

O WhatsApp permite que os participantes de um grupo criem um rótulo ou descrição curta de até 30 caracteres para si mesmos (ex: definir seu papel ou cargo no grupo).

Definindo sua própria Etiqueta de Membro no Grupo

// Define a sua etiqueta como "Suporte Técnico" no grupo especificado
await sock.updateMemberLabel(grupoJid, "Suporte Técnico")

Monitorando Atualizações de Etiquetas de Outros Membros

Você pode escutar o evento group.member-tag.update para monitorar quando qualquer participante alterar a etiqueta de membro dele no grupo:

sock.ev.on('group.member-tag.update', (update) => {
    const { groupId, label, participant } = update
    console.log(`O usuário ${participant} definiu a etiqueta "${label}" no grupo ${groupId}`)
})

📢 Newsletters / Canais v2 (Pilar 3)

O WaSockets traz suporte avançado para a criação, monitoramento, consumo e interação em Newsletters (Canais de Transmissão públicos do WhatsApp):

// 1. Criar uma Newsletter (Canal)
const canal = await sock.newsletterCreate('Notícias Tecnológicas Áreum', 'Canal oficial de novidades')
console.log('Canal criado com ID:', canal.id)

// 2. Obter metadados de um Canal público pelo ID ou Invite Code
const metadadosCanal = await sock.newsletterMetadata('JID', canal.id)
console.log('Nome do Canal:', metadadosCanal.name)

// 3. Listar todos os Canais inscritos
const canaisInscritos = await sock.newsletterSubscribed()
console.log('Canais que eu sigo:', canaisInscritos)

// 4. Buscar e decodificar mensagens do Canal (com contagem de visualizações e reações)
const { messages } = await sock.newsletterFetchMessages(canal.id, 20)
for (const msg of messages) {
    console.log(`[ID: ${msg.server_id}] Visualizações: ${msg.views}`)
    console.log('Conteúdo:', msg.message?.conversation || msg.message?.extendedTextMessage?.text)
    console.log('Reações:', msg.reactions) // [{ code: '👍', count: 12 }, { code: '❤️', count: 5 }]
}

// 5. Buscar mensagem individual do Canal
const singleMsg = await sock.newsletterFetchMessage(canal.id, '12345')

// 6. Consultar contadores de reações de uma postagem
const reacoes = await sock.newsletterFetchReactions(canal.id, '12345')
console.log('Reações do post:', reacoes)

// 7. Reagir a uma postagem do Canal (suporta server_id, id ou chave da mensagem)
await sock.newsletterReactMessage(canal.id, '12345', '🔥')

// 8. Seguir / Deixar de Seguir
await sock.newsletterFollow(canal.id)
await sock.newsletterUnfollow(canal.id)

// 9. Silenciar / Ativar notificações
await sock.newsletterMute(canal.id)
await sock.newsletterUnmute(canal.id)
await sock.newsletterToggleMute(canal.id, true) // ou false para desativar

// 10. Atualizar nome, descrição ou foto do Canal (Admins)
await sock.newsletterUpdateName(canal.id, 'Novo Nome do Canal')
await sock.newsletterUpdateDescription(canal.id, 'Nova descrição detalhada do canal')
await sock.newsletterUpdatePicture(canal.id, './novo_avatar_canal.jpg')
await sock.newsletterRemovePicture(canal.id)

// 11. Consultar inscritos e administradores
const inscritos = await sock.newsletterSubscribers(canal.id)
const totalAdmins = await sock.newsletterAdminCount(canal.id)

// 12. Transferir propriedade ou excluir o Canal
await sock.newsletterChangeOwner(canal.id, '[email protected]')
await sock.newsletterDelete(canal.id)

💼 WhatsApp Business (Catálogo, Produtos e Perfil Comercial)

Caso a conta conectada seja comercial (WhatsApp Business), o WaSockets oferece suporte para interagir com o catálogo de produtos, obter detalhes de pedidos e gerenciar o perfil público e as mídias da empresa.

Gerenciamento de Perfil e Capa Comercial

Você pode atualizar dados públicos de endereço, e-mail, descrição, websites, horários de funcionamento e foto de capa:

// Atualizar o perfil comercial do usuário
await sock.updateBussinesProfile({
    address: 'Av. Paulista, 1000 - São Paulo, SP',
    email: '[email protected]',
    description: 'Empresa especializada em soluções de tecnologia.',
    websites: ['https://suaempresa.com.br', 'https://blog.suaempresa.com.br'],
    hours: {
        timezone: 'America/Sao_Paulo',
        days: [
            { day: '1', mode: 'open_24_h' }, // Segunda-feira (1=Segunda, 7=Domingo)
            { 
                day: '2', 
                mode: 'specific_hours', 
                openTimeInMinutes: 540,  // 09:00 (9h * 60)
                closeTimeInMinutes: 1080 // 18:00 (18h * 60)
            }
        ]
    }
})

// Atualizar ou definir a foto de capa comercial
const coverPhotoId = await sock.updateCoverPhoto('./capa_empresa.jpg')

// Remover a foto de capa atual
await sock.removeCoverPhoto(coverPhotoId)

Consulta de Catálogo, Coleções e Pedidos

// Obter a lista de produtos do catálogo de um contato (ou do seu próprio)
const catalogo = await sock.getCatalog({
    jid: '[email protected]',
    limit: 15
})
console.log('Produtos:', catalogo.products)

// Obter as coleções de produtos organizadas do catálogo
const colecoes = await sock.getCollections('[email protected]', 10)

// Obter os detalhes completos de um pedido comercial a partir do ID e do Token da mensagem de carrinho
const detalhesPedido = await sock.getOrderDetails('ID_DO_PEDIDO', 'TOKEN_DO_PEDIDO')
console.log('Itens do Pedido:', detalhesPedido.items)

Cadastro e Modificação de Produtos no Catálogo

// Adicionar um novo produto no catálogo
const novoProduto = await sock.productCreate({
    name: 'Caneca Personalizada WaSockets',
    description: 'Caneca de cerâmica de alta qualidade.',
    price: 4990, // R$ 49,90 (valor representado sem decimais, multiplicado por 100)
    currency: 'BRL',
    isHidden: false,
    image: { url: './caneca.jpg' } // Caminho local, buffer ou stream
})
console.log('Produto Criado com ID:', novoProduto.id)

// Atualizar dados de um produto existente
await sock.productUpdate(novoProduto.id, {
    name: 'Caneca Personalizada WaSockets (Edição Especial)',
    price: 5990
})

// Obter detalhes de um único produto
const produto = await sock.getProduct(sock.user.id, novoProduto.id)
console.log('Detalhes do Produto:', produto)

// Remover produtos do catálogo (aceita um array de IDs de produtos)
await sock.productDelete([novoProduto.id])

👥 Grupos, Comunidades v2 e Moderação Avançada

O WaSockets oferece um conjunto completo e modernizado para gerenciamento profissional de Grupos e Comunidades no WhatsApp.

Gestão e Moderação de Entrada (Approval Mode)

Controle quem pode entrar no grupo através do fluxo oficial de aprovação de membros:

const groupJid = '[email protected]'

// Ativar modo de aprovação obrigatória de novos membros
await sock.groupMembershipApprovalMode(groupJid, 'on') // ou true / 'off'

// Listar participantes aguardando aprovação
const pendentes = await sock.groupRequestParticipantsList(groupJid)
console.log('Solicitações pendentes:', pendentes)

// Aprovar participantes pendentes (aceita string única ou array)
await sock.groupApprovePendingParticipants(groupJid, ['[email protected]'])

// Rejeitar participantes pendentes
await sock.groupRejectPendingParticipants(groupJid, ['[email protected]'])

Configuração Unificada de Políticas do Grupo

Altere facilmente todas as diretrizes de segurança e permissões do grupo em uma única chamada:

await sock.groupUpdatePermissions(groupJid, {
    announce: true,              // true: apenas admins enviam mensagens; false: todos
    restrict: true,              // true: apenas admins editam dados do grupo; false: todos
    memberAddMode: 'admin_add',  // 'admin_add' ou 'all_member_add'
    approvalMode: true,          // Exigir aprovação de admin para novos participantes
    ephemeral: 86400             // Mensagens temporárias (24h = 86400s, 7 dias = 604800s, false = desativar)
})

Menção a Todos os Membros (@everyone / Mention All)

Notifique ou mencione todos os participantes de um grupo de forma prática e sem boilerplate:

// Método direto
await sock.groupSendMentionAll(groupJid, '📢 Atenção a todos os membros: reunião às 15h!')

// Ou apenas para administradores, excluindo a si próprio:
await sock.groupSendMentionAll(groupJid, 'Aviso importante aos administradores', {
    adminsOnly: true,
    excludeMe: true
})

// Ou diretamente através do sendMessage usando o parâmetro mentionAll:
await sock.sendMessage(groupJid, {
    text: 'Olá a todos!',
    mentionAll: true
})

Extração Rápida de Administradores e Membros

// Retorna array de JIDs apenas de administradores e criador
const adminJids = await sock.groupGetAdminJids(groupJid)

// Retorna lista completa normalizada de participantes com status de admin e LID
const participantes = await sock.groupGetParticipants(groupJid)

Comunidades v2 (Subgrupos e Anúncios)

Gerencie Comunidades do WhatsApp com suporte a separação de subgrupos e grupo de avisos geral:

// Criar uma comunidade
const comunidade = await sock.communityCreate('Minha Comunidade', 'Descrição da comunidade')

// Vincular um grupo existente como subgrupo da comunidade
await sock.communityLinkGroup(groupJid, comunidade.id)

// Desvincular um subgrupo da comunidade
await sock.communityUnlinkGroup(groupJid, comunidade.id)

// Obter subgrupos organizados (grupo padrão de anúncios vs subgrupos comuns)
const { defaultSubGroup, subGroups, allGroups } = await sock.communityFetchSubGroups(comunidade.id)
console.log('Grupo Geral de Anúncios:', defaultSubGroup)
console.log('Subgrupos de discussão:', subGroups)

// Gerenciar aprovações de entrada na Comunidade
await sock.communityMembershipApprovalMode(comunidade.id, 'on')
await sock.communityApprovePendingParticipants(comunidade.id, ['[email protected]'])

Mensagens de Visualização Única (View Once)

Envie imagens, vídeos ou mídias efêmeras com a flag viewOnce: true:

await sock.sendMessage(jid, {
    image: { url: './comprovante.jpg' },
    caption: 'Comprovante confidencial',
    viewOnce: true
})

🧩 Arquitetura de Plugins e Middlewares

O WaSockets introduz uma arquitetura modular de plugins e ciclo de vida de middlewares que permite estender o socket de maneira limpa, sem monkey-patching.

Criando e Instalando Plugins

Um plugin pode ser uma função simples ou um objeto estruturado:

// Exemplo de Plugin de Boas-Vindas ou Auto-Resposta
const meuPluginBot = {
    name: 'auto-reply-plugin',
    version: '1.0.0',
    description: 'Responde automaticamente a palavras-chave',
    install(sock, options, manager) {
        console.log('Plugin instalado com opções:', options)

        // Escuta eventos normais da conexão
        sock.ev.on('messages.upsert', async ({ messages, type }) => {
            if (type !== 'notify') return
            for (const msg of messages) {
                if (!msg.key.fromMe && msg.message?.conversation === '!ping') {
                    await sock.sendMessage(msg.key.remoteJid, { text: '🏓 Pong via Plugin!' })
                }
            }
        })
    }
}

// Instalação do plugin no socket
sock.use(meuPluginBot, { prefix: '!' })

// Listar plugins ativos
console.log('Plugins ativos:', sock.listPlugins())

Middlewares de Interceptação de Mensagens

Intercepte ou cancele envios e recebimentos antes que cheguem à rede:

// Intercepta qualquer mensagem antes do envio (retornar false cancela o envio)
sock.registerMiddleware('beforeSendMessage', async ({ jid, content, options }, socket) => {
    console.log(`Enviando mensagem para ${jid}...`)
    
    // Bloquear envio se contiver palavras proibidas
    if (typeof content?.text === 'string' && content.text.includes('palavra_bloqueada')) {
        console.warn('Mensagem bloqueada por política de segurança.')
        return false // Cancela o disparo
    }
})

// Executa após a mensagem ser enviada com sucesso
sock.registerMiddleware('afterSendMessage', async ({ jid, content, fullMsg }, socket) => {
    console.log(`Mensagem ${fullMsg.key.id} entregue ao servidor com sucesso!`)
})

⚡ Alta Performance, Cache e Controle de Memória

Cache Integrado de Metadados de Grupo (TTL LRU)

Por padrão, o WaSockets ativa um cache inteligente com expiração por tempo (TTL de 5 minutos e limite de grupos em memória). Ao enviar mensagens para grupos ou listar participantes, as requisições repetidas ao WhatsApp são evitadas, acelerando disparos em massa em até 10x:

const sock = makeWASocket({
    enableGroupCache: true // Ativado por padrão com TTL de 5 minutos
})

Proteção de Memória na Store (makeInMemoryStore)

Evite vazamento de memória em bots de alta demanda com limpeza automática e limite configurável de mensagens por chat:

const store = makeInMemoryStore({
    maxMessagesPerChat: 200 // Limita o histórico a 200 mensagens por chat em RAM (padrão: 500)
})

// Limpeza manual sob demanda
store.pruneMessages(groupJid, 50) // Mantém apenas as últimas 50 mensagens do chat especificado
store.pruneMessages(undefined, 100) // Trunca todos os chats para no máximo 100 mensagens

// Obter contagem de mensagens armazenadas
const qtdTotal = store.getMessageCount()
const qtdChat = store.getMessageCount(groupJid)

// Limpar mensagens de um chat ou resetar toda a memória
store.clear(groupJid)

🔷 Suporte Completo a TypeScript

O WaSockets inclui definições de tipo completas em lib/index.d.ts e exporta a tipagem de todos os métodos dos 5 pilares, interfaces de mensagens, eventos e plugins:

import makeWASocket, { WASocket, AnyMessageContent, DisconnectReason, GroupMetadata } from '@areumtecnologia/wasockets'

const sock: WASocket = makeWASocket({
    printQRInTerminal: true
})

🔒 Configurações de Privacidade

// Bloquear ou desbloquear um usuário
await sock.updateBlockStatus('[email protected]', 'block') // ou 'unblock'

// Obter lista de usuários bloqueados
const listaBloqueados = await sock.fetchBlocklist()

// Atualizar privacidade do "Visto por Último"
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
await sock.updateLastSeenPrivacy('contacts')

// Atualizar privacidade do "Visto Online"
// Valores aceitos: 'all' | 'match_last_seen'
await sock.updateOnlinePrivacy('match_last_seen')

// Atualizar privacidade das confirmações de leitura (ticks azuis)
// Valores aceitos: 'all' | 'none'
await sock.updateReadReceiptsPrivacy('none')

// Atualizar privacidade da Foto de Perfil
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
await sock.updateProfilePicturePrivacy('contacts')

// Atualizar privacidade do Recado/Status (About)
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
await sock.updateStatusPrivacy('contacts')

// Atualizar quem pode adicionar você a grupos
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist'
await sock.updateGroupsAddPrivacy('contacts')

// Silenciar chamadas de números desconhecidos
// Valores aceitos: 'all' (permite todos) | 'known' (apenas contatos conhecidos)
await sock.updateCallPrivacy('known')

// Consultar todas as configurações de privacidade ativas da conta
const privacySettings = await sock.fetchPrivacySettings()
console.log('Configurações de privacidade atuais:', privacySettings)

🛡️ Logs e Protocolo

Para habilitar a depuração detalhada e ver o tráfego bruto do Websocket trocado com o WhatsApp, inicialize o logger no nível debug ou trace. O WaSockets usa a biblioteca estruturada pino para logs ultra rápidos:

const pino = require('pino')

const sock = makeWASocket({
    logger: pino({ level: 'debug' })
})

Como o WhatsApp se comunica (BinaryNodes)

As mensagens são trocadas em formato binário encapsuladas em estruturas chamadas BinaryNode. Cada nó possui três atributos:

  • tag: Nome da ação (ex: message, ib, presence, iq)
  • attrs: Objeto contendo propriedades em string/chave-valor (ID, timestamp, remetente, etc.)
  • content: O corpo de dados do nó (geralmente outro array de nós ou um buffer criptografado)

Você pode interagir diretamente com o tráfego do Websocket do WhatsApp registrando callbacks específicos:

// Monitora todos os pacotes recebidos que possuem a tag 'edge_routing'
sock.ws.on('CB:edge_routing', (node) => {
    console.log('Recebido nó de roteamento:', node)
})

// Monitora pacotes 'message' específicos
sock.ws.on('CB:message', (node) => {
    console.log('Mensagem de protocolo bruta:', node)
})