@systemzero/baileys 1.0.5 → 1.0.6
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 +506 -601
- package/lib/Socket/chats.js +12 -1
- package/lib/Socket/groups.js +13 -4
- package/lib/Socket/messages-recv.js +36 -2
- package/lib/Socket/messages-recv.js.bak +1273 -0
- package/lib/Socket/messages-send.js +1 -0
- package/lib/Utils/bad-mac-handler.js +158 -0
- package/lib/Utils/get-best-version.js +41 -0
- package/lib/Utils/get-name.d.ts +1 -0
- package/lib/Utils/get-name.js +54 -0
- package/lib/Utils/group-status-detection.js +113 -0
- package/lib/Utils/index.js +7 -0
- package/lib/Utils/logger.js +4 -1
- package/lib/Utils/messages-media.js +38 -0
- package/lib/Utils/messages.js +113 -7
- package/lib/Utils/payment-detection.js +212 -0
- package/lib/Utils/payment-guard.d.ts +15 -0
- package/lib/Utils/payment-guard.js +142 -0
- package/lib/Utils/resolve-lid-phone.js +30 -0
- package/lib/WABinary/jid-utils.js +245 -1
- package/package.json +3 -2
- package/lib/Defaults/index.d.ts.map +0 -1
- package/lib/Defaults/index.js.map +0 -1
- package/lib/Signal/Group/ciphertext-message.d.ts.map +0 -1
- package/lib/Signal/Group/ciphertext-message.js.map +0 -1
- package/lib/Signal/Group/group-session-builder.d.ts.map +0 -1
- package/lib/Signal/Group/group-session-builder.js.map +0 -1
- package/lib/Signal/Group/group_cipher.d.ts.map +0 -1
- package/lib/Signal/Group/group_cipher.js.map +0 -1
- package/lib/Signal/Group/index.d.ts.map +0 -1
- package/lib/Signal/Group/index.js.map +0 -1
- package/lib/Signal/Group/keyhelper.d.ts.map +0 -1
- package/lib/Signal/Group/keyhelper.js.map +0 -1
- package/lib/Signal/Group/sender-chain-key.d.ts.map +0 -1
- package/lib/Signal/Group/sender-chain-key.js.map +0 -1
- package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-distribution-message.js.map +0 -1
- package/lib/Signal/Group/sender-key-message.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-message.js.map +0 -1
- package/lib/Signal/Group/sender-key-name.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-name.js.map +0 -1
- package/lib/Signal/Group/sender-key-record.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-record.js.map +0 -1
- package/lib/Signal/Group/sender-key-state.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-state.js.map +0 -1
- package/lib/Signal/Group/sender-message-key.d.ts.map +0 -1
- package/lib/Signal/Group/sender-message-key.js.map +0 -1
- package/lib/Signal/libsignal.d.ts.map +0 -1
- package/lib/Signal/libsignal.js.map +0 -1
- package/lib/Signal/lid-mapping.d.ts.map +0 -1
- package/lib/Signal/lid-mapping.js.map +0 -1
- package/lib/Socket/Client/index.d.ts.map +0 -1
- package/lib/Socket/Client/index.js.map +0 -1
- package/lib/Socket/Client/types.d.ts.map +0 -1
- package/lib/Socket/Client/types.js.map +0 -1
- package/lib/Socket/Client/websocket.d.ts.map +0 -1
- package/lib/Socket/Client/websocket.js.map +0 -1
- package/lib/Socket/business.d.ts.map +0 -1
- package/lib/Socket/business.js.map +0 -1
- package/lib/Socket/chats.d.ts.map +0 -1
- package/lib/Socket/chats.js.map +0 -1
- package/lib/Socket/communities.d.ts.map +0 -1
- package/lib/Socket/communities.js.map +0 -1
- package/lib/Socket/groups.d.ts.map +0 -1
- package/lib/Socket/groups.js.map +0 -1
- package/lib/Socket/index.d.ts.map +0 -1
- package/lib/Socket/index.js.map +0 -1
- package/lib/Socket/messages-recv.d.ts.map +0 -1
- package/lib/Socket/messages-recv.js.map +0 -1
- package/lib/Socket/messages-send.d.ts.map +0 -1
- package/lib/Socket/messages-send.js.map +0 -1
- package/lib/Socket/mex.d.ts.map +0 -1
- package/lib/Socket/mex.js.map +0 -1
- package/lib/Socket/newsletter.d.ts.map +0 -1
- package/lib/Socket/newsletter.js.map +0 -1
- package/lib/Socket/socket.d.ts.map +0 -1
- package/lib/Socket/socket.js.map +0 -1
- package/lib/Types/Auth.d.ts.map +0 -1
- package/lib/Types/Auth.js.map +0 -1
- package/lib/Types/Bussines.d.ts.map +0 -1
- package/lib/Types/Bussines.js.map +0 -1
- package/lib/Types/Call.d.ts.map +0 -1
- package/lib/Types/Call.js.map +0 -1
- package/lib/Types/Chat.d.ts.map +0 -1
- package/lib/Types/Chat.js.map +0 -1
- package/lib/Types/Contact.d.ts.map +0 -1
- package/lib/Types/Contact.js.map +0 -1
- package/lib/Types/Events.d.ts.map +0 -1
- package/lib/Types/Events.js.map +0 -1
- package/lib/Types/GroupMetadata.d.ts.map +0 -1
- package/lib/Types/GroupMetadata.js.map +0 -1
- package/lib/Types/Label.d.ts.map +0 -1
- package/lib/Types/Label.js.map +0 -1
- package/lib/Types/LabelAssociation.d.ts.map +0 -1
- package/lib/Types/LabelAssociation.js.map +0 -1
- package/lib/Types/Message.d.ts.map +0 -1
- package/lib/Types/Message.js.map +0 -1
- package/lib/Types/Newsletter.d.ts.map +0 -1
- package/lib/Types/Newsletter.js.map +0 -1
- package/lib/Types/Product.d.ts.map +0 -1
- package/lib/Types/Product.js.map +0 -1
- package/lib/Types/Signal.d.ts.map +0 -1
- package/lib/Types/Signal.js.map +0 -1
- package/lib/Types/Socket.d.ts.map +0 -1
- package/lib/Types/Socket.js.map +0 -1
- package/lib/Types/State.d.ts.map +0 -1
- package/lib/Types/State.js.map +0 -1
- package/lib/Types/USync.d.ts.map +0 -1
- package/lib/Types/USync.js.map +0 -1
- package/lib/Types/index.d.ts.map +0 -1
- package/lib/Types/index.js.map +0 -1
- package/lib/Utils/auth-utils.d.ts.map +0 -1
- package/lib/Utils/auth-utils.js.map +0 -1
- package/lib/Utils/browser-utils.d.ts.map +0 -1
- package/lib/Utils/browser-utils.js.map +0 -1
- package/lib/Utils/business.d.ts.map +0 -1
- package/lib/Utils/business.js.map +0 -1
- package/lib/Utils/chat-utils.d.ts.map +0 -1
- package/lib/Utils/chat-utils.js.map +0 -1
- package/lib/Utils/crypto.d.ts.map +0 -1
- package/lib/Utils/crypto.js.map +0 -1
- package/lib/Utils/decode-wa-message.d.ts.map +0 -1
- package/lib/Utils/decode-wa-message.js.map +0 -1
- package/lib/Utils/event-buffer.d.ts.map +0 -1
- package/lib/Utils/event-buffer.js.map +0 -1
- package/lib/Utils/generics.d.ts.map +0 -1
- package/lib/Utils/generics.js.map +0 -1
- package/lib/Utils/history.d.ts.map +0 -1
- package/lib/Utils/history.js.map +0 -1
- package/lib/Utils/index.d.ts.map +0 -1
- package/lib/Utils/index.js.map +0 -1
- package/lib/Utils/link-preview.d.ts.map +0 -1
- package/lib/Utils/link-preview.js.map +0 -1
- package/lib/Utils/logger.d.ts.map +0 -1
- package/lib/Utils/logger.js.map +0 -1
- package/lib/Utils/lt-hash.d.ts.map +0 -1
- package/lib/Utils/lt-hash.js.map +0 -1
- package/lib/Utils/make-mutex.d.ts.map +0 -1
- package/lib/Utils/make-mutex.js.map +0 -1
- package/lib/Utils/message-retry-manager.d.ts.map +0 -1
- package/lib/Utils/message-retry-manager.js.map +0 -1
- package/lib/Utils/messages-media.d.ts.map +0 -1
- package/lib/Utils/messages-media.js.map +0 -1
- package/lib/Utils/messages.d.ts.map +0 -1
- package/lib/Utils/messages.js.map +0 -1
- package/lib/Utils/noise-handler.d.ts.map +0 -1
- package/lib/Utils/noise-handler.js.map +0 -1
- package/lib/Utils/pre-key-manager.d.ts.map +0 -1
- package/lib/Utils/pre-key-manager.js.map +0 -1
- package/lib/Utils/process-message.d.ts.map +0 -1
- package/lib/Utils/process-message.js.map +0 -1
- package/lib/Utils/signal.d.ts.map +0 -1
- package/lib/Utils/signal.js.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.js.map +0 -1
- package/lib/Utils/validate-connection.d.ts.map +0 -1
- package/lib/Utils/validate-connection.js.map +0 -1
- package/lib/WABinary/constants.d.ts.map +0 -1
- package/lib/WABinary/constants.js.map +0 -1
- package/lib/WABinary/decode.d.ts.map +0 -1
- package/lib/WABinary/decode.js.map +0 -1
- package/lib/WABinary/encode.d.ts.map +0 -1
- package/lib/WABinary/encode.js.map +0 -1
- package/lib/WABinary/generic-utils.d.ts.map +0 -1
- package/lib/WABinary/generic-utils.js.map +0 -1
- package/lib/WABinary/index.d.ts.map +0 -1
- package/lib/WABinary/index.js.map +0 -1
- package/lib/WABinary/jid-utils.d.ts.map +0 -1
- package/lib/WABinary/jid-utils.js.map +0 -1
- package/lib/WABinary/types.d.ts.map +0 -1
- package/lib/WABinary/types.js.map +0 -1
- package/lib/WAM/BinaryInfo.d.ts.map +0 -1
- package/lib/WAM/BinaryInfo.js.map +0 -1
- package/lib/WAM/constants.d.ts.map +0 -1
- package/lib/WAM/constants.js.map +0 -1
- package/lib/WAM/encode.d.ts.map +0 -1
- package/lib/WAM/encode.js.map +0 -1
- package/lib/WAM/index.d.ts.map +0 -1
- package/lib/WAM/index.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/index.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/index.js.map +0 -1
- package/lib/WAUSync/USyncQuery.d.ts.map +0 -1
- package/lib/WAUSync/USyncQuery.js.map +0 -1
- package/lib/WAUSync/USyncUser.d.ts.map +0 -1
- package/lib/WAUSync/USyncUser.js.map +0 -1
- package/lib/WAUSync/index.d.ts.map +0 -1
- package/lib/WAUSync/index.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
# @systemzero/baileys
|
|
6
6
|
|
|
7
|
-
**v1.0.
|
|
7
|
+
**v1.0.6** · Fork avançado do Baileys com suporte nativo a todos os tipos de mensagens do WhatsApp
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@systemzero/baileys)
|
|
10
10
|
[](LICENSE)
|
|
11
11
|
[](https://t.me/blackhzx)
|
|
12
|
+
[](https://nodejs.org)
|
|
12
13
|
|
|
13
14
|
</div>
|
|
14
15
|
|
|
@@ -20,13 +21,14 @@
|
|
|
20
21
|
npm i @systemzero/baileys
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
Dependências opcionais
|
|
24
|
+
Dependências opcionais:
|
|
24
25
|
```bash
|
|
25
|
-
npm i sharp
|
|
26
|
-
#
|
|
27
|
-
npm i @napi-rs/image
|
|
26
|
+
npm i sharp # conversão de imagem para sticker pack
|
|
27
|
+
npm i @napi-rs/image # alternativa ao sharp
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
Requer `ffmpeg` instalado no sistema (com suporte a `libopus`) para conversão automática de áudio PTT e para o sistema anti-fraude de pagamento processar mídia. Confirme com `ffmpeg -encoders | grep opus`.
|
|
31
|
+
|
|
30
32
|
---
|
|
31
33
|
|
|
32
34
|
## Índice
|
|
@@ -39,17 +41,27 @@ npm i @napi-rs/image
|
|
|
39
41
|
6. [Canais Newsletter](#6-canais-newsletter)
|
|
40
42
|
7. [Enquetes com decrypt](#7-enquetes-com-decrypt)
|
|
41
43
|
8. [AI Rich](#8-ai-rich)
|
|
42
|
-
9. [
|
|
43
|
-
10. [
|
|
44
|
-
11. [
|
|
45
|
-
12. [
|
|
44
|
+
9. [LID / JID — Sistema avançado](#9-lid--jid--sistema-avançado)
|
|
45
|
+
10. [Username (@usuario)](#10-username-usuario)
|
|
46
|
+
11. [MessageBuilder — Button, ButtonV2, Carousel, AIRich](#11-messagebuilder--button-buttonv2-carousel-airich)
|
|
47
|
+
12. [Botões estendidos (v1.0.6)](#12-botões-estendidos-v106)
|
|
48
|
+
13. [Grupos](#13-grupos)
|
|
49
|
+
14. [Perfil e privacidade](#14-perfil-e-privacidade)
|
|
50
|
+
15. [Eventos do socket](#15-eventos-do-socket)
|
|
51
|
+
16. [Utilitários](#16-utilitários)
|
|
52
|
+
17. [Fixar / Desfixar mensagens](#17-fixar--desfixar-mensagens)
|
|
53
|
+
18. [Resolução de nomes (getName)](#18-resolução-de-nomes-getname)
|
|
54
|
+
19. [PTT real com qualquer formato de entrada](#19-ptt-real-com-qualquer-formato-de-entrada)
|
|
55
|
+
20. [Guard de pagamento stealth (anti-fraude)](#20-guard-de-pagamento-stealth-anti-fraude)
|
|
56
|
+
21. [Bad MAC Handler — sessões Signal](#21-bad-mac-handler--sessões-signal)
|
|
57
|
+
22. [Resolução LID → telefone via grupo](#22-resolução-lid--telefone-via-grupo)
|
|
58
|
+
23. [Versão do WhatsApp sempre atualizada](#23-versão-do-whatsapp-sempre-atualizada)
|
|
59
|
+
24. [WhatsApp Flows — Formulários interativos](#24-whatsapp-flows--formulários-interativos)
|
|
46
60
|
|
|
47
61
|
---
|
|
48
62
|
|
|
49
63
|
## 1. Conexão
|
|
50
64
|
|
|
51
|
-
### Setup básico
|
|
52
|
-
|
|
53
65
|
```js
|
|
54
66
|
const {
|
|
55
67
|
default: makeWASocket,
|
|
@@ -84,13 +96,15 @@ sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
|
84
96
|
})
|
|
85
97
|
```
|
|
86
98
|
|
|
99
|
+
> Veja a seção [23](#23-versão-do-whatsapp-sempre-atualizada) para um jeito mais robusto de buscar a versão, que não falha silenciosamente.
|
|
100
|
+
|
|
87
101
|
### Pairing Code
|
|
88
102
|
|
|
89
103
|
```js
|
|
90
|
-
//
|
|
104
|
+
// Automático
|
|
91
105
|
const code = await sock.requestPairingCode('5511999999999')
|
|
92
106
|
|
|
93
|
-
//
|
|
107
|
+
// Personalizado — exatamente 8 caracteres
|
|
94
108
|
const code = await sock.requestPairingCode('5511999999999', 'MYBOT001')
|
|
95
109
|
```
|
|
96
110
|
|
|
@@ -110,7 +124,6 @@ const store = {
|
|
|
110
124
|
},
|
|
111
125
|
loadMessage: async (jid, id) => store.messages[jid]?.[id] || null
|
|
112
126
|
}
|
|
113
|
-
|
|
114
127
|
store.bind(sock.ev)
|
|
115
128
|
```
|
|
116
129
|
|
|
@@ -118,111 +131,52 @@ store.bind(sock.ev)
|
|
|
118
131
|
|
|
119
132
|
## 2. Mensagens de mídia
|
|
120
133
|
|
|
121
|
-
Todos os campos de mídia aceitam `Buffer`, `{ url: 'https://...' }` ou `{ stream
|
|
122
|
-
|
|
123
|
-
### Texto
|
|
134
|
+
Todos os campos de mídia aceitam `Buffer`, `{ url: 'https://...' }` ou `{ stream }`.
|
|
124
135
|
|
|
125
136
|
```js
|
|
137
|
+
// Texto
|
|
126
138
|
await sock.sendMessage(jid, { text: 'Olá!' })
|
|
127
139
|
|
|
128
|
-
//
|
|
140
|
+
// Texto com menção
|
|
129
141
|
await sock.sendMessage(jid, {
|
|
130
|
-
text: '@
|
|
142
|
+
text: '@5511...!',
|
|
131
143
|
mentions: ['5511999999999@s.whatsapp.net']
|
|
132
144
|
})
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Imagem
|
|
136
|
-
|
|
137
|
-
```js
|
|
138
|
-
await sock.sendMessage(jid, {
|
|
139
|
-
image: { url: 'https://exemplo.com/foto.jpg' },
|
|
140
|
-
caption: 'Legenda'
|
|
141
|
-
})
|
|
142
|
-
```
|
|
143
145
|
|
|
144
|
-
|
|
146
|
+
// Imagem
|
|
147
|
+
await sock.sendMessage(jid, { image: { url: 'https://...' }, caption: 'Legenda' })
|
|
145
148
|
|
|
146
|
-
|
|
147
|
-
await sock.sendMessage(jid, {
|
|
148
|
-
video: { url: 'https://exemplo.com/video.mp4' },
|
|
149
|
-
caption: 'Legenda',
|
|
150
|
-
gifPlayback: false // true envia como GIF silencioso
|
|
151
|
-
})
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### Áudio
|
|
149
|
+
// Vídeo
|
|
150
|
+
await sock.sendMessage(jid, { video: buffer, caption: 'Legenda', gifPlayback: false })
|
|
155
151
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
await sock.sendMessage(jid, {
|
|
159
|
-
audio: buffer,
|
|
160
|
-
mimetype: 'audio/mpeg',
|
|
161
|
-
ptt: false
|
|
162
|
-
})
|
|
152
|
+
// Áudio normal (música)
|
|
153
|
+
await sock.sendMessage(jid, { audio: buffer, mimetype: 'audio/mpeg', ptt: false })
|
|
163
154
|
|
|
164
|
-
// Nota de voz (PTT)
|
|
165
|
-
await sock.sendMessage(jid, {
|
|
166
|
-
audio: buffer,
|
|
167
|
-
mimetype: 'audio/ogg; codecs=opus',
|
|
168
|
-
ptt: true
|
|
169
|
-
})
|
|
170
|
-
```
|
|
155
|
+
// Nota de voz (PTT) — ver seção 19 para conversão automática de qualquer formato
|
|
156
|
+
await sock.sendMessage(jid, { audio: buffer, ptt: true })
|
|
171
157
|
|
|
172
|
-
|
|
158
|
+
// Documento
|
|
159
|
+
await sock.sendMessage(jid, { document: buffer, mimetype: 'application/pdf', fileName: 'doc.pdf' })
|
|
173
160
|
|
|
174
|
-
|
|
175
|
-
await sock.sendMessage(jid, {
|
|
176
|
-
document: buffer,
|
|
177
|
-
mimetype: 'application/pdf',
|
|
178
|
-
fileName: 'relatorio.pdf',
|
|
179
|
-
caption: 'Segue o relatório'
|
|
180
|
-
})
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
### Figurinha
|
|
184
|
-
|
|
185
|
-
```js
|
|
161
|
+
// Figurinha
|
|
186
162
|
await sock.sendMessage(jid, { sticker: buffer })
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Album (múltiplas mídias agrupadas)
|
|
190
|
-
|
|
191
|
-
Mínimo 2 itens.
|
|
192
163
|
|
|
193
|
-
|
|
164
|
+
// Album (mínimo 2 itens)
|
|
194
165
|
await sock.sendMessage(jid, {
|
|
195
|
-
album: [
|
|
196
|
-
{ image: buffer1 },
|
|
197
|
-
{ image: buffer2, caption: 'Segunda foto' },
|
|
198
|
-
{ video: bufferVideo },
|
|
199
|
-
]
|
|
166
|
+
album: [{ image: buffer1 }, { image: buffer2 }, { video: bufferVideo }]
|
|
200
167
|
})
|
|
201
|
-
```
|
|
202
168
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
```js
|
|
169
|
+
// Contato
|
|
206
170
|
await sock.sendMessage(jid, {
|
|
207
171
|
contacts: {
|
|
208
172
|
displayName: 'João',
|
|
209
|
-
contacts: [{
|
|
210
|
-
vcard: `BEGIN:VCARD\nVERSION:3.0\nFN:João Silva\nTEL:+5511999999999\nEND:VCARD`
|
|
211
|
-
}]
|
|
173
|
+
contacts: [{ vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:João\nTEL:+5511999999999\nEND:VCARD' }]
|
|
212
174
|
}
|
|
213
175
|
})
|
|
214
|
-
```
|
|
215
176
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
```js
|
|
177
|
+
// Localização
|
|
219
178
|
await sock.sendMessage(jid, {
|
|
220
|
-
location: {
|
|
221
|
-
degreesLatitude: -23.550520,
|
|
222
|
-
degreesLongitude: -46.633308,
|
|
223
|
-
name: 'São Paulo',
|
|
224
|
-
address: 'SP, Brasil'
|
|
225
|
-
}
|
|
179
|
+
location: { degreesLatitude: -23.55, degreesLongitude: -46.63, name: 'São Paulo' }
|
|
226
180
|
})
|
|
227
181
|
```
|
|
228
182
|
|
|
@@ -230,201 +184,67 @@ await sock.sendMessage(jid, {
|
|
|
230
184
|
|
|
231
185
|
## 3. Mensagens especiais
|
|
232
186
|
|
|
233
|
-
### Reação
|
|
234
|
-
|
|
235
187
|
```js
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
// text: '' remove a reação
|
|
239
|
-
})
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Deletar mensagem
|
|
188
|
+
// Reação
|
|
189
|
+
await sock.sendMessage(jid, { react: { text: '❤️', key: message.key } })
|
|
243
190
|
|
|
244
|
-
|
|
191
|
+
// Deletar
|
|
245
192
|
await sock.sendMessage(jid, { delete: message.key })
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Editar mensagem
|
|
249
193
|
|
|
250
|
-
|
|
251
|
-
await sock.sendMessage(jid, {
|
|
252
|
-
edit: message.key,
|
|
253
|
-
text: 'Texto editado'
|
|
254
|
-
})
|
|
255
|
-
```
|
|
194
|
+
// Editar
|
|
195
|
+
await sock.sendMessage(jid, { edit: message.key, text: 'Texto editado' })
|
|
256
196
|
|
|
257
|
-
|
|
197
|
+
// Fixar — ver seção 17 para a versão completa
|
|
198
|
+
await sock.sendMessage(jid, { pin: message.key, type: 1 })
|
|
258
199
|
|
|
259
|
-
|
|
260
|
-
await sock.sendMessage(jid, {
|
|
261
|
-
pin: {
|
|
262
|
-
type: 1, // 1 = fixar, 2 = desfixar
|
|
263
|
-
time: 86400, // duração em segundos
|
|
264
|
-
messageKey: message.key
|
|
265
|
-
}
|
|
266
|
-
})
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### Encaminhar
|
|
270
|
-
|
|
271
|
-
```js
|
|
272
|
-
const { generateForwardMessageContent, generateWAMessageFromContent } = require('@systemzero/baileys')
|
|
273
|
-
|
|
274
|
-
const content = generateForwardMessageContent(message, false)
|
|
275
|
-
const msg = generateWAMessageFromContent(jid, content, { quoted: m })
|
|
276
|
-
await sock.relayMessage(jid, msg.message, { messageId: msg.key.id })
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### View Once
|
|
280
|
-
|
|
281
|
-
```js
|
|
200
|
+
// View Once
|
|
282
201
|
await sock.sendMessage(jid, { image: buffer, viewOnce: true })
|
|
283
|
-
|
|
284
|
-
// V2
|
|
285
202
|
await sock.sendMessage(jid, { image: buffer, viewOnceV2: true })
|
|
286
203
|
|
|
287
|
-
//
|
|
288
|
-
await sock.sendMessage(jid, { image: buffer,
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
### Spoiler
|
|
292
|
-
|
|
293
|
-
```js
|
|
294
|
-
await sock.sendMessage(jid, {
|
|
295
|
-
image: buffer,
|
|
296
|
-
caption: 'Spoiler!',
|
|
297
|
-
spoiler: true
|
|
298
|
-
})
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### Status de grupo
|
|
302
|
-
|
|
303
|
-
```js
|
|
304
|
-
await sock.sendMessage(jid, {
|
|
305
|
-
image: buffer,
|
|
306
|
-
caption: 'Status do grupo',
|
|
307
|
-
groupStatus: true
|
|
308
|
-
})
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
### Mensagem efêmera
|
|
312
|
-
|
|
313
|
-
```js
|
|
314
|
-
await sock.sendMessage(jid, {
|
|
315
|
-
image: buffer,
|
|
316
|
-
ephemeral: true
|
|
317
|
-
})
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
### Lottie (sticker animado especial)
|
|
321
|
-
|
|
322
|
-
```js
|
|
323
|
-
await sock.sendMessage(jid, {
|
|
324
|
-
sticker: buffer,
|
|
325
|
-
isLottie: true
|
|
326
|
-
})
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Keep (salvar mensagem)
|
|
330
|
-
|
|
331
|
-
```js
|
|
332
|
-
await sock.sendMessage(jid, {
|
|
333
|
-
keep: message.key,
|
|
334
|
-
type: 1 // 1 = salvar, 2 = remover
|
|
335
|
-
})
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### Evento
|
|
204
|
+
// Spoiler
|
|
205
|
+
await sock.sendMessage(jid, { image: buffer, caption: '!', spoiler: true })
|
|
339
206
|
|
|
340
|
-
|
|
341
|
-
await sock.sendMessage(jid, {
|
|
342
|
-
event: {
|
|
343
|
-
isCanceled: false,
|
|
344
|
-
name: 'Reunião',
|
|
345
|
-
description: 'Alinhamento',
|
|
346
|
-
location: { name: 'Sala 3', address: 'Rua X, 100' },
|
|
347
|
-
startTime: Math.floor(Date.now() / 1000) + 3600,
|
|
348
|
-
endTime: Math.floor(Date.now() / 1000) + 7200,
|
|
349
|
-
}
|
|
350
|
-
})
|
|
351
|
-
```
|
|
207
|
+
// Status de grupo
|
|
208
|
+
await sock.sendMessage(jid, { image: buffer, groupStatus: true })
|
|
352
209
|
|
|
353
|
-
|
|
210
|
+
// Efêmera
|
|
211
|
+
await sock.sendMessage(jid, { image: buffer, ephemeral: true })
|
|
354
212
|
|
|
355
|
-
|
|
356
|
-
await sock.sendMessage(jid, {
|
|
357
|
-
poll: {
|
|
358
|
-
name: 'Qual seu time?',
|
|
359
|
-
values: ['Flamengo', 'Corinthians', 'Palmeiras'],
|
|
360
|
-
selectableCount: 1 // 0 = múltipla escolha
|
|
361
|
-
}
|
|
362
|
-
})
|
|
363
|
-
```
|
|
213
|
+
// Lottie sticker
|
|
214
|
+
await sock.sendMessage(jid, { sticker: buffer, isLottie: true })
|
|
364
215
|
|
|
365
|
-
|
|
216
|
+
// Mention All
|
|
217
|
+
await sock.sendMessage(jid, { text: '@all', mentionAll: true })
|
|
366
218
|
|
|
367
|
-
|
|
368
|
-
await sock.sendMessage(jid, {
|
|
369
|
-
image: buffer,
|
|
370
|
-
invoiceNote: 'Pagamento pedido #1234'
|
|
371
|
-
})
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
### External Ad Reply
|
|
375
|
-
|
|
376
|
-
```js
|
|
219
|
+
// External Ad Reply
|
|
377
220
|
await sock.sendMessage(jid, {
|
|
378
221
|
text: 'Confira!',
|
|
379
222
|
externalAdReply: {
|
|
380
|
-
title:
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
mediaType: 1,
|
|
384
|
-
sourceUrl: 'https://systemzone.store',
|
|
223
|
+
title: 'Título', body: 'Descrição',
|
|
224
|
+
thumbnail: bufferImg, mediaType: 1,
|
|
225
|
+
sourceUrl: 'https://systemzone.store',
|
|
385
226
|
renderLargerThumbnail: true
|
|
386
227
|
}
|
|
387
228
|
})
|
|
388
|
-
```
|
|
389
229
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
```js
|
|
230
|
+
// Enquete
|
|
393
231
|
await sock.sendMessage(jid, {
|
|
394
|
-
|
|
395
|
-
mentionAll: true
|
|
232
|
+
poll: { name: 'Pergunta?', values: ['A', 'B', 'C'], selectableCount: 1 }
|
|
396
233
|
})
|
|
397
|
-
```
|
|
398
234
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
})
|
|
235
|
+
// Encaminhar
|
|
236
|
+
const { generateForwardMessageContent, generateWAMessageFromContent } = require('@systemzero/baileys')
|
|
237
|
+
const fwd = generateForwardMessageContent(message, false)
|
|
238
|
+
const msg = generateWAMessageFromContent(jid, fwd, { quoted: m })
|
|
239
|
+
await sock.relayMessage(jid, msg.message, { messageId: msg.key.id })
|
|
405
240
|
```
|
|
406
241
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
```js
|
|
410
|
-
await sock.sendMessage(jid, {
|
|
411
|
-
pollResult: {
|
|
412
|
-
name: 'Pergunta?',
|
|
413
|
-
pollType: 0, // 0 = poll, 1 = quiz
|
|
414
|
-
votes: [
|
|
415
|
-
{ name: 'Opção A', voteCount: 12 },
|
|
416
|
-
{ name: 'Opção B', voteCount: 7 },
|
|
417
|
-
]
|
|
418
|
-
}
|
|
419
|
-
})
|
|
420
|
-
```
|
|
242
|
+
> ⚠️ **Removido desta versão do README:** preview de link customizado (`linkPreview` manual) e áudio embutido em rodapé de card interativo (`audioFooter`). Os dois existem no proto do WhatsApp, mas em testes reais (Android e iOS) **não renderizaram corretamente** — o `audioFooter` não mostrou o player de áudio, e o `linkPreview` manual caiu num formato de card genérico em vez do esperado. Não são recursos confiáveis hoje.
|
|
421
243
|
|
|
422
244
|
---
|
|
423
245
|
|
|
424
246
|
## 4. Botões e interativos
|
|
425
247
|
|
|
426
|
-
### Estrutura base
|
|
427
|
-
|
|
428
248
|
```js
|
|
429
249
|
const { generateWAMessageFromContent, proto } = require('@systemzero/baileys')
|
|
430
250
|
|
|
@@ -433,11 +253,9 @@ const msg = generateWAMessageFromContent(jid, {
|
|
|
433
253
|
message: {
|
|
434
254
|
interactiveMessage: proto.Message.InteractiveMessage.create({
|
|
435
255
|
header: { title: 'Título', hasMediaAttachment: false },
|
|
436
|
-
body: { text: 'Texto
|
|
256
|
+
body: { text: 'Texto' },
|
|
437
257
|
footer: { text: 'Rodapé' },
|
|
438
|
-
nativeFlowMessage: {
|
|
439
|
-
buttons: [ /* tipos abaixo */ ]
|
|
440
|
-
}
|
|
258
|
+
nativeFlowMessage: { buttons: [ /* tipos abaixo */ ] }
|
|
441
259
|
})
|
|
442
260
|
}
|
|
443
261
|
}
|
|
@@ -446,178 +264,70 @@ const msg = generateWAMessageFromContent(jid, {
|
|
|
446
264
|
await sock.relayMessage(jid, msg.message, { messageId: msg.key.id })
|
|
447
265
|
```
|
|
448
266
|
|
|
449
|
-
### Tipos de botão
|
|
267
|
+
### Tipos de botão (testados e funcionais)
|
|
450
268
|
|
|
451
269
|
```js
|
|
452
270
|
// Resposta rápida
|
|
453
|
-
{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: '
|
|
271
|
+
{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'OK', id: 'ok' }) }
|
|
454
272
|
|
|
455
|
-
// Link
|
|
273
|
+
// Link
|
|
456
274
|
{ name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Abrir', url: 'https://systemzone.store' }) }
|
|
457
275
|
|
|
458
|
-
// Copiar
|
|
459
|
-
{ name: 'cta_copy', buttonParamsJson: JSON.stringify({ display_text: 'Copiar
|
|
276
|
+
// Copiar
|
|
277
|
+
{ name: 'cta_copy', buttonParamsJson: JSON.stringify({ display_text: 'Copiar', copy_code: 'CODIGO' }) }
|
|
460
278
|
|
|
461
279
|
// Ligar
|
|
462
280
|
{ name: 'cta_call', buttonParamsJson: JSON.stringify({ display_text: 'Ligar', phone_number: '5511999999999' }) }
|
|
463
281
|
|
|
464
|
-
//
|
|
465
|
-
{ name: 'cta_webview', buttonParamsJson: JSON.stringify({ title: 'Painel', url: 'https://systemzone.store' }) }
|
|
466
|
-
|
|
467
|
-
// Lista dropdown com seções
|
|
282
|
+
// Lista dropdown
|
|
468
283
|
{
|
|
469
284
|
name: 'single_select',
|
|
470
285
|
buttonParamsJson: JSON.stringify({
|
|
471
286
|
title: 'Escolher',
|
|
472
|
-
sections: [{
|
|
473
|
-
title: '
|
|
474
|
-
|
|
475
|
-
{ header: 'Op 1', title: 'Opção 1', description: 'Desc', id: 'op1' },
|
|
476
|
-
{ header: 'Op 2', title: 'Opção 2', description: 'Desc', id: 'op2' },
|
|
477
|
-
]
|
|
478
|
-
}]
|
|
287
|
+
sections: [{ title: 'Cat', rows: [
|
|
288
|
+
{ header: 'Op1', title: 'Opção 1', description: 'Desc', id: 'op1' }
|
|
289
|
+
]}]
|
|
479
290
|
})
|
|
480
291
|
}
|
|
481
292
|
```
|
|
482
293
|
|
|
483
|
-
### Header com imagem
|
|
484
|
-
|
|
485
|
-
Upload da imagem antes de usar no header:
|
|
294
|
+
### Header com imagem (funciona — confirmado em teste real)
|
|
486
295
|
|
|
487
296
|
```js
|
|
488
297
|
const { generateWAMessage, generateMessageIDV2 } = require('@systemzero/baileys')
|
|
489
298
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
userJid: sock.user.id,
|
|
493
|
-
messageId: generateMessageIDV2(sock.user.id),
|
|
494
|
-
})
|
|
495
|
-
const img = uploaded.message?.imageMessage
|
|
496
|
-
|
|
497
|
-
// No header:
|
|
498
|
-
header: {
|
|
499
|
-
title: '',
|
|
500
|
-
hasMediaAttachment: true,
|
|
501
|
-
imageMessage: {
|
|
502
|
-
url: img.url,
|
|
503
|
-
mimetype: img.mimetype,
|
|
504
|
-
fileSha256: img.fileSha256,
|
|
505
|
-
fileLength: img.fileLength,
|
|
506
|
-
mediaKey: img.mediaKey,
|
|
507
|
-
fileEncSha256: img.fileEncSha256,
|
|
508
|
-
directPath: img.directPath,
|
|
509
|
-
mediaKeyTimestamp: img.mediaKeyTimestamp,
|
|
510
|
-
jpegThumbnail: img.jpegThumbnail,
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
### Catálogo (product no header)
|
|
516
|
-
|
|
517
|
-
```js
|
|
518
|
-
header: {
|
|
519
|
-
title: 'Produto',
|
|
520
|
-
hasMediaAttachment: true,
|
|
521
|
-
productMessage: proto.Message.ProductMessage.create({
|
|
522
|
-
product: proto.Message.ProductMessage.ProductSnapshot.create({
|
|
523
|
-
productImage: proto.Message.ImageMessage.create({ ...img }),
|
|
524
|
-
productId: 'ID-001',
|
|
525
|
-
title: 'Nome do Produto',
|
|
526
|
-
description: 'Descrição completa',
|
|
527
|
-
currencyCode: 'BRL',
|
|
528
|
-
priceAmount1000: 29990, // R$ 29,99
|
|
529
|
-
retailerId: 'minha-loja',
|
|
530
|
-
url: 'https://loja.com/produto',
|
|
531
|
-
productImageCount: 1,
|
|
532
|
-
}),
|
|
533
|
-
businessOwnerJid: sock.user.id
|
|
534
|
-
})
|
|
535
|
-
}
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
### Carousel
|
|
539
|
-
|
|
540
|
-
```js
|
|
299
|
+
// Forma simplificada e já testada: usar `image` + `caption` direto no sendMessage,
|
|
300
|
+
// junto com nativeFlow — a lib monta o header automaticamente.
|
|
541
301
|
await sock.sendMessage(jid, {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
caption: 'Texto do card 1',
|
|
546
|
-
title: 'Card 1',
|
|
547
|
-
nativeFlow: [
|
|
548
|
-
{ text: 'Ver mais', id: 'card1' },
|
|
549
|
-
{ text: 'Site', url: 'https://systemzone.store' }
|
|
550
|
-
]
|
|
551
|
-
},
|
|
552
|
-
{
|
|
553
|
-
image: buffer2,
|
|
554
|
-
caption: 'Texto do card 2',
|
|
555
|
-
nativeFlow: [{ text: 'Clique', id: 'card2' }]
|
|
556
|
-
}
|
|
557
|
-
],
|
|
558
|
-
footer: 'Rodapé'
|
|
302
|
+
image: { url: 'https://...' },
|
|
303
|
+
caption: 'Texto do card',
|
|
304
|
+
nativeFlow: [{ text: 'Botão', id: 'btn1' }]
|
|
559
305
|
})
|
|
560
306
|
```
|
|
561
307
|
|
|
308
|
+
> Use `caption`, não `text`, quando quiser header com imagem junto de `nativeFlow` — usar `text` faz a lib pular inteiro o bloco que monta o header.
|
|
309
|
+
|
|
562
310
|
### Template Buttons
|
|
563
311
|
|
|
564
312
|
```js
|
|
565
313
|
await sock.sendMessage(jid, {
|
|
566
|
-
text:
|
|
314
|
+
text: 'Escolha:',
|
|
567
315
|
templateButtons: [
|
|
568
|
-
{ text: 'Resposta', id:
|
|
569
|
-
{ text: 'Site',
|
|
570
|
-
{ text: 'Ligar',
|
|
571
|
-
]
|
|
572
|
-
})
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
### Sections (lista clássica)
|
|
576
|
-
|
|
577
|
-
```js
|
|
578
|
-
await sock.sendMessage(jid, {
|
|
579
|
-
text: 'Selecione',
|
|
580
|
-
buttonText: 'Ver opções',
|
|
581
|
-
sections: [{
|
|
582
|
-
title: 'Categoria',
|
|
583
|
-
rows: [
|
|
584
|
-
{ title: 'Item 1', description: 'Desc', id: 'item1' },
|
|
585
|
-
{ title: 'Item 2', description: 'Desc', id: 'item2' },
|
|
586
|
-
]
|
|
587
|
-
}]
|
|
588
|
-
})
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
### Interactive como Template
|
|
592
|
-
|
|
593
|
-
```js
|
|
594
|
-
await sock.sendMessage(jid, {
|
|
595
|
-
nativeFlow: [{ text: 'Clique', id: 'btn' }],
|
|
596
|
-
text: 'Mensagem',
|
|
597
|
-
interactiveAsTemplate: true
|
|
598
|
-
})
|
|
599
|
-
```
|
|
600
|
-
|
|
601
|
-
### Botões com imagem no corpo (não no header)
|
|
602
|
-
|
|
603
|
-
```js
|
|
604
|
-
await sock.sendMessage(jid, {
|
|
605
|
-
image: buffer,
|
|
606
|
-
caption: 'Escolha:',
|
|
607
|
-
buttons: [
|
|
608
|
-
{ text: 'Opção 1', id: 'op1' },
|
|
609
|
-
{ text: 'Link', url: 'https://systemzone.store' },
|
|
316
|
+
{ text: 'Resposta', id: 'r1' },
|
|
317
|
+
{ text: 'Site', url: 'https://systemzone.store' },
|
|
318
|
+
{ text: 'Ligar', call: '5511999999999' },
|
|
610
319
|
]
|
|
611
320
|
})
|
|
612
321
|
```
|
|
613
322
|
|
|
614
|
-
###
|
|
323
|
+
### Sections
|
|
615
324
|
|
|
616
325
|
```js
|
|
617
326
|
await sock.sendMessage(jid, {
|
|
618
|
-
text:
|
|
619
|
-
|
|
620
|
-
|
|
327
|
+
text: 'Selecione', buttonText: 'Ver opções',
|
|
328
|
+
sections: [{ title: 'Cat', rows: [
|
|
329
|
+
{ title: 'Item 1', description: 'Desc', id: 'i1' }
|
|
330
|
+
]}]
|
|
621
331
|
})
|
|
622
332
|
```
|
|
623
333
|
|
|
@@ -625,100 +335,55 @@ await sock.sendMessage(jid, {
|
|
|
625
335
|
|
|
626
336
|
## 5. Sticker Pack nativo
|
|
627
337
|
|
|
628
|
-
Envia um pack de figurinhas que aparece na aba de stickers do WhatsApp, igual a um pack real.
|
|
629
|
-
|
|
630
338
|
```js
|
|
631
339
|
await sock.sendMessage(jid, {
|
|
632
|
-
cover:
|
|
340
|
+
cover: bufferWebP,
|
|
633
341
|
stickers: [
|
|
634
|
-
{ data:
|
|
635
|
-
{ data:
|
|
636
|
-
{ data: bufferPng,
|
|
342
|
+
{ data: bufferWebP, emojis: ['😂'] },
|
|
343
|
+
{ data: bufferAnima, emojis: ['🔥'] }, // animada
|
|
344
|
+
{ data: bufferPng, emojis: ['✨'] }, // PNG converte auto
|
|
637
345
|
],
|
|
638
346
|
name: 'Nome do Pack',
|
|
639
347
|
publisher: 'Autor',
|
|
640
|
-
description: 'Descrição
|
|
348
|
+
description: 'Descrição'
|
|
641
349
|
})
|
|
642
350
|
```
|
|
643
351
|
|
|
644
|
-
`cover`
|
|
645
|
-
|
|
646
|
-
Limites: máximo **60 figurinhas** por pack, cada uma com até **1MB**.
|
|
352
|
+
> Tanto `cover` quanto cada item de `stickers[].data` esperam **Buffer**, não `{ url }`. Se você baixou as figurinhas de uma API, baixe o buffer primeiro (`axios.get(url, { responseType: 'arraybuffer' })`) antes de montar o objeto.
|
|
647
353
|
|
|
648
|
-
Requer `sharp` ou `@napi-rs/image` para
|
|
354
|
+
Máximo 60 figurinhas, cada uma até 1MB. Requer `sharp` ou `@napi-rs/image` para PNG.
|
|
649
355
|
|
|
650
356
|
---
|
|
651
357
|
|
|
652
358
|
## 6. Canais Newsletter
|
|
653
359
|
|
|
654
|
-
### Enviar texto
|
|
655
|
-
|
|
656
360
|
```js
|
|
361
|
+
// Texto
|
|
657
362
|
await sock.sendMessage('120363...@newsletter', { text: 'Novidade!' })
|
|
658
|
-
```
|
|
659
|
-
|
|
660
|
-
### Enviar mídia
|
|
661
|
-
|
|
662
|
-
`sendMessage` não passa pelo `encodeNewsletterMessage` corretamente para mídia. Use sempre `generateWAMessage` + `relayMessage`:
|
|
663
363
|
|
|
664
|
-
|
|
364
|
+
// Mídia — sempre via generateWAMessage + relayMessage
|
|
665
365
|
const { generateWAMessage, generateMessageIDV2 } = require('@systemzero/baileys')
|
|
666
366
|
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
const fullMsg = await generateWAMessage(canalJid, {
|
|
670
|
-
image: buffer,
|
|
671
|
-
caption: 'Legenda'
|
|
672
|
-
}, {
|
|
673
|
-
upload: sock.waUploadToServer,
|
|
674
|
-
userJid: sock.user.id,
|
|
367
|
+
const fullMsg = await generateWAMessage(canalJid, { image: buffer, caption: 'Legenda' }, {
|
|
368
|
+
upload: sock.waUploadToServer, userJid: sock.user.id,
|
|
675
369
|
messageId: generateMessageIDV2(sock.user.id),
|
|
676
370
|
})
|
|
371
|
+
await sock.relayMessage(canalJid, fullMsg.message, { messageId: fullMsg.key.id })
|
|
677
372
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
})
|
|
681
|
-
```
|
|
682
|
-
|
|
683
|
-
Funciona para `image`, `video`, `audio`, `sticker`, `document`.
|
|
684
|
-
|
|
685
|
-
### Gerenciar canais
|
|
686
|
-
|
|
687
|
-
```js
|
|
688
|
-
// Criar
|
|
689
|
-
const canal = await sock.newsletterCreate('Nome do Canal', 'Descrição')
|
|
690
|
-
|
|
691
|
-
// Seguir / deixar
|
|
373
|
+
// Gerenciar
|
|
374
|
+
const canal = await sock.newsletterCreate('Nome', 'Descrição')
|
|
692
375
|
await sock.newsletterFollow(jid)
|
|
693
376
|
await sock.newsletterUnfollow(jid)
|
|
694
|
-
|
|
695
|
-
// Silenciar
|
|
696
377
|
await sock.newsletterMute(jid)
|
|
697
378
|
await sock.newsletterUnmute(jid)
|
|
698
|
-
|
|
699
|
-
// Metadata
|
|
700
379
|
const meta = await sock.newsletterMetadata('jid', jid)
|
|
701
|
-
const meta = await sock.newsletterMetadata('invite', 'CODIGO')
|
|
702
|
-
|
|
703
|
-
// Atualizar
|
|
704
380
|
await sock.newsletterUpdateName(jid, 'Novo Nome')
|
|
705
381
|
await sock.newsletterUpdateDescription(jid, 'Nova descrição')
|
|
706
382
|
await sock.newsletterUpdatePicture(jid, buffer)
|
|
707
383
|
await sock.newsletterRemovePicture(jid)
|
|
708
|
-
|
|
709
|
-
// Reagir a mensagem
|
|
710
384
|
await sock.newsletterReactMessage(jid, serverId, '❤️')
|
|
711
|
-
|
|
712
|
-
// Listar mensagens
|
|
713
385
|
const msgs = await sock.newsletterFetchMessages(jid, 30, 0, 0)
|
|
714
|
-
|
|
715
|
-
// Admin
|
|
716
|
-
const count = await sock.newsletterAdminCount(jid)
|
|
717
|
-
await sock.newsletterChangeOwner(jid, novoDonoJid)
|
|
718
|
-
await sock.newsletterDemote(jid, usuarioJid)
|
|
719
386
|
await sock.newsletterDelete(jid)
|
|
720
|
-
|
|
721
|
-
// Seguidores
|
|
722
387
|
const { subscribers } = await sock.newsletterSubscribers(jid)
|
|
723
388
|
```
|
|
724
389
|
|
|
@@ -726,56 +391,32 @@ const { subscribers } = await sock.newsletterSubscribers(jid)
|
|
|
726
391
|
|
|
727
392
|
## 7. Enquetes com decrypt
|
|
728
393
|
|
|
729
|
-
### Criar enquete
|
|
730
|
-
|
|
731
394
|
```js
|
|
395
|
+
// Criar
|
|
732
396
|
await sock.sendMessage(jid, {
|
|
733
|
-
poll: {
|
|
734
|
-
name: 'Pergunta?',
|
|
735
|
-
values: ['A', 'B', 'C'],
|
|
736
|
-
selectableCount: 1 // 0 = múltipla escolha
|
|
737
|
-
}
|
|
397
|
+
poll: { name: 'Pergunta?', values: ['A', 'B', 'C'], selectableCount: 1 }
|
|
738
398
|
})
|
|
739
|
-
```
|
|
740
|
-
|
|
741
|
-
### Receber e descriptografar votos
|
|
742
|
-
|
|
743
|
-
No `connect.js`, após `saveCreds`:
|
|
744
399
|
|
|
745
|
-
|
|
400
|
+
// Receber votos — no connect.js após saveCreds:
|
|
746
401
|
const { getAggregateVotesInPollMessage } = require('@systemzero/baileys/lib/Utils/messages.js')
|
|
747
402
|
|
|
748
403
|
sock.ev.on('messages.update', async (updates) => {
|
|
749
404
|
for (const { key, update } of updates) {
|
|
750
405
|
if (!update.pollUpdates) continue
|
|
751
|
-
|
|
752
406
|
const pollMsg = await store.loadMessage(key.remoteJid, key.id)
|
|
753
407
|
if (!pollMsg?.message) continue
|
|
754
|
-
|
|
755
408
|
const result = getAggregateVotesInPollMessage({
|
|
756
|
-
message:
|
|
757
|
-
pollUpdates: update.pollUpdates,
|
|
409
|
+
message: pollMsg.message, pollUpdates: update.pollUpdates
|
|
758
410
|
})
|
|
759
|
-
|
|
760
|
-
// [{ name: 'Opção A', voters: ['5511...@s.whatsapp.net'] }]
|
|
761
|
-
console.log(result)
|
|
762
|
-
|
|
763
|
-
if (!global.pollResults) global.pollResults = {}
|
|
764
|
-
global.pollResults[key.id] = { options: result, jid: key.remoteJid }
|
|
411
|
+
// [{ name: 'A', voters: ['5511...@s.whatsapp.net'] }]
|
|
765
412
|
}
|
|
766
413
|
})
|
|
767
414
|
```
|
|
768
415
|
|
|
769
|
-
O `getMessage` precisa estar configurado no `makeWASocket` (veja seção 1).
|
|
770
|
-
|
|
771
416
|
---
|
|
772
417
|
|
|
773
418
|
## 8. AI Rich
|
|
774
419
|
|
|
775
|
-
Mensagens com formatação avançada: markdown, código, tabelas, hyperlinks clicáveis no texto.
|
|
776
|
-
|
|
777
|
-
### Direto pelo socket
|
|
778
|
-
|
|
779
420
|
```js
|
|
780
421
|
// Texto com hyperlink
|
|
781
422
|
await sock.sendRich(jid, [
|
|
@@ -789,231 +430,495 @@ await sock.sendRich(jid, [
|
|
|
789
430
|
|
|
790
431
|
// Tabela
|
|
791
432
|
await sock.sendRich(jid, [
|
|
792
|
-
sock.makeTable([
|
|
793
|
-
['Nome', 'Status'],
|
|
794
|
-
['Botões', '✅'],
|
|
795
|
-
['Canais', '✅'],
|
|
796
|
-
])
|
|
433
|
+
sock.makeTable([['Nome', 'Status'], ['Botões', '✅'], ['Canais', '✅']])
|
|
797
434
|
], null, ['RICH_RESPONSE_TABLE'])
|
|
798
435
|
|
|
799
436
|
// Lista
|
|
800
|
-
await sock.sendRich(jid, [
|
|
801
|
-
sock.makeList(['Item 1', 'Item 2', 'Item 3'])
|
|
802
|
-
])
|
|
437
|
+
await sock.sendRich(jid, [sock.makeList(['Item 1', 'Item 2'])])
|
|
803
438
|
|
|
804
|
-
//
|
|
805
|
-
await sock.
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
sock.makeTable([['Col A', 'Col B'], ['val1', 'val2']]),
|
|
809
|
-
], quotedMsg, ['RICH_RESPONSE_CODE', 'RICH_RESPONSE_TABLE'])
|
|
439
|
+
// Atalhos
|
|
440
|
+
await sock.sendRichText(jid, 'Texto com [link](https://systemzone.store)', quotedMsg)
|
|
441
|
+
await sock.sendRichCode(jid, 'Título', 'javascript', 'const x = 1', quotedMsg)
|
|
442
|
+
await sock.sendRichList(jid, 'Lista', ['A', 'B'], quotedMsg)
|
|
810
443
|
```
|
|
811
444
|
|
|
812
|
-
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 9. LID / JID — Sistema avançado
|
|
448
|
+
|
|
449
|
+
O WhatsApp usa dois tipos de identificador:
|
|
450
|
+
- **JID** (`@s.whatsapp.net`) — formato baseado em número de telefone
|
|
451
|
+
- **LID** (`@lid`) — identificador opaco, não contém o número de telefone
|
|
452
|
+
|
|
453
|
+
A partir da v1.0.6, a baileys resolve automaticamente LID↔JID em mensagens recebidas e na metadata de grupo (ver seção 22), via `sharedLidPhoneCache`.
|
|
813
454
|
|
|
814
455
|
```js
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
456
|
+
const {
|
|
457
|
+
lidToJid, resolveJid, resolveAll, normalizeJid, validateJid,
|
|
458
|
+
getSenderInfo, sharedLidPhoneCache, isLidUser, isPnUser,
|
|
459
|
+
getBotJid, setBotMap
|
|
460
|
+
} = require('@systemzero/baileys')
|
|
818
461
|
```
|
|
819
462
|
|
|
820
|
-
|
|
463
|
+
```js
|
|
464
|
+
const jid = lidToJid('123456@lid')
|
|
465
|
+
const { jid, lid } = resolveAll('5511999999999@s.whatsapp.net')
|
|
466
|
+
normalizeJid('5511999999999') // → '5511999999999@s.whatsapp.net'
|
|
467
|
+
normalizeJid('123456@lid') // → resolve via cache
|
|
468
|
+
const { isValid, error } = validateJid('5511999999999@s.whatsapp.net')
|
|
469
|
+
const { jid, lid, isGroup, isValid } = getSenderInfo(message)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Cache bidirecional
|
|
473
|
+
|
|
474
|
+
O cache é populado automaticamente ao processar mensagens **e** ao buscar metadata de grupo (`groupMetadata`) — esse segundo ponto foi corrigido na v1.0.6, antes o par LID↔telefone que vem pronto na lista de participantes do grupo era descartado.
|
|
475
|
+
|
|
476
|
+
```js
|
|
477
|
+
sharedLidPhoneCache.set('123456@lid', '5511999999999@s.whatsapp.net') // manual, raro
|
|
478
|
+
const jid = sharedLidPhoneCache.getPhoneForLid('123456@lid')
|
|
479
|
+
const lid = sharedLidPhoneCache.getLidForPhone('5511999999999@s.whatsapp.net')
|
|
480
|
+
console.log('Entradas no cache:', sharedLidPhoneCache.size)
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
> ⚠️ Atenção com sufixo de dispositivo: identidades do **próprio bot** (`sock.user.id` / `sock.user.lid`) costumam vir como `numero:N@dominio` (ex: `558892659041:10@s.whatsapp.net`). Pra comparar com a lista de `participants` (que não tem sufixo), remova só o `:N`, preservando o domínio: `jid.replace(/:\d+(?=@)/, '')` — **não use** `jid.split(':')[0]`, isso corta o domínio inteiro junto.
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
## 10. Username (@usuario)
|
|
821
488
|
|
|
822
489
|
```js
|
|
823
|
-
const {
|
|
490
|
+
const { resolveUsername, isUsername } = require('@systemzero/baileys')
|
|
824
491
|
|
|
492
|
+
isUsername('@josue') // true
|
|
493
|
+
isUsername('josue') // false
|
|
494
|
+
|
|
495
|
+
const jid = await resolveUsername('@josue', sock.onWhatsApp.bind(sock))
|
|
496
|
+
if (jid) await sock.sendMessage(jid, { text: 'Olá!' })
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## 11. MessageBuilder — Button, ButtonV2, Carousel, AIRich
|
|
502
|
+
|
|
503
|
+
```js
|
|
504
|
+
const { Button, ButtonV2, Carousel, AIRich } = require('@systemzero/baileys/lib/MB.cjs')
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
> O socket vai sempre no construtor: `new ButtonV2(sock)`
|
|
508
|
+
|
|
509
|
+
### ButtonV2 — botões clássicos
|
|
510
|
+
|
|
511
|
+
```js
|
|
512
|
+
const msg = new ButtonV2(sock)
|
|
513
|
+
msg.setTitle('Título')
|
|
514
|
+
msg.setBody('Corpo')
|
|
515
|
+
msg.setFooter('Rodapé')
|
|
516
|
+
msg.setThumbnail('https://exemplo.com/imagem.jpg')
|
|
517
|
+
msg.addButton('✅ Opção 1', 'opcao_1')
|
|
518
|
+
msg.addButton('❌ Opção 2', 'opcao_2')
|
|
519
|
+
await msg.send(jid, { quoted: m })
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Capturar clique: `m.body` chega com o id do botão.
|
|
523
|
+
|
|
524
|
+
### Button — native flow avançado
|
|
525
|
+
|
|
526
|
+
```js
|
|
527
|
+
const msg = new Button(sock)
|
|
528
|
+
msg.setTitle('Título')
|
|
529
|
+
msg.setBody('Corpo')
|
|
530
|
+
msg.addReply('✅ Confirmar', 'confirmar')
|
|
531
|
+
msg.addUrl('🔗 Abrir site', 'https://systemzone.store')
|
|
532
|
+
msg.addCopy('📋 Copiar código', 'PROMO2025')
|
|
533
|
+
msg.addCall('📞 Ligar', '5511999999999')
|
|
534
|
+
await msg.send(jid, { quoted: m })
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### Carousel
|
|
538
|
+
|
|
539
|
+
```js
|
|
540
|
+
const msg = new Carousel(sock)
|
|
541
|
+
msg.setBody('Escolha um item:')
|
|
542
|
+
msg.card(c => c.image('https://...').title('Card 1').text('Descrição').button('Ver', 'c1'))
|
|
543
|
+
msg.card(c => c.image('https://...').title('Card 2').text('Descrição').button('Ver', 'c2'))
|
|
544
|
+
await msg.send(jid, { quoted: m })
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### AIRich
|
|
548
|
+
|
|
549
|
+
```js
|
|
825
550
|
const msg = new AIRich(sock)
|
|
826
|
-
msg.addText('
|
|
827
|
-
msg.addCode('javascript',
|
|
828
|
-
msg.addTable([['
|
|
551
|
+
msg.addText('Acesse [System Zero](https://systemzone.store).')
|
|
552
|
+
msg.addCode('javascript', `const baileys = require('@systemzero/baileys')`)
|
|
553
|
+
msg.addTable([['Comando', 'Descrição'], ['!menu', 'Abre o menu']])
|
|
829
554
|
await msg.send(jid, { quoted: m })
|
|
830
555
|
```
|
|
831
556
|
|
|
832
557
|
---
|
|
833
558
|
|
|
834
|
-
##
|
|
559
|
+
## 12. Botões estendidos (v1.0.6)
|
|
560
|
+
|
|
561
|
+
> ⚠️ **Não verificado nesta versão do README.** Os tipos abaixo (`catalog`, `products`, `otp`, `orderDetails`, `flow`, etc) exigem conta **WhatsApp Business API verificada** com catálogo/pagamentos configurados — nenhum deles foi testado numa conta pessoal real. Os tipos mais simples (`reminder`, `address`, `location`, `phoneNumber`, `urlBtn`, `clearChat`) têm chance maior de funcionar em qualquer conta, mas também não foram confirmados em teste real. Trate como documentação do proto, não como garantia de funcionamento. Para formulários reais e testados, veja a seção 24.
|
|
562
|
+
|
|
563
|
+
```js
|
|
564
|
+
{ text: '⏰ Me lembre', reminder: 'lembrete_id' }
|
|
565
|
+
{ text: '🔕 Cancelar', cancelReminder: 'lembrete_id' }
|
|
566
|
+
{ text: '📍 Enviar endereço', address: true }
|
|
567
|
+
{ text: '📡 Localização', location: true }
|
|
568
|
+
{ text: '🛍️ Ver catálogo', catalog: '5511999999999@s.whatsapp.net' }
|
|
569
|
+
{ text: '📦 Produtos', products: ['prod_id_1'], bizJid: '5511...@s.whatsapp.net' }
|
|
570
|
+
{ text: 'Copiar código', otp: '123456' }
|
|
571
|
+
{ text: '📞 Ligar', phoneNumber: '5511999999999' }
|
|
572
|
+
{ text: '📋 Ver pedido', orderDetails: { order_id: '123', token: 'abc' } }
|
|
573
|
+
{ text: '🗑️ Limpar chat', clearChat: true }
|
|
574
|
+
{ text: '🔗 Abrir', urlBtn: 'https://systemzone.store' }
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### isSystemNotification
|
|
578
|
+
|
|
579
|
+
```js
|
|
580
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
581
|
+
const msg = messages[0]
|
|
582
|
+
if (msg.isSystemNotification) return // ignora notificação de sistema
|
|
583
|
+
})
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## 13. Grupos
|
|
835
589
|
|
|
836
590
|
```js
|
|
837
|
-
// Criar
|
|
838
591
|
const grupo = await sock.groupCreate('Nome', ['5511...@s.whatsapp.net'])
|
|
592
|
+
const meta = await sock.groupMetadata(jid)
|
|
839
593
|
|
|
840
|
-
// Participantes
|
|
841
594
|
await sock.groupParticipantsUpdate(jid, ['5511...@s.whatsapp.net'], 'add')
|
|
842
595
|
await sock.groupParticipantsUpdate(jid, ['5511...@s.whatsapp.net'], 'remove')
|
|
843
596
|
await sock.groupParticipantsUpdate(jid, ['5511...@s.whatsapp.net'], 'promote')
|
|
844
597
|
await sock.groupParticipantsUpdate(jid, ['5511...@s.whatsapp.net'], 'demote')
|
|
845
|
-
|
|
846
|
-
// Sair
|
|
847
598
|
await sock.groupLeave(jid)
|
|
848
|
-
|
|
849
|
-
// Nome e descrição
|
|
850
599
|
await sock.groupUpdateSubject(jid, 'Novo Nome')
|
|
851
600
|
await sock.groupUpdateDescription(jid, 'Nova descrição')
|
|
852
601
|
|
|
853
|
-
// Convite
|
|
854
602
|
const code = await sock.groupInviteCode(jid)
|
|
855
603
|
await sock.groupRevokeInvite(jid)
|
|
856
604
|
await sock.groupAcceptInvite('CODIGO')
|
|
857
|
-
|
|
858
|
-
// Mensagens efêmeras (0 = desativar)
|
|
859
605
|
await sock.groupToggleEphemeral(jid, 86400)
|
|
860
606
|
|
|
861
|
-
// Metadata
|
|
862
|
-
const meta = await sock.groupMetadata(jid)
|
|
863
607
|
const grupos = await sock.groupFetchAllParticipating()
|
|
864
608
|
```
|
|
865
609
|
|
|
866
610
|
---
|
|
867
611
|
|
|
868
|
-
##
|
|
612
|
+
## 14. Perfil e privacidade
|
|
869
613
|
|
|
870
614
|
```js
|
|
871
|
-
// Foto de perfil
|
|
872
615
|
const url = await sock.profilePictureUrl(jid, 'image')
|
|
873
616
|
await sock.updateProfilePicture(jid, buffer)
|
|
874
|
-
|
|
875
|
-
// Bio
|
|
876
617
|
await sock.updateProfileStatus('🤖 Bot ativo')
|
|
877
618
|
|
|
878
|
-
// Verificar número
|
|
879
619
|
const [result] = await sock.onWhatsApp('5511999999999')
|
|
880
|
-
// { exists: true, jid: '5511...@s.whatsapp.net' }
|
|
881
620
|
|
|
882
|
-
// Bloquear / desbloquear
|
|
883
621
|
await sock.updateBlockStatus(jid, 'block')
|
|
884
622
|
await sock.updateBlockStatus(jid, 'unblock')
|
|
885
623
|
|
|
886
|
-
|
|
887
|
-
await sock.sendPresenceUpdate('
|
|
888
|
-
await sock.
|
|
889
|
-
await sock.sendPresenceUpdate('available', jid) // online
|
|
890
|
-
await sock.sendPresenceUpdate('unavailable') // offline
|
|
891
|
-
await sock.presenceSubscribe(jid) // receber presence de contato
|
|
624
|
+
await sock.sendPresenceUpdate('composing', jid)
|
|
625
|
+
await sock.sendPresenceUpdate('available', jid)
|
|
626
|
+
await sock.presenceSubscribe(jid)
|
|
892
627
|
|
|
893
|
-
// Marcar como lido
|
|
894
628
|
await sock.readMessages([message.key])
|
|
895
629
|
|
|
896
|
-
// Privacidade da foto
|
|
897
|
-
await sock.updateProfilePicturePrivacy('all') // 'all' | 'contacts' | 'none'
|
|
898
|
-
|
|
899
|
-
// Modificar chat
|
|
900
630
|
await sock.chatModify({ archive: true }, jid)
|
|
901
631
|
await sock.chatModify({ pin: true }, jid)
|
|
902
632
|
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
|
|
903
|
-
await sock.chatModify({ star: { messages: [{ id, fromMe }], star: true } }, jid)
|
|
904
|
-
await sock.chatModify({ clear: { messages: [{ id, fromMe, timestamp }] } }, jid)
|
|
905
633
|
|
|
906
|
-
// Desconectar
|
|
907
634
|
await sock.logout()
|
|
908
635
|
```
|
|
909
636
|
|
|
910
637
|
---
|
|
911
638
|
|
|
912
|
-
##
|
|
639
|
+
## 15. Eventos do socket
|
|
913
640
|
|
|
914
641
|
```js
|
|
915
|
-
sock.ev.on('messages.upsert',
|
|
916
|
-
sock.ev.on('messages.update',
|
|
917
|
-
sock.ev.on('messages.delete',
|
|
918
|
-
sock.ev.on('messages.reaction',
|
|
919
|
-
sock.ev.on('
|
|
920
|
-
sock.ev.on('
|
|
642
|
+
sock.ev.on('messages.upsert', ({ messages, type }) => {})
|
|
643
|
+
sock.ev.on('messages.update', (updates) => {})
|
|
644
|
+
sock.ev.on('messages.delete', (item) => {})
|
|
645
|
+
sock.ev.on('messages.reaction', (reactions) => {})
|
|
646
|
+
sock.ev.on('messages.decrypt-failed', (failInfo) => {}) // ver seção 20
|
|
647
|
+
sock.ev.on('presence.update', ({ id, presences }) => {})
|
|
648
|
+
sock.ev.on('groups.update', (updates) => {})
|
|
921
649
|
sock.ev.on('group-participants.update', ({ id, participants, action }) => {})
|
|
922
|
-
sock.ev.on('contacts.update',
|
|
923
|
-
sock.ev.on('
|
|
924
|
-
sock.ev.on('
|
|
925
|
-
sock.ev.on('creds.update', saveCreds)
|
|
650
|
+
sock.ev.on('contacts.update', (contacts) => {})
|
|
651
|
+
sock.ev.on('connection.update', ({ connection, lastDisconnect, qr }) => {})
|
|
652
|
+
sock.ev.on('creds.update', saveCreds)
|
|
926
653
|
|
|
927
|
-
// Chamadas
|
|
928
654
|
sock.ev.on('call', (calls) => {
|
|
929
655
|
for (const call of calls) {
|
|
930
|
-
if (call.status === 'offer')
|
|
931
|
-
sock.rejectCall(call.id, call.from)
|
|
932
|
-
}
|
|
656
|
+
if (call.status === 'offer') sock.rejectCall(call.id, call.from)
|
|
933
657
|
}
|
|
934
658
|
})
|
|
935
659
|
```
|
|
936
660
|
|
|
937
661
|
---
|
|
938
662
|
|
|
939
|
-
##
|
|
663
|
+
## 16. Utilitários
|
|
664
|
+
|
|
665
|
+
```js
|
|
666
|
+
const { downloadMediaMessage, downloadContentFromMessage } = require('@systemzero/baileys')
|
|
667
|
+
const buffer = await downloadMediaMessage(message, 'buffer', {})
|
|
668
|
+
|
|
669
|
+
const { generateWAMessage, generateWAMessageFromContent, generateMessageIDV2 } = require('@systemzero/baileys')
|
|
670
|
+
|
|
671
|
+
const {
|
|
672
|
+
jidNormalizedUser, isJidGroup, isJidNewsletter,
|
|
673
|
+
isLidUser, isPnUser, isUsername,
|
|
674
|
+
normalizeJid, resolveAll, getSenderInfo,
|
|
675
|
+
jidEncode, jidDecode
|
|
676
|
+
} = require('@systemzero/baileys')
|
|
677
|
+
|
|
678
|
+
// Detectar dispositivo — analisa o FORMATO DO ID DA MENSAGEM, não o JID
|
|
679
|
+
const { getDevice } = require('@systemzero/baileys')
|
|
680
|
+
const device = getDevice(message.key.id) // 'android' | 'ios' | 'web' | 'unknown'
|
|
681
|
+
```
|
|
940
682
|
|
|
941
|
-
|
|
683
|
+
> `getDevice` só funciona em cima de um `message.key.id` real — não dá pra usar pra "descobrir o dispositivo" de alguém sem ter uma mensagem recente dela pra inspecionar.
|
|
684
|
+
|
|
685
|
+
---
|
|
686
|
+
|
|
687
|
+
## 17. Fixar / Desfixar mensagens
|
|
942
688
|
|
|
943
689
|
```js
|
|
944
|
-
|
|
690
|
+
// Fixar (type: 1 = PIN_FOR_ALL)
|
|
691
|
+
await sock.sendMessage(jid, { pin: quotedMsg.key, type: 1 })
|
|
945
692
|
|
|
946
|
-
|
|
947
|
-
|
|
693
|
+
// Desfixar (type: 2 = UNPIN_FOR_ALL)
|
|
694
|
+
await sock.sendMessage(jid, { pin: quotedMsg.key, type: 2 })
|
|
948
695
|
```
|
|
949
696
|
|
|
950
|
-
|
|
697
|
+
`quotedMsg.key` precisa conter `remoteJid`, `fromMe`, `id` e (em grupos) `participant`.
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
## 18. Resolução de nomes (getName)
|
|
951
702
|
|
|
952
703
|
```js
|
|
953
|
-
const {
|
|
704
|
+
const { getName } = require('@systemzero/baileys')
|
|
705
|
+
const nome = getName(msg, contactStore) // contactStore opcional: { [jid]: { name, notify, verifiedName } }
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
Ordem de prioridade: contato salvo localmente → `verifiedName` → `pushName`/`notify` → resolução `@lid` via cache → número formatado → `"Usuário desconhecido"`. Nunca retorna vazio.
|
|
709
|
+
|
|
710
|
+
---
|
|
954
711
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
712
|
+
## 19. PTT real com qualquer formato de entrada
|
|
713
|
+
|
|
714
|
+
Antes da correção, `ptt: true` só **etiquetava** o mimetype como opus sem converter os bytes de verdade — qualquer entrada que não já fosse opus puro dava "algo errado com o arquivo de áudio" no WhatsApp. Agora a lib transcodifica de verdade via `ffmpeg` quando necessário.
|
|
715
|
+
|
|
716
|
+
```js
|
|
717
|
+
await sock.sendMessage(jid, {
|
|
718
|
+
audio: { url: 'https://qualquer-formato.mp3' }, // mp3, m4a, wav, o que for
|
|
719
|
+
ptt: true
|
|
720
|
+
})
|
|
962
721
|
```
|
|
963
722
|
|
|
964
|
-
|
|
723
|
+
A lib detecta se a fonte já é `.opus`/`.ogg` (pela extensão real, não pelo que você declarar em `mimetype`) e só converte quando necessário, pra mono/16kHz — a especificação que o player de voz do WhatsApp espera.
|
|
724
|
+
|
|
725
|
+
> Requer `ffmpeg` com `libopus` no `PATH` do servidor.
|
|
726
|
+
|
|
727
|
+
---
|
|
728
|
+
|
|
729
|
+
## 20. Guard de pagamento stealth (anti-fraude)
|
|
730
|
+
|
|
731
|
+
A lib emite o evento `messages.decrypt-failed` sempre que uma mensagem de grupo falha na descriptografia (PreKey/CIPHERTEXT) — cobre o golpe de cobrança "invisível": mensagem normal enviada, depois **editada** pra conteúdo de pagamento.
|
|
965
732
|
|
|
966
733
|
```js
|
|
967
|
-
const {
|
|
968
|
-
generateWAMessage,
|
|
969
|
-
generateWAMessageFromContent,
|
|
970
|
-
generateMessageIDV2,
|
|
971
|
-
generateForwardMessageContent
|
|
972
|
-
} = require('@systemzero/baileys')
|
|
734
|
+
const { bindPaymentGuard } = require('@systemzero/baileys')
|
|
973
735
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
736
|
+
bindPaymentGuard(sock, {
|
|
737
|
+
isPaymentMessage: (webMessage) => { /* sua lógica de detecção */ },
|
|
738
|
+
recordEnvelope: (webMessage, isPayment) => { /* seu registro de corroboração */ },
|
|
739
|
+
treatDecryptFailureAsSuspicious: true,
|
|
740
|
+
onDetect: (detection) => {
|
|
741
|
+
// detection.type: 'direct' | 'edited' | 'undecryptable'
|
|
742
|
+
}
|
|
979
743
|
})
|
|
744
|
+
```
|
|
980
745
|
|
|
981
|
-
|
|
982
|
-
|
|
746
|
+
| Caminho | Evento | Garantia |
|
|
747
|
+
|---|---|---|
|
|
748
|
+
| Mensagem direta | `messages.upsert` | Roda seu detector no conteúdo normal |
|
|
749
|
+
| Mensagem editada | `messages.update` | Extrai `editedMessage` e roda o mesmo detector |
|
|
750
|
+
| Falha de decrypt | `messages.decrypt-failed` | Nunca ignora em silêncio, mesmo sem conteúdo |
|
|
983
751
|
|
|
984
|
-
|
|
985
|
-
|
|
752
|
+
> Falha de decrypt nunca foi lida pelo bot — não existe forma de confirmar que era pagamento. O guard garante que isso nunca passe sem nenhum aviso, não que vai "adivinhar" o conteúdo.
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## 21. Bad MAC Handler — sessões Signal
|
|
757
|
+
|
|
758
|
+
```js
|
|
759
|
+
const { BadMacHandler, badMacHandler } = require('@systemzero/baileys')
|
|
760
|
+
|
|
761
|
+
if (badMacHandler.isBadMacError(error)) {
|
|
762
|
+
badMacHandler.handleError(error, 'algum-contexto')
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// limpa sessões Signal problemáticas, preservando creds.json
|
|
766
|
+
badMacHandler.clearProblematicSessionFiles()
|
|
986
767
|
```
|
|
987
768
|
|
|
988
|
-
|
|
769
|
+
Erros "Bad MAC" são esperados ocasionalmente em qualquer cliente Signal Protocol (sessão desincronizada do outro lado) — esse handler conta, dá reset automático após um intervalo, e remove só arquivos de sessão por par, nunca as credenciais principais.
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
## 22. Resolução LID → telefone via grupo
|
|
989
774
|
|
|
990
775
|
```js
|
|
991
|
-
const {
|
|
992
|
-
const
|
|
993
|
-
// 'android' | 'ios' | 'web' | 'unknown'
|
|
776
|
+
const { resolveLidPhoneFromGroup } = require('@systemzero/baileys')
|
|
777
|
+
const telefone = await resolveLidPhoneFromGroup(sock, groupJid, lid)
|
|
994
778
|
```
|
|
995
779
|
|
|
996
|
-
|
|
780
|
+
Força a resolução de um `@lid` pro telefone real buscando a metadata do grupo (que já entrega o par pronto por participante) — útil quando o cache ainda não tem aquele par.
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
## 23. Versão do WhatsApp sempre atualizada
|
|
997
785
|
|
|
998
786
|
```js
|
|
999
|
-
const {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
787
|
+
const { getBestWaVersion } = require('@systemzero/baileys')
|
|
788
|
+
const { version, isLatest, source } = await getBestWaVersion()
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
Tenta `web.whatsapp.com`, depois GitHub, e só aceita um resultado se `isLatest === true` de verdade. Diferente de `fetchLatestWaWebVersion()`/`fetchLatestBaileysVersion()` isoladas, que sempre retornam algo (mesmo em falha, caindo num valor fixo antigo) sem deixar isso óbvio.
|
|
792
|
+
|
|
793
|
+
---
|
|
794
|
+
|
|
795
|
+
## 24. WhatsApp Flows — Formulários interativos
|
|
796
|
+
|
|
797
|
+
> ⚠️ WhatsApp Flows é um recurso de **WhatsApp Business API**, normalmente exigindo um `flow_id` aprovado pela Meta pra sua conta/app específico. O exemplo abaixo é o que está em uso real no System Zero — funciona pro `flow_id` configurado nessa conta, mas **não é garantido que o mesmo `flow_id` funcione pra qualquer outra conta**. Pra criar seu próprio Flow, você precisa cadastrar e aprovar ele no Meta Business Manager.
|
|
798
|
+
|
|
799
|
+
### Enviando o formulário
|
|
800
|
+
|
|
801
|
+
```js
|
|
802
|
+
const { generateWAMessageFromContent } = require('@systemzero/baileys')
|
|
803
|
+
|
|
804
|
+
const formMsg = generateWAMessageFromContent(jid, {
|
|
805
|
+
viewOnceMessage: {
|
|
806
|
+
message: {
|
|
807
|
+
messageContextInfo: {
|
|
808
|
+
deviceListMetadata: {},
|
|
809
|
+
deviceListMetadataVersion: 2
|
|
810
|
+
},
|
|
811
|
+
interactiveMessage: {
|
|
812
|
+
body: { text: 'Formulário de teste\n\nPreencha seus dados.' },
|
|
813
|
+
nativeFlowMessage: {
|
|
814
|
+
buttons: [{
|
|
815
|
+
name: 'galaxy_message',
|
|
816
|
+
buttonParamsJson: JSON.stringify({
|
|
817
|
+
flow_message_version: '4',
|
|
818
|
+
flow_id: 'SEU_FLOW_ID_AQUI',
|
|
819
|
+
flow_action_payload: {
|
|
820
|
+
screen: 'contact_details',
|
|
821
|
+
data: {
|
|
822
|
+
full_name_visible: true,
|
|
823
|
+
phone_number_visible: true,
|
|
824
|
+
email_visible: true,
|
|
825
|
+
offer_name: 'Olá, seja bem-vindo',
|
|
826
|
+
offer_description: 'Sistema de teste'
|
|
827
|
+
}
|
|
828
|
+
},
|
|
829
|
+
well_version: 'V700',
|
|
830
|
+
flow_cta: '__localize:FLOWS_SIGN_UP_BUTTON_TITLE',
|
|
831
|
+
flow_action: 'navigate',
|
|
832
|
+
flow_token: 'T0ZGRVJfU0lHTlVQ'
|
|
833
|
+
})
|
|
834
|
+
}],
|
|
835
|
+
messageParamsJson: '{}'
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}, { userJid: sock.user.id })
|
|
1006
841
|
|
|
1007
|
-
|
|
1008
|
-
isJidGroup('120363...@g.us') // true
|
|
1009
|
-
isJidNewsletter('120363...@newsletter') // true
|
|
842
|
+
await sock.relayMessage(jid, formMsg.message, { messageId: formMsg.key.id })
|
|
1010
843
|
```
|
|
1011
844
|
|
|
845
|
+
### Recebendo a resposta
|
|
846
|
+
|
|
847
|
+
A resposta do formulário chega como `interactiveResponseMessage`. O `nativeFlowResponseMessage.paramsJson` traz os dados preenchidos dentro de `wa_flow_response_params.response_message` (uma string JSON aninhada — precisa de `JSON.parse` duplo).
|
|
848
|
+
|
|
849
|
+
```js
|
|
850
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
851
|
+
const m = messages[0]
|
|
852
|
+
if (m.message?.interactiveResponseMessage) {
|
|
853
|
+
const nfr = m.message.interactiveResponseMessage.nativeFlowResponseMessage
|
|
854
|
+
|
|
855
|
+
if (nfr?.name === 'galaxy_message' && nfr?.paramsJson) {
|
|
856
|
+
const parsed = JSON.parse(nfr.paramsJson)
|
|
857
|
+
if (!parsed.wa_flow_response_params) return
|
|
858
|
+
|
|
859
|
+
const flowParams = parsed.wa_flow_response_params
|
|
860
|
+
const flowId = flowParams.flow_id || ''
|
|
861
|
+
const rawResponse = flowParams.response_message || ''
|
|
862
|
+
|
|
863
|
+
let screens = []
|
|
864
|
+
try { screens = JSON.parse(rawResponse).screens || [] } catch {}
|
|
865
|
+
|
|
866
|
+
// extrai só os campos preenchidos
|
|
867
|
+
const campos = {}
|
|
868
|
+
for (const screen of screens) {
|
|
869
|
+
for (const comp of (screen.components || [])) {
|
|
870
|
+
if (comp.name && comp.value !== undefined && comp.value !== '') {
|
|
871
|
+
campos[comp.name] = comp.value
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// roteia por flow_id — adicione mais formulários aqui
|
|
877
|
+
if (flowId === 'SEU_FLOW_ID_AQUI') {
|
|
878
|
+
let resposta = 'Formulário recebido!\n\n'
|
|
879
|
+
if (campos.full_name) resposta += `Nome: ${campos.full_name}\n`
|
|
880
|
+
if (campos.phone_number) resposta += `Telefone: +${campos.phone_number}\n`
|
|
881
|
+
if (campos.email) resposta += `Email: ${campos.email}\n`
|
|
882
|
+
await sock.sendMessage(m.key.remoteJid, { text: resposta }, { quoted: m })
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
})
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
---
|
|
890
|
+
|
|
891
|
+
## Changelog
|
|
892
|
+
|
|
893
|
+
### v1.0.6
|
|
894
|
+
- **Fix PTT real** — `ptt: true` agora transcodifica via `ffmpeg` quando necessário, em vez de só etiquetar o mimetype
|
|
895
|
+
- **Fix groupMetadata → sharedLidPhoneCache** — pares LID↔telefone da lista de participantes de grupo agora são registrados no cache (antes eram descartados)
|
|
896
|
+
- **Fix cleanId de identidade própria** — comparação de `sock.user.id`/`sock.user.lid` com sufixo de dispositivo (`:N`) agora preserva o domínio
|
|
897
|
+
- **Guard de pagamento stealth** — `bindPaymentGuard`, evento `messages.decrypt-failed`
|
|
898
|
+
- **Bad MAC Handler** — `BadMacHandler`, `badMacHandler`
|
|
899
|
+
- **getName** — resolução de nome em cascata, nunca vazia
|
|
900
|
+
- **getBestWaVersion** — busca de versão que não falha em silêncio
|
|
901
|
+
- **resolveLidPhoneFromGroup** — força resolução via metadata de grupo
|
|
902
|
+
- **WhatsApp Flows** — suporte documentado a formulários interativos (`nativeFlowResponseMessage`)
|
|
903
|
+
- **isSystemNotification** — flag em mensagens de notificação de sistema
|
|
904
|
+
- Sistema LID/JID avançado com cache bidirecional (`sharedLidPhoneCache`)
|
|
905
|
+
- `lidToJid`, `resolveJid`, `resolveAll`, `normalizeJid`, `validateJid`, `getSenderInfo`
|
|
906
|
+
- Suporte a `@username` — `isUsername`, `resolveUsername`
|
|
907
|
+
|
|
908
|
+
### v1.0.5
|
|
909
|
+
- Sticker Pack nativo com suporte a animadas e PNG
|
|
910
|
+
- Fix canal newsletter (`extraAttrs` no `plaintext`)
|
|
911
|
+
- Album, Spoiler, ViewOnce V2, Ephemeral, Lottie, Evento
|
|
912
|
+
- Native Flow, Carousel, Template Buttons
|
|
913
|
+
- AI Rich (makeText, makeCode, makeTable, makeList, sendRich)
|
|
914
|
+
- Poll decrypt com `getAggregateVotesInPollMessage`
|
|
915
|
+
- MessageBuilder (`Button`, `ButtonV2`, `Carousel`, `AIRich`)
|
|
916
|
+
|
|
1012
917
|
---
|
|
1013
918
|
|
|
1014
919
|
<div align="center">
|
|
1015
920
|
|
|
1016
|
-
**@systemzero/baileys v1.0.
|
|
921
|
+
**@systemzero/baileys v1.0.6**
|
|
1017
922
|
|
|
1018
923
|
Desenvolvido por [Josué </>](https://t.me/blackhzx) · [Canal WhatsApp](https://whatsapp.com/channel/0029VaqUb9aGk1FxqeKKOd2i) · [systemzone.store](https://systemzone.store)
|
|
1019
924
|
|