@areumtecnologia/wasockets 2.0.0-alpha.1 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +1929 -1649
  2. package/lib/Defaults/baileys-version.json +1 -1
  3. package/lib/Defaults/connection.js +14 -1
  4. package/lib/Socket/index.js +51 -48
  5. package/lib/Socket/messages-recv.js +74 -13
  6. package/lib/Socket/messages-send.js +50 -25
  7. package/lib/Socket/socket.js +13 -0
  8. package/lib/Socket/voip.js +123 -0
  9. package/lib/Store/make-cache-manager-store.js +14 -5
  10. package/lib/Types/index.d.ts +4 -0
  11. package/lib/Utils/auth-utils.js +16 -1
  12. package/lib/Utils/browser-utils.js +6 -2
  13. package/lib/Utils/generics.js +47 -8
  14. package/lib/Utils/index.d.ts +1 -0
  15. package/lib/Utils/messages-media.js +44 -21
  16. package/lib/Utils/pre-key-manager.js +16 -1
  17. package/lib/Utils/validate-connection.js +10 -11
  18. package/lib/VoIP/VoIPCrypto.js +150 -0
  19. package/lib/VoIP/VoIPManager.js +469 -0
  20. package/lib/VoIP/VoIPMediaEngine.js +224 -0
  21. package/lib/VoIP/VoIPProtocol.js +354 -0
  22. package/lib/VoIP/VoIPRelayTransport.js +173 -0
  23. package/lib/VoIP/VoIPSession.js +314 -0
  24. package/lib/VoIP/assets/wasm/loader.js +5 -0
  25. package/lib/VoIP/assets/wasm/whatsapp.wasm +0 -0
  26. package/lib/VoIP/assets/wasm/worker-modules.js +305 -0
  27. package/lib/VoIP/engine/audio-feeder.d.mts +15 -0
  28. package/lib/VoIP/engine/audio-feeder.mjs +243 -0
  29. package/lib/VoIP/engine/index.d.mts +91 -0
  30. package/lib/VoIP/engine/index.mjs +1683 -0
  31. package/lib/VoIP/engine/relay-transport.d.mts +43 -0
  32. package/lib/VoIP/engine/relay-transport.mjs +607 -0
  33. package/lib/VoIP/engine/signaling.d.mts +44 -0
  34. package/lib/VoIP/engine/signaling.mjs +893 -0
  35. package/lib/VoIP/engine/types.d.mts +183 -0
  36. package/lib/VoIP/engine/types.mjs +17 -0
  37. package/lib/VoIP/engine/wasm-engine.d.mts +103 -0
  38. package/lib/VoIP/engine/wasm-engine.mjs +1397 -0
  39. package/lib/VoIP/engine/worker-bootstrap.mjs +1049 -0
  40. package/lib/VoIP/index.js +51 -0
  41. package/lib/VoIP/utils/audio.d.ts +28 -0
  42. package/lib/VoIP/utils/audio.js +148 -0
  43. package/lib/WABinary/generic-utils.js +22 -6
  44. package/lib/index.d.ts +382 -274
  45. package/lib/index.js +5 -0
  46. package/package.json +28 -32
