@areumtecnologia/wasockets 1.1.5 → 2.0.0-alpha.1
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.
- package/README.md +867 -27
- package/WAProto/index.d.ts +17 -0
- package/lib/Defaults/connection.js +34 -2
- package/lib/Defaults/index.d.ts +6 -0
- package/lib/Plugins/index.d.ts +33 -0
- package/lib/Plugins/index.js +125 -0
- package/lib/Socket/business.js +33 -0
- package/lib/Socket/chats.js +173 -1
- package/lib/Socket/community.js +126 -69
- package/lib/Socket/groups.js +103 -26
- package/lib/Socket/index.js +27 -3
- package/lib/Socket/messages-recv.js +42 -0
- package/lib/Socket/messages-send.js +174 -2
- package/lib/Socket/newsletter.js +125 -3
- package/lib/Store/index.d.ts +4 -0
- package/lib/Store/make-in-memory-store.js +294 -25
- package/lib/Types/index.d.ts +199 -0
- package/lib/Utils/chat-utils.js +51 -0
- package/lib/Utils/index.d.ts +33 -0
- package/lib/Utils/index.js +2 -1
- package/lib/Utils/messages.js +48 -3
- package/lib/Utils/reconnect.js +136 -0
- package/lib/Utils/validate-connection.js +5 -5
- package/lib/WABinary/index.d.ts +17 -0
- package/lib/index.d.ts +274 -0
- package/lib/index.js +1 -0
- package/package.json +19 -5
package/README.md
CHANGED
|
@@ -30,6 +30,16 @@ O **WaSockets** foi criado para resolver problemas crônicos de estabilidade e a
|
|
|
30
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
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
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. |
|
|
33
43
|
|
|
34
44
|
---
|
|
35
45
|
|
|
@@ -43,19 +53,45 @@ O **WaSockets** foi criado para resolver problemas crônicos de estabilidade e a
|
|
|
43
53
|
- [Salvando e Restaurando Sessões](#-salvando-e-restaurando-sessões)
|
|
44
54
|
- [Configurações Importantes do Socket](#-configurações-importantes-do-socket)
|
|
45
55
|
- [Exemplo Prático Inicial (Bootstrap)](#-exemplo-prático-inicial-bootstrap)
|
|
46
|
-
- [Tratamento de Eventos](#-tratamento-de-eventos)
|
|
56
|
+
- [Tratamento de Eventos e Mídia](#-tratamento-de-eventos-e-mídia)
|
|
57
|
+
- [Download de Mídias Recebidas](#download-de-mídias-recebidas)
|
|
47
58
|
- [Decifrar Votos de Enquetes](#decifrar-votos-de-enquetes)
|
|
48
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)
|
|
49
63
|
- [Enviando Mensagens](#-enviando-mensagens)
|
|
50
|
-
- [Mensagens de Texto e
|
|
64
|
+
- [Mensagens de Texto, Menções e Links](#mensagens-de-texto-e-menções)
|
|
51
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)
|
|
52
73
|
- [Botões Interativos](#botões-interativos)
|
|
53
74
|
- [Botão de Pagamento PIX](#botão-de-pagamento-pix)
|
|
54
75
|
- [Fluxos de Checkout (PAY)](#fluxos-de-checkout-pay)
|
|
55
|
-
- [
|
|
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)
|
|
56
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)
|
|
57
89
|
- [Gerenciamento de Grupos](#-gerenciamento-de-grupos)
|
|
58
|
-
- [Newsletters (Canais)](#-newsletters-
|
|
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)
|
|
59
95
|
- [Configurações de Privacidade](#-configurações-de-privacidade)
|
|
60
96
|
- [Logs e Protocolo](#-logs-e-protocolo)
|
|
61
97
|
|
|
@@ -188,6 +224,24 @@ const sock = makeWASocket({
|
|
|
188
224
|
})
|
|
189
225
|
```
|
|
190
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
|
+
|
|
191
245
|
---
|
|
192
246
|
|
|
193
247
|
## 🚀 Exemplo Prático Inicial (Bootstrap)
|
|
@@ -195,34 +249,36 @@ const sock = makeWASocket({
|
|
|
195
249
|
Aqui está um arquivo funcional completo em JavaScript (CommonJS) para iniciar a sua integração:
|
|
196
250
|
|
|
197
251
|
```javascript
|
|
198
|
-
const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require('@areumtecnologia/wasockets')
|
|
252
|
+
const { default: makeWASocket, DisconnectReason, useMultiFileAuthState, makeReconnectManager, shouldReconnect } = require('@areumtecnologia/wasockets')
|
|
199
253
|
const { Boom } = require('@hapi/boom')
|
|
200
254
|
|
|
201
255
|
async function connectToWhatsApp() {
|
|
202
256
|
// 1. Inicializa o estado de autenticação baseado em arquivos
|
|
203
257
|
const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
|
|
204
258
|
|
|
205
|
-
// 2. Cria o Socket de Conexão
|
|
259
|
+
// 2. Cria o Socket de Conexão com fila de mensagens inteligente ativada por padrão
|
|
206
260
|
const sock = makeWASocket({
|
|
207
261
|
auth: state,
|
|
208
|
-
printQRInTerminal: true
|
|
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
|
+
}
|
|
209
272
|
})
|
|
210
273
|
|
|
211
274
|
// 3. Monitora o status da conexão
|
|
212
|
-
sock.ev.on('connection.update', (update) => {
|
|
275
|
+
sock.ev.on('connection.update', async (update) => {
|
|
213
276
|
const { connection, lastDisconnect } = update
|
|
214
277
|
|
|
215
278
|
if (connection === 'close') {
|
|
216
|
-
|
|
217
|
-
? lastDisconnect.error.output.statusCode !== DisconnectReason.loggedOut
|
|
218
|
-
: true
|
|
219
|
-
|
|
220
|
-
console.log('Conexão fechada devido a:', lastDisconnect.error, '. Reconectando:', shouldReconnect)
|
|
221
|
-
|
|
222
|
-
if (shouldReconnect) {
|
|
223
|
-
connectToWhatsApp() // Reconexão automática se não tiver feito logout
|
|
224
|
-
}
|
|
279
|
+
await reconnectManager.handleDisconnect(lastDisconnect?.error)
|
|
225
280
|
} else if (connection === 'open') {
|
|
281
|
+
reconnectManager.reset()
|
|
226
282
|
console.log('Conexão com o WhatsApp estabelecida com sucesso!')
|
|
227
283
|
}
|
|
228
284
|
})
|
|
@@ -251,14 +307,48 @@ connectToWhatsApp()
|
|
|
251
307
|
|
|
252
308
|
---
|
|
253
309
|
|
|
254
|
-
## 📡 Tratamento de Eventos
|
|
310
|
+
## 📡 Tratamento de Eventos e Mídia
|
|
255
311
|
|
|
256
312
|
O **WaSockets** utiliza um sistema de eventos tipado baseado no `EventEmitter`.
|
|
257
313
|
|
|
258
314
|
```javascript
|
|
259
315
|
sock.ev.on('messages.upsert', ({ messages, type }) => {
|
|
260
316
|
// type pode ser 'notify' (nova notificação) ou 'append' (carregamento histórico)
|
|
261
|
-
console.log('Novas mensagens:', messages)
|
|
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
|
+
}
|
|
262
352
|
})
|
|
263
353
|
```
|
|
264
354
|
|
|
@@ -314,6 +404,53 @@ sock.ev.on('messages.update', async (updates) => {
|
|
|
314
404
|
|
|
315
405
|
---
|
|
316
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
|
+
|
|
317
454
|
## ✉️ Enviando Mensagens
|
|
318
455
|
|
|
319
456
|
### Mensagens de Texto e Menções
|
|
@@ -382,6 +519,145 @@ await sock.sendMessage(jid, {
|
|
|
382
519
|
|
|
383
520
|
---
|
|
384
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
|
+
|
|
385
661
|
### Botões Interativos
|
|
386
662
|
|
|
387
663
|
Os botões nativos do WhatsApp são suportados através da propriedade `interactiveButtons`.
|
|
@@ -508,6 +784,76 @@ await sock.sendStatusMentions(
|
|
|
508
784
|
},
|
|
509
785
|
contatosParaMencionar
|
|
510
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
|
+
})
|
|
511
857
|
```
|
|
512
858
|
|
|
513
859
|
---
|
|
@@ -537,10 +883,200 @@ await sock.chatModify({ mute: null }, jid)
|
|
|
537
883
|
// Marcar chat como Não Lido
|
|
538
884
|
await sock.chatModify({ markRead: false, lastMessages: [msg] }, jid)
|
|
539
885
|
|
|
540
|
-
// Fixar chat na lista
|
|
886
|
+
// Fixar chat na lista de conversas
|
|
541
887
|
await sock.chatModify({ pin: true }, jid)
|
|
542
888
|
```
|
|
543
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
|
+
|
|
544
1080
|
---
|
|
545
1081
|
|
|
546
1082
|
## 🏷️ Etiquetas de Negócio (Labels - WhatsApp Business)
|
|
@@ -581,6 +1117,23 @@ await sock.addMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
|
|
|
581
1117
|
await sock.removeMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
|
|
582
1118
|
```
|
|
583
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
|
+
|
|
584
1137
|
---
|
|
585
1138
|
|
|
586
1139
|
## 👥 Gerenciamento de Grupos
|
|
@@ -596,6 +1149,10 @@ console.log('Grupo criado com ID:', grupo.id)
|
|
|
596
1149
|
// Parâmetros de ação: 'add' | 'remove' | 'promote' | 'demote'
|
|
597
1150
|
await sock.groupParticipantsUpdate(grupo.id, ['5511888888888@s.whatsapp.net'], 'add')
|
|
598
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
|
+
|
|
599
1156
|
// Obter o código/link de convite do grupo
|
|
600
1157
|
const codigoConvite = await sock.groupInviteCode(grupo.id)
|
|
601
1158
|
console.log(`Link: https://chat.whatsapp.com/${codigoConvite}`)
|
|
@@ -606,6 +1163,15 @@ const novoCodigo = await sock.groupRevokeInvite(grupo.id)
|
|
|
606
1163
|
// Entrar em um grupo usando um código de convite (apenas o código, sem o domínio completo)
|
|
607
1164
|
const resposta = await sock.groupAcceptInvite('ABcdEFghIJklMnOpQrStUv')
|
|
608
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
|
+
|
|
609
1175
|
// Obter a lista de pessoas aguardando aprovação para entrar no grupo
|
|
610
1176
|
const solicitacoes = await sock.groupRequestParticipantsList(grupo.id)
|
|
611
1177
|
console.log(solicitacoes)
|
|
@@ -644,30 +1210,63 @@ sock.ev.on('group.member-tag.update', (update) => {
|
|
|
644
1210
|
|
|
645
1211
|
---
|
|
646
1212
|
|
|
647
|
-
## 📢 Newsletters (
|
|
1213
|
+
## 📢 Newsletters / Canais v2 (Pilar 3)
|
|
648
1214
|
|
|
649
|
-
O **WaSockets** traz suporte avançado para a criação e
|
|
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):
|
|
650
1216
|
|
|
651
1217
|
```javascript
|
|
652
|
-
// Criar uma Newsletter (Canal)
|
|
1218
|
+
// 1. Criar uma Newsletter (Canal)
|
|
653
1219
|
const canal = await sock.newsletterCreate('Notícias Tecnológicas Áreum', 'Canal oficial de novidades')
|
|
654
1220
|
console.log('Canal criado com ID:', canal.id)
|
|
655
1221
|
|
|
656
|
-
// Obter metadados de um Canal público pelo ID
|
|
1222
|
+
// 2. Obter metadados de um Canal público pelo ID ou Invite Code
|
|
657
1223
|
const metadadosCanal = await sock.newsletterMetadata('JID', canal.id)
|
|
658
1224
|
console.log('Nome do Canal:', metadadosCanal.name)
|
|
659
1225
|
|
|
660
|
-
// Listar
|
|
1226
|
+
// 3. Listar todos os Canais inscritos
|
|
661
1227
|
const canaisInscritos = await sock.newsletterSubscribed()
|
|
662
1228
|
console.log('Canais que eu sigo:', canaisInscritos)
|
|
663
1229
|
|
|
664
|
-
//
|
|
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
|
|
665
1249
|
await sock.newsletterFollow(canal.id)
|
|
666
1250
|
await sock.newsletterUnfollow(canal.id)
|
|
667
1251
|
|
|
668
|
-
// Silenciar / Ativar notificações
|
|
1252
|
+
// 9. Silenciar / Ativar notificações
|
|
669
1253
|
await sock.newsletterMute(canal.id)
|
|
670
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)
|
|
671
1270
|
```
|
|
672
1271
|
|
|
673
1272
|
---
|
|
@@ -746,12 +1345,233 @@ await sock.productUpdate(novoProduto.id, {
|
|
|
746
1345
|
price: 5990
|
|
747
1346
|
})
|
|
748
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
|
+
|
|
749
1352
|
// Remover produtos do catálogo (aceita um array de IDs de produtos)
|
|
750
1353
|
await sock.productDelete([novoProduto.id])
|
|
751
1354
|
```
|
|
752
1355
|
|
|
753
1356
|
---
|
|
754
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
|
+
|
|
755
1575
|
## 🔒 Configurações de Privacidade
|
|
756
1576
|
|
|
757
1577
|
```javascript
|
|
@@ -772,6 +1592,26 @@ await sock.updateOnlinePrivacy('match_last_seen')
|
|
|
772
1592
|
// Atualizar privacidade das confirmações de leitura (ticks azuis)
|
|
773
1593
|
// Valores aceitos: 'all' | 'none'
|
|
774
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)
|
|
775
1615
|
```
|
|
776
1616
|
|
|
777
1617
|
---
|