package/README.md CHANGED
@@ -1,1650 +1,1930 @@
1
- # WaSockets - API do WhatsApp Web em TypeScript/JavaScript
2
-
3
- <div align="center">
4
- <p><strong>Uma modificação otimizada e de alta performance da API do WhatsApp (baseada no Baileys), mantida e aprimorada pela Áreum Tecnologia.</strong></p>
5
- </div>
6
-
7
- ---
8
-
9
- ### ⚠️ Nota Importante e Licença
10
-
11
- 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.
12
-
13
- 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`).
14
-
15
- ---
16
-
17
- ## 🚀 Diferenciais e Correções da Áreum Tecnologia
18
-
19
- 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:
20
-
21
- | Categoria | Recurso / Correção | Descrição |
22
- | :--- | :--- | :--- |
23
- | **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). |
24
- | **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. |
25
- | **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. |
26
- | **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. |
27
- | **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`. |
28
- | **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. |
29
- | **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`). |
30
- | **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. |
31
- | **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. |
32
- | **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`). |
33
- | **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`. |
34
- | **Recursos Web (v1.1.6)** | Reação a Status | Método nativo `reactToStatus` para curtir e reagir diretamente a publicações de Status. |
35
- | **Recursos Web (v1.1.6)** | Eventos & RSVP | Criação, cancelamento (`cancelEvent`) e confirmação de presença (`sendEventResponse`) em eventos de grupo. |
36
- | **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`). |
37
- | **Recursos Web (v1.1.6)** | Chamadas Web (Web Calling) | Sinalização completa de chamadas no navegador (`offerCall`, `acceptCall`, `terminateCall`, `rejectCall`). |
38
- | **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`). |
39
- | **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. |
40
- | **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. |
41
- | **Multimídia & Canais (Pilar 3)** | Álbum Nativo & Waveforms | Envio de álbuns (`sendAlbumMessage`), ordenação indexada e suporte a waveforms PTT customizadas. |
42
- | **Multimídia & Canais (Pilar 3)** | Newsletters (Canais) v2 | Consulta de reações (`newsletterFetchReactions`), mensagens individuais (`newsletterFetchMessage`) e lista parseada. |
43
-
44
- ---
45
-
46
- ## 📌 Índice
47
-
48
- - [Instalação](#-instalação)
49
- - [Conectando a Conta](#-conectando-a-conta)
50
- - [Conexão via QR Code](#conexão-via-qr-code)
51
- - [Conexão via Código de Emparelhamento (Pairing Code)](#conexão-via-código-de-emparelhamento-pairing-code)
52
- - [Recebendo Histórico Completo](#recebendo-histórico-completo)
53
- - [Salvando e Restaurando Sessões](#-salvando-e-restaurando-sessões)
54
- - [Configurações Importantes do Socket](#-configurações-importantes-do-socket)
55
- - [Exemplo Prático Inicial (Bootstrap)](#-exemplo-prático-inicial-bootstrap)
56
- - [Tratamento de Eventos e Mídia](#-tratamento-de-eventos-e-mídia)
57
- - [Download de Mídias Recebidas](#download-de-mídias-recebidas)
58
- - [Decifrar Votos de Enquetes](#decifrar-votos-de-enquetes)
59
- - [Decifrar Respostas de Eventos](#decifrar-respostas-de-eventos)
60
- - [Verificação de Contatos e Presença](#-verificação-de-contatos-e-presença)
61
- - [Verificação de Números no WhatsApp (onWhatsApp)](#verificação-de-números-no-whatsapp-onwhatsapp)
62
- - [Presença e Digitando / Gravando Áudio](#presença-e-digitando--gravando-áudio)
63
- - [Enviando Mensagens](#-enviando-mensagens)
64
- - [Mensagens de Texto, Menções e Links](#mensagens-de-texto-e-menções)
65
- - [Mensagens de Mídia](#mensagens-de-mídia)
66
- - [Documentos e Arquivos](#documentos-e-arquivos)
67
- - [Figurinhas (Stickers)](#figurinhas-stickers)
68
- - [Localização Fixa e Tempo Real](#localização-fixa-e-em-tempo-real)
69
- - [Contatos e Cartões vCard](#contatos-e-cartões-vcard)
70
- - [Reações a Mensagens](#reações-a-mensagens)
71
- - [Criação de Enquetes](#criação-de-enquetes)
72
- - [Listas Interativas de Opções](#listas-interativas-de-opções-sections)
73
- - [Botões Interativos](#botões-interativos)
74
- - [Botão de Pagamento PIX](#botão-de-pagamento-pix)
75
- - [Fluxos de Checkout (PAY)](#fluxos-de-checkout-pay)
76
- - [Encaminhamento de Mensagens](#encaminhamento-de-mensagens)
77
- - [Menção em Status e Reações](#menção-em-status)
78
- - [Comentários em Canais e Comunidades](#comentários-em-canais-e-comunidades)
79
- - [Modificando Mensagens e Chats](#-modificando-mensagens-e-chats)
80
- - [Confirmação de Leitura (readMessages)](#confirmação-de-leitura-readmessages)
81
- - [Mensagens com Estrela (star)](#mensagens-com-estrela-star)
82
- - [Fixação de Mensagens com Duração](#fixação-de-mensagens-com-duração)
83
- - [Favoritos e Anotações de Contato](#favoritos-e-anotações-de-contato)
84
- - [Perfil do Usuário e Foto](#-perfil-do-usuário-e-foto)
85
- - [Eventos em Grupos e RSVP](#-eventos-em-grupos-e-rsvp)
86
- - [Chamadas Web (Web Calling)](#-chamadas-web-web-calling)
87
- - [Resolução de Usuários (LID e Telefone)](#-resolução-de-usuários--transição-lid-pilar-2)
88
- - [Etiquetas e Respostas Rápidas (WhatsApp Business)](#-etiquetas-de-negócio-labels---whatsapp-business)
89
- - [Gerenciamento de Grupos](#-gerenciamento-de-grupos)
90
- - [Newsletters (Canais)](#-newsletters--canais-v2-pilar-3)
91
- - [WhatsApp Business (Catálogo e Produtos)](#-whatsapp-business-catálogo-produtos-e-perfil-comercial)
92
- - [Grupos e Comunidades v2](#-grupos-comunidades-v2-e-moderação-avançada)
93
- - [Arquitetura de Plugins e Middlewares](#-arquitetura-de-plugins-e-middlewares)
94
- - [Alta Performance, Cache e Memória](#-alta-performance-cache-e-controle-de-memória)
95
- - [Configurações de Privacidade](#-configurações-de-privacidade)
96
- - [Logs e Protocolo](#-logs-e-protocolo)
97
-
98
- ---
99
-
100
- ## 📦 Instalação
101
-
102
- Adicione o pacote ao seu projeto via Yarn ou NPM:
103
-
104
- **Versão Estável (Recomendado):**
105
- ```bash
106
- yarn add @areumtecnologia/wasockets
107
- # ou
108
- npm install @areumtecnologia/wasockets
109
- ```
110
-
111
- **Versão de Desenvolvimento (Edge):**
112
- ```bash
113
- yarn add github:areumtecnologia/WaSockets
114
- ```
115
-
116
- ---
117
-
118
- ## 🔑 Conectando a Conta
119
-
120
- 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**.
121
-
122
- ### Conexão via QR Code
123
-
124
- ```javascript
125
- const { default: makeWASocket, Browsers } = require('@areumtecnologia/wasockets')
126
-
127
- const sock = makeWASocket({
128
- // Configurações do navegador exibidas no WhatsApp do celular
129
- browser: Browsers.ubuntu('Chrome'),
130
- printQRInTerminal: true
131
- })
132
- ```
133
-
134
- ### Conexão via Código de Emparelhamento (Pairing Code)
135
-
136
- 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.
137
-
138
- ```javascript
139
- const { default: makeWASocket } = require('@areumtecnologia/wasockets')
140
-
141
- const sock = makeWASocket({
142
- printQRInTerminal: false // Deve ser false
143
- })
144
-
145
- if (!sock.authState.creds.registered) {
146
- const numeroTelefone = '5511999999999' // Insira o número completo
147
- const codigo = await sock.requestPairingCode(numeroTelefone)
148
- console.log(`Digite este código no seu WhatsApp: ${codigo}`)
149
- }
150
- ```
151
-
152
- ### Recebendo Histórico Completo
153
-
154
- 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:
155
-
156
- ```javascript
157
- const sock = makeWASocket({
158
- browser: Browsers.macOS('Desktop'),
159
- syncFullHistory: true
160
- })
161
- ```
162
-
163
- ---
164
-
165
- ## 💾 Salvando e Restaurando Sessões
166
-
167
- 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.
168
-
169
- ```javascript
170
- const { default: makeWASocket, useMultiFileAuthState } = require('@areumtecnologia/wasockets')
171
-
172
- async function iniciar() {
173
- // Carrega o estado da pasta especificada
174
- const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
175
-
176
- const sock = makeWASocket({
177
- auth: state
178
- })
179
-
180
- // Salva as credenciais sempre que forem atualizadas
181
- sock.ev.on('creds.update', saveCreds)
182
- }
183
- iniciar()
184
- ```
185
-
186
- > [!IMPORTANT]
187
- > 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.
188
-
189
- ---
190
-
191
- ## ⚙️ Configurações Importantes do Socket
192
-
193
- ### 1. Cache de Metadados de Grupo (Altamente Recomendado)
194
- 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:
195
-
196
- ```javascript
197
- const NodeCache = require('@cacheable/node-cache') // ou similar
198
- const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
199
-
200
- const sock = makeWASocket({
201
- cachedGroupMetadata: async (jid) => groupCache.get(jid)
202
- })
203
-
204
- sock.ev.on('groups.update', async ([event]) => {
205
- const metadata = await sock.groupMetadata(event.id)
206
- groupCache.set(event.id, metadata)
207
- })
208
-
209
- sock.ev.on('group-participants.update', async (event) => {
210
- const metadata = await sock.groupMetadata(event.id)
211
- groupCache.set(event.id, metadata)
212
- })
213
- ```
214
-
215
- ### 2. Recuperação de Mensagens e Enquetes
216
- Para descriptografar respostas de enquetes antigas ou gerenciar tentativas de reenvio automáticas do WhatsApp, configure a função `getMessage`:
217
-
218
- ```javascript
219
- const sock = makeWASocket({
220
- getMessage: async (key) => {
221
- // Busque a mensagem salva no seu banco de dados ou store local
222
- return await buscarMensagemSalva(key.id)
223
- }
224
- })
225
- ```
226
-
227
- ### 3. Fila Inteligente de Mensagens Durante Quedas Transitórias
228
- 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:
229
-
230
- ```javascript
231
- const sock = makeWASocket({
232
- enableMessageQueue: true, // Ativado por padrão (evita perda de mensagens durante reconexão)
233
- messageQueueTtlMs: 5 * 60 * 1000 // TTL de expiração na fila (padrão: 5 minutos)
234
- })
235
- ```
236
-
237
- ### 4. Auto-Reparo de Sessão E2E / Signal (`repairSession`)
238
- 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`:
239
-
240
- ```javascript
241
- // Remove a sessão danificada e força a renegociação de chaves E2E com o contato
242
- await sock.repairSession('5511999999999@s.whatsapp.net')
243
- ```
244
-
245
- ---
246
-
247
- ## 🚀 Exemplo Prático Inicial (Bootstrap)
248
-
249
- Aqui está um arquivo funcional completo em JavaScript (CommonJS) para iniciar a sua integração:
250
-
251
- ```javascript
252
- const { default: makeWASocket, DisconnectReason, useMultiFileAuthState, makeReconnectManager, shouldReconnect } = require('@areumtecnologia/wasockets')
253
- const { Boom } = require('@hapi/boom')
254
-
255
- async function connectToWhatsApp() {
256
- // 1. Inicializa o estado de autenticação baseado em arquivos
257
- const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
258
-
259
- // 2. Cria o Socket de Conexão com fila de mensagens inteligente ativada por padrão
260
- const sock = makeWASocket({
261
- auth: state,
262
- printQRInTerminal: true,
263
- enableMessageQueue: true // Fila de envio automático durante reconexões transitórias
264
- })
265
-
266
- // Gerenciador de reconexão adaptativa com Backoff Exponencial e Full Jitter (evita banimentos)
267
- const reconnectManager = makeReconnectManager({
268
- onReconnect: async (attempt) => {
269
- console.log(`Reconectando ao WhatsApp (tentativa #${attempt})...`)
270
- await connectToWhatsApp()
271
- }
272
- })
273
-
274
- // 3. Monitora o status da conexão
275
- sock.ev.on('connection.update', async (update) => {
276
- const { connection, lastDisconnect } = update
277
-
278
- if (connection === 'close') {
279
- await reconnectManager.handleDisconnect(lastDisconnect?.error)
280
- } else if (connection === 'open') {
281
- reconnectManager.reset()
282
- console.log('Conexão com o WhatsApp estabelecida com sucesso!')
283
- }
284
- })
285
-
286
- // 4. Salva credenciais atualizadas
287
- sock.ev.on('creds.update', saveCreds)
288
-
289
- // 5. Escuta e responde a novas mensagens recebidas
290
- sock.ev.on('messages.upsert', async (event) => {
291
- for (const m of event.messages) {
292
- // Ignora mensagens que não sejam do tipo padrão ou geradas pelo próprio bot
293
- if (!m.message || m.key.fromMe) continue
294
-
295
- console.log('Mensagem recebida de:', m.key.remoteJid)
296
- console.log('Conteúdo:', JSON.stringify(m, null, 2))
297
-
298
- // Responde à mensagem
299
- await sock.sendMessage(m.key.remoteJid, { text: 'Olá! Recebi sua mensagem com sucesso.' })
300
- }
301
- })
302
- }
303
-
304
- // Inicia o processo
305
- connectToWhatsApp()
306
- ```
307
-
308
- ---
309
-
310
- ## 📡 Tratamento de Eventos e Mídia
311
-
312
- O **WaSockets** utiliza um sistema de eventos tipado baseado no `EventEmitter`.
313
-
314
- ```javascript
315
- sock.ev.on('messages.upsert', ({ messages, type }) => {
316
- // type pode ser 'notify' (nova notificação) ou 'append' (carregamento histórico)
317
- console.log('Novas mensagens recebidas:', messages)
318
- })
319
- ```
320
-
321
- ### Download de Mídias Recebidas
322
-
323
- Para baixar mídias (fotos, vídeos, áudios, documentos ou stickers) recebidas no evento `messages.upsert`, utilize a função utilitária `downloadMediaMessage`:
324
-
325
- ```javascript
326
- const { downloadMediaMessage } = require('@areumtecnologia/wasockets')
327
- const fs = require('fs')
328
-
329
- sock.ev.on('messages.upsert', async ({ messages }) => {
330
- for (const msg of messages) {
331
- if (!msg.message || msg.key.fromMe) continue
332
-
333
- const isMedia = msg.message.imageMessage ||
334
- msg.message.videoMessage ||
335
- msg.message.audioMessage ||
336
- msg.message.documentMessage ||
337
- msg.message.stickerMessage
338
-
339
- if (isMedia) {
340
- // Baixa o arquivo diretamente em formato Buffer
341
- const buffer = await downloadMediaMessage(msg, 'buffer', {})
342
-
343
- // Exemplo: Salvar no disco
344
- const ext = msg.message.imageMessage ? 'jpg' : msg.message.audioMessage ? 'ogg' : 'bin'
345
- fs.writeFileSync(`./download_${msg.key.id}.${ext}`, buffer)
346
- console.log(`Mídia baixada com sucesso (${buffer.length} bytes)!`)
347
-
348
- // Ou baixar como stream de leitura para processamento em tempo real:
349
- // const stream = await downloadMediaMessage(msg, 'stream', {})
350
- }
351
- }
352
- })
353
- ```
354
-
355
- ### Decifrar Votos de Enquetes
356
-
357
- Os votos em enquetes chegam como mensagens criptografadas no evento `messages.update`. É preciso usar o helper `getAggregateVotesInPollMessage` passando a mensagem original da enquete.
358
-
359
- ```javascript
360
- const { getAggregateVotesInPollMessage } = require('@areumtecnologia/wasockets')
361
-
362
- sock.ev.on('messages.update', async (updates) => {
363
- for (const { key, update } of updates) {
364
- if (update.pollUpdates) {
365
- // 1. Busca a mensagem original da enquete que foi criada anteriormente
366
- const pollCreationMessage = await obterMensagemSalva(key)
367
- if (pollCreationMessage) {
368
- // 2. Agrega os votos
369
- const pollVotes = await getAggregateVotesInPollMessage({
370
- message: pollCreationMessage,
371
- pollUpdates: update.pollUpdates
372
- })
373
-
374
- // 3. Exibe as opções votadas e os respectivos eleitores
375
- console.log('Resultado da Enquete Atualizado:', pollVotes)
376
- }
377
- }
378
- }
379
- })
380
- ```
381
-
382
- ### Decifrar Respostas de Eventos
383
-
384
- 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.
385
-
386
- ```javascript
387
- const { getAggregateResponsesInEventMessage } = require('@areumtecnologia/wasockets')
388
-
389
- sock.ev.on('messages.update', async (updates) => {
390
- for (const { key, update } of updates) {
391
- if (update.eventResponses) {
392
- const eventCreationMessage = await obterMensagemSalva(key)
393
- if (eventCreationMessage) {
394
- const responses = await getAggregateResponsesInEventMessage({
395
- message: eventCreationMessage,
396
- eventResponses: update.eventResponses
397
- })
398
- console.log('Respostas ao evento atualizadas:', responses)
399
- }
400
- }
401
- }
402
- })
403
- ```
404
-
405
- ---
406
-
407
- ## 🔍 Verificação de Contatos e Presença
408
-
409
- ### Verificação de Números no WhatsApp (onWhatsApp)
410
-
411
- Valide se um ou vários números de telefone possuem contas ativas registradas no WhatsApp antes de disparar mensagens:
412
-
413
- ```javascript
414
- // Aceita um ou vários números (com DDI e DDD)
415
- const resultados = await sock.onWhatsApp('5511999999999', '5511888888888', '5521977777777')
416
-
417
- for (const { jid, exists } of resultados) {
418
- if (exists) {
419
- console.log(`O número ${jid} está ativo no WhatsApp!`)
420
- } else {
421
- console.log(`O número ${jid} NÃO possui conta no WhatsApp.`)
422
- }
423
- }
424
- ```
425
-
426
- ### Presença e Digitando / Gravando Áudio
427
-
428
- Simule atividade humana enviando estados de presença ou monitore o status de contatos:
429
-
430
- ```javascript
431
- // 1. Indicar que está digitando...
432
- await sock.sendPresenceUpdate('composing', jid)
433
-
434
- // 2. Indicar que está gravando áudio...
435
- await sock.sendPresenceUpdate('recording', jid)
436
-
437
- // 3. Pausar status de digitação/gravação
438
- await sock.sendPresenceUpdate('paused', jid)
439
-
440
- // 4. Alterar presença geral da conta ('available' = Online, 'unavailable' = Offline)
441
- await sock.sendPresenceUpdate('available')
442
-
443
- // 5. Inscrever-se para escutar presença de um contato específico
444
- await sock.presenceSubscribe(jid)
445
-
446
- // 6. Monitorar atualizações de presença recebidas
447
- sock.ev.on('presence.update', ({ id, presences }) => {
448
- console.log(`Atualização de presença de ${id}:`, presences)
449
- })
450
- ```
451
-
452
- ---
453
-
454
- ## ✉️ Enviando Mensagens
455
-
456
- ### Mensagens de Texto e Menções
457
-
458
- ```javascript
459
- // Mensagem de texto simples
460
- await sock.sendMessage(jid, { text: 'Olá Mundo!' })
461
-
462
- // Mensagem citando (respondendo a) outra mensagem
463
- await sock.sendMessage(jid, { text: 'Esta é uma resposta.' }, { quoted: mensagemOriginal })
464
-
465
- // Mensagem mencionando contatos no grupo
466
- await sock.sendMessage(jid, {
467
- text: 'Olá @5511999999999 e @5511888888888!',
468
- mentions: ['5511999999999@s.whatsapp.net', '5511888888888@s.whatsapp.net']
469
- })
470
- ```
471
-
472
- ### Mensagens de Mídia
473
-
474
- É possível passar caminhos de arquivos locais (`url`), links da internet (`url`), buffers ou streams de leitura.
475
-
476
- ```javascript
477
- const fs = require('fs')
478
-
479
- // Imagem com legenda
480
- await sock.sendMessage(jid, {
481
- image: { url: './foto.jpg' }, // ou { url: 'https://example.com/foto.jpg' } ou Buffer
482
- caption: 'Minha foto legal!'
483
- })
484
-
485
- // Álbum de mídias (Múltiplas fotos/vídeos no mesmo bloco)
486
- await sock.sendMessage(jid, {
487
- album: [
488
- { image: { url: './foto1.jpg' }, caption: 'Foto 1' },
489
- { image: { url: './foto2.jpg' }, caption: 'Foto 2' },
490
- { video: { url: './video.mp4' }, caption: 'Vídeo do Álbum' }
491
- ]
492
- })
493
-
494
- // GIF (vídeo mp4 simulado como reprodução contínua)
495
- await sock.sendMessage(jid, {
496
- video: fs.readFileSync('./video-gif.mp4'),
497
- gifPlayback: true,
498
- caption: 'Olha esse gif!'
499
- })
500
-
501
- // Áudio Gravado (Simula o gravador de voz do WhatsApp - PTT)
502
- await sock.sendMessage(jid, {
503
- audio: { url: './audio.ogg' },
504
- mimetype: 'audio/mp4', // obrigatório
505
- ptt: true // Define como mensagem de voz
506
- })
507
-
508
- // Mensagem de Visualização Única (View Once)
509
- await sock.sendMessage(jid, {
510
- image: { url: './foto.jpg' },
511
- viewOnce: true,
512
- caption: 'Esta foto desaparecerá após ser aberta!'
513
- })
514
- ```
515
-
516
- > [!TIP]
517
- > 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:
518
- > `ffmpeg -i input.mp3 -c:a libopus -ac 1 -avoid_negative_ts make_zero output.ogg`
519
-
520
- ---
521
-
522
- ### Documentos e Arquivos
523
-
524
- Envie qualquer formato de arquivo (PDF, planilhas, arquivos compactados) informando o `mimetype` e o `fileName` para exibição correta no aplicativo:
525
-
526
- ```javascript
527
- await sock.sendMessage(jid, {
528
- document: { url: './fatura_setembro.pdf' }, // ou Buffer ou { url: 'https://exemplo.com/doc.pdf' }
529
- mimetype: 'application/pdf',
530
- fileName: 'Fatura_Setembro_2026.pdf'
531
- })
532
- ```
533
-
534
- ### Figurinhas (Stickers)
535
-
536
- Envie figurinhas estáticas ou animadas no formato WebP:
537
-
538
- ```javascript
539
- await sock.sendMessage(jid, {
540
- sticker: fs.readFileSync('./minha_figurinha.webp') // aceita Buffer ou { url: './figurinha.webp' }
541
- })
542
- ```
543
-
544
- ### Localização Fixa e em Tempo Real
545
-
546
- Envie pontos no mapa ou compartilhe localização em tempo real com latitude e longitude:
547
-
548
- ```javascript
549
- // Localização Fixa
550
- await sock.sendMessage(jid, {
551
- location: {
552
- degreesLatitude: -23.55052,
553
- degreesLongitude: -46.633308,
554
- name: 'Sede da Áreum Tecnologia',
555
- address: 'Av. Paulista, 1000 - Bela Vista, São Paulo - SP'
556
- }
557
- })
558
-
559
- // Localização em Tempo Real (Live Location)
560
- await sock.sendMessage(jid, {
561
- location: {
562
- degreesLatitude: -23.55052,
563
- degreesLongitude: -46.633308
564
- },
565
- live: true
566
- })
567
- ```
568
-
569
- ### Contatos e Cartões vCard
570
-
571
- Envie um ou múltiplos contatos com cartão vCard formatado:
572
-
573
- ```javascript
574
- const vcard = 'BEGIN:VCARD\n'
575
- + 'VERSION:3.0\n'
576
- + 'FN:Suporte Técnico Áreum\n'
577
- + 'ORG:Áreum Tecnologia;\n'
578
- + 'TEL;type=CELL;type=VOICE;waid=5511999999999:+55 11 99999-9999\n'
579
- + 'END:VCARD'
580
-
581
- await sock.sendMessage(jid, {
582
- contacts: {
583
- displayName: 'Suporte Técnico Áreum',
584
- contacts: [{ vcard }]
585
- }
586
- })
587
- ```
588
-
589
- ### Reações a Mensagens
590
-
591
- Reaja com emojis a qualquer mensagem enviada ou recebida (ou remova a reação enviando string vazia `''`):
592
-
593
- ```javascript
594
- // Reagir à mensagem com um emoji
595
- await sock.sendMessage(jid, {
596
- react: {
597
- text: '🔥', // Emoji da reação
598
- key: msg.key // Chave da mensagem original que receberá a reação
599
- }
600
- })
601
-
602
- // Remover reação anterior
603
- await sock.sendMessage(jid, {
604
- react: {
605
- text: '',
606
- key: msg.key
607
- }
608
- })
609
- ```
610
-
611
- ### Criação de Enquetes
612
-
613
- Crie enquetes interativas com contagem configurável de seleção (voto único ou múltiplo):
614
-
615
- ```javascript
616
- await sock.sendMessage(jid, {
617
- poll: {
618
- name: 'Qual o melhor diferencial do WaSockets?',
619
- values: [
620
- 'Resolução Transparente de LID',
621
- 'Envio Nativo de Álbuns',
622
- 'Newsletters v2 e Canais',
623
- 'Fila Inteligente de Reconexão'
624
- ],
625
- selectableCount: 1 // 1 para escolha única; > 1 para permitir múltiplas escolhas
626
- }
627
- })
628
- ```
629
-
630
- ### Listas Interativas de Opções (Sections)
631
-
632
- Envie menus organizados por categorias e linhas para navegação intuitiva:
633
-
634
- ```javascript
635
- await sock.sendMessage(jid, {
636
- text: 'Selecione o setor desejado para atendimento:',
637
- footer: 'Áreum Tecnologia • Atendimento Automatizado',
638
- title: 'Central de Relacionamento',
639
- buttonText: 'Ver Departamentos',
640
- sections: [
641
- {
642
- title: 'Atendimento Comercial',
643
- rows: [
644
- { title: 'Novas Contratações', rowId: 'row_vendas', description: 'Conheça nossos planos e soluções' },
645
- { title: 'Upgrade de Plano', rowId: 'row_upgrade', description: 'Amplie os limites da sua conta' }
646
- ]
647
- },
648
- {
649
- title: 'Suporte & Operações',
650
- rows: [
651
- { title: 'Suporte Técnico', rowId: 'row_suporte', description: 'Dúvidas de integração e bugs' },
652
- { title: 'Financeiro', rowId: 'row_financeiro', description: '2ª via de boleto e notas fiscais' }
653
- ]
654
- }
655
- ]
656
- })
657
- ```
658
-
659
- ---
660
-
661
- ### Botões Interativos
662
-
663
- Os botões nativos do WhatsApp são suportados através da propriedade `interactiveButtons`.
664
-
665
- ```javascript
666
- await sock.sendMessage(jid, {
667
- text: 'Olá! Escolha uma das opções abaixo:',
668
- title: 'Painel Interativo',
669
- subtitle: 'Selecione com um clique',
670
- footer: 'Áreum Tecnologia',
671
- interactiveButtons: [
672
- {
673
- name: 'quick_reply',
1
+ # WaSockets - API do WhatsApp Web em TypeScript/JavaScript
2
+
3
+ <div align="center">
4
+ <p><strong>Uma modificação otimizada e de alta performance da API do WhatsApp (baseada no Baileys), mantida e aprimorada pela Áreum Tecnologia.</strong></p>
5
+ </div>
6
+
7
+ ---
8
+
9
+ > 💡 **Nota:** Esta é a documentação padrão da biblioteca (mensagens, mídias, comunidades, canais, grupos, botões e gerenciamento de conta). Para a documentação técnica detalhada de arquitetura e módulos adicionais, consulte o [README_DETALHADO.md](./README_DETALHADO.md).
10
+
11
+ ---
12
+
13
+ ### ⚠️ Nota Importante e Licença
14
+
15
+ 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.
16
+
17
+ 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`).
18
+
19
+ ---
20
+
21
+ ## 🚀 Diferenciais e Correções da Áreum Tecnologia
22
+
23
+ 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:
24
+
25
+ | Categoria | Recurso / Correção | Descrição |
26
+ | :--- | :--- | :--- |
27
+ | **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). |
28
+ | **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. |
29
+ | **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. |
30
+ | **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. |
31
+ | **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`. |
32
+ | **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. |
33
+ | **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`). |
34
+ | **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. |
35
+ | **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. |
36
+ | **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`). |
37
+ | **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`. |
38
+ | **Recursos Web (v1.1.6)** | Reação a Status | Método nativo `reactToStatus` para curtir e reagir diretamente a publicações de Status. |
39
+ | **Recursos Web (v1.1.6)** | Eventos & RSVP | Criação, cancelamento (`cancelEvent`) e confirmação de presença (`sendEventResponse`) em eventos de grupo. |
40
+ | **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`). |
41
+ | **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`). |
42
+ | **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. |
43
+ | **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. |
44
+ | **Multimídia & Canais (Pilar 3)** | Álbum Nativo & Waveforms | Envio de álbuns (`sendAlbumMessage`), ordenação indexada e suporte a waveforms PTT customizadas. |
45
+ | **Multimídia & Canais (Pilar 3)** | Newsletters (Canais) v2 | Consulta de reações (`newsletterFetchReactions`), mensagens individuais (`newsletterFetchMessage`) e lista parseada. |
46
+ | **Conectividade & Histórico** | Plataforma Nativa `WIN_HYBRID` | Substitui o `WIN32` depreciado pelo `WIN_HYBRID` nativo em `Browsers.windows('Desktop')`, eliminando o erro 428 e desbloqueando a sincronização de histórico completo (`syncFullHistory: true`). |
47
+ | **Multimídia & ViewOnce** | Emulação de Browser Android | Introdução do preset `Browsers.android('Chrome')` permitindo à sessão receber mensagens e mídias de visualização única (*View Once*). |
48
+ | **Alta Performance** | Cache WeakMap em Nós Binários | Indexação de tags filhas com `WeakMap` em `getBinaryNodeChildren` e `getBinaryNodeChild` gerando aceleração de até 30x no processamento de pacotes XML sem vazamento de memória. |
49
+ | **Privacidade & Contatos** | TC Token Nesting em Fotos de Perfil | Aninhamento do nó `<tctoken>` diretamente na query `<picture>` para atender ao protocolo `profilePicPrivacyToken`, suportando busca em alta resolução (`image`) e miniatura (`preview`). |
50
+
51
+ ---
52
+
53
+ ## 📌 Índice
54
+
55
+ - [🌟 Camada de Abstração de Alto Nível (WaClient) — Recomendado](#-camada-de-abstração-de-alto-nível-waclient--recomendado)
56
+ - [Por que usar o WaClient?](#por-que-usar-o-waclient)
57
+ - [Guia Rápido (Quick Start)](#guia-rápido-quick-start)
58
+ - [Eventos Semânticos](#eventos-semânticos)
59
+ - [O Contexto de Mensagem (MessageContext / ctx)](#o-contexto-de-mensagem-messagecontext--ctx)
60
+ - [Builders de Botões Interativos (InteractiveMessage)](#builders-de-botões-interativos-interactivemessage)
61
+ - [Controle de Presença Fluente (Typing / Recording)](#controle-de-presença-fluente-typing--recording)
62
+ - [Os 13 Submódulos Especializados](#os-13-submódulos-especializados)
63
+ - [Opções de Configuração (WaClientOptions)](#opções-de-configuração-waclientoptions)
64
+ - [Instalação](#-instalação)
65
+ - [API de Baixo Nível (makeWASocket Legado)](#-conectando-a-conta)
66
+ - [Conexão via QR Code](#conexão-via-qr-code)
67
+ - [Conexão via Código de Emparelhamento (Pairing Code)](#conexão-via-código-de-emparelhamento-pairing-code)
68
+ - [Recebendo Histórico Completo](#recebendo-histórico-completo)
69
+ - [Salvando e Restaurando Sessões](#-salvando-e-restaurando-sessões)
70
+ - [Configurações Importantes do Socket](#-configurações-importantes-do-socket)
71
+ - [Exemplo Prático Inicial (Bootstrap)](#-exemplo-prático-inicial-bootstrap)
72
+ - [Tratamento de Eventos e Mídia](#-tratamento-de-eventos-e-mídia)
73
+ - [Download de Mídias Recebidas](#download-de-mídias-recebidas)
74
+ - [Decifrar Votos de Enquetes](#decifrar-votos-de-enquetes)
75
+ - [Decifrar Respostas de Eventos](#decifrar-respostas-de-eventos)
76
+ - [Verificação de Contatos e Presença](#-verificação-de-contatos-e-presença)
77
+ - [Verificação de Números no WhatsApp (onWhatsApp)](#verificação-de-números-no-whatsapp-onwhatsapp)
78
+ - [Presença e Digitando / Gravando Áudio](#presença-e-digitando--gravando-áudio)
79
+ - [Enviando Mensagens](#-enviando-mensagens)
80
+ - [Mensagens de Texto, Menções e Links](#mensagens-de-texto-e-menções)
81
+ - [Mensagens de Mídia](#mensagens-de-mídia)
82
+ - [Documentos e Arquivos](#documentos-e-arquivos)
83
+ - [Figurinhas (Stickers)](#figurinhas-stickers)
84
+ - [Localização Fixa e Tempo Real](#localização-fixa-e-em-tempo-real)
85
+ - [Contatos e Cartões vCard](#contatos-e-cartões-vcard)
86
+ - [Reações a Mensagens](#reações-a-mensagens)
87
+ - [Criação de Enquetes](#criação-de-enquetes)
88
+ - [Listas Interativas de Opções](#listas-interativas-de-opções-sections)
89
+ - [Botões Interativos](#botões-interativos)
90
+ - [Botão de Pagamento PIX](#botão-de-pagamento-pix)
91
+ - [Fluxos de Checkout (PAY)](#fluxos-de-checkout-pay)
92
+ - [Encaminhamento de Mensagens](#encaminhamento-de-mensagens)
93
+ - [Menção em Status e Reações](#menção-em-status)
94
+ - [Comentários em Canais e Comunidades](#comentários-em-canais-e-comunidades)
95
+ - [Modificando Mensagens e Chats](#-modificando-mensagens-e-chats)
96
+ - [Confirmação de Leitura (readMessages)](#confirmação-de-leitura-readmessages)
97
+ - [Mensagens com Estrela (star)](#mensagens-com-estrela-star)
98
+ - [Fixação de Mensagens com Duração](#fixação-de-mensagens-com-duração)
99
+ - [Favoritos e Anotações de Contato](#favoritos-e-anotações-de-contato)
100
+ - [Perfil do Usuário e Foto](#-perfil-do-usuário-e-foto)
101
+ - [Eventos em Grupos e RSVP](#-eventos-em-grupos-e-rsvp)
102
+ - [Resolução de Usuários (LID e Telefone)](#-resolução-de-usuários--transição-lid-pilar-2)
103
+ - [Etiquetas e Respostas Rápidas (WhatsApp Business)](#-etiquetas-de-negócio-labels---whatsapp-business)
104
+ - [Gerenciamento de Grupos](#-gerenciamento-de-grupos)
105
+ - [Newsletters (Canais)](#-newsletters--canais-v2-pilar-3)
106
+ - [WhatsApp Business (Catálogo e Produtos)](#-whatsapp-business-catálogo-produtos-e-perfil-comercial)
107
+ - [Grupos e Comunidades v2](#-grupos-comunidades-v2-e-moderação-avançada)
108
+ - [Arquitetura de Plugins e Middlewares](#-arquitetura-de-plugins-e-middlewares)
109
+ - [Alta Performance, Cache e Memória](#-alta-performance-cache-e-controle-de-memória)
110
+ - [Configurações de Privacidade](#-configurações-de-privacidade)
111
+ - [Logs e Protocolo](#-logs-e-protocolo)
112
+
113
+ ---
114
+
115
+ ## 📦 Instalação
116
+
117
+ Adicione o pacote ao seu projeto via Yarn ou NPM:
118
+
119
+ **Versão Estável (Recomendado):**
120
+ ```bash
121
+ yarn add @areumtecnologia/wasockets
122
+ # ou
123
+ npm install @areumtecnologia/wasockets
124
+ ```
125
+
126
+ **Versão de Desenvolvimento (Edge):**
127
+ ```bash
128
+ yarn add github:areumtecnologia/WaSockets
129
+ ```
130
+
131
+ ---
132
+
133
+ ## 🌟 Camada de Abstração de Alto Nível (WaClient) — Recomendado
134
+
135
+ > **Novo no WaSockets!** A classe `WaClient` é uma camada de abstração de alto nível que elimina mais de **85% do boilerplate** comum de integrações com WhatsApp. Ela gerencia automaticamente autenticação multi-arquivos, reconexões inteligentes, normalização instantânea de mensagens e mídias, oferece builders fluentes de botões interativos e divide todas as funcionalidades em **13 submódulos especializados**.
136
+
137
+ ### Por que usar o WaClient?
138
+
139
+ | Recurso | `makeWASocket` (Baixo Nível) | `WaClient` (Alto Nível) |
140
+ | :--- | :--- | :--- |
141
+ | **Autenticação & Sessão** | Configurar `useMultiFileAuthState`, gerenciar pastas e `creds.update` manualmente. | **Automático:** apenas defina `sessionName` e o cliente gerencia tudo. |
142
+ | **Reconexão** | Analisar códigos do `Boom`, verificar `DisconnectReason` e agendar timeouts. | **Automático:** reconexão inteligente em quedas transitórias sem loopings. |
143
+ | **Tratamento de Mensagens** | Escutar `messages.upsert`, iterar arrays brutos, extrair nós Proto profundamente. | **`ctx` Enriquecido:** objeto limpo com `ctx.reply()`, `ctx.react()`, `ctx.delete()`, etc. |
144
+ | **Download de Mídias** | Importar `downloadContentFromMessage`, gerenciar streams e conversão de Buffers. | **`MediaObject`:** métodos diretos `ctx.media.save()`, `toBase64()`, `toStream()`, `toSharp()`. |
145
+ | **Botões Interativos & PIX** | Montar estruturas JSON aninhadas e complexas de `interactiveMessage`. | **Builders Fluentes:** `new InteractiveMessage().addButton(new PixButton(...))`. |
146
+ | **Presença (Digitando)** | Disparar `sendPresenceUpdate` manual e lembrar de cancelar com timeout. | **Lifecycle Automático:** `const typing = client.startTyping(jid); ... typing.stop()`. |
147
+ | **Validação de Destinatário** | Erros de envio quando número não existe no WhatsApp. | **`isOnWhatsApp` Embutido:** validação prévia transparente sem quebrar sua aplicação. |
148
+
149
+ ---
150
+
151
+ ### Guia Rápido (Quick Start)
152
+
153
+ ```javascript
154
+ const { WaClient, Events } = require('@areumtecnologia/wasockets/client');
155
+
156
+ // 1. Inicializa o cliente com configurações simplificadas
157
+ const client = new WaClient({
158
+ sessionName: 'atendimento-sac',
159
+ dataPath: './sessions',
160
+ printQRInTerminal: true,
161
+ restartOnClose: true
162
+ });
163
+
164
+ // 2. Eventos Semânticos
165
+ client.on(Events.CONNECTED, ({ user }) => {
166
+ console.log(`✓ Bot online com sucesso como: ${user.name} (${user.id})`);
167
+ });
168
+
169
+ // 3. Recepção de Mensagens com Contexto Enriquecido
170
+ client.on(Events.MESSAGE_RECEIVED, async (ctx) => {
171
+ // Ignora mensagens do próprio bot
172
+ if (ctx.isFromMe) return;
173
+
174
+ console.log(`[${ctx.senderName}]: ${ctx.body}`);
175
+
176
+ // Resposta automática com citação
177
+ if (ctx.body === '!ping') {
178
+ await ctx.react('🏓');
179
+ return ctx.reply('Pong! 🚀');
180
+ }
181
+
182
+ // Se receber mídia (foto, áudio, vídeo, doc)
183
+ if (ctx.media) {
184
+ console.log(`Mídia recebida: ${ctx.media.mimetype} (${ctx.media.fileLength} bytes)`);
185
+ await ctx.media.save(`./downloads/${ctx.id}.${ctx.media.mimetype.split('/')[1]}`);
186
+ await ctx.reply('Arquivo salvo com sucesso!');
187
+ }
188
+ });
189
+
190
+ // 4. Inicia a conexão
191
+ client.connect();
192
+ ```
193
+
194
+ ---
195
+
196
+ ### Eventos Semânticos
197
+
198
+ A classe `WaClient` emite eventos limpos e intuitivos através do enum `Events`:
199
+
200
+ ```javascript
201
+ const { Events } = require('@areumtecnologia/wasockets/client');
202
+
203
+ client.on(Events.CONNECTED, ({ user }) => { /* Conexão estabelecida */ });
204
+ client.on(Events.DISCONNECTED, ({ reason, willReconnect, error }) => { /* Queda de conexão */ });
205
+ client.on(Events.QR_CODE, ({ qr, base64 }) => { /* QR code emitido (terminal ou base64 para frontend) */ });
206
+ client.on(Events.PAIRING_CODE, ({ code }) => { /* Código de emparelhamento por telefone */ });
207
+ client.on(Events.LOGGED_OUT, () => { /* Desconectado/revogado pelo celular */ });
208
+
209
+ client.on(Events.MESSAGE_RECEIVED, async (ctx, rawMsg) => { /* Nova mensagem recebida */ });
210
+ client.on(Events.MESSAGE_SENT, async (ctx, rawMsg) => { /* Mensagem enviada pelo bot */ });
211
+ client.on(Events.MESSAGE_UPDATE, (updates) => { /* Edições de mensagem, apagadas ou confirmações */ });
212
+
213
+ client.on(Events.GROUP_PARTICIPANTS_UPDATE, (update) => { /* Entrada, saída ou promoção em grupo */ });
214
+ client.on(Events.PRESENCE_UPDATE, (presence) => { /* Usuário online, digitando ou offline */ });
215
+ client.on(Events.CONTACTS_UPSERT, (contacts) => { /* Novos contatos sincronizados */ });
216
+ client.on(Events.LABELS_UPDATE, (labels) => { /* Criação ou associação de etiquetas comerciais */ });
217
+ ```
218
+
219
+ ---
220
+
221
+ ### O Contexto de Mensagem (`MessageContext` / `ctx`)
222
+
223
+ Ao escutar `Events.MESSAGE_RECEIVED`, você recebe um objeto `ctx` que já contém todos os dados mastigados e métodos de ação vinculados diretamente àquela mensagem:
224
+
225
+ #### Propriedades de `ctx`:
226
+ - `ctx.id`: ID único da mensagem.
227
+ - `ctx.chatId`: JID do chat (usuário, grupo ou canal).
228
+ - `ctx.sender`: JID de quem enviou.
229
+ - `ctx.senderNumber`: Apenas os números de telefone do remetente (sem `@s.whatsapp.net`).
230
+ - `ctx.senderName`: Nome formatado (nome salvo, apelido comercial ou pushName).
231
+ - `ctx.isGroup`: Booleano indicando se é grupo (`@g.us`).
232
+ - `ctx.isChannel`: Booleano indicando se é newsletter/canal (`@newsletter`).
233
+ - `ctx.isFromMe`: Booleano se a mensagem foi enviada pelo próprio bot.
234
+ - `ctx.body`: Texto principal da mensagem (já decodificado de texto, legenda, botão ou lista).
235
+ - `ctx.type`: Tipo normalizado (`text`, `image`, `video`, `audio`, `document`, `sticker`, `poll`, etc.).
236
+ - `ctx.media`: Instância de `MediaObject` (se houver mídia na mensagem).
237
+ - `ctx.quoted`: Instância recursiva de `MessageContext` para a mensagem que foi citada/respondida.
238
+ - `ctx.raw`: O nó bruto original do WhatsApp/Baileys para casos de baixo nível.
239
+
240
+ #### Ações Disponíveis em `ctx`:
241
+ ```javascript
242
+ // Responde citando a mensagem automaticamente
243
+ await ctx.reply('Olá! Em que posso ajudar?');
244
+
245
+ // Reage com emoji
246
+ await ctx.react('👍');
247
+
248
+ // Remove reação anterior
249
+ await ctx.removeReaction();
250
+
251
+ // Apaga a mensagem para todos no chat
252
+ await ctx.delete();
253
+
254
+ // Edita o texto da mensagem (quando enviada anteriormente pelo próprio bot)
255
+ await ctx.edit('Texto corrigido');
256
+
257
+ // Encaminha para outro destinatário
258
+ await ctx.forward('5511999999999@s.whatsapp.net');
259
+
260
+ // Marca a mensagem como lida (ticks azuis)
261
+ await ctx.markRead();
262
+
263
+ // Fixa a mensagem no topo da conversa (duração em segundos: 24h, 7d, 30d)
264
+ await ctx.pin(86400);
265
+
266
+ // Desafixa a mensagem
267
+ await ctx.unpin();
268
+
269
+ // Favorita ou desfavorita a mensagem com estrela
270
+ await ctx.star();
271
+ await ctx.unstar();
272
+ ```
273
+
274
+ #### Utilitários de Mídia (`MediaObject`):
275
+ Se a mensagem contiver imagem, vídeo, áudio ou documento, `ctx.media` fornece métodos instantâneos:
276
+
277
+ ```javascript
278
+ if (ctx.media) {
279
+ // 1. Salva diretamente em disco
280
+ await ctx.media.save('./pasta/comprovante.pdf');
281
+
282
+ // 2. Converte para Base64 (ideal para enviar para APIs de IA ou frontend)
283
+ const base64 = ctx.media.toBase64();
284
+ const dataUri = ctx.media.toDataUri(); // 'data:image/jpeg;base64,...'
285
+
286
+ // 3. Obtém como Stream legível (Node Readable)
287
+ const stream = ctx.media.toStream();
288
+
289
+ // 4. Integração nativa com Sharp (se instalado) para redimensionamento/corte
290
+ const sharpInstance = ctx.media.toSharp();
291
+ }
292
+ ```
293
+
294
+ ---
295
+
296
+ ### Builders de Botões Interativos (`InteractiveMessage`)
297
+
298
+ Crie botões nativos de alta conversão para WhatsApp sem precisar montar árvores JSON complexas:
299
+
300
+ ```javascript
301
+ const {
302
+ InteractiveMessage,
303
+ QuickReplyButton,
304
+ UrlButton,
305
+ CopyCodeButton,
306
+ PixButton,
307
+ ListButton,
308
+ ListSection,
309
+ ListRow
310
+ } = require('@areumtecnologia/wasockets/client');
311
+
312
+ // 1. Menu com Resposta Rápida, Link, Cupom e Chave PIX Estática
313
+ const interactive = new InteractiveMessage()
314
+ .setTitle('Plano Pro - Áreum Tecnologia')
315
+ .setText('Escolha a forma de prosseguir com a sua assinatura:')
316
+ .setFooter('Pagamento seguro via WhatsApp')
317
+ .addButton(new QuickReplyButton('Ativar Teste Grátis', 'btn_trial'))
318
+ .addButton(new UrlButton('Ver Recursos', 'https://areumtecnologia.com.br'))
319
+ .addButton(new CopyCodeButton('Copiar Cupom 20%', 'DESCONTO20'))
320
+ .addButton(new PixButton('Pagar via PIX', '12345678900', 'CPF', 'Áreum Tecnologia'));
321
+
322
+ await client.sendInteractive('5511999999999@s.whatsapp.net', interactive);
323
+
324
+ // 2. Menu com Lista de Opções (Dropdown / Sections)
325
+ const lista = new InteractiveMessage()
326
+ .setTitle('Cardápio Digital')
327
+ .setText('Selecione uma categoria de produtos:')
328
+ .addButton(new ListButton('Ver Cardápio', [
329
+ new ListSection('Bebidas', [
330
+ new ListRow('Suco de Laranja 500ml', 'R$ 9,90', 'item_suco'),
331
+ new ListRow('Refrigerante Lata', 'R$ 6,50', 'item_refri')
332
+ ]),
333
+ new ListSection('Pratos Principais', [
334
+ new ListRow('Hambúrguer Artesanal', 'Pão brioche, 180g blend', 'item_burger'),
335
+ new ListRow('Pizza Individual', 'Mussarela e tomate', 'item_pizza')
336
+ ])
337
+ ]));
338
+
339
+ await client.sendInteractive('5511999999999@s.whatsapp.net', lista);
340
+ ```
341
+
342
+ ---
343
+
344
+ ### Controle de Presença Fluente (Typing / Recording)
345
+
346
+ Indique que o bot está digitando ou gravando áudio de forma segura, com cancelamento automático ao enviar ou via objeto retornado:
347
+
348
+ ```javascript
349
+ // Inicia estado digitando ('composing')
350
+ const typing = client.startTyping(jid);
351
+
352
+ // Realiza processamento pesado (ex: consulta LLM / banco de dados)
353
+ await processarRequisicao();
354
+
355
+ // Para a digitação manualmente
356
+ await typing.stop();
357
+
358
+ // Ou para gravação de áudio ('recording')
359
+ const recording = client.startRecording(jid);
360
+ await sintetizarVoz();
361
+ await recording.stop();
362
+ ```
363
+
364
+ ---
365
+
366
+ ### Os 13 Submódulos Especializados
367
+
368
+ O `WaClient` divide as operações em 13 módulos focados, acessíveis diretamente na instância:
369
+
370
+ | Submódulo | Acesso | Descrição e Principais Métodos |
371
+ | :--- | :--- | :--- |
372
+ | **Mensagens** | `client.messages` | Envio inteligente com validação `isOnWhatsApp`, textos, mídias, álbuns (`sendAlbum`), enquetes (`sendPoll`), vCards (`sendContacts`), reações e encaminhamento. |
373
+ | **Grupos** | `client.groups` | Criar grupos, adicionar/remover membros, promover/rebaixar admins, convites, permissões de grupo e menção em massa (`mentionAll`). |
374
+ | **Canais / Newsletters** | `client.channels` | Criação e gestão de Newsletters v2, busca por código de convite ou JID, seguir, deixar de seguir, silenciar e buscar reações. |
375
+ | **Privacidade** | `client.privacy` | Bloquear/desbloquear contatos, gerenciar lista de bloqueio (`getBlocklist`) e configurar privacidade de Visto por Último, Online, Foto e Recado. |
376
+ | **Perfil** | `client.profile` | Atualizar nome de exibição (`updateName`), recado/status (`updateStatus`), foto de perfil (`updatePicture`) e obter foto em alta resolução. |
377
+ | **Chats** | `client.chat` | Fixar conversas no topo (`pin`/`unpin`), silenciar (`mute`/`unmute`), arquivar (`archive`/`unarchive`), limpar e excluir histórico. |
378
+ | **Presença** | `client.presence` | `startTyping()`, `startRecording()`, marcar conta como online/offline e assinar atualizações de presença de contatos específicos. |
379
+ | **Status / Stories** | `client.stories` | Publicar Status em texto, imagem, áudio ou vídeo, com suporte a menções direcionadas (`statusJidList`) ou broadcast público. |
380
+ | **WhatsApp Business** | `client.business` | Gestão de catálogo comercial, cadastro de produtos (`createProduct`), coleções, perfil da empresa e detalhes de pedidos (`getOrderDetails`). |
381
+ | **Etiquetas / Labels** | `client.labels` | CRUD completo de etiquetas do WhatsApp Business, associação de etiquetas a chats e mensagens específicas. |
382
+ | **Comunidades** | `client.communities` | Criação de comunidades, vinculação de subgrupos (`addSubgroups`), remoção e gestão do grupo de avisos gerais. |
383
+ | **Usuários** | `client.users` | Verificação de existência no WhatsApp (`isOnWhatsApp`), metadados, busca de perfil comercial e resolução reversa de LID para PN (`getPnForLid`). |
384
+ | **Contatos** | `client.contacts` | Cache unificado de contatos em memória com resolução profunda assíncrona de informações completas (`fetchDeep`). |
385
+
386
+ ---
387
+
388
+ ### Opções de Configuração (`WaClientOptions`)
389
+
390
+ Ao instanciar `new WaClient(options)`, você pode customizar:
391
+
392
+ ```typescript
393
+ interface WaClientOptions {
394
+ /** Nome da sessão (cria a pasta em dataPath/sessionName) - Padrão: 'default' */
395
+ sessionName?: string;
396
+ /** Diretório base de armazenamento das credenciais - Padrão: './sessions' */
397
+ dataPath?: string;
398
+ /** Auth state customizado (opcional, se desejar gerenciar externamente) */
399
+ auth?: { state: AuthenticationState; saveCreds: () => Promise<void> };
400
+ /** Número de telefone para iniciar autenticação por Pairing Code ao invés de QR */
401
+ phoneNumber?: string;
402
+ /** Imprimir QR Code formatado no terminal - Padrão: true */
403
+ printQRInTerminal?: boolean;
404
+ /** Reconectar automaticamente em quedas transitórias de rede - Padrão: true */
405
+ restartOnClose?: boolean;
406
+ /** Sincronizar histórico completo de mensagens antigas - Padrão: false */
407
+ syncFullHistory?: boolean;
408
+ /** Marcar a conta como online assim que conectar - Padrão: true */
409
+ markOnlineOnConnect?: boolean;
410
+ /** Sobrescrever ou adicionar opções do makeWASocket subjacente */
411
+ socketOptions?: any;
412
+ /** Logger customizado (compatível com Pino ou Console) */
413
+ logger?: any;
414
+ }
415
+ ```
416
+
417
+ ---
418
+
419
+
420
+
421
+
422
+ ## 🔑 Conectando a Conta
423
+
424
+ 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**.
425
+
426
+ ### Conexão via QR Code
427
+
428
+ ```javascript
429
+ const { default: makeWASocket, Browsers } = require('@areumtecnologia/wasockets')
430
+
431
+ const sock = makeWASocket({
432
+ // Configurações do navegador exibidas no WhatsApp do celular
433
+ browser: Browsers.ubuntu('Chrome'),
434
+ printQRInTerminal: true
435
+ })
436
+ ```
437
+
438
+ ### Conexão via Código de Emparelhamento (Pairing Code)
439
+
440
+ 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.
441
+
442
+ ```javascript
443
+ const { default: makeWASocket } = require('@areumtecnologia/wasockets')
444
+
445
+ const sock = makeWASocket({
446
+ printQRInTerminal: false // Deve ser false
447
+ })
448
+
449
+ if (!sock.authState.creds.registered) {
450
+ const numeroTelefone = '5511999999999' // Insira o número completo
451
+ const codigo = await sock.requestPairingCode(numeroTelefone)
452
+ console.log(`Digite este código no seu WhatsApp: ${codigo}`)
453
+ }
454
+ ```
455
+
456
+ ### Recebendo Histórico Completo
457
+
458
+ 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:
459
+
460
+ ```javascript
461
+ const sock = makeWASocket({
462
+ browser: Browsers.macOS('Desktop'),
463
+ syncFullHistory: true
464
+ })
465
+ ```
466
+
467
+ ---
468
+
469
+ ## 💾 Salvando e Restaurando Sessões
470
+
471
+ 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.
472
+
473
+ ```javascript
474
+ const { default: makeWASocket, useMultiFileAuthState } = require('@areumtecnologia/wasockets')
475
+
476
+ async function iniciar() {
477
+ // Carrega o estado da pasta especificada
478
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
479
+
480
+ const sock = makeWASocket({
481
+ auth: state
482
+ })
483
+
484
+ // Salva as credenciais sempre que forem atualizadas
485
+ sock.ev.on('creds.update', saveCreds)
486
+ }
487
+ iniciar()
488
+ ```
489
+
490
+ > [!IMPORTANT]
491
+ > 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.
492
+
493
+ ---
494
+
495
+ ## ⚙️ Configurações Importantes do Socket
496
+
497
+ ### 1. Cache de Metadados de Grupo (Altamente Recomendado)
498
+ 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:
499
+
500
+ ```javascript
501
+ const NodeCache = require('@cacheable/node-cache') // ou similar
502
+ const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
503
+
504
+ const sock = makeWASocket({
505
+ cachedGroupMetadata: async (jid) => groupCache.get(jid)
506
+ })
507
+
508
+ sock.ev.on('groups.update', async ([event]) => {
509
+ const metadata = await sock.groupMetadata(event.id)
510
+ groupCache.set(event.id, metadata)
511
+ })
512
+
513
+ sock.ev.on('group-participants.update', async (event) => {
514
+ const metadata = await sock.groupMetadata(event.id)
515
+ groupCache.set(event.id, metadata)
516
+ })
517
+ ```
518
+
519
+ ### 2. Recuperação de Mensagens e Enquetes
520
+ Para descriptografar respostas de enquetes antigas ou gerenciar tentativas de reenvio automáticas do WhatsApp, configure a função `getMessage`:
521
+
522
+ ```javascript
523
+ const sock = makeWASocket({
524
+ getMessage: async (key) => {
525
+ // Busque a mensagem salva no seu banco de dados ou store local
526
+ return await buscarMensagemSalva(key.id)
527
+ }
528
+ })
529
+ ```
530
+
531
+ ### 3. Fila Inteligente de Mensagens Durante Quedas Transitórias
532
+ 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:
533
+
534
+ ```javascript
535
+ const sock = makeWASocket({
536
+ enableMessageQueue: true, // Ativado por padrão (evita perda de mensagens durante reconexão)
537
+ messageQueueTtlMs: 5 * 60 * 1000 // TTL de expiração na fila (padrão: 5 minutos)
538
+ })
539
+ ```
540
+
541
+ ### 4. Auto-Reparo de Sessão E2E / Signal (`repairSession`)
542
+ 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`:
543
+
544
+ ```javascript
545
+ // Remove a sessão danificada e força a renegociação de chaves E2E com o contato
546
+ await sock.repairSession('5511999999999@s.whatsapp.net')
547
+ ```
548
+
549
+ ---
550
+
551
+ ## 🚀 Exemplo Prático Inicial (Bootstrap)
552
+
553
+ Aqui está um arquivo funcional completo em JavaScript (CommonJS) para iniciar a sua integração:
554
+
555
+ ```javascript
556
+ const { default: makeWASocket, DisconnectReason, useMultiFileAuthState, makeReconnectManager, shouldReconnect } = require('@areumtecnologia/wasockets')
557
+ const { Boom } = require('@hapi/boom')
558
+
559
+ async function connectToWhatsApp() {
560
+ // 1. Inicializa o estado de autenticação baseado em arquivos
561
+ const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
562
+
563
+ // 2. Cria o Socket de Conexão com fila de mensagens inteligente ativada por padrão
564
+ const sock = makeWASocket({
565
+ auth: state,
566
+ printQRInTerminal: true,
567
+ enableMessageQueue: true // Fila de envio automático durante reconexões transitórias
568
+ })
569
+
570
+ // Gerenciador de reconexão adaptativa com Backoff Exponencial e Full Jitter (evita banimentos)
571
+ const reconnectManager = makeReconnectManager({
572
+ onReconnect: async (attempt) => {
573
+ console.log(`Reconectando ao WhatsApp (tentativa #${attempt})...`)
574
+ await connectToWhatsApp()
575
+ }
576
+ })
577
+
578
+ // 3. Monitora o status da conexão
579
+ sock.ev.on('connection.update', async (update) => {
580
+ const { connection, lastDisconnect } = update
581
+
582
+ if (connection === 'close') {
583
+ await reconnectManager.handleDisconnect(lastDisconnect?.error)
584
+ } else if (connection === 'open') {
585
+ reconnectManager.reset()
586
+ console.log('Conexão com o WhatsApp estabelecida com sucesso!')
587
+ }
588
+ })
589
+
590
+ // 4. Salva credenciais atualizadas
591
+ sock.ev.on('creds.update', saveCreds)
592
+
593
+ // 5. Escuta e responde a novas mensagens recebidas
594
+ sock.ev.on('messages.upsert', async (event) => {
595
+ for (const m of event.messages) {
596
+ // Ignora mensagens que não sejam do tipo padrão ou geradas pelo próprio bot
597
+ if (!m.message || m.key.fromMe) continue
598
+
599
+ console.log('Mensagem recebida de:', m.key.remoteJid)
600
+ console.log('Conteúdo:', JSON.stringify(m, null, 2))
601
+
602
+ // Responde à mensagem
603
+ await sock.sendMessage(m.key.remoteJid, { text: 'Olá! Recebi sua mensagem com sucesso.' })
604
+ }
605
+ })
606
+ }
607
+
608
+ // Inicia o processo
609
+ connectToWhatsApp()
610
+ ```
611
+
612
+ ---
613
+
614
+ ## 📡 Tratamento de Eventos e Mídia
615
+
616
+ O **WaSockets** utiliza um sistema de eventos tipado baseado no `EventEmitter`.
617
+
618
+ ```javascript
619
+ sock.ev.on('messages.upsert', ({ messages, type }) => {
620
+ // type pode ser 'notify' (nova notificação) ou 'append' (carregamento histórico)
621
+ console.log('Novas mensagens recebidas:', messages)
622
+ })
623
+ ```
624
+
625
+ ### Download de Mídias Recebidas
626
+
627
+ Para baixar mídias (fotos, vídeos, áudios, documentos ou stickers) recebidas no evento `messages.upsert`, utilize a função utilitária `downloadMediaMessage`:
628
+
629
+ ```javascript
630
+ const { downloadMediaMessage } = require('@areumtecnologia/wasockets')
631
+ const fs = require('fs')
632
+
633
+ sock.ev.on('messages.upsert', async ({ messages }) => {
634
+ for (const msg of messages) {
635
+ if (!msg.message || msg.key.fromMe) continue
636
+
637
+ const isMedia = msg.message.imageMessage ||
638
+ msg.message.videoMessage ||
639
+ msg.message.audioMessage ||
640
+ msg.message.documentMessage ||
641
+ msg.message.stickerMessage
642
+
643
+ if (isMedia) {
644
+ // Baixa o arquivo diretamente em formato Buffer
645
+ const buffer = await downloadMediaMessage(msg, 'buffer', {})
646
+
647
+ // Exemplo: Salvar no disco
648
+ const ext = msg.message.imageMessage ? 'jpg' : msg.message.audioMessage ? 'ogg' : 'bin'
649
+ fs.writeFileSync(`./download_${msg.key.id}.${ext}`, buffer)
650
+ console.log(`Mídia baixada com sucesso (${buffer.length} bytes)!`)
651
+
652
+ // Ou baixar como stream de leitura para processamento em tempo real:
653
+ // const stream = await downloadMediaMessage(msg, 'stream', {})
654
+ }
655
+ }
656
+ })
657
+ ```
658
+
659
+ ### Decifrar Votos de Enquetes
660
+
661
+ Os votos em enquetes chegam como mensagens criptografadas no evento `messages.update`. É preciso usar o helper `getAggregateVotesInPollMessage` passando a mensagem original da enquete.
662
+
663
+ ```javascript
664
+ const { getAggregateVotesInPollMessage } = require('@areumtecnologia/wasockets')
665
+
666
+ sock.ev.on('messages.update', async (updates) => {
667
+ for (const { key, update } of updates) {
668
+ if (update.pollUpdates) {
669
+ // 1. Busca a mensagem original da enquete que foi criada anteriormente
670
+ const pollCreationMessage = await obterMensagemSalva(key)
671
+ if (pollCreationMessage) {
672
+ // 2. Agrega os votos
673
+ const pollVotes = await getAggregateVotesInPollMessage({
674
+ message: pollCreationMessage,
675
+ pollUpdates: update.pollUpdates
676
+ })
677
+
678
+ // 3. Exibe as opções votadas e os respectivos eleitores
679
+ console.log('Resultado da Enquete Atualizado:', pollVotes)
680
+ }
681
+ }
682
+ }
683
+ })
684
+ ```
685
+
686
+ ### Decifrar Respostas de Eventos
687
+
688
+ 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.
689
+
690
+ ```javascript
691
+ const { getAggregateResponsesInEventMessage } = require('@areumtecnologia/wasockets')
692
+
693
+ sock.ev.on('messages.update', async (updates) => {
694
+ for (const { key, update } of updates) {
695
+ if (update.eventResponses) {
696
+ const eventCreationMessage = await obterMensagemSalva(key)
697
+ if (eventCreationMessage) {
698
+ const responses = await getAggregateResponsesInEventMessage({
699
+ message: eventCreationMessage,
700
+ eventResponses: update.eventResponses
701
+ })
702
+ console.log('Respostas ao evento atualizadas:', responses)
703
+ }
704
+ }
705
+ }
706
+ })
707
+ ```
708
+
709
+ ---
710
+
711
+ ## 🔍 Verificação de Contatos e Presença
712
+
713
+ ### Verificação de Números no WhatsApp (onWhatsApp)
714
+
715
+ Valide se um ou vários números de telefone possuem contas ativas registradas no WhatsApp antes de disparar mensagens:
716
+
717
+ ```javascript
718
+ // Aceita um ou vários números (com DDI e DDD)
719
+ const resultados = await sock.onWhatsApp('5511999999999', '5511888888888', '5521977777777')
720
+
721
+ for (const { jid, exists } of resultados) {
722
+ if (exists) {
723
+ console.log(`O número ${jid} está ativo no WhatsApp!`)
724
+ } else {
725
+ console.log(`O número ${jid} NÃO possui conta no WhatsApp.`)
726
+ }
727
+ }
728
+ ```
729
+
730
+ ### Presença e Digitando / Gravando Áudio
731
+
732
+ Simule atividade humana enviando estados de presença ou monitore o status de contatos:
733
+
734
+ ```javascript
735
+ // 1. Indicar que está digitando...
736
+ await sock.sendPresenceUpdate('composing', jid)
737
+
738
+ // 2. Indicar que está gravando áudio...
739
+ await sock.sendPresenceUpdate('recording', jid)
740
+
741
+ // 3. Pausar status de digitação/gravação
742
+ await sock.sendPresenceUpdate('paused', jid)
743
+
744
+ // 4. Alterar presença geral da conta ('available' = Online, 'unavailable' = Offline)
745
+ await sock.sendPresenceUpdate('available')
746
+
747
+ // 5. Inscrever-se para escutar presença de um contato específico
748
+ await sock.presenceSubscribe(jid)
749
+
750
+ // 6. Monitorar atualizações de presença recebidas
751
+ sock.ev.on('presence.update', ({ id, presences }) => {
752
+ console.log(`Atualização de presença de ${id}:`, presences)
753
+ })
754
+ ```
755
+
756
+ ---
757
+
758
+ ## ✉️ Enviando Mensagens
759
+
760
+ ### Mensagens de Texto e Menções
761
+
762
+ ```javascript
763
+ // Mensagem de texto simples
764
+ await sock.sendMessage(jid, { text: 'Olá Mundo!' })
765
+
766
+ // Mensagem citando (respondendo a) outra mensagem
767
+ await sock.sendMessage(jid, { text: 'Esta é uma resposta.' }, { quoted: mensagemOriginal })
768
+
769
+ // Mensagem mencionando contatos no grupo
770
+ await sock.sendMessage(jid, {
771
+ text: 'Olá @5511999999999 e @5511888888888!',
772
+ mentions: ['5511999999999@s.whatsapp.net', '5511888888888@s.whatsapp.net']
773
+ })
774
+ ```
775
+
776
+ ### Mensagens de Mídia
777
+
778
+ É possível passar caminhos de arquivos locais (`url`), links da internet (`url`), buffers ou streams de leitura.
779
+
780
+ ```javascript
781
+ const fs = require('fs')
782
+
783
+ // Imagem com legenda
784
+ await sock.sendMessage(jid, {
785
+ image: { url: './foto.jpg' }, // ou { url: 'https://example.com/foto.jpg' } ou Buffer
786
+ caption: 'Minha foto legal!'
787
+ })
788
+
789
+ // Álbum de mídias (Múltiplas fotos/vídeos no mesmo bloco)
790
+ await sock.sendMessage(jid, {
791
+ album: [
792
+ { image: { url: './foto1.jpg' }, caption: 'Foto 1' },
793
+ { image: { url: './foto2.jpg' }, caption: 'Foto 2' },
794
+ { video: { url: './video.mp4' }, caption: 'Vídeo do Álbum' }
795
+ ]
796
+ })
797
+
798
+ // GIF (vídeo mp4 simulado como reprodução contínua)
799
+ await sock.sendMessage(jid, {
800
+ video: fs.readFileSync('./video-gif.mp4'),
801
+ gifPlayback: true,
802
+ caption: 'Olha esse gif!'
803
+ })
804
+
805
+ // Áudio Gravado (Simula o gravador de voz do WhatsApp - PTT)
806
+ await sock.sendMessage(jid, {
807
+ audio: { url: './audio.ogg' },
808
+ mimetype: 'audio/mp4', // obrigatório
809
+ ptt: true // Define como mensagem de voz
810
+ })
811
+
812
+ // Mensagem de Visualização Única (View Once)
813
+ await sock.sendMessage(jid, {
814
+ image: { url: './foto.jpg' },
815
+ viewOnce: true,
816
+ caption: 'Esta foto desaparecerá após ser aberta!'
817
+ })
818
+ ```
819
+
820
+ > [!TIP]
821
+ > 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:
822
+ > `ffmpeg -i input.mp3 -c:a libopus -ac 1 -avoid_negative_ts make_zero output.ogg`
823
+
824
+ ---
825
+
826
+ ### Documentos e Arquivos
827
+
828
+ Envie qualquer formato de arquivo (PDF, planilhas, arquivos compactados) informando o `mimetype` e o `fileName` para exibição correta no aplicativo:
829
+
830
+ ```javascript
831
+ await sock.sendMessage(jid, {
832
+ document: { url: './fatura_setembro.pdf' }, // ou Buffer ou { url: 'https://exemplo.com/doc.pdf' }
833
+ mimetype: 'application/pdf',
834
+ fileName: 'Fatura_Setembro_2026.pdf'
835
+ })
836
+ ```
837
+
838
+ ### Figurinhas (Stickers)
839
+
840
+ Envie figurinhas estáticas ou animadas no formato WebP:
841
+
842
+ ```javascript
843
+ await sock.sendMessage(jid, {
844
+ sticker: fs.readFileSync('./minha_figurinha.webp') // aceita Buffer ou { url: './figurinha.webp' }
845
+ })
846
+ ```
847
+
848
+ ### Localização Fixa e em Tempo Real
849
+
850
+ Envie pontos no mapa ou compartilhe localização em tempo real com latitude e longitude:
851
+
852
+ ```javascript
853
+ // Localização Fixa
854
+ await sock.sendMessage(jid, {
855
+ location: {
856
+ degreesLatitude: -23.55052,
857
+ degreesLongitude: -46.633308,
858
+ name: 'Sede da Áreum Tecnologia',
859
+ address: 'Av. Paulista, 1000 - Bela Vista, São Paulo - SP'
860
+ }
861
+ })
862
+
863
+ // Localização em Tempo Real (Live Location)
864
+ await sock.sendMessage(jid, {
865
+ location: {
866
+ degreesLatitude: -23.55052,
867
+ degreesLongitude: -46.633308
868
+ },
869
+ live: true
870
+ })
871
+ ```
872
+
873
+ ### Contatos e Cartões vCard
874
+
875
+ Envie um ou múltiplos contatos com cartão vCard formatado:
876
+
877
+ ```javascript
878
+ const vcard = 'BEGIN:VCARD\n'
879
+ + 'VERSION:3.0\n'
880
+ + 'FN:Suporte Técnico Áreum\n'
881
+ + 'ORG:Áreum Tecnologia;\n'
882
+ + 'TEL;type=CELL;type=VOICE;waid=5511999999999:+55 11 99999-9999\n'
883
+ + 'END:VCARD'
884
+
885
+ await sock.sendMessage(jid, {
886
+ contacts: {
887
+ displayName: 'Suporte Técnico Áreum',
888
+ contacts: [{ vcard }]
889
+ }
890
+ })
891
+ ```
892
+
893
+ ### Reações a Mensagens
894
+
895
+ Reaja com emojis a qualquer mensagem enviada ou recebida (ou remova a reação enviando string vazia `''`):
896
+
897
+ ```javascript
898
+ // Reagir à mensagem com um emoji
899
+ await sock.sendMessage(jid, {
900
+ react: {
901
+ text: '🔥', // Emoji da reação
902
+ key: msg.key // Chave da mensagem original que receberá a reação
903
+ }
904
+ })
905
+
906
+ // Remover reação anterior
907
+ await sock.sendMessage(jid, {
908
+ react: {
909
+ text: '',
910
+ key: msg.key
911
+ }
912
+ })
913
+ ```
914
+
915
+ ### Criação de Enquetes
916
+
917
+ Crie enquetes interativas com contagem configurável de seleção (voto único ou múltiplo):
918
+
919
+ ```javascript
920
+ await sock.sendMessage(jid, {
921
+ poll: {
922
+ name: 'Qual o melhor diferencial do WaSockets?',
923
+ values: [
924
+ 'Resolução Transparente de LID',
925
+ 'Envio Nativo de Álbuns',
926
+ 'Newsletters v2 e Canais',
927
+ 'Fila Inteligente de Reconexão'
928
+ ],
929
+ selectableCount: 1 // 1 para escolha única; > 1 para permitir múltiplas escolhas
930
+ }
931
+ })
932
+ ```
933
+
934
+ ### Listas Interativas de Opções (Sections)
935
+
936
+ Envie menus organizados por categorias e linhas para navegação intuitiva:
937
+
938
+ ```javascript
939
+ await sock.sendMessage(jid, {
940
+ text: 'Selecione o setor desejado para atendimento:',
941
+ footer: 'Áreum Tecnologia • Atendimento Automatizado',
942
+ title: 'Central de Relacionamento',
943
+ buttonText: 'Ver Departamentos',
944
+ sections: [
945
+ {
946
+ title: 'Atendimento Comercial',
947
+ rows: [
948
+ { title: 'Novas Contratações', rowId: 'row_vendas', description: 'Conheça nossos planos e soluções' },
949
+ { title: 'Upgrade de Plano', rowId: 'row_upgrade', description: 'Amplie os limites da sua conta' }
950
+ ]
951
+ },
952
+ {
953
+ title: 'Suporte & Operações',
954
+ rows: [
955
+ { title: 'Suporte Técnico', rowId: 'row_suporte', description: 'Dúvidas de integração e bugs' },
956
+ { title: 'Financeiro', rowId: 'row_financeiro', description: '2ª via de boleto e notas fiscais' }
957
+ ]
958
+ }
959
+ ]
960
+ })
961
+ ```
962
+
963
+ ---
964
+
965
+ ### Botões Interativos
966
+
967
+ Os botões nativos do WhatsApp são suportados através da propriedade `interactiveButtons`.
968
+
969
+ ```javascript
970
+ await sock.sendMessage(jid, {
971
+ text: 'Olá! Escolha uma das opções abaixo:',
972
+ title: 'Painel Interativo',
973
+ subtitle: 'Selecione com um clique',
974
+ footer: 'Áreum Tecnologia',
975
+ interactiveButtons: [
976
+ {
977
+ name: 'quick_reply',
978
+ buttonParamsJson: JSON.stringify({
979
+ display_text: 'Suporte Técnico',
980
+ id: 'btn_suporte'
981
+ })
982
+ },
983
+ {
984
+ name: 'cta_url',
985
+ buttonParamsJson: JSON.stringify({
986
+ display_text: 'Acessar Site',
987
+ url: 'https://areum.com.br',
988
+ merchant_url: 'https://areum.com.br'
989
+ })
990
+ },
991
+ {
992
+ name: 'cta_copy',
674
993
  buttonParamsJson: JSON.stringify({
675
- display_text: 'Suporte Técnico',
676
- id: 'btn_suporte'
677
- })
678
- },
679
- {
680
- name: 'cta_url',
681
- buttonParamsJson: JSON.stringify({
682
- display_text: 'Acessar Site',
683
- url: 'https://areum.com.br',
684
- merchant_url: 'https://areum.com.br'
685
- })
686
- },
687
- {
688
- name: 'cta_call',
689
- buttonParamsJson: JSON.stringify({
690
- display_text: 'Ligar Agora',
691
- phone_number: '5511999999999'
692
- })
693
- }
694
- ]
695
- })
696
- ```
697
-
698
- ---
699
-
700
- ### Botão de Pagamento PIX
701
-
702
- 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`.
703
-
704
- ```javascript
705
- await sock.sendMessage(jid, {
706
- text: 'Efetue o pagamento do pedido abaixo clicando em Pagar:',
707
- interactiveButtons: [
708
- {
709
- name: 'payment_info',
710
- buttonParamsJson: JSON.stringify({
711
- payment_settings: [{
712
- type: 'pix_static_code',
713
- pix_static_code: {
714
- merchant_name: 'Áreum Tecnologia LTDA',
715
- key: 'financeiro@areum.com.br', // Chave PIX (E-mail, CPF/CNPJ, Telefone ou EVP)
716
- key_type: 'EMAIL' // Tipos suportados: PHONE, EMAIL, CPF, EVP
717
- }
718
- }]
719
- })
720
- }
721
- ]
722
- })
723
- ```
724
-
725
- ---
726
-
727
- ### Fluxos de Checkout (PAY)
728
-
729
- É 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`.
730
-
731
- ```javascript
732
- await sock.sendMessage(jid, {
733
- text: 'Fatura gerada com sucesso!',
734
- interactiveButtons: [
735
- {
736
- name: 'review_and_pay',
737
- buttonParamsJson: JSON.stringify({
738
- currency: 'BRL',
739
- payment_type: 'physical-goods',
740
- total_amount: {
741
- value: '15000', // R$ 150,00 (representado sem decimais, multiplicado pelo offset)
742
- offset: '100'
743
- },
744
- reference_id: 'REF_PEDIDO_12345',
745
- payment_method: 'confirm',
746
- payment_status: 'captured',
747
- payment_timestamp: Math.floor(Date.now() / 1000),
748
- order: {
749
- status: 'completed',
750
- order_type: 'PAYMENT_REQUEST',
751
- subtotal: { value: '15000', offset: '100' },
752
- items: [{
753
- retailer_id: 'item_01',
754
- name: 'Licença Anual WaSockets',
755
- amount: { value: '15000', offset: '100' },
756
- quantity: '1'
757
- }]
758
- },
759
- additional_note: 'Agradecemos a sua preferência!'
760
- })
761
- }
762
- ]
763
- })
764
- ```
765
-
766
- ---
767
-
768
- ### Menção em Status
769
-
770
- Permite publicar status (stories) e marcar diretamente contatos/grupos específicos (máximo de 5 menções por status).
771
-
772
- ```javascript
773
- const contatosParaMencionar = [
774
- '5511999999999@s.whatsapp.net',
775
- '5511888888888@s.whatsapp.net'
776
- ]
777
-
778
- // Envia um status em formato de texto mencionando os contatos acima
779
- await sock.sendStatusMentions(
780
- {
781
- text: 'Novidade incrível para vocês! 🚀',
782
- backgroundColor: '#1c1c1c',
783
- textColor: '#ffffff'
784
- },
785
- contatosParaMencionar
786
- )
787
-
788
- // Curtir / Reagir diretamente a uma publicação de Status (Stories)
789
- await sock.reactToStatus(statusMsgKey, '❤️')
790
- ```
791
-
792
- ### Comentários em Canais e Comunidades
793
-
794
- Envie respostas e comentários estruturados em postagens de canais (Newsletters) ou mensagens de aviso em comunidades:
795
-
796
- ```javascript
797
- await sock.sendMessage(jid, {
798
- comment: {
799
- targetMessageKey: mensagemOriginal.key,
800
- message: { text: 'Excelente atualização! 👏' }
801
- }
802
- })
803
- ```
804
-
805
- ### Envio Nativo de Álbuns de Fotos e Vídeos (Pilar 3)
806
-
807
- 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:
808
-
809
- ```javascript
810
- // Método direto e simplificado
811
- await sock.sendAlbumMessage(jid, [
812
- { image: { url: 'https://exemplo.com/foto1.jpg' }, caption: 'Foto 1 do produto' },
813
- { image: { url: 'https://exemplo.com/foto2.jpg' }, caption: 'Foto 2 em outro ângulo' },
814
- { video: { url: 'https://exemplo.com/demonstracao.mp4' }, caption: 'Vídeo explicativo' }
815
- ])
816
-
817
- // Ou através de sendMessage com a propriedade album:
818
- await sock.sendMessage(jid, {
819
- album: [
820
- { image: { url: './local/foto1.jpg' } },
821
- { image: { url: './local/foto2.jpg' } }
822
- ]
823
- })
824
- ```
825
-
826
- ### Mensagens de Áudio PTT com Waveform Customizada (Pilar 3)
827
-
828
- 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):
829
-
830
- ```javascript
831
- // Áudio PTT com waveform automática gerada a partir do arquivo
832
- await sock.sendMessage(jid, {
833
- audio: { url: './audio.mp3' },
834
- mimetype: 'audio/ogg; codecs=opus',
835
- ptt: true
836
- })
837
-
838
- // Áudio PTT com waveform predefinida (evita decodificação intensiva de CPU)
839
- await sock.sendMessage(jid, {
840
- audio: { url: './audio.mp3' },
841
- mimetype: 'audio/ogg; codecs=opus',
842
- ptt: true,
843
- waveform: [0, 15, 30, 75, 100, 80, 45, 20, 10, 0] // 64 barras de amplitude
844
- })
845
- ```
846
-
847
- ### Encaminhamento de Mensagens
848
-
849
- Encaminhe mensagens para outros chats preservando ou forçando o status de encaminhado:
850
-
851
- ```javascript
852
- // Encaminhar uma mensagem recebida para outro destinatário
853
- await sock.sendMessage(outroJid, {
854
- forward: mensagemOriginal,
855
- force: true // Exibe o selo de mensagem encaminhada
856
- })
857
- ```
858
-
859
- ---
860
-
861
- ## 📝 Modificando Mensagens e Chats
862
-
863
- ```javascript
864
- // Apagar uma mensagem para todos
865
- const msg = await sock.sendMessage(jid, { text: 'Mensagem enviada com erro!' })
866
- await sock.sendMessage(jid, { delete: msg.key })
867
-
868
- // Editar uma mensagem enviada
869
- await sock.sendMessage(jid, {
870
- text: 'Esta é a mensagem com o texto corrigido.',
871
- edit: msg.key
872
- })
873
-
874
- // Arquivar um chat
875
- await sock.chatModify({ archive: true, lastMessages: [msg] }, jid)
876
-
877
- // Silenciar um chat por 8 horas
878
- await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
879
-
880
- // Remover silenciamento de um chat
881
- await sock.chatModify({ mute: null }, jid)
882
-
883
- // Marcar chat como Não Lido
884
- await sock.chatModify({ markRead: false, lastMessages: [msg] }, jid)
885
-
886
- // Fixar chat na lista de conversas
887
- await sock.chatModify({ pin: true }, jid)
888
- ```
889
-
890
- ### Confirmação de Leitura (readMessages)
891
-
892
- Envie confirmações de leitura explícitas para exibir os ticks azuis ao remetente:
893
-
894
- ```javascript
895
- // Marca uma ou mais mensagens recebidas como lidas
896
- await sock.readMessages([msg.key])
897
- ```
898
-
899
- ### Mensagens com Estrela (star)
900
-
901
- Marque mensagens importantes com estrela (favoritas) na conversa:
902
-
903
- ```javascript
904
- // Adicionar estrela à mensagem
905
- await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], true)
906
-
907
- // Remover estrela da mensagem
908
- await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], false)
909
- ```
910
-
911
- ### Fixação de Mensagens com Duração
912
-
913
- Fixe mensagens em conversas individuais ou grupos escolhendo a duração desejada:
914
-
915
- ```javascript
916
- // Fixar mensagem por 7 dias (604800 segundos)
917
- // Durações padrão: 86400 (24h), 604800 (7 dias), 2592000 (30 dias)
918
- await sock.sendMessage(jid, {
919
- pin: {
920
- key: msg.key,
921
- type: 1, // 1: Fixar, 2: Desafixar
922
- time: 604800
923
- }
924
- })
925
-
926
- // Desafixar mensagem
927
- await sock.sendMessage(jid, {
928
- pin: {
929
- key: msg.key,
930
- type: 2
931
- }
932
- })
933
- ```
934
-
935
- ### Favoritos e Anotações de Contato
936
-
937
- Organize suas conversas sincronizando com o WhatsApp Web e celular:
938
-
939
- ```javascript
940
- // Marcar conversa como Favorita
941
- await sock.updateFavorite(jid, true)
942
-
943
- // Desmarcar conversa como Favorita
944
- await sock.updateFavorite(jid, false)
945
-
946
- // Adicionar ou atualizar nota interna no contato (Chat Note)
947
- await sock.updateChatNote(jid, 'Cliente solicitou proposta para 50 atendentes.')
948
-
949
- // Remover nota interna do contato
950
- await sock.removeChatNote(jid)
951
- ```
952
-
953
- ---
954
-
955
- ## 👤 Perfil do Usuário e Foto
956
-
957
- Gerencie fotos de perfil, recados e nome de exibição (PushName) diretamente pelo socket:
958
-
959
- ```javascript
960
- // 1. Obter a URL da foto de perfil de um contato ou grupo
961
- const pfpUrl = await sock.profilePictureUrl(jid, 'image') // ou 'preview' para miniatura
962
- console.log('Foto de Perfil:', pfpUrl)
963
-
964
- // 2. Atualizar a sua própria foto de perfil (ou a foto de um grupo do qual você é admin)
965
- await sock.updateProfilePicture(jid, { url: './nova_foto.jpg' }) // Aceita caminho, URL ou Buffer
966
-
967
- // 3. Remover a foto de perfil
968
- await sock.removeProfilePicture(jid)
969
-
970
- // 4. Consultar o recado / About (Status) de um contato
971
- const statusInfo = await sock.fetchStatus(jid)
972
- console.log(`Recado de ${jid}: ${statusInfo?.status} (Definido em: ${statusInfo?.setAt})`)
973
-
974
- // 5. Atualizar o seu próprio recado / About
975
- await sock.updateProfileStatus('Disponível apenas para atendimentos prioritários 🚀')
976
-
977
- // 6. Atualizar o seu nome público de exibição (PushName)
978
- await sock.updateProfileName('Áreum Tecnologia - Suporte Oficial')
979
- ```
980
-
981
- ---
982
-
983
- ## 📅 Eventos em Grupos e RSVP
984
-
985
- Crie eventos colaborativos, responda confirmações de presença e cancele eventos:
986
-
987
- ```javascript
988
- // 1. Criar um novo evento no grupo
989
- const evento = await sock.sendMessage(grupoJid, {
990
- event: {
991
- name: 'Reunião de Planejamento de Sprints',
992
- description: 'Alinhamento estratégico dos projetos da Áreum Tecnologia.',
993
- startTime: Math.floor(Date.now() / 1000) + 86400, // Amanhã
994
- extraGuestsAllowed: true
995
- }
996
- })
997
-
998
- // 2. Responder ao Evento (RSVP)
999
- // Tipos de resposta: 'GOING' (1), 'NOT_GOING' (2), 'MAYBE' (3)
1000
- await sock.sendEventResponse(grupoJid, evento.key, 'GOING', 1 /* +1 convidado extra */)
1001
-
1002
- // 3. Cancelar o Evento
1003
- await sock.cancelEvent(grupoJid, evento.key)
1004
- ```
1005
-
1006
- ---
1007
-
1008
- ## 📞 Chamadas Web (Web Calling)
1009
-
1010
- Gerencie o ciclo completo de sinalização de chamadas de voz e vídeo:
1011
-
1012
- ```javascript
1013
- // Iniciar uma chamada (áudio ou vídeo)
1014
- const chamada = await sock.offerCall('5511999999999@s.whatsapp.net', false /* isVideo */)
1015
- console.log('ID da chamada:', chamada.id)
1016
-
1017
- // Atender uma chamada recebida
1018
- await sock.acceptCall(callId, callerJid)
1019
-
1020
- // Encerrar uma chamada em andamento
1021
- await sock.terminateCall(callId, callerJid)
1022
-
1023
- // Rejeitar uma chamada recebida
1024
- await sock.rejectCall(callId, callerJid)
1025
- ```
1026
-
1027
- ---
1028
-
1029
- ## 🔍 Resolução de Usuários & Transição LID (Pilar 2)
1030
-
1031
- 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:
1032
-
1033
- ### Métodos de Resolução Transparente no Socket
1034
-
1035
- ```javascript
1036
- // 1. Converter LID para número de telefone (PN) com busca em cache/DB
1037
- const pnJid = await sock.toPn('12345678901234@lid')
1038
- console.log('JID com número real:', pnJid) // '5511999999999@s.whatsapp.net'
1039
-
1040
- // Caso não esteja em cache local, pode passar true para consultar o servidor via USync:
1041
- const pnJidFromNetwork = await sock.toPn('12345678901234@lid', true)
1042
-
1043
- // 2. Converter número de telefone (PN) para LID
1044
- const lidJid = await sock.toLid('5511999999999@s.whatsapp.net')
1045
- console.log('LID correspondente:', lidJid) // '12345678901234@lid'
1046
-
1047
- // 3. Resolução completa e unificada (retorna ambos)
1048
- const resolved = await sock.resolveJid(authorJid)
1049
- console.log(resolved) // { pn: '5511999999999@s.whatsapp.net', lid: '12345678901234@lid', jid: ... }
1050
-
1051
- // 4. Registrar manualmente um mapeamento conhecido
1052
- await sock.storeLidPnMapping('5511999999999@s.whatsapp.net', '12345678901234@lid')
1053
-
1054
- // 5. Consultas diretas via protocolo USync (baixo nível)
1055
- const [lidUser] = await sock.getLidUser('5511999999999@s.whatsapp.net')
1056
- const [pnUser] = await sock.getPnUser('12345678901234@lid')
1057
- ```
1058
-
1059
- ### Store Unificado de Contatos e Conversas (`makeInMemoryStore`)
1060
-
1061
- 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:
1062
-
1063
- ```javascript
1064
- import { makeInMemoryStore } from '@areumtecnologia/wasockets'
1065
-
1066
- const store = makeInMemoryStore({})
1067
- store.bind(sock.ev)
1068
-
1069
- // Busca unificada: localiza o contato quer você passe o número (@s.whatsapp.net), o @lid ou apenas os dígitos
1070
- const contact = store.getContact('12345678901234@lid')
1071
- // Retorna o contato completo contendo .id, .lid, .phoneNumber, .name, etc.
1072
-
1073
- // Busca unificada de chat: localiza a conversa mesmo se foi iniciada com PN ou com LID
1074
- const chat = store.getChat('12345678901234@lid')
1075
-
1076
- // Carregamento de mensagens com fallback cruzado automático entre LID e PN
1077
- const messages = await store.loadMessages('12345678901234@lid', 25)
1078
- ```
1079
-
1080
- ---
1081
-
1082
- ## 🏷️ Etiquetas de Negócio (Labels - WhatsApp Business)
1083
-
1084
- O **WaSockets** permite que você gerencie etiquetas e organize contatos ou mensagens diretamente pelo aplicativo WhatsApp Business.
1085
-
1086
- ### Criando, Editando e Deletando Etiquetas (CRUD de Sistema)
1087
-
1088
- Você pode criar, editar e excluir as etiquetas globais da sua conta:
1089
-
1090
- ```javascript
1091
- // Criar uma nova etiqueta com cor específica
1092
- // Cores suportadas: de 0 a 19 correspondentes à paleta do WhatsApp Business
1093
- const novaLabel = await sock.createLabel('Lead Qualificado', 5)
1094
-
1095
- // Atualizar o nome e a cor de uma etiqueta existente
1096
- await sock.updateLabel('label_id_123', 'Pagamento Aprovado', 2)
1097
-
1098
- // Deletar uma etiqueta definitivamente da conta
1099
- await sock.deleteLabel('label_id_123')
1100
- ```
1101
-
1102
- ### Associando Etiquetas a Conversas e Mensagens
1103
-
1104
- Para categorizar chats específicos ou marcar mensagens individuais dentro de uma conversa:
1105
-
1106
- ```javascript
1107
- // Associar etiqueta a uma conversa (JID)
1108
- await sock.addChatLabel(jid, 'label_id_123')
1109
-
1110
- // Remover etiqueta de uma conversa (JID)
1111
- await sock.removeChatLabel(jid, 'label_id_123')
1112
-
1113
- // Associar etiqueta a uma mensagem específica
1114
- await sock.addMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
1115
-
1116
- // Remover etiqueta de uma mensagem específica
1117
- await sock.removeMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
1118
- ```
1119
-
1120
- ### Respostas Rápidas (Quick Replies)
1121
-
1122
- Para contas WhatsApp Business, gerencie respostas rápidas acessíveis via atalhos:
1123
-
1124
- ```javascript
1125
- // Criar ou atualizar resposta rápida
1126
- await sock.addOrEditQuickReply({
1127
- id: 'qr_ola',
1128
- shortcut: '/ola',
1129
- message: 'Olá! Seja muito bem-vindo à Áreum Tecnologia. Como podemos te ajudar hoje?',
1130
- keywords: ['ola', 'ajuda', 'suporte', 'inicio']
1131
- })
1132
-
1133
- // Remover resposta rápida pelo ID
1134
- await sock.removeQuickReply('qr_ola')
1135
- ```
1136
-
1137
- ---
1138
-
1139
- ## 👥 Gerenciamento de Grupos
1140
-
1141
- As operações de alteração estrutural em grupos requerem que a conta conectada seja administradora do grupo correspondente.
1142
-
1143
- ```javascript
1144
- // Criar um novo grupo
1145
- const grupo = await sock.groupCreate('Equipe de Suporte Áreum', ['5511999999999@s.whatsapp.net'])
1146
- console.log('Grupo criado com ID:', grupo.id)
1147
-
1148
- // Adicionar/Remover/Promover participantes
1149
- // Parâmetros de ação: 'add' | 'remove' | 'promote' | 'demote'
1150
- await sock.groupParticipantsUpdate(grupo.id, ['5511888888888@s.whatsapp.net'], 'add')
1151
-
1152
- // Obter dados/metadados de um grupo ANTES de entrar usando o código de convite
1153
- const infoConvite = await sock.groupGetInviteInfo('ABcdEFghIJklMnOpQrStUv')
1154
- console.log(`Nome do grupo no convite: ${infoConvite.subject}`)
1155
-
1156
- // Obter o código/link de convite do grupo
1157
- const codigoConvite = await sock.groupInviteCode(grupo.id)
1158
- console.log(`Link: https://chat.whatsapp.com/${codigoConvite}`)
1159
-
1160
- // Revogar link de convite anterior e gerar um novo
1161
- const novoCodigo = await sock.groupRevokeInvite(grupo.id)
1162
-
1163
- // Entrar em um grupo usando um código de convite (apenas o código, sem o domínio completo)
1164
- const resposta = await sock.groupAcceptInvite('ABcdEFghIJklMnOpQrStUv')
1165
-
1166
- // Alterar o assunto (título) do grupo
1167
- await sock.groupUpdateSubject(grupo.id, 'Novo Nome do Grupo')
1168
-
1169
- // Alterar a descrição do grupo
1170
- await sock.groupUpdateDescription(grupo.id, 'Regras do grupo e links importantes.')
1171
-
1172
- // Sair do grupo
1173
- await sock.groupLeave(grupo.id)
1174
-
1175
- // Obter a lista de pessoas aguardando aprovação para entrar no grupo
1176
- const solicitacoes = await sock.groupRequestParticipantsList(grupo.id)
1177
- console.log(solicitacoes)
1178
-
1179
- // Aprovar entrada pendente
1180
- await sock.groupRequestParticipantsUpdate(grupo.id, ['5511777777777@s.whatsapp.net'], 'approve') // ou 'reject'
1181
-
1182
- // Obter metadados do grupo (participantes, título, regras, descrição)
1183
- const metadados = await sock.groupMetadata(grupo.id)
1184
- console.log(`Título: ${metadados.subject}, Membros: ${metadados.participants.length}`)
1185
- ```
1186
-
1187
- ---
1188
-
1189
- ## 👥 Etiquetas de Membro (Member Tags) em Grupos
1190
-
1191
- 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).
1192
-
1193
- ### Definindo sua própria Etiqueta de Membro no Grupo
1194
-
1195
- ```javascript
1196
- // Define a sua etiqueta como "Suporte Técnico" no grupo especificado
1197
- await sock.updateMemberLabel(grupoJid, "Suporte Técnico")
1198
- ```
1199
-
1200
- ### Monitorando Atualizações de Etiquetas de Outros Membros
1201
-
1202
- Você pode escutar o evento `group.member-tag.update` para monitorar quando qualquer participante alterar a etiqueta de membro dele no grupo:
1203
-
1204
- ```javascript
1205
- sock.ev.on('group.member-tag.update', (update) => {
1206
- const { groupId, label, participant } = update
1207
- console.log(`O usuário ${participant} definiu a etiqueta "${label}" no grupo ${groupId}`)
1208
- })
1209
- ```
1210
-
1211
- ---
1212
-
1213
- ## 📢 Newsletters / Canais v2 (Pilar 3)
1214
-
1215
- 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):
1216
-
1217
- ```javascript
1218
- // 1. Criar uma Newsletter (Canal)
1219
- const canal = await sock.newsletterCreate('Notícias Tecnológicas Áreum', 'Canal oficial de novidades')
1220
- console.log('Canal criado com ID:', canal.id)
1221
-
1222
- // 2. Obter metadados de um Canal público pelo ID ou Invite Code
1223
- const metadadosCanal = await sock.newsletterMetadata('JID', canal.id)
1224
- console.log('Nome do Canal:', metadadosCanal.name)
1225
-
1226
- // 3. Listar todos os Canais inscritos
1227
- const canaisInscritos = await sock.newsletterSubscribed()
1228
- console.log('Canais que eu sigo:', canaisInscritos)
1229
-
1230
- // 4. Buscar e decodificar mensagens do Canal (com contagem de visualizações e reações)
1231
- const { messages } = await sock.newsletterFetchMessages(canal.id, 20)
1232
- for (const msg of messages) {
1233
- console.log(`[ID: ${msg.server_id}] Visualizações: ${msg.views}`)
1234
- console.log('Conteúdo:', msg.message?.conversation || msg.message?.extendedTextMessage?.text)
1235
- console.log('Reações:', msg.reactions) // [{ code: '👍', count: 12 }, { code: '❤️', count: 5 }]
1236
- }
1237
-
1238
- // 5. Buscar mensagem individual do Canal
1239
- const singleMsg = await sock.newsletterFetchMessage(canal.id, '12345')
1240
-
1241
- // 6. Consultar contadores de reações de uma postagem
1242
- const reacoes = await sock.newsletterFetchReactions(canal.id, '12345')
1243
- console.log('Reações do post:', reacoes)
1244
-
1245
- // 7. Reagir a uma postagem do Canal (suporta server_id, id ou chave da mensagem)
1246
- await sock.newsletterReactMessage(canal.id, '12345', '🔥')
1247
-
1248
- // 8. Seguir / Deixar de Seguir
1249
- await sock.newsletterFollow(canal.id)
1250
- await sock.newsletterUnfollow(canal.id)
1251
-
1252
- // 9. Silenciar / Ativar notificações
1253
- await sock.newsletterMute(canal.id)
1254
- await sock.newsletterUnmute(canal.id)
1255
- await sock.newsletterToggleMute(canal.id, true) // ou false para desativar
1256
-
1257
- // 10. Atualizar nome, descrição ou foto do Canal (Admins)
1258
- await sock.newsletterUpdateName(canal.id, 'Novo Nome do Canal')
1259
- await sock.newsletterUpdateDescription(canal.id, 'Nova descrição detalhada do canal')
1260
- await sock.newsletterUpdatePicture(canal.id, './novo_avatar_canal.jpg')
1261
- await sock.newsletterRemovePicture(canal.id)
1262
-
1263
- // 11. Consultar inscritos e administradores
1264
- const inscritos = await sock.newsletterSubscribers(canal.id)
1265
- const totalAdmins = await sock.newsletterAdminCount(canal.id)
1266
-
1267
- // 12. Transferir propriedade ou excluir o Canal
1268
- await sock.newsletterChangeOwner(canal.id, '5511888888888@s.whatsapp.net')
1269
- await sock.newsletterDelete(canal.id)
1270
- ```
1271
-
1272
- ---
1273
-
1274
- ## 💼 WhatsApp Business (Catálogo, Produtos e Perfil Comercial)
1275
-
1276
- 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.
1277
-
1278
- ### Gerenciamento de Perfil e Capa Comercial
1279
-
1280
- Você pode atualizar dados públicos de endereço, e-mail, descrição, websites, horários de funcionamento e foto de capa:
1281
-
1282
- ```javascript
1283
- // Atualizar o perfil comercial do usuário
1284
- await sock.updateBussinesProfile({
1285
- address: 'Av. Paulista, 1000 - São Paulo, SP',
1286
- email: 'contato@suaempresa.com.br',
1287
- description: 'Empresa especializada em soluções de tecnologia.',
1288
- websites: ['https://suaempresa.com.br', 'https://blog.suaempresa.com.br'],
1289
- hours: {
1290
- timezone: 'America/Sao_Paulo',
1291
- days: [
1292
- { day: '1', mode: 'open_24_h' }, // Segunda-feira (1=Segunda, 7=Domingo)
1293
- {
1294
- day: '2',
1295
- mode: 'specific_hours',
1296
- openTimeInMinutes: 540, // 09:00 (9h * 60)
1297
- closeTimeInMinutes: 1080 // 18:00 (18h * 60)
1298
- }
1299
- ]
1300
- }
1301
- })
1302
-
1303
- // Atualizar ou definir a foto de capa comercial
1304
- const coverPhotoId = await sock.updateCoverPhoto('./capa_empresa.jpg')
1305
-
1306
- // Remover a foto de capa atual
1307
- await sock.removeCoverPhoto(coverPhotoId)
1308
- ```
1309
-
1310
- ### Consulta de Catálogo, Coleções e Pedidos
1311
-
1312
- ```javascript
1313
- // Obter a lista de produtos do catálogo de um contato (ou do seu próprio)
1314
- const catalogo = await sock.getCatalog({
1315
- jid: '5511999999999@s.whatsapp.net',
1316
- limit: 15
1317
- })
1318
- console.log('Produtos:', catalogo.products)
1319
-
1320
- // Obter as coleções de produtos organizadas do catálogo
1321
- const colecoes = await sock.getCollections('5511999999999@s.whatsapp.net', 10)
1322
-
1323
- // Obter os detalhes completos de um pedido comercial a partir do ID e do Token da mensagem de carrinho
1324
- const detalhesPedido = await sock.getOrderDetails('ID_DO_PEDIDO', 'TOKEN_DO_PEDIDO')
1325
- console.log('Itens do Pedido:', detalhesPedido.items)
1326
- ```
1327
-
1328
- ### Cadastro e Modificação de Produtos no Catálogo
1329
-
1330
- ```javascript
1331
- // Adicionar um novo produto no catálogo
1332
- const novoProduto = await sock.productCreate({
1333
- name: 'Caneca Personalizada WaSockets',
1334
- description: 'Caneca de cerâmica de alta qualidade.',
1335
- price: 4990, // R$ 49,90 (valor representado sem decimais, multiplicado por 100)
1336
- currency: 'BRL',
1337
- isHidden: false,
1338
- image: { url: './caneca.jpg' } // Caminho local, buffer ou stream
1339
- })
1340
- console.log('Produto Criado com ID:', novoProduto.id)
1341
-
1342
- // Atualizar dados de um produto existente
1343
- await sock.productUpdate(novoProduto.id, {
1344
- name: 'Caneca Personalizada WaSockets (Edição Especial)',
1345
- price: 5990
1346
- })
1347
-
1348
- // Obter detalhes de um único produto
1349
- const produto = await sock.getProduct(sock.user.id, novoProduto.id)
1350
- console.log('Detalhes do Produto:', produto)
1351
-
1352
- // Remover produtos do catálogo (aceita um array de IDs de produtos)
1353
- await sock.productDelete([novoProduto.id])
1354
- ```
1355
-
1356
- ---
1357
-
1358
- ## 👥 Grupos, Comunidades v2 e Moderação Avançada
1359
-
1360
- O **WaSockets** oferece um conjunto completo e modernizado para gerenciamento profissional de Grupos e Comunidades no WhatsApp.
1361
-
1362
- ### Gestão e Moderação de Entrada (Approval Mode)
1363
-
1364
- Controle quem pode entrar no grupo através do fluxo oficial de aprovação de membros:
1365
-
1366
- ```javascript
1367
- const groupJid = '1234567890-987654@g.us'
1368
-
1369
- // Ativar modo de aprovação obrigatória de novos membros
1370
- await sock.groupMembershipApprovalMode(groupJid, 'on') // ou true / 'off'
1371
-
1372
- // Listar participantes aguardando aprovação
1373
- const pendentes = await sock.groupRequestParticipantsList(groupJid)
1374
- console.log('Solicitações pendentes:', pendentes)
1375
-
1376
- // Aprovar participantes pendentes (aceita string única ou array)
1377
- await sock.groupApprovePendingParticipants(groupJid, ['5511999999999@s.whatsapp.net'])
1378
-
1379
- // Rejeitar participantes pendentes
1380
- await sock.groupRejectPendingParticipants(groupJid, ['5511888888888@s.whatsapp.net'])
1381
- ```
1382
-
1383
- ### Configuração Unificada de Políticas do Grupo
1384
-
1385
- Altere facilmente todas as diretrizes de segurança e permissões do grupo em uma única chamada:
1386
-
1387
- ```javascript
1388
- await sock.groupUpdatePermissions(groupJid, {
1389
- announce: true, // true: apenas admins enviam mensagens; false: todos
1390
- restrict: true, // true: apenas admins editam dados do grupo; false: todos
1391
- memberAddMode: 'admin_add', // 'admin_add' ou 'all_member_add'
1392
- approvalMode: true, // Exigir aprovação de admin para novos participantes
1393
- ephemeral: 86400 // Mensagens temporárias (24h = 86400s, 7 dias = 604800s, false = desativar)
1394
- })
1395
- ```
1396
-
1397
- ### Menção a Todos os Membros (@everyone / Mention All)
1398
-
1399
- Notifique ou mencione todos os participantes de um grupo de forma prática e sem boilerplate:
1400
-
1401
- ```javascript
1402
- // Método direto
1403
- await sock.groupSendMentionAll(groupJid, '📢 Atenção a todos os membros: reunião às 15h!')
1404
-
1405
- // Ou apenas para administradores, excluindo a si próprio:
1406
- await sock.groupSendMentionAll(groupJid, 'Aviso importante aos administradores', {
1407
- adminsOnly: true,
1408
- excludeMe: true
1409
- })
1410
-
1411
- // Ou diretamente através do sendMessage usando o parâmetro mentionAll:
1412
- await sock.sendMessage(groupJid, {
1413
- text: 'Olá a todos!',
1414
- mentionAll: true
1415
- })
1416
- ```
1417
-
1418
- ### Extração Rápida de Administradores e Membros
1419
-
1420
- ```javascript
1421
- // Retorna array de JIDs apenas de administradores e criador
1422
- const adminJids = await sock.groupGetAdminJids(groupJid)
1423
-
1424
- // Retorna lista completa normalizada de participantes com status de admin e LID
1425
- const participantes = await sock.groupGetParticipants(groupJid)
1426
- ```
1427
-
1428
- ### Comunidades v2 (Subgrupos e Anúncios)
1429
-
1430
- Gerencie Comunidades do WhatsApp com suporte a separação de subgrupos e grupo de avisos geral:
1431
-
1432
- ```javascript
1433
- // Criar uma comunidade
1434
- const comunidade = await sock.communityCreate('Minha Comunidade', 'Descrição da comunidade')
1435
-
1436
- // Vincular um grupo existente como subgrupo da comunidade
1437
- await sock.communityLinkGroup(groupJid, comunidade.id)
1438
-
1439
- // Desvincular um subgrupo da comunidade
1440
- await sock.communityUnlinkGroup(groupJid, comunidade.id)
1441
-
1442
- // Obter subgrupos organizados (grupo padrão de anúncios vs subgrupos comuns)
1443
- const { defaultSubGroup, subGroups, allGroups } = await sock.communityFetchSubGroups(comunidade.id)
1444
- console.log('Grupo Geral de Anúncios:', defaultSubGroup)
1445
- console.log('Subgrupos de discussão:', subGroups)
1446
-
1447
- // Gerenciar aprovações de entrada na Comunidade
1448
- await sock.communityMembershipApprovalMode(comunidade.id, 'on')
1449
- await sock.communityApprovePendingParticipants(comunidade.id, ['5511999999999@s.whatsapp.net'])
1450
- ```
1451
-
1452
- ### Mensagens de Visualização Única (View Once)
1453
-
1454
- Envie imagens, vídeos ou mídias efêmeras com a flag `viewOnce: true`:
1455
-
1456
- ```javascript
1457
- await sock.sendMessage(jid, {
1458
- image: { url: './comprovante.jpg' },
1459
- caption: 'Comprovante confidencial',
1460
- viewOnce: true
1461
- })
1462
- ```
1463
-
1464
- ---
1465
-
1466
- ## 🧩 Arquitetura de Plugins e Middlewares
1467
-
1468
- 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.
1469
-
1470
- ### Criando e Instalando Plugins
1471
-
1472
- Um plugin pode ser uma função simples ou um objeto estruturado:
1473
-
1474
- ```javascript
1475
- // Exemplo de Plugin de Boas-Vindas ou Auto-Resposta
1476
- const meuPluginBot = {
1477
- name: 'auto-reply-plugin',
1478
- version: '1.0.0',
1479
- description: 'Responde automaticamente a palavras-chave',
1480
- install(sock, options, manager) {
1481
- console.log('Plugin instalado com opções:', options)
1482
-
1483
- // Escuta eventos normais da conexão
1484
- sock.ev.on('messages.upsert', async ({ messages, type }) => {
1485
- if (type !== 'notify') return
1486
- for (const msg of messages) {
1487
- if (!msg.key.fromMe && msg.message?.conversation === '!ping') {
1488
- await sock.sendMessage(msg.key.remoteJid, { text: '🏓 Pong via Plugin!' })
1489
- }
1490
- }
1491
- })
1492
- }
1493
- }
1494
-
1495
- // Instalação do plugin no socket
1496
- sock.use(meuPluginBot, { prefix: '!' })
1497
-
1498
- // Listar plugins ativos
1499
- console.log('Plugins ativos:', sock.listPlugins())
1500
- ```
1501
-
1502
- ### Middlewares de Interceptação de Mensagens
1503
-
1504
- Intercepte ou cancele envios e recebimentos antes que cheguem à rede:
1505
-
1506
- ```javascript
1507
- // Intercepta qualquer mensagem antes do envio (retornar false cancela o envio)
1508
- sock.registerMiddleware('beforeSendMessage', async ({ jid, content, options }, socket) => {
1509
- console.log(`Enviando mensagem para ${jid}...`)
1510
-
1511
- // Bloquear envio se contiver palavras proibidas
1512
- if (typeof content?.text === 'string' && content.text.includes('palavra_bloqueada')) {
1513
- console.warn('Mensagem bloqueada por política de segurança.')
1514
- return false // Cancela o disparo
1515
- }
1516
- })
1517
-
1518
- // Executa após a mensagem ser enviada com sucesso
1519
- sock.registerMiddleware('afterSendMessage', async ({ jid, content, fullMsg }, socket) => {
1520
- console.log(`Mensagem ${fullMsg.key.id} entregue ao servidor com sucesso!`)
1521
- })
1522
- ```
1523
-
1524
- ---
1525
-
1526
- ## ⚡ Alta Performance, Cache e Controle de Memória
1527
-
1528
- ### Cache Integrado de Metadados de Grupo (TTL LRU)
1529
-
1530
- 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:
1531
-
1532
- ```javascript
1533
- const sock = makeWASocket({
1534
- enableGroupCache: true // Ativado por padrão com TTL de 5 minutos
1535
- })
1536
- ```
1537
-
1538
- ### Proteção de Memória na Store (`makeInMemoryStore`)
1539
-
1540
- Evite vazamento de memória em bots de alta demanda com limpeza automática e limite configurável de mensagens por chat:
1541
-
1542
- ```javascript
1543
- const store = makeInMemoryStore({
1544
- maxMessagesPerChat: 200 // Limita o histórico a 200 mensagens por chat em RAM (padrão: 500)
1545
- })
1546
-
1547
- // Limpeza manual sob demanda
1548
- store.pruneMessages(groupJid, 50) // Mantém apenas as últimas 50 mensagens do chat especificado
1549
- store.pruneMessages(undefined, 100) // Trunca todos os chats para no máximo 100 mensagens
1550
-
1551
- // Obter contagem de mensagens armazenadas
1552
- const qtdTotal = store.getMessageCount()
1553
- const qtdChat = store.getMessageCount(groupJid)
1554
-
1555
- // Limpar mensagens de um chat ou resetar toda a memória
1556
- store.clear(groupJid)
1557
- ```
1558
-
1559
- ---
1560
-
1561
- ## 🔷 Suporte Completo a TypeScript
1562
-
1563
- 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:
1564
-
1565
- ```typescript
1566
- import makeWASocket, { WASocket, AnyMessageContent, DisconnectReason, GroupMetadata } from '@areumtecnologia/wasockets'
1567
-
1568
- const sock: WASocket = makeWASocket({
1569
- printQRInTerminal: true
1570
- })
1571
- ```
1572
-
1573
- ---
1574
-
1575
- ## 🔒 Configurações de Privacidade
1576
-
1577
- ```javascript
1578
- // Bloquear ou desbloquear um usuário
1579
- await sock.updateBlockStatus('5511999999999@s.whatsapp.net', 'block') // ou 'unblock'
1580
-
1581
- // Obter lista de usuários bloqueados
1582
- const listaBloqueados = await sock.fetchBlocklist()
1583
-
1584
- // Atualizar privacidade do "Visto por Último"
1585
- // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
1586
- await sock.updateLastSeenPrivacy('contacts')
1587
-
1588
- // Atualizar privacidade do "Visto Online"
1589
- // Valores aceitos: 'all' | 'match_last_seen'
1590
- await sock.updateOnlinePrivacy('match_last_seen')
1591
-
1592
- // Atualizar privacidade das confirmações de leitura (ticks azuis)
1593
- // Valores aceitos: 'all' | 'none'
1594
- await sock.updateReadReceiptsPrivacy('none')
1595
-
1596
- // Atualizar privacidade da Foto de Perfil
1597
- // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
1598
- await sock.updateProfilePicturePrivacy('contacts')
1599
-
1600
- // Atualizar privacidade do Recado/Status (About)
1601
- // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
1602
- await sock.updateStatusPrivacy('contacts')
1603
-
1604
- // Atualizar quem pode adicionar você a grupos
1605
- // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist'
1606
- await sock.updateGroupsAddPrivacy('contacts')
1607
-
1608
- // Silenciar chamadas de números desconhecidos
1609
- // Valores aceitos: 'all' (permite todos) | 'known' (apenas contatos conhecidos)
1610
- await sock.updateCallPrivacy('known')
1611
-
1612
- // Consultar todas as configurações de privacidade ativas da conta
1613
- const privacySettings = await sock.fetchPrivacySettings()
1614
- console.log('Configurações de privacidade atuais:', privacySettings)
1615
- ```
1616
-
1617
- ---
1618
-
1619
- ## 🛡️ Logs e Protocolo
1620
-
1621
- 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:
1622
-
1623
- ```javascript
1624
- const pino = require('pino')
1625
-
1626
- const sock = makeWASocket({
1627
- logger: pino({ level: 'debug' })
1628
- })
1629
- ```
1630
-
1631
- ### Como o WhatsApp se comunica (BinaryNodes)
1632
-
1633
- As mensagens são trocadas em formato binário encapsuladas em estruturas chamadas `BinaryNode`. Cada nó possui três atributos:
1634
- - **`tag`**: Nome da ação (ex: `message`, `ib`, `presence`, `iq`)
1635
- - **`attrs`**: Objeto contendo propriedades em string/chave-valor (ID, timestamp, remetente, etc.)
1636
- - **`content`**: O corpo de dados do nó (geralmente outro array de nós ou um buffer criptografado)
1637
-
1638
- Você pode interagir diretamente com o tráfego do Websocket do WhatsApp registrando callbacks específicos:
1639
-
1640
- ```javascript
1641
- // Monitora todos os pacotes recebidos que possuem a tag 'edge_routing'
1642
- sock.ws.on('CB:edge_routing', (node) => {
1643
- console.log('Recebido nó de roteamento:', node)
1644
- })
1645
-
1646
- // Monitora pacotes 'message' específicos
1647
- sock.ws.on('CB:message', (node) => {
1648
- console.log('Mensagem de protocolo bruta:', node)
1649
- })
1650
- ```
994
+ display_text: 'Copiar Cupom',
995
+ id: 'btn_cupom',
996
+ copy_code: 'DESCONTO20'
997
+ })
998
+ }
999
+ ]
1000
+ })
1001
+ ```
1002
+
1003
+ ---
1004
+
1005
+ ### Botão de Pagamento PIX
1006
+
1007
+ 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`.
1008
+
1009
+ ```javascript
1010
+ await sock.sendMessage(jid, {
1011
+ text: 'Efetue o pagamento do pedido abaixo clicando em Pagar:',
1012
+ interactiveButtons: [
1013
+ {
1014
+ name: 'payment_info',
1015
+ buttonParamsJson: JSON.stringify({
1016
+ payment_settings: [{
1017
+ type: 'pix_static_code',
1018
+ pix_static_code: {
1019
+ merchant_name: 'Áreum Tecnologia LTDA',
1020
+ key: 'financeiro@areum.com.br', // Chave PIX (E-mail, CPF/CNPJ, Telefone ou EVP)
1021
+ key_type: 'EMAIL' // Tipos suportados: PHONE, EMAIL, CPF, EVP
1022
+ }
1023
+ }]
1024
+ })
1025
+ }
1026
+ ]
1027
+ })
1028
+ ```
1029
+
1030
+ ---
1031
+
1032
+ ### Fluxos de Checkout (PAY)
1033
+
1034
+ É 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`.
1035
+
1036
+ ```javascript
1037
+ await sock.sendMessage(jid, {
1038
+ text: 'Fatura gerada com sucesso!',
1039
+ interactiveButtons: [
1040
+ {
1041
+ name: 'review_and_pay',
1042
+ buttonParamsJson: JSON.stringify({
1043
+ currency: 'BRL',
1044
+ payment_type: 'physical-goods',
1045
+ total_amount: {
1046
+ value: '15000', // R$ 150,00 (representado sem decimais, multiplicado pelo offset)
1047
+ offset: '100'
1048
+ },
1049
+ reference_id: 'REF_PEDIDO_12345',
1050
+ payment_method: 'confirm',
1051
+ payment_status: 'captured',
1052
+ payment_timestamp: Math.floor(Date.now() / 1000),
1053
+ order: {
1054
+ status: 'completed',
1055
+ order_type: 'PAYMENT_REQUEST',
1056
+ subtotal: { value: '15000', offset: '100' },
1057
+ items: [{
1058
+ retailer_id: 'item_01',
1059
+ name: 'Licença Anual WaSockets',
1060
+ amount: { value: '15000', offset: '100' },
1061
+ quantity: '1'
1062
+ }]
1063
+ },
1064
+ additional_note: 'Agradecemos a sua preferência!'
1065
+ })
1066
+ }
1067
+ ]
1068
+ })
1069
+ ```
1070
+
1071
+ ---
1072
+
1073
+ ### Menção em Status
1074
+
1075
+ Permite publicar status (stories) e marcar diretamente contatos/grupos específicos (máximo de 5 menções por status).
1076
+
1077
+ ```javascript
1078
+ const contatosParaMencionar = [
1079
+ '5511999999999@s.whatsapp.net',
1080
+ '5511888888888@s.whatsapp.net'
1081
+ ]
1082
+
1083
+ // Envia um status em formato de texto mencionando os contatos acima
1084
+ await sock.sendStatusMentions(
1085
+ {
1086
+ text: 'Novidade incrível para vocês! 🚀',
1087
+ backgroundColor: '#1c1c1c',
1088
+ textColor: '#ffffff'
1089
+ },
1090
+ contatosParaMencionar
1091
+ )
1092
+
1093
+ // Curtir / Reagir diretamente a uma publicação de Status (Stories)
1094
+ await sock.reactToStatus(statusMsgKey, '❤️')
1095
+ ```
1096
+
1097
+ ### Comentários em Canais e Comunidades
1098
+
1099
+ Envie respostas e comentários estruturados em postagens de canais (Newsletters) ou mensagens de aviso em comunidades:
1100
+
1101
+ ```javascript
1102
+ await sock.sendMessage(jid, {
1103
+ comment: {
1104
+ targetMessageKey: mensagemOriginal.key,
1105
+ message: { text: 'Excelente atualização! 👏' }
1106
+ }
1107
+ })
1108
+ ```
1109
+
1110
+ ### Envio Nativo de Álbuns de Fotos e Vídeos (Pilar 3)
1111
+
1112
+ 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:
1113
+
1114
+ ```javascript
1115
+ // Método direto e simplificado
1116
+ await sock.sendAlbumMessage(jid, [
1117
+ { image: { url: 'https://exemplo.com/foto1.jpg' }, caption: 'Foto 1 do produto' },
1118
+ { image: { url: 'https://exemplo.com/foto2.jpg' }, caption: 'Foto 2 em outro ângulo' },
1119
+ { video: { url: 'https://exemplo.com/demonstracao.mp4' }, caption: 'Vídeo explicativo' }
1120
+ ])
1121
+
1122
+ // Ou através de sendMessage com a propriedade album:
1123
+ await sock.sendMessage(jid, {
1124
+ album: [
1125
+ { image: { url: './local/foto1.jpg' } },
1126
+ { image: { url: './local/foto2.jpg' } }
1127
+ ]
1128
+ })
1129
+ ```
1130
+
1131
+ ### Mensagens de Áudio PTT com Waveform Customizada (Pilar 3)
1132
+
1133
+ 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):
1134
+
1135
+ ```javascript
1136
+ // Áudio PTT com waveform automática gerada a partir do arquivo
1137
+ await sock.sendMessage(jid, {
1138
+ audio: { url: './audio.mp3' },
1139
+ mimetype: 'audio/ogg; codecs=opus',
1140
+ ptt: true
1141
+ })
1142
+
1143
+ // Áudio PTT com waveform predefinida (evita decodificação intensiva de CPU)
1144
+ await sock.sendMessage(jid, {
1145
+ audio: { url: './audio.mp3' },
1146
+ mimetype: 'audio/ogg; codecs=opus',
1147
+ ptt: true,
1148
+ waveform: [0, 15, 30, 75, 100, 80, 45, 20, 10, 0] // 64 barras de amplitude
1149
+ })
1150
+ ```
1151
+
1152
+ ### Encaminhamento de Mensagens
1153
+
1154
+ Encaminhe mensagens para outros chats preservando ou forçando o status de encaminhado:
1155
+
1156
+ ```javascript
1157
+ // Encaminhar uma mensagem recebida para outro destinatário
1158
+ await sock.sendMessage(outroJid, {
1159
+ forward: mensagemOriginal,
1160
+ force: true // Exibe o selo de mensagem encaminhada
1161
+ })
1162
+ ```
1163
+
1164
+ ---
1165
+
1166
+ ## 📝 Modificando Mensagens e Chats
1167
+
1168
+ ```javascript
1169
+ // Apagar uma mensagem para todos
1170
+ const msg = await sock.sendMessage(jid, { text: 'Mensagem enviada com erro!' })
1171
+ await sock.sendMessage(jid, { delete: msg.key })
1172
+
1173
+ // Editar uma mensagem enviada
1174
+ await sock.sendMessage(jid, {
1175
+ text: 'Esta é a mensagem com o texto corrigido.',
1176
+ edit: msg.key
1177
+ })
1178
+
1179
+ // Arquivar um chat
1180
+ await sock.chatModify({ archive: true, lastMessages: [msg] }, jid)
1181
+
1182
+ // Silenciar um chat por 8 horas
1183
+ await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
1184
+
1185
+ // Remover silenciamento de um chat
1186
+ await sock.chatModify({ mute: null }, jid)
1187
+
1188
+ // Marcar chat como Não Lido
1189
+ await sock.chatModify({ markRead: false, lastMessages: [msg] }, jid)
1190
+
1191
+ // Fixar chat na lista de conversas
1192
+ await sock.chatModify({ pin: true }, jid)
1193
+ ```
1194
+
1195
+ ### Confirmação de Leitura (readMessages)
1196
+
1197
+ Envie confirmações de leitura explícitas para exibir os ticks azuis ao remetente:
1198
+
1199
+ ```javascript
1200
+ // Marca uma ou mais mensagens recebidas como lidas
1201
+ await sock.readMessages([msg.key])
1202
+ ```
1203
+
1204
+ ### Mensagens com Estrela (star)
1205
+
1206
+ Marque mensagens importantes com estrela (favoritas) na conversa:
1207
+
1208
+ ```javascript
1209
+ // Adicionar estrela à mensagem
1210
+ await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], true)
1211
+
1212
+ // Remover estrela da mensagem
1213
+ await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], false)
1214
+ ```
1215
+
1216
+ ### Fixação de Mensagens com Duração
1217
+
1218
+ Fixe mensagens em conversas individuais ou grupos escolhendo a duração desejada:
1219
+
1220
+ ```javascript
1221
+ // Fixar mensagem por 7 dias (604800 segundos)
1222
+ // Durações padrão: 86400 (24h), 604800 (7 dias), 2592000 (30 dias)
1223
+ await sock.sendMessage(jid, {
1224
+ pin: {
1225
+ key: msg.key,
1226
+ type: 1, // 1: Fixar, 2: Desafixar
1227
+ time: 604800
1228
+ }
1229
+ })
1230
+
1231
+ // Desafixar mensagem
1232
+ await sock.sendMessage(jid, {
1233
+ pin: {
1234
+ key: msg.key,
1235
+ type: 2
1236
+ }
1237
+ })
1238
+ ```
1239
+
1240
+ ### Favoritos e Anotações de Contato
1241
+
1242
+ Organize suas conversas sincronizando com o WhatsApp Web e celular:
1243
+
1244
+ ```javascript
1245
+ // Marcar conversa como Favorita
1246
+ await sock.updateFavorite(jid, true)
1247
+
1248
+ // Desmarcar conversa como Favorita
1249
+ await sock.updateFavorite(jid, false)
1250
+
1251
+ // Adicionar ou atualizar nota interna no contato (Chat Note)
1252
+ await sock.updateChatNote(jid, 'Cliente solicitou proposta para 50 atendentes.')
1253
+
1254
+ // Remover nota interna do contato
1255
+ await sock.removeChatNote(jid)
1256
+ ```
1257
+
1258
+ ---
1259
+
1260
+ ## 👤 Perfil do Usuário e Foto
1261
+
1262
+ Gerencie fotos de perfil, recados e nome de exibição (PushName) diretamente pelo socket:
1263
+
1264
+ ```javascript
1265
+ // 1. Obter a URL da foto de perfil de um contato ou grupo
1266
+ const pfpUrl = await sock.profilePictureUrl(jid, 'image') // ou 'preview' para miniatura
1267
+ console.log('Foto de Perfil:', pfpUrl)
1268
+
1269
+ // 2. Atualizar a sua própria foto de perfil (ou a foto de um grupo do qual você é admin)
1270
+ await sock.updateProfilePicture(jid, { url: './nova_foto.jpg' }) // Aceita caminho, URL ou Buffer
1271
+
1272
+ // 3. Remover a foto de perfil
1273
+ await sock.removeProfilePicture(jid)
1274
+
1275
+ // 4. Consultar o recado / About (Status) de um contato
1276
+ const statusInfo = await sock.fetchStatus(jid)
1277
+ console.log(`Recado de ${jid}: ${statusInfo?.status} (Definido em: ${statusInfo?.setAt})`)
1278
+
1279
+ // 5. Atualizar o seu próprio recado / About
1280
+ await sock.updateProfileStatus('Disponível apenas para atendimentos prioritários 🚀')
1281
+
1282
+ // 6. Atualizar o seu nome público de exibição (PushName)
1283
+ await sock.updateProfileName('Áreum Tecnologia - Suporte Oficial')
1284
+ ```
1285
+
1286
+ ---
1287
+
1288
+ ## 📅 Eventos em Grupos e RSVP
1289
+
1290
+ Crie eventos colaborativos, responda confirmações de presença e cancele eventos:
1291
+
1292
+ ```javascript
1293
+ // 1. Criar um novo evento no grupo
1294
+ const evento = await sock.sendMessage(grupoJid, {
1295
+ event: {
1296
+ name: 'Reunião de Planejamento de Sprints',
1297
+ description: 'Alinhamento estratégico dos projetos da Áreum Tecnologia.',
1298
+ startTime: Math.floor(Date.now() / 1000) + 86400, // Amanhã
1299
+ extraGuestsAllowed: true
1300
+ }
1301
+ })
1302
+
1303
+ // 2. Responder ao Evento (RSVP)
1304
+ // Tipos de resposta: 'GOING' (1), 'NOT_GOING' (2), 'MAYBE' (3)
1305
+ await sock.sendEventResponse(grupoJid, evento.key, 'GOING', 1 /* +1 convidado extra */)
1306
+
1307
+ // 3. Cancelar o Evento
1308
+ await sock.cancelEvent(grupoJid, evento.key)
1309
+ ```
1310
+
1311
+ ---
1312
+
1313
+ ## 🔍 Resolução de Usuários & Transição LID (Pilar 2)
1314
+
1315
+ 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:
1316
+
1317
+ ### Métodos de Resolução Transparente no Socket
1318
+
1319
+ ```javascript
1320
+ // 1. Converter LID para número de telefone (PN) com busca em cache/DB
1321
+ const pnJid = await sock.toPn('12345678901234@lid')
1322
+ console.log('JID com número real:', pnJid) // '5511999999999@s.whatsapp.net'
1323
+
1324
+ // Caso não esteja em cache local, pode passar true para consultar o servidor via USync:
1325
+ const pnJidFromNetwork = await sock.toPn('12345678901234@lid', true)
1326
+
1327
+ // 2. Converter número de telefone (PN) para LID
1328
+ const lidJid = await sock.toLid('5511999999999@s.whatsapp.net')
1329
+ console.log('LID correspondente:', lidJid) // '12345678901234@lid'
1330
+
1331
+ // 3. Resolução completa e unificada (retorna ambos)
1332
+ const resolved = await sock.resolveJid(authorJid)
1333
+ console.log(resolved) // { pn: '5511999999999@s.whatsapp.net', lid: '12345678901234@lid', jid: ... }
1334
+
1335
+ // 4. Registrar manualmente um mapeamento conhecido
1336
+ await sock.storeLidPnMapping('5511999999999@s.whatsapp.net', '12345678901234@lid')
1337
+
1338
+ // 5. Consultas diretas via protocolo USync (baixo nível)
1339
+ const [lidUser] = await sock.getLidUser('5511999999999@s.whatsapp.net')
1340
+ const [pnUser] = await sock.getPnUser('12345678901234@lid')
1341
+ ```
1342
+
1343
+ ### Store Unificado de Contatos e Conversas (`makeInMemoryStore`)
1344
+
1345
+ Tradicionalmente, quando o WhatsApp chaveia as mensagens para `@lid`, consultas 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:
1346
+
1347
+ ```javascript
1348
+ import { makeInMemoryStore } from '@areumtecnologia/wasockets'
1349
+
1350
+ const store = makeInMemoryStore({})
1351
+ store.bind(sock.ev)
1352
+
1353
+ // Busca unificada: localiza o contato quer você passe o número (@s.whatsapp.net), o @lid ou apenas os dígitos
1354
+ const contact = store.getContact('12345678901234@lid')
1355
+ // Retorna o contato completo contendo .id, .lid, .phoneNumber, .name, etc.
1356
+
1357
+ // Busca unificada de chat: localiza a conversa mesmo se foi iniciada com PN ou com LID
1358
+ const chat = store.getChat('12345678901234@lid')
1359
+
1360
+ // Carregamento de mensagens com fallback cruzado automático entre LID e PN
1361
+ const messages = await store.loadMessages('12345678901234@lid', 25)
1362
+ ```
1363
+
1364
+ ---
1365
+
1366
+ ## 🏷️ Etiquetas de Negócio (Labels - WhatsApp Business)
1367
+
1368
+ O **WaSockets** permite que você gerencie etiquetas e organize contatos ou mensagens diretamente pelo aplicativo WhatsApp Business.
1369
+
1370
+ ### Criando, Editando e Deletando Etiquetas (CRUD de Sistema)
1371
+
1372
+ Você pode criar, editar e excluir as etiquetas globais da sua conta:
1373
+
1374
+ ```javascript
1375
+ // Criar uma nova etiqueta com cor específica
1376
+ // Cores suportadas: de 0 a 19 correspondentes à paleta do WhatsApp Business
1377
+ const novaLabel = await sock.createLabel('Lead Qualificado', 5)
1378
+
1379
+ // Atualizar o nome e a cor de uma etiqueta existente
1380
+ await sock.updateLabel('label_id_123', 'Pagamento Aprovado', 2)
1381
+
1382
+ // Deletar uma etiqueta definitivamente da conta
1383
+ await sock.deleteLabel('label_id_123')
1384
+ ```
1385
+
1386
+ ### Associando Etiquetas a Conversas e Mensagens
1387
+
1388
+ Para categorizar chats específicos ou marcar mensagens individuais dentro de uma conversa:
1389
+
1390
+ ```javascript
1391
+ // Associar etiqueta a uma conversa (JID)
1392
+ await sock.addChatLabel(jid, 'label_id_123')
1393
+
1394
+ // Remover etiqueta de uma conversa (JID)
1395
+ await sock.removeChatLabel(jid, 'label_id_123')
1396
+
1397
+ // Associar etiqueta a uma mensagem específica
1398
+ await sock.addMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
1399
+
1400
+ // Remover etiqueta de uma mensagem específica
1401
+ await sock.removeMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
1402
+ ```
1403
+
1404
+ ### Respostas Rápidas (Quick Replies)
1405
+
1406
+ Para contas WhatsApp Business, gerencie respostas rápidas acessíveis via atalhos:
1407
+
1408
+ ```javascript
1409
+ // Criar ou atualizar resposta rápida
1410
+ await sock.addOrEditQuickReply({
1411
+ id: 'qr_ola',
1412
+ shortcut: '/ola',
1413
+ message: 'Olá! Seja muito bem-vindo à Áreum Tecnologia. Como podemos te ajudar hoje?',
1414
+ keywords: ['ola', 'ajuda', 'suporte', 'inicio']
1415
+ })
1416
+
1417
+ // Remover resposta rápida pelo ID
1418
+ await sock.removeQuickReply('qr_ola')
1419
+ ```
1420
+
1421
+ ---
1422
+
1423
+ ## 👥 Gerenciamento de Grupos
1424
+
1425
+ As operações de alteração estrutural em grupos requerem que a conta conectada seja administradora do grupo correspondente.
1426
+
1427
+ ```javascript
1428
+ // Criar um novo grupo
1429
+ const grupo = await sock.groupCreate('Equipe de Suporte Áreum', ['5511999999999@s.whatsapp.net'])
1430
+ console.log('Grupo criado com ID:', grupo.id)
1431
+
1432
+ // Adicionar/Remover/Promover participantes
1433
+ // Parâmetros de ação: 'add' | 'remove' | 'promote' | 'demote'
1434
+ await sock.groupParticipantsUpdate(grupo.id, ['5511888888888@s.whatsapp.net'], 'add')
1435
+
1436
+ // Obter dados/metadados de um grupo ANTES de entrar usando o código de convite
1437
+ const infoConvite = await sock.groupGetInviteInfo('ABcdEFghIJklMnOpQrStUv')
1438
+ console.log(`Nome do grupo no convite: ${infoConvite.subject}`)
1439
+
1440
+ // Obter o código/link de convite do grupo
1441
+ const codigoConvite = await sock.groupInviteCode(grupo.id)
1442
+ console.log(`Link: https://chat.whatsapp.com/${codigoConvite}`)
1443
+
1444
+ // Revogar link de convite anterior e gerar um novo
1445
+ const novoCodigo = await sock.groupRevokeInvite(grupo.id)
1446
+
1447
+ // Entrar em um grupo usando um código de convite (apenas o código, sem o domínio completo)
1448
+ const resposta = await sock.groupAcceptInvite('ABcdEFghIJklMnOpQrStUv')
1449
+
1450
+ // Alterar o assunto (título) do grupo
1451
+ await sock.groupUpdateSubject(grupo.id, 'Novo Nome do Grupo')
1452
+
1453
+ // Alterar a descrição do grupo
1454
+ await sock.groupUpdateDescription(grupo.id, 'Regras do grupo e links importantes.')
1455
+
1456
+ // Sair do grupo
1457
+ await sock.groupLeave(grupo.id)
1458
+
1459
+ // Obter a lista de pessoas aguardando aprovação para entrar no grupo
1460
+ const solicitacoes = await sock.groupRequestParticipantsList(grupo.id)
1461
+ console.log(solicitacoes)
1462
+
1463
+ // Aprovar entrada pendente
1464
+ await sock.groupRequestParticipantsUpdate(grupo.id, ['5511777777777@s.whatsapp.net'], 'approve') // ou 'reject'
1465
+
1466
+ // Obter metadados do grupo (participantes, título, regras, descrição)
1467
+ const metadados = await sock.groupMetadata(grupo.id)
1468
+ console.log(`Título: ${metadados.subject}, Membros: ${metadados.participants.length}`)
1469
+ ```
1470
+
1471
+ ---
1472
+
1473
+ ## 👥 Etiquetas de Membro (Member Tags) em Grupos
1474
+
1475
+ 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).
1476
+
1477
+ ### Definindo sua própria Etiqueta de Membro no Grupo
1478
+
1479
+ ```javascript
1480
+ // Define a sua etiqueta como "Suporte Técnico" no grupo especificado
1481
+ await sock.updateMemberLabel(grupoJid, "Suporte Técnico")
1482
+ ```
1483
+
1484
+ ### Monitorando Atualizações de Etiquetas de Outros Membros
1485
+
1486
+ Você pode escutar o evento `group.member-tag.update` para monitorar quando qualquer participante alterar a etiqueta de membro dele no grupo:
1487
+
1488
+ ```javascript
1489
+ sock.ev.on('group.member-tag.update', (update) => {
1490
+ const { groupId, label, participant } = update
1491
+ console.log(`O usuário ${participant} definiu a etiqueta "${label}" no grupo ${groupId}`)
1492
+ })
1493
+ ```
1494
+
1495
+ ---
1496
+
1497
+ ## 📢 Newsletters / Canais v2 (Pilar 3)
1498
+
1499
+ 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):
1500
+
1501
+ ```javascript
1502
+ // 1. Criar uma Newsletter (Canal)
1503
+ const canal = await sock.newsletterCreate('Notícias Tecnológicas Áreum', 'Canal oficial de novidades')
1504
+ console.log('Canal criado com ID:', canal.id)
1505
+
1506
+ // 2. Obter metadados de um Canal público pelo ID ou Invite Code
1507
+ const metadadosCanal = await sock.newsletterMetadata('JID', canal.id)
1508
+ console.log('Nome do Canal:', metadadosCanal.name)
1509
+
1510
+ // 3. Listar todos os Canais inscritos
1511
+ const canaisInscritos = await sock.newsletterSubscribed()
1512
+ console.log('Canais que eu sigo:', canaisInscritos)
1513
+
1514
+ // 4. Buscar e decodificar mensagens do Canal (com contagem de visualizações e reações)
1515
+ const { messages } = await sock.newsletterFetchMessages(canal.id, 20)
1516
+ for (const msg of messages) {
1517
+ console.log(`[ID: ${msg.server_id}] Visualizações: ${msg.views}`)
1518
+ console.log('Conteúdo:', msg.message?.conversation || msg.message?.extendedTextMessage?.text)
1519
+ console.log('Reações:', msg.reactions) // [{ code: '👍', count: 12 }, { code: '❤️', count: 5 }]
1520
+ }
1521
+
1522
+ // 5. Buscar mensagem individual do Canal
1523
+ const singleMsg = await sock.newsletterFetchMessage(canal.id, '12345')
1524
+
1525
+ // 6. Consultar contadores de reações de uma postagem
1526
+ const reacoes = await sock.newsletterFetchReactions(canal.id, '12345')
1527
+ console.log('Reações do post:', reacoes)
1528
+
1529
+ // 7. Reagir a uma postagem do Canal (suporta server_id, id ou chave da mensagem)
1530
+ await sock.newsletterReactMessage(canal.id, '12345', '🔥')
1531
+
1532
+ // 8. Seguir / Deixar de Seguir
1533
+ await sock.newsletterFollow(canal.id)
1534
+ await sock.newsletterUnfollow(canal.id)
1535
+
1536
+ // 9. Silenciar / Ativar notificações
1537
+ await sock.newsletterMute(canal.id)
1538
+ await sock.newsletterUnmute(canal.id)
1539
+ await sock.newsletterToggleMute(canal.id, true) // ou false para desativar
1540
+
1541
+ // 10. Atualizar nome, descrição ou foto do Canal (Admins)
1542
+ await sock.newsletterUpdateName(canal.id, 'Novo Nome do Canal')
1543
+ await sock.newsletterUpdateDescription(canal.id, 'Nova descrição detalhada do canal')
1544
+ await sock.newsletterUpdatePicture(canal.id, './novo_avatar_canal.jpg')
1545
+ await sock.newsletterRemovePicture(canal.id)
1546
+
1547
+ // 11. Consultar inscritos e administradores
1548
+ const inscritos = await sock.newsletterSubscribers(canal.id)
1549
+ const totalAdmins = await sock.newsletterAdminCount(canal.id)
1550
+
1551
+ // 12. Transferir propriedade ou excluir o Canal
1552
+ await sock.newsletterChangeOwner(canal.id, '5511888888888@s.whatsapp.net')
1553
+ await sock.newsletterDelete(canal.id)
1554
+ ```
1555
+
1556
+ ---
1557
+
1558
+ ## 💼 WhatsApp Business (Catálogo, Produtos e Perfil Comercial)
1559
+
1560
+ 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.
1561
+
1562
+ ### Gerenciamento de Perfil e Capa Comercial
1563
+
1564
+ Você pode atualizar dados públicos de endereço, e-mail, descrição, websites, horários de funcionamento e foto de capa:
1565
+
1566
+ ```javascript
1567
+ // Atualizar o perfil comercial do usuário
1568
+ await sock.updateBussinesProfile({
1569
+ address: 'Av. Paulista, 1000 - São Paulo, SP',
1570
+ email: 'contato@suaempresa.com.br',
1571
+ description: 'Empresa especializada em soluções de tecnologia.',
1572
+ websites: ['https://suaempresa.com.br', 'https://blog.suaempresa.com.br'],
1573
+ hours: {
1574
+ timezone: 'America/Sao_Paulo',
1575
+ days: [
1576
+ { day: '1', mode: 'open_24_h' }, // Segunda-feira (1=Segunda, 7=Domingo)
1577
+ {
1578
+ day: '2',
1579
+ mode: 'specific_hours',
1580
+ openTimeInMinutes: 540, // 09:00 (9h * 60)
1581
+ closeTimeInMinutes: 1080 // 18:00 (18h * 60)
1582
+ }
1583
+ ]
1584
+ }
1585
+ })
1586
+
1587
+ // Atualizar ou definir a foto de capa comercial
1588
+ const coverPhotoId = await sock.updateCoverPhoto('./capa_empresa.jpg')
1589
+
1590
+ // Remover a foto de capa atual
1591
+ await sock.removeCoverPhoto(coverPhotoId)
1592
+ ```
1593
+
1594
+ ### Consulta de Catálogo, Coleções e Pedidos
1595
+
1596
+ ```javascript
1597
+ // Obter a lista de produtos do catálogo de um contato (ou do seu próprio)
1598
+ const catalogo = await sock.getCatalog({
1599
+ jid: '5511999999999@s.whatsapp.net',
1600
+ limit: 15
1601
+ })
1602
+ console.log('Produtos:', catalogo.products)
1603
+
1604
+ // Obter as coleções de produtos organizadas do catálogo
1605
+ const colecoes = await sock.getCollections('5511999999999@s.whatsapp.net', 10)
1606
+
1607
+ // Obter os detalhes completos de um pedido comercial a partir do ID e do Token da mensagem de carrinho
1608
+ const detalhesPedido = await sock.getOrderDetails('ID_DO_PEDIDO', 'TOKEN_DO_PEDIDO')
1609
+ console.log('Itens do Pedido:', detalhesPedido.items)
1610
+ ```
1611
+
1612
+ ### Cadastro e Modificação de Produtos no Catálogo
1613
+
1614
+ ```javascript
1615
+ // Adicionar um novo produto no catálogo
1616
+ const novoProduto = await sock.productCreate({
1617
+ name: 'Caneca Personalizada WaSockets',
1618
+ description: 'Caneca de cerâmica de alta qualidade.',
1619
+ price: 4990, // R$ 49,90 (valor representado sem decimais, multiplicado por 100)
1620
+ currency: 'BRL',
1621
+ isHidden: false,
1622
+ image: { url: './caneca.jpg' } // Caminho local, buffer ou stream
1623
+ })
1624
+ console.log('Produto Criado com ID:', novoProduto.id)
1625
+
1626
+ // Atualizar dados de um produto existente
1627
+ await sock.productUpdate(novoProduto.id, {
1628
+ name: 'Caneca Personalizada WaSockets (Edição Especial)',
1629
+ price: 5990
1630
+ })
1631
+
1632
+ // Obter detalhes de um único produto
1633
+ const produto = await sock.getProduct(sock.user.id, novoProduto.id)
1634
+ console.log('Detalhes do Produto:', produto)
1635
+
1636
+ // Remover produtos do catálogo (aceita um array de IDs de produtos)
1637
+ await sock.productDelete([novoProduto.id])
1638
+ ```
1639
+
1640
+ ---
1641
+
1642
+ ## 👥 Grupos, Comunidades v2 e Moderação Avançada
1643
+
1644
+ O **WaSockets** oferece um conjunto completo e modernizado para gerenciamento profissional de Grupos e Comunidades no WhatsApp.
1645
+
1646
+ ### Gestão e Moderação de Entrada (Approval Mode)
1647
+
1648
+ Controle quem pode entrar no grupo através do fluxo oficial de aprovação de membros:
1649
+
1650
+ ```javascript
1651
+ const groupJid = '1234567890-987654@g.us'
1652
+
1653
+ // Ativar modo de aprovação obrigatória de novos membros
1654
+ await sock.groupMembershipApprovalMode(groupJid, 'on') // ou true / 'off'
1655
+
1656
+ // Listar participantes aguardando aprovação
1657
+ const pendentes = await sock.groupRequestParticipantsList(groupJid)
1658
+ console.log('Solicitações pendentes:', pendentes)
1659
+
1660
+ // Aprovar participantes pendentes (aceita string única ou array)
1661
+ await sock.groupApprovePendingParticipants(groupJid, ['5511999999999@s.whatsapp.net'])
1662
+
1663
+ // Rejeitar participantes pendentes
1664
+ await sock.groupRejectPendingParticipants(groupJid, ['5511888888888@s.whatsapp.net'])
1665
+ ```
1666
+
1667
+ ### Configuração Unificada de Políticas do Grupo
1668
+
1669
+ Altere facilmente todas as diretrizes de segurança e permissões do grupo em uma única operação:
1670
+
1671
+ ```javascript
1672
+ await sock.groupUpdatePermissions(groupJid, {
1673
+ announce: true, // true: apenas admins enviam mensagens; false: todos
1674
+ restrict: true, // true: apenas admins editam dados do grupo; false: todos
1675
+ memberAddMode: 'admin_add', // 'admin_add' ou 'all_member_add'
1676
+ approvalMode: true, // Exigir aprovação de admin para novos participantes
1677
+ ephemeral: 86400 // Mensagens temporárias (24h = 86400s, 7 dias = 604800s, false = desativar)
1678
+ })
1679
+ ```
1680
+
1681
+ ### Menção a Todos os Membros (@everyone / Mention All)
1682
+
1683
+ Notifique ou mencione todos os participantes de um grupo de forma prática e sem boilerplate:
1684
+
1685
+ ```javascript
1686
+ // Método direto
1687
+ await sock.groupSendMentionAll(groupJid, '📢 Atenção a todos os membros: reunião às 15h!')
1688
+
1689
+ // Ou apenas para administradores, excluindo a si próprio:
1690
+ await sock.groupSendMentionAll(groupJid, 'Aviso importante aos administradores', {
1691
+ adminsOnly: true,
1692
+ excludeMe: true
1693
+ })
1694
+
1695
+ // Ou diretamente através do sendMessage usando o parâmetro mentionAll:
1696
+ await sock.sendMessage(groupJid, {
1697
+ text: 'Olá a todos!',
1698
+ mentionAll: true
1699
+ })
1700
+ ```
1701
+
1702
+ ### Extração Rápida de Administradores e Membros
1703
+
1704
+ ```javascript
1705
+ // Retorna array de JIDs apenas de administradores e criador
1706
+ const adminJids = await sock.groupGetAdminJids(groupJid)
1707
+
1708
+ // Retorna lista completa normalizada de participantes com status de admin e LID
1709
+ const participantes = await sock.groupGetParticipants(groupJid)
1710
+ ```
1711
+
1712
+ ### Comunidades v2 (Subgrupos e Anúncios)
1713
+
1714
+ Gerencie Comunidades do WhatsApp com suporte a separação de subgrupos e grupo de avisos geral:
1715
+
1716
+ ```javascript
1717
+ // Criar uma comunidade
1718
+ const comunidade = await sock.communityCreate('Minha Comunidade', 'Descrição da comunidade')
1719
+
1720
+ // Vincular um grupo existente como subgrupo da comunidade
1721
+ await sock.communityLinkGroup(groupJid, comunidade.id)
1722
+
1723
+ // Desvincular um subgrupo da comunidade
1724
+ await sock.communityUnlinkGroup(groupJid, comunidade.id)
1725
+
1726
+ // Obter subgrupos organizados (grupo padrão de anúncios vs subgrupos comuns)
1727
+ const { defaultSubGroup, subGroups, allGroups } = await sock.communityFetchSubGroups(comunidade.id)
1728
+ console.log('Grupo Geral de Anúncios:', defaultSubGroup)
1729
+ console.log('Subgrupos de discussão:', subGroups)
1730
+
1731
+ // Gerenciar aprovações de entrada na Comunidade
1732
+ await sock.communityMembershipApprovalMode(comunidade.id, 'on')
1733
+ await sock.communityApprovePendingParticipants(comunidade.id, ['5511999999999@s.whatsapp.net'])
1734
+ ```
1735
+
1736
+ ### Mensagens de Visualização Única (View Once)
1737
+
1738
+ Envie imagens, vídeos ou mídias efêmeras com a flag `viewOnce: true`:
1739
+
1740
+ ```javascript
1741
+ await sock.sendMessage(jid, {
1742
+ image: { url: './comprovante.jpg' },
1743
+ caption: 'Comprovante confidencial',
1744
+ viewOnce: true
1745
+ })
1746
+ ```
1747
+
1748
+ ---
1749
+
1750
+ ## 🧩 Arquitetura de Plugins e Middlewares
1751
+
1752
+ 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.
1753
+
1754
+ ### Criando e Instalando Plugins
1755
+
1756
+ Um plugin pode ser uma função simples ou um objeto estruturado:
1757
+
1758
+ ```javascript
1759
+ // Exemplo de Plugin de Boas-Vindas ou Auto-Resposta
1760
+ const meuPluginBot = {
1761
+ name: 'auto-reply-plugin',
1762
+ version: '1.0.0',
1763
+ description: 'Responde automaticamente a palavras-chave',
1764
+ install(sock, options, manager) {
1765
+ console.log('Plugin instalado com opções:', options)
1766
+
1767
+ // Escuta eventos normais da conexão
1768
+ sock.ev.on('messages.upsert', async ({ messages, type }) => {
1769
+ if (type !== 'notify') return
1770
+ for (const msg of messages) {
1771
+ if (!msg.key.fromMe && msg.message?.conversation === '!ping') {
1772
+ await sock.sendMessage(msg.key.remoteJid, { text: '🏓 Pong via Plugin!' })
1773
+ }
1774
+ }
1775
+ })
1776
+ }
1777
+ }
1778
+
1779
+ // Instalação do plugin no socket
1780
+ sock.use(meuPluginBot, { prefix: '!' })
1781
+
1782
+ // Listar plugins ativos
1783
+ console.log('Plugins ativos:', sock.listPlugins())
1784
+ ```
1785
+
1786
+ ### Middlewares de Interceptação de Mensagens
1787
+
1788
+ Intercepte ou cancele envios e recebimentos antes que cheguem à rede:
1789
+
1790
+ ```javascript
1791
+ // Intercepta qualquer mensagem antes do envio (retornar false cancela o envio)
1792
+ sock.registerMiddleware('beforeSendMessage', async ({ jid, content, options }, socket) => {
1793
+ console.log(`Enviando mensagem para ${jid}...`)
1794
+
1795
+ // Bloquear envio se contiver palavras proibidas
1796
+ if (typeof content?.text === 'string' && content.text.includes('palavra_bloqueada')) {
1797
+ console.warn('Mensagem bloqueada por política de segurança.')
1798
+ return false // Cancela o disparo
1799
+ }
1800
+ })
1801
+
1802
+ // Executa após a mensagem ser enviada com sucesso
1803
+ sock.registerMiddleware('afterSendMessage', async ({ jid, content, fullMsg }, socket) => {
1804
+ console.log(`Mensagem ${fullMsg.key.id} entregue ao servidor com sucesso!`)
1805
+ })
1806
+ ```
1807
+
1808
+ ---
1809
+
1810
+ ## ⚡ Alta Performance, Cache e Controle de Memória
1811
+
1812
+ ### Cache Integrado de Metadados de Grupo (TTL LRU)
1813
+
1814
+ 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:
1815
+
1816
+ ```javascript
1817
+ const sock = makeWASocket({
1818
+ enableGroupCache: true // Ativado por padrão com TTL de 5 minutos
1819
+ })
1820
+ ```
1821
+
1822
+ ### Proteção de Memória na Store (`makeInMemoryStore`)
1823
+
1824
+ Evite vazamento de memória em bots de alta demanda com limpeza automática e limite configurável de mensagens por chat:
1825
+
1826
+ ```javascript
1827
+ const store = makeInMemoryStore({
1828
+ maxMessagesPerChat: 200 // Limita o histórico a 200 mensagens por chat em RAM (padrão: 500)
1829
+ })
1830
+
1831
+ // Limpeza manual sob demanda
1832
+ store.pruneMessages(groupJid, 50) // Mantém apenas as últimas 50 mensagens do chat especificado
1833
+ store.pruneMessages(undefined, 100) // Trunca todos os chats para no máximo 100 mensagens
1834
+
1835
+ // Obter contagem de mensagens armazenadas
1836
+ const qtdTotal = store.getMessageCount()
1837
+ const qtdChat = store.getMessageCount(groupJid)
1838
+
1839
+ // Limpar mensagens de um chat ou resetar toda a memória
1840
+ store.clear(groupJid)
1841
+ ```
1842
+
1843
+ ---
1844
+
1845
+ ## 🔷 Suporte Completo a TypeScript
1846
+
1847
+ 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:
1848
+
1849
+ ```typescript
1850
+ import makeWASocket, { WASocket, AnyMessageContent, DisconnectReason, GroupMetadata } from '@areumtecnologia/wasockets'
1851
+
1852
+ const sock: WASocket = makeWASocket({
1853
+ printQRInTerminal: true
1854
+ })
1855
+ ```
1856
+
1857
+ ---
1858
+
1859
+ ## 🔒 Configurações de Privacidade
1860
+
1861
+ ```javascript
1862
+ // Bloquear ou desbloquear um usuário
1863
+ await sock.updateBlockStatus('5511999999999@s.whatsapp.net', 'block') // ou 'unblock'
1864
+
1865
+ // Obter lista de usuários bloqueados
1866
+ const listaBloqueados = await sock.fetchBlocklist()
1867
+
1868
+ // Atualizar privacidade do "Visto por Último"
1869
+ // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
1870
+ await sock.updateLastSeenPrivacy('contacts')
1871
+
1872
+ // Atualizar privacidade do "Visto Online"
1873
+ // Valores aceitos: 'all' | 'match_last_seen'
1874
+ await sock.updateOnlinePrivacy('match_last_seen')
1875
+
1876
+ // Atualizar privacidade das confirmações de leitura (ticks azuis)
1877
+ // Valores aceitos: 'all' | 'none'
1878
+ await sock.updateReadReceiptsPrivacy('none')
1879
+
1880
+ // Atualizar privacidade da Foto de Perfil
1881
+ // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
1882
+ await sock.updateProfilePicturePrivacy('contacts')
1883
+
1884
+ // Atualizar privacidade do Recado/Status (About)
1885
+ // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
1886
+ await sock.updateStatusPrivacy('contacts')
1887
+
1888
+ // Atualizar quem pode adicionar você a grupos
1889
+ // Valores aceitos: 'all' | 'contacts' | 'contact_blacklist'
1890
+ await sock.updateGroupsAddPrivacy('contacts')
1891
+
1892
+ // Consultar todas as configurações de privacidade ativas da conta
1893
+ const privacySettings = await sock.fetchPrivacySettings()
1894
+ console.log('Configurações de privacidade atuais:', privacySettings)
1895
+ ```
1896
+
1897
+ ---
1898
+
1899
+ ## 🛡️ Logs e Protocolo
1900
+
1901
+ 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:
1902
+
1903
+ ```javascript
1904
+ const pino = require('pino')
1905
+
1906
+ const sock = makeWASocket({
1907
+ logger: pino({ level: 'debug' })
1908
+ })
1909
+ ```
1910
+
1911
+ ### Como o WhatsApp se comunica (BinaryNodes)
1912
+
1913
+ As mensagens são trocadas em formato binário encapsuladas em estruturas denominadas `BinaryNode`. Cada nó possui três atributos:
1914
+ - **`tag`**: Nome da ação (ex: `message`, `ib`, `presence`, `iq`)
1915
+ - **`attrs`**: Objeto contendo propriedades em string/chave-valor (ID, timestamp, remetente, etc.)
1916
+ - **`content`**: O corpo de dados do nó (geralmente outro array de nós ou um buffer criptografado)
1917
+
1918
+ Você pode interagir diretamente com o tráfego do Websocket do WhatsApp registrando callbacks específicos:
1919
+
1920
+ ```javascript
1921
+ // Monitora todos os pacotes recebidos que possuem a tag 'edge_routing'
1922
+ sock.ws.on('CB:edge_routing', (node) => {
1923
+ console.log('Recebido nó de roteamento:', node)
1924
+ })
1925
+
1926
+ // Monitora pacotes 'message' específicos
1927
+ sock.ws.on('CB:message', (node) => {
1928
+ console.log('Mensagem de protocolo bruta:', node)
1929
+ })
1930
+ ```