@zervonex/baileys 0.0.0-stage → 3.0.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/LICENSE +21 -0
- package/README.md +3203 -2
- package/WAProto/WAProtoCompile.js +291 -0
- package/WAProto/fetcher.js +69 -0
- package/WAProto/index.js +88 -0
- package/WAProto/parser.js +313 -0
- package/engine-requirements.js +10 -0
- package/lib/Builders/AIRich.js +590 -0
- package/lib/Builders/base.js +130 -0
- package/lib/Builders/builders.js +448 -0
- package/lib/Builders/index.js +3 -0
- package/lib/Defaults/index.js +225 -0
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/index.js +2 -0
- package/lib/Signal/libsignal.js +523 -0
- package/lib/Signal/lid-mapping.js +283 -0
- package/lib/Socket/Client/index.js +2 -0
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.js +84 -0
- package/lib/Socket/business.js +152 -0
- package/lib/Socket/chats.js +855 -0
- package/lib/Socket/communities.js +147 -0
- package/lib/Socket/groups.js +294 -0
- package/lib/Socket/index.js +15 -0
- package/lib/Socket/messages-recv.js +904 -0
- package/lib/Socket/messages-send.js +693 -0
- package/lib/Socket/mex.js +34 -0
- package/lib/Socket/newsletter.js +752 -0
- package/lib/Socket/nexus-handler.js +55 -0
- package/lib/Socket/registration.js +155 -0
- package/lib/Socket/socket.js +798 -0
- package/lib/Socket/spam-report.js +65 -0
- package/lib/Socket/username.js +82 -0
- package/lib/Store/index.js +6 -0
- package/lib/Store/make-cache-manager-store.js +81 -0
- package/lib/Store/make-in-memory-store.js +425 -0
- package/lib/Store/make-ordered-dictionary.js +82 -0
- package/lib/Store/object-repository.js +31 -0
- package/lib/Store/reporting-info-store.js +38 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.js +8 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.js +25 -0
- package/lib/Types/LabelAssociation.js +7 -0
- package/lib/Types/Message.js +15 -0
- package/lib/Types/Newsletter.js +100 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.js +14 -0
- package/lib/Types/State.js +26 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.js +30 -0
- package/lib/Utils/auth-utils.js +142 -0
- package/lib/Utils/baileys-event-stream.js +33 -0
- package/lib/Utils/bot-capabilities.js +40 -0
- package/lib/Utils/bot-planning-replay.js +44 -0
- package/lib/Utils/browser-utils.js +26 -0
- package/lib/Utils/business.js +75 -0
- package/lib/Utils/chat-utils.js +316 -0
- package/lib/Utils/companion-reg-client-utils.js +20 -0
- package/lib/Utils/consumer-application.js +38 -0
- package/lib/Utils/crypto.js +52 -0
- package/lib/Utils/decode-wa-message.js +197 -0
- package/lib/Utils/event-buffer.js +273 -0
- package/lib/Utils/extras.js +186 -0
- package/lib/Utils/generics.js +195 -0
- package/lib/Utils/history.js +51 -0
- package/lib/Utils/identity-change-handler.js +19 -0
- package/lib/Utils/index.js +39 -0
- package/lib/Utils/key-store.js +3 -0
- package/lib/Utils/link-preview.js +51 -0
- package/lib/Utils/logger.js +2 -0
- package/lib/Utils/lt-hash.js +3 -0
- package/lib/Utils/make-mutex.js +16 -0
- package/lib/Utils/message-composer.js +59 -0
- package/lib/Utils/message-retry-manager.js +48 -0
- package/lib/Utils/messages-media.js +520 -0
- package/lib/Utils/messages.js +742 -0
- package/lib/Utils/meta-ai-msmsg.js +122 -0
- package/lib/Utils/meta-compositing.js +75 -0
- package/lib/Utils/modern-messages.js +235 -0
- package/lib/Utils/native-flow.js +55 -0
- package/lib/Utils/noise-handler.js +161 -0
- package/lib/Utils/pre-key-manager.js +76 -0
- package/lib/Utils/process-message.js +399 -0
- package/lib/Utils/reporting-utils.js +171 -0
- package/lib/Utils/signal.js +167 -0
- package/lib/Utils/spam-report-utils.js +142 -0
- package/lib/Utils/sync-action-utils.js +33 -0
- package/lib/Utils/tc-token-utils.js +102 -0
- package/lib/Utils/use-multi-file-auth-state.js +307 -0
- package/lib/Utils/validate-connection.js +181 -0
- package/lib/WABinary/constants.js +1321 -0
- package/lib/WABinary/decode.js +152 -0
- package/lib/WABinary/encode.js +140 -0
- package/lib/WABinary/generic-utils.js +179 -0
- package/lib/WABinary/index.js +6 -0
- package/lib/WABinary/jid-utils.js +235 -0
- package/lib/WABinary/types.js +4 -0
- package/lib/WAM/BinaryInfo.js +10 -0
- package/lib/WAM/constants.js +22853 -0
- package/lib/WAM/encode.js +150 -0
- package/lib/WAM/index.js +3 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +48 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +23 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +28 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +15 -0
- package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +24 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +9 -0
- package/lib/WAUSync/Protocols/USyncPictureProtocol.js +21 -0
- package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +19 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +19 -0
- package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +22 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +16 -0
- package/lib/WAUSync/Protocols/index.js +12 -0
- package/lib/WAUSync/USyncQuery.js +100 -0
- package/lib/WAUSync/USyncUser.js +20 -0
- package/lib/WAUSync/index.js +3 -0
- package/lib/index.js +68 -0
- package/package.json +216 -5
package/README.md
CHANGED
|
@@ -1,3 +1,3204 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p>
|
|
4
|
+
<!-- Banner -->
|
|
5
|
+
<img src="https://files.catbox.moe/gzkpf8.jpg" alt="zervonex Banner" />
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
# @zervonex/baileys
|
|
9
|
+
|
|
10
|
+
<p>
|
|
11
|
+
<img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="100%">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
**Advanced WhatsApp Web API — Built on WhiskeySockets/Baileys**
|
|
16
|
+
|
|
17
|
+
<p>
|
|
18
|
+
<!-- NPM Version -->
|
|
19
|
+
<a href="https://www.npmjs.com/package/@zervonex/baileys">
|
|
20
|
+
<img src="https://img.shields.io/npm/v/@zervonex/baileys?color=success&logo=npm&style=flat-square" alt="NPM Version" />
|
|
21
|
+
</a>
|
|
22
|
+
<!-- Downloads -->
|
|
23
|
+
<a href="https://www.npmjs.com/package/@zervonex/baileys">
|
|
24
|
+
<img src="https://img.shields.io/npm/dt/@zervonex/baileys?color=blue&logo=npm&style=flat-square" alt="Downloads" />
|
|
25
|
+
</a>
|
|
26
|
+
<!-- License -->
|
|
27
|
+
<a href="https://github.com/nexustechpro2/baileys/blob/main/LICENSE">
|
|
28
|
+
<img src="https://img.shields.io/npm/l/@zervonex/baileys?color=yellow&style=flat-square" alt="License" />
|
|
29
|
+
</a>
|
|
30
|
+
<!-- Node Version -->
|
|
31
|
+
<a href="https://nodejs.org">
|
|
32
|
+
<img src="https://img.shields.io/node/v/@zervonex/baileys?style=flat-square" alt="Node Version" />
|
|
33
|
+
</a>
|
|
34
|
+
<!-- Socket Badge -->
|
|
35
|
+
<a href="https://socket.dev/npm/package/@zervonex/baileys">
|
|
36
|
+
<img src="https://socket.dev/api/badge/npm/package/@zervonex/baileys" alt="Socket Badge" />
|
|
37
|
+
</a>
|
|
38
|
+
</p>
|
|
39
|
+
<p>
|
|
40
|
+
<!-- WhatsApp Channel -->
|
|
41
|
+
<a href="https://www.whatsapp.com/channel/0029VbBK53XBvvslYeZlBe0V">
|
|
42
|
+
<img src="https://img.shields.io/badge/Join-WhatsApp%20Channel-25D366?logo=whatsapp&logoColor=white" alt="WhatsApp Channel" />
|
|
43
|
+
</a>
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
*Modern, feature-rich, and developer-friendly WhatsApp automation library*
|
|
47
|
+
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 📋 Table of Contents
|
|
53
|
+
|
|
54
|
+
- [Installation](#-installation)
|
|
55
|
+
- [Quick Start](#-quick-start)
|
|
56
|
+
- [Authentication](#-authentication)
|
|
57
|
+
- [Browser Options](#-browser-options)
|
|
58
|
+
- [Socket Configuration](#-socket-configuration)
|
|
59
|
+
- [Session Management](#-session-management)
|
|
60
|
+
- [File-based](#file-based-default)
|
|
61
|
+
- [Keyv-based (MongoDB, Redis, PostgreSQL, SQLite...)](#keyv-based-production)
|
|
62
|
+
- [Per-type routing](#per-type-routing-advanced)
|
|
63
|
+
- [Sending Messages](#-sending-messages)
|
|
64
|
+
- [Content Key Reference](#content-key-reference)
|
|
65
|
+
- [Text Messages](#text-messages)
|
|
66
|
+
- [Media Messages](#media-messages)
|
|
67
|
+
- [Buttons & Interactive](#buttons--interactive-messages)
|
|
68
|
+
- [Extended Types](#extended-message-types)
|
|
69
|
+
- [AI Rich Messages](#ai-rich-messages)
|
|
70
|
+
- [Status & Stories](#personal-status--story-statusbroadcast)
|
|
71
|
+
- [Sticker Pack](#sticker-pack)
|
|
72
|
+
- [Shorthand Wrappers](#shorthand-wrappers)
|
|
73
|
+
- [Message Modifications](#️-message-modifications)
|
|
74
|
+
- [Media Download](#-media-download)
|
|
75
|
+
- [Group Management](#-group-management)
|
|
76
|
+
- [AI Groups](#ai-groups)
|
|
77
|
+
- [User Operations](#-user-operations)
|
|
78
|
+
- [Usernames](#usernames)
|
|
79
|
+
- [Check Number Status](#ban-checker)
|
|
80
|
+
- [Privacy Controls](#-privacy-controls)
|
|
81
|
+
- [Reporting](#reporting)
|
|
82
|
+
- [Reporting Info Store](#reporting-info-store)
|
|
83
|
+
- [Chat Operations](#-chat-operations)
|
|
84
|
+
- [Newsletter / Channels](#-newsletter--channels)
|
|
85
|
+
- [Builder API](#-builder-api)
|
|
86
|
+
- [AIRich Builder](#airich-builder)
|
|
87
|
+
- [Button Builder](#button-builder)
|
|
88
|
+
- [Carousel Builder](#carousel-builder)
|
|
89
|
+
- [Album Builder](#album-builder)
|
|
90
|
+
- [VerticalAlbum Builder](#verticalalbum-builder)
|
|
91
|
+
- [GridImage Builder](#gridimage-builder)
|
|
92
|
+
- [VideoGrid Builder](#videogrid-builder)
|
|
93
|
+
- [A2UI Builder](#a2ui-builder)
|
|
94
|
+
- [Poll Builder](#poll-builder)
|
|
95
|
+
- [Event Builder](#event-builder)
|
|
96
|
+
- [Payment Builder](#payment-builder)
|
|
97
|
+
- [Order Builder](#order-builder)
|
|
98
|
+
- [Utility Methods](#-utility-methods)
|
|
99
|
+
- [Exported Utilities](#-exported-utilities)
|
|
100
|
+
- [Events Reference](#-events-reference)
|
|
101
|
+
- [Best Practices](#-best-practices)
|
|
102
|
+
- [Disclaimer](#️-disclaimer)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 📦 Installation
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# npm
|
|
110
|
+
npm install @zervonex/baileys
|
|
111
|
+
|
|
112
|
+
# yarn
|
|
113
|
+
yarn add @zervonex/baileys
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Drop-in replacement for `@whiskeysockets/baileys`** — add this to `package.json`:
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"dependencies": {
|
|
120
|
+
"@whiskeysockets/baileys": "npm:@zervonex/baileys"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// OR
|
|
125
|
+
|
|
126
|
+
{
|
|
127
|
+
"dependencies": {
|
|
128
|
+
"@zervonex/baileys": "latest"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Import:**
|
|
134
|
+
```javascript
|
|
135
|
+
// ESM (recommended)
|
|
136
|
+
import makeWASocket from '@zervonex/baileys'
|
|
137
|
+
|
|
138
|
+
// CommonJS
|
|
139
|
+
const { default: makeWASocket } = require('@zervonex/baileys')
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 🚀 Quick Start
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
import makeWASocket, {
|
|
148
|
+
useMultiFileAuthState,
|
|
149
|
+
DisconnectReason,
|
|
150
|
+
makeCacheableSignalKeyStore,
|
|
151
|
+
Browsers
|
|
152
|
+
} from '@zervonex/baileys'
|
|
153
|
+
import pino from 'pino'
|
|
154
|
+
|
|
155
|
+
const connectToWhatsApp = async () => {
|
|
156
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_session')
|
|
157
|
+
const logger = pino({ level: 'silent' })
|
|
158
|
+
|
|
159
|
+
const sock = makeWASocket({
|
|
160
|
+
auth: {
|
|
161
|
+
creds: state.creds,
|
|
162
|
+
keys: makeCacheableSignalKeyStore(state.keys, logger)
|
|
163
|
+
},
|
|
164
|
+
browser: Browsers.ubuntu('Chrome'),
|
|
165
|
+
generateHighQualityLinkPreview: true,
|
|
166
|
+
logger
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
170
|
+
if (connection === 'close') {
|
|
171
|
+
const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut
|
|
172
|
+
if (shouldReconnect) connectToWhatsApp()
|
|
173
|
+
} else if (connection === 'open') {
|
|
174
|
+
console.log('✅ Connected!')
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
sock.ev.on('creds.update', saveCreds)
|
|
179
|
+
|
|
180
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
181
|
+
for (const msg of messages) {
|
|
182
|
+
if (!msg.key.fromMe && msg.message) {
|
|
183
|
+
await sock.sendMessage(msg.key.remoteJid, { text: 'Hello!' })
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
connectToWhatsApp()
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 🔐 Authentication
|
|
195
|
+
|
|
196
|
+
### Pairing Code (Recommended)
|
|
197
|
+
|
|
198
|
+
No QR scanning — just a phone number. Call `requestPairingCode` directly after creating the socket. The socket internally waits for the WebSocket to be ready before sending the request, so **no manual polling or delays needed on your end**.
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
import makeWASocket, {
|
|
202
|
+
useMultiFileAuthState,
|
|
203
|
+
makeCacheableSignalKeyStore,
|
|
204
|
+
Browsers
|
|
205
|
+
} from '@zervonex/baileys'
|
|
206
|
+
import pino from 'pino'
|
|
207
|
+
|
|
208
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_session')
|
|
209
|
+
const logger = pino({ level: 'silent' })
|
|
210
|
+
|
|
211
|
+
const sock = makeWASocket({
|
|
212
|
+
auth: {
|
|
213
|
+
creds: state.creds,
|
|
214
|
+
keys: makeCacheableSignalKeyStore(state.keys, logger)
|
|
215
|
+
},
|
|
216
|
+
browser: Browsers.ubuntu('Chrome'),
|
|
217
|
+
logger
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
sock.ev.on('creds.update', saveCreds)
|
|
221
|
+
|
|
222
|
+
// Just call it — no need to wait or poll for WS state
|
|
223
|
+
if (!sock.authState.creds.registered) {
|
|
224
|
+
const code = await sock.requestPairingCode('1234567890') // digits only, no + or spaces
|
|
225
|
+
console.log('Pairing code:', code)
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Custom Pairing Code
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// Must be exactly 8 characters
|
|
233
|
+
const code = await sock.requestPairingCode('1234567890', 'NEXUS001')
|
|
234
|
+
console.log('Custom code:', code)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### QR Code
|
|
238
|
+
|
|
239
|
+
Scan the QR with your WhatsApp mobile app under **Linked Devices**.
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
import makeWASocket, {
|
|
243
|
+
useMultiFileAuthState,
|
|
244
|
+
makeCacheableSignalKeyStore,
|
|
245
|
+
Browsers
|
|
246
|
+
} from '@zervonex/baileys'
|
|
247
|
+
import qrcode from 'qrcode-terminal'
|
|
248
|
+
import pino from 'pino'
|
|
249
|
+
|
|
250
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_session')
|
|
251
|
+
const logger = pino({ level: 'silent' })
|
|
252
|
+
|
|
253
|
+
const sock = makeWASocket({
|
|
254
|
+
auth: {
|
|
255
|
+
creds: state.creds,
|
|
256
|
+
keys: makeCacheableSignalKeyStore(state.keys, logger)
|
|
257
|
+
},
|
|
258
|
+
browser: Browsers.ubuntu('Chrome'),
|
|
259
|
+
logger
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
sock.ev.on('connection.update', ({ connection, qr, lastDisconnect }) => {
|
|
263
|
+
if (qr) qrcode.generate(qr, { small: true })
|
|
264
|
+
if (connection === 'open') console.log('✅ Connected!')
|
|
265
|
+
if (connection === 'close') {
|
|
266
|
+
const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut
|
|
267
|
+
if (shouldReconnect) connectToWhatsApp()
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
sock.ev.on('creds.update', saveCreds)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Install the QR renderer: `npm install qrcode-terminal`
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## 🌐 Browser Options
|
|
279
|
+
|
|
280
|
+
The `browser` config tells WhatsApp what client you appear to be. This affects how WhatsApp treats your session and which features it enables.
|
|
281
|
+
|
|
282
|
+
| Option | Value | Notes |
|
|
283
|
+
|--------|-------|-------|
|
|
284
|
+
| `Browsers.ubuntu('Chrome')` | `['Ubuntu', 'Chrome', '22.04.4']` | ✅ Recommended — stable, widely used |
|
|
285
|
+
| `Browsers.macOS('Safari')` | `['Mac OS', 'Safari', '14.4.1']` | Good alternative |
|
|
286
|
+
| `Browsers.windows('Chrome')` | `['Windows', 'Chrome', '10.0.22631']` | Works well |
|
|
287
|
+
| `Browsers.baileys('Desktop')` | `['Baileys', 'Desktop', '6.5.0']` | Identifies as Baileys explicitly |
|
|
288
|
+
| `Browsers.appropriate('Chrome')` | Auto-detects your OS | Uses your actual platform |
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
import { Browsers } from '@zervonex/baileys'
|
|
292
|
+
|
|
293
|
+
// Pass any browser string as the second argument (Chrome, Safari, Firefox, etc.)
|
|
294
|
+
const sock = makeWASocket({
|
|
295
|
+
browser: Browsers.ubuntu('Chrome') // recommended
|
|
296
|
+
// browser: Browsers.macOS('Safari')
|
|
297
|
+
// browser: Browsers.windows('Chrome')
|
|
298
|
+
// browser: Browsers.appropriate('Chrome') // auto-detects your server OS
|
|
299
|
+
})
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## ⚙️ Socket Configuration
|
|
305
|
+
|
|
306
|
+
Key options from `DEFAULT_CONNECTION_CONFIG`:
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
const sock = makeWASocket({
|
|
310
|
+
// Required
|
|
311
|
+
auth: { creds, keys },
|
|
312
|
+
|
|
313
|
+
// Browser identity
|
|
314
|
+
browser: Browsers.ubuntu('Chrome'),
|
|
315
|
+
|
|
316
|
+
// Link preview quality (true = upload full image, false = compressed local thumb)
|
|
317
|
+
generateHighQualityLinkPreview: true,
|
|
318
|
+
|
|
319
|
+
// Cache group metadata to avoid repeated fetches
|
|
320
|
+
cachedGroupMetadata: async (jid) => groupCache.get(jid),
|
|
321
|
+
|
|
322
|
+
// Suppress your online status when connecting
|
|
323
|
+
markOnlineOnConnect: false,
|
|
324
|
+
|
|
325
|
+
// Sync full message history on connect
|
|
326
|
+
syncFullHistory: false,
|
|
327
|
+
|
|
328
|
+
// Mark all outgoing messages as AI-generated (global default)
|
|
329
|
+
aiLabel: false,
|
|
330
|
+
|
|
331
|
+
// Logger (use pino({ level: 'silent' }) to suppress logs)
|
|
332
|
+
logger: pino({ level: 'silent' }),
|
|
333
|
+
|
|
334
|
+
// Connection timeout in ms
|
|
335
|
+
connectTimeoutMs: 60000,
|
|
336
|
+
|
|
337
|
+
// Max retries for failed message sends
|
|
338
|
+
maxMsgRetryCount: 5,
|
|
339
|
+
|
|
340
|
+
// Custom message retrieval for retry/poll decryption
|
|
341
|
+
getMessage: async (key) => store.loadMessage(key.remoteJid, key.id),
|
|
342
|
+
})
|
|
343
|
+
```
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 💾 Session Management
|
|
347
|
+
|
|
348
|
+
Two adapters are available. They do **not** share an identical return shape — see the differences noted below each.
|
|
349
|
+
|
|
350
|
+
### File-based (default)
|
|
351
|
+
|
|
352
|
+
Atomic writes, sha256 checksum integrity, per-file mutex locking, corrupt file recovery, and legacy file upgrade. Best for single-instance bots or local development.
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
import { useMultiFileAuthState } from '@zervonex/baileys'
|
|
356
|
+
|
|
357
|
+
const { state, saveCreds, getStats } = await useMultiFileAuthState('auth_session', {
|
|
358
|
+
preKeyRetention: 150, // how many recent prekeys to keep (default: 150)
|
|
359
|
+
cleanupThreshold: 50, // new prekeys before a cleanup runs (default: 50)
|
|
360
|
+
logger, // optional — logs checksum mismatches and cleanup events
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
const sock = makeWASocket({ auth: state })
|
|
364
|
+
sock.ev.on('creds.update', saveCreds)
|
|
365
|
+
|
|
366
|
+
// Diagnostics
|
|
367
|
+
const stats = await getStats()
|
|
368
|
+
// { totalFiles: 42, preKeyCount: 150, nextPreKeyId: 3200, lastCleanupAt: '2026-07-05T...' }
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
To fully log out and delete a session's files, remove the session folder directly (e.g. `fs.rm(folder, { recursive: true, force: true })`) — there is no `clearSession`/`close` method on this adapter.
|
|
372
|
+
|
|
373
|
+
### Keyv-based (production)
|
|
374
|
+
|
|
375
|
+
Universal adapter for any database backend via [Keyv](https://github.com/jaredwray/keyv). Pass a connection string — the matching backend driver is resolved and imported automatically, no manual adapter imports needed.
|
|
376
|
+
|
|
377
|
+
Storage format matches `useMultiFileAuthState` exactly: every value is wrapped as `{ data, __checksum }` with a sha256 integrity check, so corruption is detected and self-healed the same way on both adapters. Reads also auto-detect and repair values that were written by an older/buggy version of this adapter (including arbitrarily nested `{ value: { value: ... } }` wrapping) — no manual data-fixing needed if you're upgrading from an earlier release.
|
|
378
|
+
|
|
379
|
+
The first argument is the **session ID** — equivalent to the folder name in `useMultiFileAuthState`. It's used as the Keyv namespace, so multiple bots can safely share one backend. The second argument is a connection string, a pre-built `Keyv` instance, or a raw `KeyvStoreAdapter`:
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
import { useKeyvAuthState } from '@zervonex/baileys'
|
|
383
|
+
|
|
384
|
+
// ── Redis ─────────────────────────────────────────────────────────────────────
|
|
385
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'redis://localhost:6379')
|
|
386
|
+
|
|
387
|
+
// ── PostgreSQL / Supabase / Neon ──────────────────────────────────────────────
|
|
388
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'postgresql://user:pass@localhost/db')
|
|
389
|
+
|
|
390
|
+
// ── MongoDB ───────────────────────────────────────────────────────────────────
|
|
391
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'mongodb://localhost/baileys')
|
|
392
|
+
|
|
393
|
+
// ── MySQL / PlanetScale ───────────────────────────────────────────────────────
|
|
394
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'mysql://user:pass@localhost/db')
|
|
395
|
+
|
|
396
|
+
// ── SQLite (local, zero-config) ───────────────────────────────────────────────
|
|
397
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'sqlite://auth.db')
|
|
398
|
+
|
|
399
|
+
// ── etcd ──────────────────────────────────────────────────────────────────────
|
|
400
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'etcd://localhost:2379')
|
|
401
|
+
|
|
402
|
+
// ── Memcache ──────────────────────────────────────────────────────────────────
|
|
403
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'memcache://localhost:11211')
|
|
404
|
+
|
|
405
|
+
// ── In-memory (testing / ephemeral — data lost on restart) ───────────────────
|
|
406
|
+
const { state, saveCreds } = await useKeyvAuthState('test')
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Supported connection string protocols: `redis:`/`rediss:`, `mongodb:`/`mongodb+srv:`, `postgres:`/`postgresql:`, `mysql:`, `sqlite:`, `etcd:`, `memcache:`/`memcached:`. All matching driver packages (`@keyv/redis`, `@keyv/mongo`, `@keyv/postgres`, `@keyv/mysql`, `@keyv/sqlite`, `@keyv/etcd`, `@keyv/memcache`) ship as regular dependencies of this package — nothing extra to install.
|
|
410
|
+
|
|
411
|
+
For backends without a connection string (e.g. DynamoDB), or to reuse one connection across multiple `useKeyvAuthState` calls yourself, pass a pre-built adapter or `Keyv` instance instead of a string:
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
import { useKeyvAuthState } from '@zervonex/baileys'
|
|
415
|
+
import KeyvMongo from '@keyv/mongo'
|
|
416
|
+
|
|
417
|
+
const backend = new KeyvMongo('mongodb://localhost/baileys') // build once, share across sessions
|
|
418
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', backend)
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Same connection string passed as a plain string is automatically cached and reused across every `useKeyvAuthState` call in the process — you don't need to build the instance yourself just to avoid opening duplicate connections, but you can if you want the reference for other purposes.
|
|
422
|
+
|
|
423
|
+
By default, Mongo/Postgres/MySQL/SQLite store everything in a collection/table named `keyv` (each adapter's own default). Set `collectionName` to use your own name instead — it's mapped to whatever each backend actually calls it (`collection` for Mongo, `table` for Postgres/MySQL/SQLite):
|
|
424
|
+
|
|
425
|
+
```javascript
|
|
426
|
+
const { state, saveCreds } = await useKeyvAuthState('bot1', 'mongodb://localhost/baileys', {
|
|
427
|
+
collectionName: 'baileys_auth', // instead of the default "keyv" collection
|
|
428
|
+
})
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
> Per-type backend routing (e.g. prekeys on SQLite, sessions on Postgres) is not currently supported — one `useKeyvAuthState` call uses one backend for every key type.
|
|
432
|
+
|
|
433
|
+
#### Clearing a session (logout)
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
const { state, saveCreds, clearSession } = await useKeyvAuthState('bot1', 'redis://localhost:6379')
|
|
437
|
+
|
|
438
|
+
// on logout / when you want to wipe this session's auth entirely:
|
|
439
|
+
await clearSession()
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
`clearSession()` wipes every key belonging to that `sessionId` — creds, prekeys, sessions, sender keys, everything — using each backend's native namespace-scoped bulk delete (a real `deleteMany`/`DELETE WHERE`/`SCAN`+delete under the hood, not a per-key loop). It only affects this session; other sessions sharing the same backend are untouched. There's no equivalent method on `useMultiFileAuthState` — delete the session folder instead.
|
|
443
|
+
|
|
444
|
+
#### Options
|
|
445
|
+
|
|
446
|
+
| Option | Type | Default | Description |
|
|
447
|
+
|--------|------|---------|-------------|
|
|
448
|
+
| `preKeyRetention` | `number` | `150` | Number of recent prekeys to keep |
|
|
449
|
+
| `cleanupThreshold` | `number` | `50` | New prekeys generated before cleanup runs |
|
|
450
|
+
| `logger` | `object` | `undefined` | Logger with `.info` / `.warn` methods |
|
|
451
|
+
| `collectionName` | `string` | adapter's own default (`"keyv"`) | Custom collection/table name — Keyv-based adapter only, ignored for connection-string-less (in-memory) and pre-built adapter/`Keyv` instances |
|
|
452
|
+
|
|
453
|
+
#### Return values
|
|
454
|
+
|
|
455
|
+
| | `useMultiFileAuthState` | `useKeyvAuthState` |
|
|
456
|
+
|---|---|---|
|
|
457
|
+
| `state` | ✅ | ✅ |
|
|
458
|
+
| `saveCreds` | ✅ | ✅ |
|
|
459
|
+
| `getStats` | ✅ | ❌ |
|
|
460
|
+
| `clearSession` | ❌ (delete the folder instead) | ✅ |
|
|
461
|
+
| `close` | ❌ | ✅ (drops local listeners; safe to call, does not disconnect a shared backend) |
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## 💬 Sending Messages
|
|
466
|
+
|
|
467
|
+
`sock.sendMessage(jid, content, options?)` handles **every message type**. The `jid` can be a user, group, status broadcast, or newsletter.
|
|
468
|
+
|
|
469
|
+
```javascript
|
|
470
|
+
// JID formats
|
|
471
|
+
'1234567890@s.whatsapp.net' // personal chat
|
|
472
|
+
'123456789-987654321@g.us' // group
|
|
473
|
+
'status@broadcast' // story/status
|
|
474
|
+
'120363...@newsletter' // newsletter channel
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Content Key Reference
|
|
478
|
+
|
|
479
|
+
Every key you can pass to `sock.sendMessage`:
|
|
480
|
+
|
|
481
|
+
| Key | Description |
|
|
482
|
+
|-----|-------------|
|
|
483
|
+
| `text` | Plain text or markdown |
|
|
484
|
+
| `image` | Image message |
|
|
485
|
+
| `video` | Video message |
|
|
486
|
+
| `audio` | Audio / voice message |
|
|
487
|
+
| `document` | File / document |
|
|
488
|
+
| `sticker` | Sticker |
|
|
489
|
+
| `location` | Location pin |
|
|
490
|
+
| `contacts` | Contact card(s) |
|
|
491
|
+
| `react` | Emoji reaction |
|
|
492
|
+
| `poll` | Poll creation |
|
|
493
|
+
| `forward` | Forward a message |
|
|
494
|
+
| `delete` | Delete a message |
|
|
495
|
+
| `edit` | Edit a sent message |
|
|
496
|
+
| `pin` | Pin / unpin a message |
|
|
497
|
+
| `keep` | Keep / unkeep a message |
|
|
498
|
+
| `disappearingMessagesInChat` | Set disappearing timer |
|
|
499
|
+
| `aiRich` | AI Rich message (text, code, table, images, sources, reels, latex, parts) |
|
|
500
|
+
| `albumMessage` | Media album (2+ images/videos) |
|
|
501
|
+
| `carouselMessage` | Interactive card carousel |
|
|
502
|
+
| `groupStatus` | Post text/media to a group's story |
|
|
503
|
+
| `interactiveMessage` | Raw interactive message object |
|
|
504
|
+
| `requestPaymentMessage` | Payment request |
|
|
505
|
+
| `orderMessage` | Order message |
|
|
506
|
+
| `eventMessage` | Event / calendar invite |
|
|
507
|
+
| `stickerPack` | Sticker pack |
|
|
508
|
+
| `verticalAlbumMessage` | Vertical stacked media album (AIRich format) |
|
|
509
|
+
| `gridImageMessage` | Image grid (GRID_IMAGE protocol type) |
|
|
510
|
+
| `videoGridMessage` | Video grid (GenAIVideoPrimitive grid) |
|
|
511
|
+
| `a2uiMessage` | A2UI bloksWidget interactive message |
|
|
512
|
+
| `statusMentionMessage` | Mention someone in a status |
|
|
513
|
+
| `pollResultMessage` | Poll result snapshot |
|
|
514
|
+
| `deliveryMode` | Controls which devices receive the message — see Delivery Mode section |
|
|
515
|
+
| `ai` | Mark message as AI-generated (injects bot label + supportPayload) |
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
### Text Messages
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
// Plain text
|
|
523
|
+
await sock.sendMessage(jid, { text: 'Hello World!' })
|
|
524
|
+
|
|
525
|
+
// With link preview (auto-detects URLs in text)
|
|
526
|
+
await sock.sendMessage(jid, { text: 'Check this out: https://github.com' })
|
|
527
|
+
|
|
528
|
+
// Quote/reply
|
|
529
|
+
await sock.sendMessage(jid, { text: 'This is a reply' }, { quoted: message })
|
|
530
|
+
|
|
531
|
+
// Mention users
|
|
532
|
+
await sock.sendMessage(jid, {
|
|
533
|
+
text: '@1234567890 hey!',
|
|
534
|
+
mentions: ['1234567890@s.whatsapp.net']
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
// AI-generated label — marks the message as bot-generated
|
|
538
|
+
// content flag (per-message)
|
|
539
|
+
await sock.sendMessage(jid, { text: 'AI response here', ai: true })
|
|
540
|
+
// options flag (per-message)
|
|
541
|
+
await sock.sendMessage(jid, { text: 'AI response here' }, { ai: true })
|
|
542
|
+
// or use aiLabel alias
|
|
543
|
+
await sock.sendMessage(jid, { text: 'AI response here' }, { aiLabel: true })
|
|
544
|
+
// global config (applies to every message from this socket)
|
|
545
|
+
const sock = makeWASocket({ aiLabel: true })
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Delivery Mode
|
|
549
|
+
|
|
550
|
+
Control which devices receive your message using the `deliveryMode` option. By default every device gets the message (`toAll`).
|
|
551
|
+
|
|
552
|
+
| Mode | Your Main | Your Companions | Recipient Main | Recipient Companions |
|
|
553
|
+
|------|-----------|-----------------|----------------|----------------------|
|
|
554
|
+
| `toAll` | ✅ | ✅ | ✅ | ✅ |
|
|
555
|
+
| `toMainOnly` | ✅ | ❌ | ✅ | ❌ |
|
|
556
|
+
| `toRecipientMain` | ✅ | ✅ | ✅ | ❌ |
|
|
557
|
+
| `toSelf` | ✅ | ✅ | ❌ | ❌ |
|
|
558
|
+
| `toRecipient` | ❌ | ❌ | ✅ | ✅ |
|
|
559
|
+
| `toSelfMain` | ✅ | ❌ | ❌ | ❌ |
|
|
560
|
+
| `toRecipientMainOnly` | ❌ | ❌ | ✅ | ❌ |
|
|
561
|
+
|
|
562
|
+
```javascript
|
|
563
|
+
// Everyone gets it (default)
|
|
564
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toAll' })
|
|
565
|
+
|
|
566
|
+
// Main phones only — no companion devices on either side
|
|
567
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toMainOnly' })
|
|
568
|
+
|
|
569
|
+
// Recipient's main phone only — your companions still get it
|
|
570
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toRecipientMain' })
|
|
571
|
+
|
|
572
|
+
// Your devices only — recipient gets nothing
|
|
573
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toSelf' })
|
|
574
|
+
|
|
575
|
+
// Recipient all devices — you see nothing
|
|
576
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toRecipient' })
|
|
577
|
+
|
|
578
|
+
// Your main phone only — nothing else
|
|
579
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toSelfMain' })
|
|
580
|
+
|
|
581
|
+
// Recipient main phone only — you see nothing
|
|
582
|
+
await sock.sendMessage(jid, { text: 'Hello!' }, { deliveryMode: 'toRecipientMainOnly' })
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
> `deliveryMode` is optional — omitting it defaults to `toAll` and behaves exactly like normal.
|
|
586
|
+
|
|
587
|
+
### Media Messages
|
|
588
|
+
|
|
589
|
+
> You can pass `{ url: '...' }`, a `Buffer`, a file path string, or `{ stream: Stream }` for any media type.
|
|
590
|
+
|
|
591
|
+
#### Image
|
|
592
|
+
```javascript
|
|
593
|
+
// From URL
|
|
594
|
+
await sock.sendMessage(jid, {
|
|
595
|
+
image: { url: 'https://example.com/image.jpg' },
|
|
596
|
+
caption: 'Caption here'
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
// From Buffer
|
|
600
|
+
await sock.sendMessage(jid, { image: buffer, caption: 'From buffer' })
|
|
601
|
+
|
|
602
|
+
// From file
|
|
603
|
+
await sock.sendMessage(jid, { image: fs.readFileSync('./image.jpg') })
|
|
604
|
+
|
|
605
|
+
// View once
|
|
606
|
+
await sock.sendMessage(jid, { image: { url: './secret.jpg' }, viewOnce: true })
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### Video
|
|
610
|
+
```javascript
|
|
611
|
+
await sock.sendMessage(jid, {
|
|
612
|
+
video: { url: './video.mp4' },
|
|
613
|
+
caption: 'Watch this!',
|
|
614
|
+
gifPlayback: false, // true for GIF
|
|
615
|
+
ptv: false // true for video note (circle)
|
|
616
|
+
})
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
#### Audio
|
|
620
|
+
```javascript
|
|
621
|
+
await sock.sendMessage(jid, {
|
|
622
|
+
audio: { url: './audio.mp3' },
|
|
623
|
+
mimetype: 'audio/mp4',
|
|
624
|
+
ptt: true // true = voice message, false = audio file
|
|
625
|
+
})
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
> Convert to voice-compatible format: `ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg`
|
|
629
|
+
|
|
630
|
+
#### Document
|
|
631
|
+
```javascript
|
|
632
|
+
await sock.sendMessage(jid, {
|
|
633
|
+
document: { url: './file.pdf' },
|
|
634
|
+
fileName: 'document.pdf',
|
|
635
|
+
mimetype: 'application/pdf',
|
|
636
|
+
caption: 'Here is the file'
|
|
637
|
+
})
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
#### Sticker
|
|
641
|
+
```javascript
|
|
642
|
+
await sock.sendMessage(jid, { sticker: { url: './sticker.webp' } })
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
#### Location
|
|
646
|
+
```javascript
|
|
647
|
+
await sock.sendMessage(jid, {
|
|
648
|
+
location: {
|
|
649
|
+
degreesLatitude: 24.121231,
|
|
650
|
+
degreesLongitude: 55.1121221,
|
|
651
|
+
name: 'Location Name',
|
|
652
|
+
address: 'Full Address Here'
|
|
653
|
+
}
|
|
654
|
+
})
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
#### Contact
|
|
658
|
+
```javascript
|
|
659
|
+
const vcard = 'BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nORG:zervonex;\nTEL;type=CELL;waid=1234567890:+1 234 567 890\nEND:VCARD'
|
|
660
|
+
|
|
661
|
+
await sock.sendMessage(jid, {
|
|
662
|
+
contacts: {
|
|
663
|
+
displayName: 'John Doe',
|
|
664
|
+
contacts: [{ vcard }]
|
|
665
|
+
}
|
|
666
|
+
})
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
#### Reaction
|
|
670
|
+
```javascript
|
|
671
|
+
await sock.sendMessage(jid, {
|
|
672
|
+
react: {
|
|
673
|
+
text: '💖', // empty string removes reaction
|
|
674
|
+
key: message.key
|
|
675
|
+
}
|
|
676
|
+
})
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
#### Poll
|
|
680
|
+
```javascript
|
|
681
|
+
// Standard poll
|
|
682
|
+
await sock.sendMessage(jid, {
|
|
683
|
+
poll: {
|
|
684
|
+
name: 'Favorite Color?',
|
|
685
|
+
values: ['Red', 'Blue', 'Green'],
|
|
686
|
+
selectableOptionsCount: 1,
|
|
687
|
+
toAnnouncementGroup: false
|
|
688
|
+
}
|
|
689
|
+
})
|
|
690
|
+
|
|
691
|
+
// Quiz poll (single correct answer)
|
|
692
|
+
await sock.sendMessage(jid, {
|
|
693
|
+
poll: {
|
|
694
|
+
name: 'What is 2+2?',
|
|
695
|
+
values: ['3', '4', '5'],
|
|
696
|
+
selectableOptionsCount: 1,
|
|
697
|
+
pollType: 1, // 1 = quiz
|
|
698
|
+
correctAnswer: '4'
|
|
699
|
+
}
|
|
700
|
+
})
|
|
701
|
+
|
|
702
|
+
// Timed poll
|
|
703
|
+
await sock.sendMessage(jid, {
|
|
704
|
+
poll: {
|
|
705
|
+
name: 'Quick vote!',
|
|
706
|
+
values: ['Yes', 'No'],
|
|
707
|
+
endTime: Math.floor(Date.now() / 1000) + 3600, // 1 hour
|
|
708
|
+
hideParticipantName: true,
|
|
709
|
+
allowAddOption: false
|
|
710
|
+
}
|
|
711
|
+
})
|
|
712
|
+
|
|
713
|
+
// Or use the Poll builder — see Builder API section
|
|
714
|
+
await sock.poll()
|
|
715
|
+
.name('Favorite Color?')
|
|
716
|
+
.options(['Red', 'Blue', 'Green'])
|
|
717
|
+
.send(jid)
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
#### Pin Message
|
|
721
|
+
```javascript
|
|
722
|
+
await sock.sendMessage(jid, {
|
|
723
|
+
pin: {
|
|
724
|
+
type: 1, // 0 to unpin
|
|
725
|
+
time: 86400, // 24h = 86400 | 7d = 604800 | 30d = 2592000
|
|
726
|
+
key: message.key
|
|
727
|
+
}
|
|
728
|
+
})
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
#### Keep Message
|
|
732
|
+
```javascript
|
|
733
|
+
await sock.sendMessage(jid, {
|
|
734
|
+
keep: message.key,
|
|
735
|
+
type: 1, // 2 to unkeep
|
|
736
|
+
time: 86400
|
|
737
|
+
})
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
#### Disappearing Messages
|
|
741
|
+
```javascript
|
|
742
|
+
// Enable (seconds: 86400 = 24h, 604800 = 7d, 7776000 = 90d)
|
|
743
|
+
await sock.sendMessage(jid, { disappearingMessagesInChat: 86400 })
|
|
744
|
+
|
|
745
|
+
// Disable
|
|
746
|
+
await sock.sendMessage(jid, { disappearingMessagesInChat: false })
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
#### Forward Message
|
|
750
|
+
```javascript
|
|
751
|
+
await sock.sendMessage(jid, { forward: message, force: true })
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
#### Edit Message
|
|
755
|
+
```javascript
|
|
756
|
+
await sock.sendMessage(jid, {
|
|
757
|
+
text: 'Updated text',
|
|
758
|
+
edit: originalMessage.key
|
|
759
|
+
})
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
#### Delete Message
|
|
763
|
+
```javascript
|
|
764
|
+
const sent = await sock.sendMessage(jid, { text: 'hello' })
|
|
765
|
+
await sock.sendMessage(jid, { delete: sent.key })
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
### 🎭 Fake Quoted Messages
|
|
771
|
+
|
|
772
|
+
Fake a reply without an actual original message — useful for AI responses, status reposts, custom UIs and more. Only the bare minimum fields are needed — WhatsApp fills in the rest visually.
|
|
773
|
+
|
|
774
|
+
#### Text Quote
|
|
775
|
+
```javascript
|
|
776
|
+
await sock.sendMessage(jid, { text: 'Actual message' }, {
|
|
777
|
+
quoted: {
|
|
778
|
+
key: { remoteJid: jid, fromMe: false, id: 'FAKE_' + Date.now(), participant: '1234567890@s.whatsapp.net' },
|
|
779
|
+
message: { conversation: 'Fake quoted text' }
|
|
780
|
+
}
|
|
781
|
+
})
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
#### Image Quote
|
|
785
|
+
```javascript
|
|
786
|
+
await sock.sendMessage(jid, { text: 'Replying to image' }, {
|
|
787
|
+
quoted: {
|
|
788
|
+
key: { remoteJid: jid, fromMe: false, id: 'FAKE_' + Date.now(), participant: '1234567890@s.whatsapp.net' },
|
|
789
|
+
message: { imageMessage: { caption: 'Fake image caption' } }
|
|
790
|
+
}
|
|
791
|
+
})
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
#### Sticker Quote
|
|
795
|
+
```javascript
|
|
796
|
+
await sock.sendMessage(jid, { text: 'Replying to sticker' }, {
|
|
797
|
+
quoted: {
|
|
798
|
+
key: { remoteJid: jid, fromMe: false, id: 'FAKE_' + Date.now(), participant: '1234567890@s.whatsapp.net' },
|
|
799
|
+
message: { stickerMessage: {} }
|
|
800
|
+
}
|
|
801
|
+
})
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
#### AI / Bot Quote
|
|
805
|
+
```javascript
|
|
806
|
+
await sock.sendMessage(jid, { text: 'My response' }, {
|
|
807
|
+
quoted: {
|
|
808
|
+
key: { remoteJid: jid, fromMe: true, id: 'FAKE_' + Date.now() },
|
|
809
|
+
message: { extendedTextMessage: { text: 'AI generated this', title: 'NexusAI' } }
|
|
810
|
+
}
|
|
811
|
+
})
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
#### Status Quote
|
|
815
|
+
```javascript
|
|
816
|
+
await sock.sendMessage(jid, { text: 'Replying to your status!' }, {
|
|
817
|
+
quoted: {
|
|
818
|
+
key: { remoteJid: 'status@broadcast', fromMe: false, id: 'FAKE_' + Date.now(), participant: '1234567890@s.whatsapp.net' },
|
|
819
|
+
message: { conversation: 'Original status text' }
|
|
820
|
+
}
|
|
821
|
+
})
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
#### Key Fields
|
|
825
|
+
|
|
826
|
+
| Field | Description |
|
|
827
|
+
|-------|-------------|
|
|
828
|
+
| `remoteJid` | Where the quoted message appears to be from (`jid`, `status@broadcast`, group etc.) |
|
|
829
|
+
| `fromMe` | `true` = appears sent by you/bot, `false` = appears sent by someone else |
|
|
830
|
+
| `id` | Any unique string — `'FAKE_' + Date.now()` avoids collisions |
|
|
831
|
+
| `participant` | Required in groups/status — the person who appears to have sent it |
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
835
|
+
### Buttons & Interactive Messages
|
|
836
|
+
|
|
837
|
+
#### Text with Buttons
|
|
838
|
+
```javascript
|
|
839
|
+
await sock.sendMessage(jid, {
|
|
840
|
+
text: 'Choose an option',
|
|
841
|
+
footer: '© zervonex',
|
|
842
|
+
buttons: [
|
|
843
|
+
{
|
|
844
|
+
name: 'quick_reply',
|
|
845
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Option 1', id: 'opt1' })
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
name: 'cta_url',
|
|
849
|
+
buttonParamsJson: JSON.stringify({
|
|
850
|
+
display_text: 'Visit Website',
|
|
851
|
+
url: 'https://zervonex.com',
|
|
852
|
+
merchant_url: 'https://zervonex.com'
|
|
853
|
+
})
|
|
854
|
+
}
|
|
855
|
+
]
|
|
856
|
+
})
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
#### Image / Video / Document with Buttons
|
|
860
|
+
```javascript
|
|
861
|
+
await sock.sendMessage(jid, {
|
|
862
|
+
image: { url: 'https://example.com/image.jpg' },
|
|
863
|
+
caption: 'Description',
|
|
864
|
+
footer: '© zervonex',
|
|
865
|
+
buttons: [
|
|
866
|
+
{
|
|
867
|
+
name: 'quick_reply',
|
|
868
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Reply', id: 'btn1' })
|
|
869
|
+
}
|
|
870
|
+
]
|
|
871
|
+
})
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
#### All Button Types
|
|
875
|
+
|
|
876
|
+
| Type | `name` value | Required params |
|
|
877
|
+
|------|-------------|-----------------|
|
|
878
|
+
| Quick Reply | `quick_reply` | `display_text`, `id` |
|
|
879
|
+
| URL | `cta_url` | `display_text`, `url`, `merchant_url` |
|
|
880
|
+
| Call | `cta_call` | `display_text`, `phone_number` |
|
|
881
|
+
| Copy | `cta_copy` | `display_text`, `copy_code` |
|
|
882
|
+
| Open Webview | `cta_open_webview` | `display_text`, `url` |
|
|
883
|
+
| Reminder | `cta_reminder` | `display_text` |
|
|
884
|
+
| Cancel Reminder | `cta_cancel_reminder` | `display_text` |
|
|
885
|
+
| Address | `address` | `display_text` |
|
|
886
|
+
| Send Location | `send_location` | `display_text` |
|
|
887
|
+
| Flow | `flow` | `display_text`, `flow_id`, `flow_token` |
|
|
888
|
+
| Catalog | `catalog` | `display_text` |
|
|
889
|
+
| Review & Pay | `review_and_pay` | `display_text` |
|
|
890
|
+
| Review Order | `review_order` | `display_text` |
|
|
891
|
+
| Order Details | `order_details` | `display_text` |
|
|
892
|
+
| Payment Status | `payment_status` | `display_text` |
|
|
893
|
+
| Transaction Details | `transaction_details` | `display_text` |
|
|
894
|
+
| List/Select | `single_select` | `title`, `sections[].rows[]` |
|
|
895
|
+
|
|
896
|
+
#### List / Single Select
|
|
897
|
+
```javascript
|
|
898
|
+
{
|
|
899
|
+
name: 'single_select',
|
|
900
|
+
buttonParamsJson: JSON.stringify({
|
|
901
|
+
title: 'Select Option',
|
|
902
|
+
sections: [{
|
|
903
|
+
title: 'Section 1',
|
|
904
|
+
highlight_label: 'Popular',
|
|
905
|
+
rows: [
|
|
906
|
+
{ title: 'Option 1', description: 'Desc 1', id: 'opt1' },
|
|
907
|
+
{ title: 'Option 2', description: 'Desc 2', id: 'opt2' }
|
|
908
|
+
]
|
|
909
|
+
}]
|
|
910
|
+
})
|
|
911
|
+
}
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
#### Full Interactive Message
|
|
915
|
+
```javascript
|
|
916
|
+
await sock.sendMessage(jid, {
|
|
917
|
+
interactiveMessage: {
|
|
918
|
+
title: 'Interactive',
|
|
919
|
+
footer: '© zervonex',
|
|
920
|
+
image: { url: 'https://example.com/image.jpg' },
|
|
921
|
+
nativeFlowMessage: {
|
|
922
|
+
messageParamsJson: JSON.stringify({ /* optional advanced config */ }),
|
|
923
|
+
buttons: [
|
|
924
|
+
{
|
|
925
|
+
name: 'single_select',
|
|
926
|
+
buttonParamsJson: JSON.stringify({
|
|
927
|
+
title: 'Select',
|
|
928
|
+
sections: [{ title: 'Options', rows: [{ title: 'Option 1', id: 'opt1' }] }]
|
|
929
|
+
})
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
name: 'cta_copy',
|
|
933
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Copy Code', copy_code: 'NEXUS2025' })
|
|
934
|
+
}
|
|
935
|
+
]
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
})
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
#### interactiveButtons Shorthand
|
|
942
|
+
|
|
943
|
+
```javascript
|
|
944
|
+
// Without media header
|
|
945
|
+
await sock.sendMessage(jid, {
|
|
946
|
+
text: 'Description of Message',
|
|
947
|
+
title: 'Title of Message',
|
|
948
|
+
subtitle: 'Subtitle Message',
|
|
949
|
+
footer: 'Footer Message',
|
|
950
|
+
interactiveButtons: [
|
|
951
|
+
{
|
|
952
|
+
name: 'quick_reply',
|
|
953
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Quick Reply', id: 'button_1' })
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
name: 'cta_url',
|
|
957
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Visit Website', url: 'https://zervonex.com' })
|
|
958
|
+
}
|
|
959
|
+
]
|
|
960
|
+
}, { quoted: message })
|
|
961
|
+
|
|
962
|
+
// With image header
|
|
963
|
+
await sock.sendMessage(jid, {
|
|
964
|
+
image: { url: 'https://example.jpg' }, // or buffer
|
|
965
|
+
caption: 'Description of Message',
|
|
966
|
+
title: 'Title of Message',
|
|
967
|
+
subtitle: 'Subtitle Message',
|
|
968
|
+
footer: 'Footer Message',
|
|
969
|
+
media: true,
|
|
970
|
+
interactiveButtons: [
|
|
971
|
+
{
|
|
972
|
+
name: 'quick_reply',
|
|
973
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Quick Reply', id: 'button_1' })
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
name: 'cta_url',
|
|
977
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Visit Website', url: 'https://zervonex.com' })
|
|
978
|
+
}
|
|
979
|
+
]
|
|
980
|
+
}, { quoted: message })
|
|
981
|
+
|
|
982
|
+
// With product header
|
|
983
|
+
await sock.sendMessage(jid, {
|
|
984
|
+
product: {
|
|
985
|
+
productImage: { url: 'https://example.jpg' }, // or buffer
|
|
986
|
+
productImageCount: 1,
|
|
987
|
+
title: 'Product Title',
|
|
988
|
+
description: 'Product Description',
|
|
989
|
+
priceAmount1000: 20000 * 1000,
|
|
990
|
+
currencyCode: 'USD',
|
|
991
|
+
retailerId: 'Retail',
|
|
992
|
+
url: 'https://example.com'
|
|
993
|
+
},
|
|
994
|
+
businessOwnerJid: '1234@s.whatsapp.net',
|
|
995
|
+
caption: 'Description of Message',
|
|
996
|
+
title: 'Title of Message',
|
|
997
|
+
footer: 'Footer Message',
|
|
998
|
+
media: true,
|
|
999
|
+
interactiveButtons: [
|
|
1000
|
+
{
|
|
1001
|
+
name: 'quick_reply',
|
|
1002
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Quick Reply', id: 'button_1' })
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
name: 'cta_url',
|
|
1006
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Visit Website', url: 'https://zervonex.com' })
|
|
1007
|
+
}
|
|
1008
|
+
]
|
|
1009
|
+
}, { quoted: message })
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
#### Classic Buttons (Old Style)
|
|
1013
|
+
|
|
1014
|
+
For compatibility with older WhatsApp versions or specific use cases:
|
|
1015
|
+
|
|
1016
|
+
```javascript
|
|
1017
|
+
// Text with classic buttons
|
|
1018
|
+
await sock.sendMessage(jid, {
|
|
1019
|
+
text: 'Message with classic buttons',
|
|
1020
|
+
footer: 'Footer text',
|
|
1021
|
+
buttons: [
|
|
1022
|
+
{ buttonId: 'btn1', buttonText: { displayText: 'Button 1' }, type: 1 },
|
|
1023
|
+
{ buttonId: 'btn2', buttonText: { displayText: 'Button 2' }, type: 1 }
|
|
1024
|
+
],
|
|
1025
|
+
headerType: 1
|
|
1026
|
+
})
|
|
1027
|
+
|
|
1028
|
+
// Image header with classic buttons
|
|
1029
|
+
await sock.sendMessage(jid, {
|
|
1030
|
+
image: { url: 'https://example.com/image.jpg' },
|
|
1031
|
+
caption: 'Body text',
|
|
1032
|
+
footer: 'Footer',
|
|
1033
|
+
buttons: [
|
|
1034
|
+
{ buttonId: 'btn1', buttonText: { displayText: 'Button 1' }, type: 1 }
|
|
1035
|
+
],
|
|
1036
|
+
headerType: 3
|
|
1037
|
+
})
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
**Header Types:**
|
|
1041
|
+
|
|
1042
|
+
| Value | Type | Description |
|
|
1043
|
+
|-------|------|-------------|
|
|
1044
|
+
| `0` | EMPTY | No header |
|
|
1045
|
+
| `1` | TEXT | Text header |
|
|
1046
|
+
| `2` | DOCUMENT | Document header |
|
|
1047
|
+
| `3` | IMAGE | Image header |
|
|
1048
|
+
| `4` | VIDEO | Video header |
|
|
1049
|
+
| `5` | LOCATION | Location header |
|
|
1050
|
+
|
|
1051
|
+
**Button Types:**
|
|
1052
|
+
|
|
1053
|
+
| Value | Type | Description |
|
|
1054
|
+
|-------|------|-------------|
|
|
1055
|
+
| `1` | RESPONSE | Standard clickable button |
|
|
1056
|
+
| `2` | NATIVE_FLOW | Native flow button |
|
|
1057
|
+
|
|
1058
|
+
---
|
|
1059
|
+
|
|
1060
|
+
### Extended Message Types
|
|
1061
|
+
|
|
1062
|
+
All of these go through `sock.sendMessage` — the library detects the type automatically.
|
|
1063
|
+
|
|
1064
|
+
#### Album
|
|
1065
|
+
|
|
1066
|
+
```javascript
|
|
1067
|
+
// via sendMessage
|
|
1068
|
+
await sock.sendMessage(jid, {
|
|
1069
|
+
albumMessage: [
|
|
1070
|
+
{ image: { url: 'https://example.com/1.jpg' }, caption: 'Photo 1' },
|
|
1071
|
+
{ image: { url: 'https://example.com/2.jpg' }, caption: 'Photo 2' },
|
|
1072
|
+
{ video: { url: 'https://example.com/3.mp4' }, caption: 'Video 1' }
|
|
1073
|
+
]
|
|
1074
|
+
}, { albumDelay: 1500 })
|
|
1075
|
+
|
|
1076
|
+
// via shorthand
|
|
1077
|
+
await sock.sendAlbumMessage(jid, [
|
|
1078
|
+
{ image: { url: 'https://example.com/1.jpg' }, caption: 'Photo 1' },
|
|
1079
|
+
{ video: { url: 'https://example.com/2.mp4' }, caption: 'Video 1' }
|
|
1080
|
+
], quoted)
|
|
1081
|
+
|
|
1082
|
+
// via builder — see Builder API section
|
|
1083
|
+
await sock.album()
|
|
1084
|
+
.image('https://example.com/1.jpg', 'Photo 1')
|
|
1085
|
+
.image('https://example.com/2.jpg', 'Photo 2')
|
|
1086
|
+
.video('https://example.com/3.mp4', 'Video 1')
|
|
1087
|
+
.send(jid)
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
#### Carousel
|
|
1091
|
+
|
|
1092
|
+
```javascript
|
|
1093
|
+
// via sendMessage
|
|
1094
|
+
await sock.sendMessage(jid, {
|
|
1095
|
+
carouselMessage: {
|
|
1096
|
+
caption: 'Our Products',
|
|
1097
|
+
footer: 'Powered by zervonex',
|
|
1098
|
+
cards: [
|
|
1099
|
+
{
|
|
1100
|
+
header: { title: 'Card 1', hasMediaAttachment: false },
|
|
1101
|
+
body: { text: 'Description of card 1' },
|
|
1102
|
+
footer: { text: 'Footer' },
|
|
1103
|
+
nativeFlowMessage: {
|
|
1104
|
+
buttons: [
|
|
1105
|
+
{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Select', id: 'card1' }) },
|
|
1106
|
+
{ name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Learn More', url: 'https://zervonex.com' }) }
|
|
1107
|
+
]
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
{
|
|
1111
|
+
header: { title: 'Card 2', hasMediaAttachment: false },
|
|
1112
|
+
body: { text: 'Description of card 2' },
|
|
1113
|
+
footer: { text: 'Footer' },
|
|
1114
|
+
nativeFlowMessage: {
|
|
1115
|
+
buttons: [
|
|
1116
|
+
{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Select', id: 'card2' }) }
|
|
1117
|
+
]
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
]
|
|
1121
|
+
}
|
|
1122
|
+
})
|
|
1123
|
+
|
|
1124
|
+
// via builder — see Builder API section
|
|
1125
|
+
await sock.carousel()
|
|
1126
|
+
.setCaption('Our Products')
|
|
1127
|
+
.setFooter('Powered by zervonex')
|
|
1128
|
+
.card(sock.button().setBody('Card 1 description').reply('Select', 'card1').url('Learn More', 'https://zervonex.com'))
|
|
1129
|
+
.card(sock.button().setBody('Card 2 description').reply('Select', 'card2'))
|
|
1130
|
+
.send(jid)
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1133
|
+
#### Event
|
|
1134
|
+
|
|
1135
|
+
```javascript
|
|
1136
|
+
// via sendMessage
|
|
1137
|
+
await sock.sendMessage(jid, {
|
|
1138
|
+
eventMessage: {
|
|
1139
|
+
name: 'NexusTech Conference',
|
|
1140
|
+
description: 'Annual developer conference',
|
|
1141
|
+
location: { degreesLatitude: 6.5244, degreesLongitude: 3.3792, name: 'Lagos, Nigeria' },
|
|
1142
|
+
joinLink: 'https://meet.example.com/nexusconf',
|
|
1143
|
+
startTime: Math.floor(Date.now() / 1000) + 86400,
|
|
1144
|
+
endTime: Math.floor(Date.now() / 1000) + 172800,
|
|
1145
|
+
extraGuestsAllowed: true,
|
|
1146
|
+
hasReminder: true,
|
|
1147
|
+
reminderOffsetSec: 3600 // remind 1 hour before
|
|
1148
|
+
}
|
|
1149
|
+
})
|
|
1150
|
+
|
|
1151
|
+
// via builder — see Builder API section
|
|
1152
|
+
await sock.event()
|
|
1153
|
+
.setName('NexusTech Conference')
|
|
1154
|
+
.setDescription('Annual developer conference')
|
|
1155
|
+
.setLocation({ degreesLatitude: 6.5244, degreesLongitude: 3.3792, name: 'Lagos, Nigeria' })
|
|
1156
|
+
.setJoinLink('https://meet.example.com/nexusconf')
|
|
1157
|
+
.setStartTime(Math.floor(Date.now() / 1000) + 86400)
|
|
1158
|
+
.setEndTime(Math.floor(Date.now() / 1000) + 172800)
|
|
1159
|
+
.setReminder(3600)
|
|
1160
|
+
.send(jid)
|
|
1161
|
+
```
|
|
1162
|
+
|
|
1163
|
+
#### Request Payment
|
|
1164
|
+
|
|
1165
|
+
```javascript
|
|
1166
|
+
// via sendMessage
|
|
1167
|
+
await sock.sendMessage(jid, {
|
|
1168
|
+
requestPaymentMessage: {
|
|
1169
|
+
currency: 'NGN',
|
|
1170
|
+
amount: 10000000,
|
|
1171
|
+
from: '1234567890@s.whatsapp.net',
|
|
1172
|
+
note: 'Payment for order #123'
|
|
1173
|
+
}
|
|
1174
|
+
})
|
|
1175
|
+
|
|
1176
|
+
// via builder
|
|
1177
|
+
await sock.payment()
|
|
1178
|
+
.setCurrency('NGN')
|
|
1179
|
+
.setAmount(10000000)
|
|
1180
|
+
.setFrom('1234567890@s.whatsapp.net')
|
|
1181
|
+
.setNote('Payment for order #123')
|
|
1182
|
+
.send(jid)
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
#### Order
|
|
1186
|
+
|
|
1187
|
+
```javascript
|
|
1188
|
+
// via sendMessage
|
|
1189
|
+
await sock.sendMessage(jid, {
|
|
1190
|
+
orderMessage: {
|
|
1191
|
+
orderId: 'ORDER_001',
|
|
1192
|
+
itemCount: 3,
|
|
1193
|
+
totalAmount1000: 45000000,
|
|
1194
|
+
totalCurrencyCode: 'NGN',
|
|
1195
|
+
orderTitle: 'My Order',
|
|
1196
|
+
message: 'Thank you for your order',
|
|
1197
|
+
sellerJid: sock.user.id,
|
|
1198
|
+
thumbnail: { url: 'https://example.com/product.jpg' }
|
|
1199
|
+
}
|
|
1200
|
+
})
|
|
1201
|
+
|
|
1202
|
+
// via builder
|
|
1203
|
+
await sock.order()
|
|
1204
|
+
.from({ orderId: 'ORDER_001', itemCount: 3, totalAmount1000: 45000000, totalCurrencyCode: 'NGN', orderTitle: 'My Order' })
|
|
1205
|
+
.send(jid)
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
#### Product Message
|
|
1209
|
+
```javascript
|
|
1210
|
+
await sock.sendMessage(jid, {
|
|
1211
|
+
productMessage: {
|
|
1212
|
+
title: 'Product Title',
|
|
1213
|
+
description: 'Product Description',
|
|
1214
|
+
thumbnail: 'https://example.com/img.png',
|
|
1215
|
+
productId: '123456789',
|
|
1216
|
+
retailerId: 'STORE',
|
|
1217
|
+
url: 'https://example.com',
|
|
1218
|
+
body: 'Product Body',
|
|
1219
|
+
footer: 'Product Footer',
|
|
1220
|
+
buttons: [
|
|
1221
|
+
{
|
|
1222
|
+
name: 'cta_url',
|
|
1223
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Buy Now', url: 'https://example.com' })
|
|
1224
|
+
}
|
|
1225
|
+
]
|
|
1226
|
+
}
|
|
1227
|
+
}, { quoted: message })
|
|
1228
|
+
```
|
|
1229
|
+
|
|
1230
|
+
#### Poll Result (Newsletter Style)
|
|
1231
|
+
```javascript
|
|
1232
|
+
await sock.sendMessage(jid, {
|
|
1233
|
+
pollResult: {
|
|
1234
|
+
name: 'Poll Title',
|
|
1235
|
+
votes: [['Option A', 42], ['Option B', 17]]
|
|
1236
|
+
}
|
|
1237
|
+
}, { quoted: message })
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
#### Group Story
|
|
1241
|
+
|
|
1242
|
+
Post a story/status visible only to a specific group.
|
|
1243
|
+
|
|
1244
|
+
> All media types accept a URL, Buffer, file path, or WhatsApp CDN URL — no manual download needed.
|
|
1245
|
+
|
|
1246
|
+
```javascript
|
|
1247
|
+
// via sendMessage
|
|
1248
|
+
await sock.sendMessage(jid, { groupStatus: { text: 'Hello group!' } })
|
|
1249
|
+
await sock.sendMessage(jid, { groupStatus: { image: { url: 'https://example.com/image.jpg' }, caption: 'Caption' } })
|
|
1250
|
+
await sock.sendMessage(jid, { groupStatus: { video: { url: 'https://example.com/video.mp4' }, caption: 'Caption' } })
|
|
1251
|
+
await sock.sendMessage(jid, { groupStatus: { audio: { url: 'https://example.com/audio.mp3' }, ptt: false } })
|
|
1252
|
+
|
|
1253
|
+
// via shorthand
|
|
1254
|
+
await sock.sendGroupStatusMessage(groupJid, { text: 'Hello group!' })
|
|
1255
|
+
await sock.sendGroupStatusMessage(groupJid, { image: { url: 'https://example.com/image.jpg' }, caption: 'Caption' })
|
|
1256
|
+
await sock.sendGroupStatusMessage(groupJid, { video: { url: 'https://example.com/video.mp4' }, caption: 'Caption' })
|
|
1257
|
+
await sock.sendGroupStatusMessage(groupJid, { audio: { url: 'https://example.com/audio.mp3' }, ptt: false })
|
|
1258
|
+
|
|
1259
|
+
// Media also accepts Buffer or file path
|
|
1260
|
+
await sock.sendGroupStatusMessage(groupJid, { image: buffer })
|
|
1261
|
+
await sock.sendGroupStatusMessage(groupJid, { image: fs.readFileSync('./image.jpg') })
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
#### Personal Status / Story (status@broadcast)
|
|
1265
|
+
|
|
1266
|
+
Post a story visible to all your contacts or a specific list.
|
|
1267
|
+
|
|
1268
|
+
```javascript
|
|
1269
|
+
// Text
|
|
1270
|
+
await sock.sendMessage('status@broadcast', { text: 'My status update!' })
|
|
1271
|
+
|
|
1272
|
+
// Image
|
|
1273
|
+
await sock.sendMessage('status@broadcast', { image: { url: 'https://example.com/image.jpg' }, caption: 'Caption' })
|
|
1274
|
+
|
|
1275
|
+
// Video
|
|
1276
|
+
await sock.sendMessage('status@broadcast', { video: { url: 'https://example.com/video.mp4' }, caption: 'Caption' })
|
|
1277
|
+
|
|
1278
|
+
// Audio
|
|
1279
|
+
await sock.sendMessage('status@broadcast', { audio: { url: 'https://example.com/audio.mp3' }, ptt: false })
|
|
1280
|
+
|
|
1281
|
+
// Send to specific contacts only
|
|
1282
|
+
await sock.sendMessage('status@broadcast', {
|
|
1283
|
+
text: 'Private status',
|
|
1284
|
+
statusJidList: [
|
|
1285
|
+
'1234567890@s.whatsapp.net',
|
|
1286
|
+
'0987654321@s.whatsapp.net'
|
|
1287
|
+
]
|
|
1288
|
+
})
|
|
1289
|
+
```
|
|
1290
|
+
|
|
1291
|
+
#### React to a Status
|
|
1292
|
+
```javascript
|
|
1293
|
+
// Method 1 — via sendMessage
|
|
1294
|
+
await sock.sendMessage('status@broadcast', {
|
|
1295
|
+
react: {
|
|
1296
|
+
text: '❤️',
|
|
1297
|
+
key: message.key // the key of the status message
|
|
1298
|
+
}
|
|
1299
|
+
}, {
|
|
1300
|
+
statusJidList: [message.key.participant] // the person who posted the status
|
|
1301
|
+
})
|
|
1302
|
+
|
|
1303
|
+
// Method 2 — via sendReaction shorthand
|
|
1304
|
+
await sock.sendReaction('status@broadcast', message.key, '❤️', {
|
|
1305
|
+
statusJidList: [message.key.participant]
|
|
1306
|
+
})
|
|
1307
|
+
```
|
|
1308
|
+
|
|
1309
|
+
#### Status Mention (tag someone in your story)
|
|
1310
|
+
|
|
1311
|
+
Mention specific users or groups in a story. They get a private notification.
|
|
1312
|
+
|
|
1313
|
+
```javascript
|
|
1314
|
+
// Text
|
|
1315
|
+
await sock.sendStatusMentions({ text: 'Hey @someone check this out!' }, ['1234567890@s.whatsapp.net'])
|
|
1316
|
+
|
|
1317
|
+
// Image
|
|
1318
|
+
await sock.sendStatusMentions({ image: { url: 'https://example.com/image.jpg' }, caption: 'Caption' }, ['1234567890@s.whatsapp.net'])
|
|
1319
|
+
|
|
1320
|
+
// Video
|
|
1321
|
+
await sock.sendStatusMentions({ video: { url: 'https://example.com/video.mp4' } }, ['1234567890@s.whatsapp.net'])
|
|
1322
|
+
|
|
1323
|
+
// Audio
|
|
1324
|
+
await sock.sendStatusMentions({ audio: { url: 'https://example.com/audio.mp3' }, ptt: true }, ['1234567890@s.whatsapp.net'])
|
|
1325
|
+
|
|
1326
|
+
// Tag a group (all members get notified)
|
|
1327
|
+
await sock.sendStatusMentions({ text: 'Hey group!' }, ['123456789@g.us'])
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
#### Sticker Pack
|
|
1331
|
+
|
|
1332
|
+
Send a full sticker pack. Supports buffers, file paths, and URLs. Packs over 60 stickers are automatically batched with a 2-second delay between batches.
|
|
1333
|
+
|
|
1334
|
+
```javascript
|
|
1335
|
+
// Method 1 — via sendMessage
|
|
1336
|
+
await sock.sendMessage(jid, {
|
|
1337
|
+
stickerPack: {
|
|
1338
|
+
name: 'My Stickers',
|
|
1339
|
+
publisher: 'zervonex',
|
|
1340
|
+
stickers: [
|
|
1341
|
+
{ data: buffer, emojis: ['😊'] },
|
|
1342
|
+
{ data: './sticker.png', emojis: ['😂'] },
|
|
1343
|
+
{ data: './sticker.webp', emojis: ['🎉'] },
|
|
1344
|
+
{ data: './sticker.gif', emojis: ['✨'], isAnimated: true },
|
|
1345
|
+
{ data: './sticker.webm', emojis: ['🎬'], isAnimated: true },
|
|
1346
|
+
{ data: 'https://example.com/sticker.jpg', emojis: ['❤️'] },
|
|
1347
|
+
{ data: buffer, type: StickerTypes.ROUNDED, emojis: ['🔥'] },
|
|
1348
|
+
],
|
|
1349
|
+
cover: coverBuffer // optional — defaults to first sticker
|
|
1350
|
+
}
|
|
1351
|
+
}, { quoted: message })
|
|
1352
|
+
|
|
1353
|
+
// Method 2 — dedicated shorthand
|
|
1354
|
+
await sock.stickerPackMessage(jid, {
|
|
1355
|
+
name: 'My Stickers',
|
|
1356
|
+
publisher: 'zervonex',
|
|
1357
|
+
stickers: [
|
|
1358
|
+
{ data: buffer, emojis: ['😊'] },
|
|
1359
|
+
{ data: './sticker.png', emojis: ['😂'] }
|
|
1360
|
+
],
|
|
1361
|
+
cover: coverBuffer
|
|
1362
|
+
}, { quoted: message })
|
|
1363
|
+
```
|
|
1364
|
+
|
|
1365
|
+
**Per-sticker options:**
|
|
1366
|
+
|
|
1367
|
+
| Field | Type | Default | Description |
|
|
1368
|
+
|-------|------|---------|-------------|
|
|
1369
|
+
| `data` | Buffer \| string | required | Buffer, file path, URL, or SVG string |
|
|
1370
|
+
| `emojis` | string[] | `[]` | Associated emojis shown in WhatsApp sticker picker |
|
|
1371
|
+
| `type` | StickerTypes | `ROUNDED` | Crop/shape style (see below) |
|
|
1372
|
+
| `isAnimated` | boolean | `false` | Mark as animated (for GIF/WebM inputs) |
|
|
1373
|
+
| `isLottie` | boolean | `false` | Mark as Lottie animated (for TGS inputs) |
|
|
1374
|
+
| `accessibilityLabel` | string | `''` | Accessibility label for the sticker |
|
|
1375
|
+
|
|
1376
|
+
**Sticker types (`StickerTypes`):**
|
|
1377
|
+
|
|
1378
|
+
| Value | Description |
|
|
1379
|
+
|-------|-------------|
|
|
1380
|
+
| `StickerTypes.DEFAULT` | Original aspect ratio, no crop |
|
|
1381
|
+
| `StickerTypes.CROPPED` | Cropped to 512×512 |
|
|
1382
|
+
| `StickerTypes.FULL` | Stretched to fill 512×512 |
|
|
1383
|
+
| `StickerTypes.CIRCLE` | Circular mask |
|
|
1384
|
+
| `StickerTypes.ROUNDED` | Rounded corners |
|
|
1385
|
+
|
|
1386
|
+
**Supported input formats:**
|
|
1387
|
+
|
|
1388
|
+
| Format | Support | Notes |
|
|
1389
|
+
|--------|---------|-------|
|
|
1390
|
+
| WebP | ✅ Full | Static and animated, passed through sharp |
|
|
1391
|
+
| PNG | ✅ Full | Auto-converted to WebP |
|
|
1392
|
+
| JPG/JPEG | ✅ Full | Auto-converted to WebP |
|
|
1393
|
+
| BMP | ✅ Full | Auto-converted to WebP |
|
|
1394
|
+
| SVG | ✅ Full | Rendered and converted to WebP |
|
|
1395
|
+
| GIF | ✅ Animated | Converted to animated WebP via sharp |
|
|
1396
|
+
| WebM (VP9) | ✅ Animated | Converted via ffmpeg → animated WebP |
|
|
1397
|
+
| MP4 | ✅ Animated | Converted via ffmpeg → animated WebP |
|
|
1398
|
+
| TGS | ✅ Animated | Telegram gzip-compressed Lottie — converted via rlottie WASM → animated WebP |
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
**Key behaviours:**
|
|
1402
|
+
- Packs >60 stickers are auto-batched with a 2-second delay between batches
|
|
1403
|
+
- Animated stickers (WebM/MP4) are converted directly via ffmpeg for best quality; static formats go through wa-sticker-formatter. EXIF metadata is embedded automatically for all formats.
|
|
1404
|
+
- Invalid or unprocessable stickers are gracefully skipped
|
|
1405
|
+
- Cover defaults to the first sticker if not provided
|
|
1406
|
+
|
|
1407
|
+
---
|
|
1408
|
+
|
|
1409
|
+
---
|
|
1410
|
+
|
|
1411
|
+
### AI Rich Messages
|
|
1412
|
+
|
|
1413
|
+
All types can be sent two ways:
|
|
1414
|
+
- **`sock.sendMessage`** with an `aiRich` content key
|
|
1415
|
+
- **`sock.airich()`** fluent builder — chain methods and call `.send(jid)`
|
|
1416
|
+
|
|
1417
|
+
---
|
|
1418
|
+
|
|
1419
|
+
##### Code Block
|
|
1420
|
+
|
|
1421
|
+
```javascript
|
|
1422
|
+
// via sendMessage
|
|
1423
|
+
await sock.sendMessage(jid, {
|
|
1424
|
+
aiRich: {
|
|
1425
|
+
language: 'javascript',
|
|
1426
|
+
code: `async function fetchUser(id) {
|
|
1427
|
+
const res = await fetch(\`/api/users/\${id}\`)
|
|
1428
|
+
if (!res.ok) throw new Error('Not found')
|
|
1429
|
+
return res.json()
|
|
1430
|
+
}`,
|
|
1431
|
+
header: '**Fetch User Example**',
|
|
1432
|
+
footer: '_Requires Node 18+_'
|
|
1433
|
+
}
|
|
1434
|
+
}, { quoted: message })
|
|
1435
|
+
|
|
1436
|
+
// via builder
|
|
1437
|
+
await sock.airich()
|
|
1438
|
+
.setTitle('Code Example')
|
|
1439
|
+
.addCode('javascript', `const greet = name => \`Hello, \${name}!\``)
|
|
1440
|
+
.send(jid)
|
|
1441
|
+
|
|
1442
|
+
// via shorthand
|
|
1443
|
+
await sock.sendCodeBlock(jid, code, quoted, { language: 'javascript', title: 'Example', footer: '© zervonex' })
|
|
1444
|
+
await sock.sendCodeBlockV2(jid, code, quoted, { language: 'go', title: 'Go Example', text: 'Here is a Go snippet:', footer: '© zervonex' })
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
**Supported languages:** Any of the 190+ languages supported by PrismJS — `javascript`, `typescript`, `python`, `rust`, `go`, `java`, `cpp`, `kotlin`, `swift`, `bash`, `sql`, `dockerfile`, `solidity`, `graphql`, and many more.
|
|
1448
|
+
|
|
1449
|
+
---
|
|
1450
|
+
|
|
1451
|
+
##### Table
|
|
1452
|
+
|
|
1453
|
+
```javascript
|
|
1454
|
+
// via sendMessage
|
|
1455
|
+
await sock.sendMessage(jid, {
|
|
1456
|
+
aiRich: {
|
|
1457
|
+
table: [
|
|
1458
|
+
'Java vs JavaScript',
|
|
1459
|
+
['Feature', 'Java', 'JavaScript'],
|
|
1460
|
+
['Type', 'Compiled', 'Interpreted'],
|
|
1461
|
+
['Typing', 'Static', 'Dynamic'],
|
|
1462
|
+
['Main Use', 'Enterprise', 'Web']
|
|
1463
|
+
],
|
|
1464
|
+
footer: 'Hope this helps!'
|
|
1465
|
+
}
|
|
1466
|
+
}, { quoted: message })
|
|
1467
|
+
|
|
1468
|
+
// via builder
|
|
1469
|
+
await sock.airich()
|
|
1470
|
+
.setTitle('Comparison')
|
|
1471
|
+
.addTable([
|
|
1472
|
+
['Feature', 'Java', 'JavaScript'],
|
|
1473
|
+
['Type', 'Compiled', 'Interpreted'],
|
|
1474
|
+
['Typing', 'Static', 'Dynamic']
|
|
1475
|
+
])
|
|
1476
|
+
.send(jid)
|
|
1477
|
+
|
|
1478
|
+
// via shorthand
|
|
1479
|
+
await sock.sendTable(jid, 'Java vs JavaScript', ['Feature', 'Java', 'JavaScript'], [
|
|
1480
|
+
['Type', 'Compiled', 'Interpreted'],
|
|
1481
|
+
['Typing', 'Static', 'Dynamic']
|
|
1482
|
+
], quoted, { footer: 'Hope this helps!' })
|
|
1483
|
+
|
|
1484
|
+
// sendTableV2 — pipe-delimited string format
|
|
1485
|
+
await sock.sendTableV2(jid, [
|
|
1486
|
+
'Java vs JavaScript',
|
|
1487
|
+
'Feature | Java | JavaScript',
|
|
1488
|
+
'Type | Compiled | Interpreted;;Typing | Static | Dynamic'
|
|
1489
|
+
], quoted, { footer: 'Hope this helps!' })
|
|
1490
|
+
|
|
1491
|
+
// sendList — two-column key/value style
|
|
1492
|
+
await sock.sendList(jid, 'Bot Info', [
|
|
1493
|
+
['Name', 'zervonex'],
|
|
1494
|
+
['Version', '2.2.7'],
|
|
1495
|
+
['Developer', 'zervonex']
|
|
1496
|
+
], quoted, { footer: '© zervonex' })
|
|
1497
|
+
```
|
|
1498
|
+
|
|
1499
|
+
---
|
|
1500
|
+
|
|
1501
|
+
##### Text
|
|
1502
|
+
|
|
1503
|
+
```javascript
|
|
1504
|
+
// via sendMessage
|
|
1505
|
+
await sock.sendMessage(jid, {
|
|
1506
|
+
aiRich: {
|
|
1507
|
+
text: '## Hello\n\nThis supports **markdown**:\n\n- Bold\n- Lists\n- Headers',
|
|
1508
|
+
footer: '_Powered by zervonex_'
|
|
1509
|
+
}
|
|
1510
|
+
}, { quoted: message })
|
|
1511
|
+
|
|
1512
|
+
// multiple text blocks
|
|
1513
|
+
await sock.sendMessage(jid, {
|
|
1514
|
+
aiRich: {
|
|
1515
|
+
texts: ['## Title', 'First paragraph', 'Second paragraph'],
|
|
1516
|
+
footer: '_zervonex_'
|
|
1517
|
+
}
|
|
1518
|
+
}, { quoted: message })
|
|
1519
|
+
|
|
1520
|
+
// via builder
|
|
1521
|
+
await sock.airich()
|
|
1522
|
+
.addText('## Hello World\nThis is *bold* and _italic_.')
|
|
1523
|
+
.addFOAText('# zervonex\n## Powered by @zervonex/baileys')
|
|
1524
|
+
.addTip('Always validate user input before processing.')
|
|
1525
|
+
.addMetadata('Generated just now · NexusBot v2.2.7')
|
|
1526
|
+
.send(jid)
|
|
1527
|
+
```
|
|
1528
|
+
|
|
1529
|
+
---
|
|
1530
|
+
|
|
1531
|
+
##### Links & Search Sources
|
|
1532
|
+
|
|
1533
|
+
```javascript
|
|
1534
|
+
// via sendMessage
|
|
1535
|
+
await sock.sendMessage(jid, {
|
|
1536
|
+
aiRich: {
|
|
1537
|
+
text: 'Upload complete:\n✅ Freeimage — {{IE_0}}view here{{/IE_0}}\n✅ Yardsansh — {{IE_1}}view here{{/IE_1}}',
|
|
1538
|
+
sources: [
|
|
1539
|
+
{ url: 'https://freeimage.host', displayName: 'Freeimage', subtitle: 'freeimage.host' },
|
|
1540
|
+
{ url: 'https://yardsansh.com', displayName: 'Yardsansh', subtitle: 'yardsansh.com' }
|
|
1541
|
+
],
|
|
1542
|
+
footer: '✨ Done!'
|
|
1543
|
+
}
|
|
1544
|
+
}, { quoted: message })
|
|
1545
|
+
|
|
1546
|
+
// via builder
|
|
1547
|
+
await sock.airich()
|
|
1548
|
+
.addText('Top results:')
|
|
1549
|
+
.addSource([
|
|
1550
|
+
{ title: 'MDN Web Docs', url: 'https://developer.mozilla.org', favicon: 'https://developer.mozilla.org/favicon.ico' },
|
|
1551
|
+
{ title: 'NPM Registry', url: 'https://npmjs.com', favicon: 'https://static.npmjs.com/favicon.ico' }
|
|
1552
|
+
])
|
|
1553
|
+
.send(jid)
|
|
1554
|
+
|
|
1555
|
+
// via shorthand
|
|
1556
|
+
await sock.sendLink(jid, 'Results:\n🔗 {{IE_0}}link one{{/IE_0}}', ['https://example.com/1'], quoted, { headerText: '📁 Results' })
|
|
1557
|
+
await sock.sendLinkV2(jid, 'Search results:', [{ url: 'https://npmjs.com', displayName: 'NPM', subtitle: 'npmjs.com' }], quoted)
|
|
1558
|
+
```
|
|
1559
|
+
|
|
1560
|
+
---
|
|
1561
|
+
|
|
1562
|
+
##### Images, Video, Reels
|
|
1563
|
+
|
|
1564
|
+
```javascript
|
|
1565
|
+
// via sendMessage
|
|
1566
|
+
await sock.sendMessage(jid, {
|
|
1567
|
+
aiRich: {
|
|
1568
|
+
text: 'Here are some results:',
|
|
1569
|
+
images: [
|
|
1570
|
+
{ url: 'https://example.com/img1.jpg', sourceUrl: 'https://example.com' },
|
|
1571
|
+
{ url: 'https://example.com/img2.jpg', sourceUrl: 'https://example.com' }
|
|
1572
|
+
]
|
|
1573
|
+
}
|
|
1574
|
+
}, { quoted: message })
|
|
1575
|
+
|
|
1576
|
+
// via builder
|
|
1577
|
+
await sock.airich()
|
|
1578
|
+
.setTitle('Image Preview')
|
|
1579
|
+
.addImage('https://example.com/image.jpg')
|
|
1580
|
+
.addVideo('https://example.com/clip.mp4')
|
|
1581
|
+
.addReels([{
|
|
1582
|
+
creator: 'Rick Astley',
|
|
1583
|
+
avatar_url: 'https://example.com/avatar.jpg',
|
|
1584
|
+
thumbnail_url: 'https://example.com/thumb.jpg',
|
|
1585
|
+
reels_url: 'https://youtube.com/watch?v=dQw4w9WgXcQ'
|
|
1586
|
+
}])
|
|
1587
|
+
.send(jid)
|
|
1588
|
+
```
|
|
1589
|
+
|
|
1590
|
+
---
|
|
1591
|
+
|
|
1592
|
+
##### Suggestions, Widgets, Footer Actions
|
|
1593
|
+
|
|
1594
|
+
```javascript
|
|
1595
|
+
// via builder
|
|
1596
|
+
await sock.airich()
|
|
1597
|
+
.addText('What would you like to do?')
|
|
1598
|
+
.addSuggest(['📥 Download Video', '🎨 Generate Image', '🔍 Web Search'])
|
|
1599
|
+
.addWidget([
|
|
1600
|
+
{ label: '📥 Download', tool_call_id: 'dl', kind: 'OTHER', toast: 'Downloading...' },
|
|
1601
|
+
{ label: '✅ Confirm', tool_call_id: 'confirm', kind: 'CONFIRM', toast: 'Confirmed!' },
|
|
1602
|
+
{ label: '❌ Cancel', tool_call_id: 'cancel', kind: 'CANCEL', toast: 'Cancelled.' }
|
|
1603
|
+
])
|
|
1604
|
+
.addFooterAction({ cta_text: '🔗 Visit GitHub', cta_type: 'OPEN_URL', cta_url: 'https://github.com/nexustechpro2' })
|
|
1605
|
+
.send(jid)
|
|
1606
|
+
```
|
|
1607
|
+
|
|
1608
|
+
---
|
|
1609
|
+
|
|
1610
|
+
##### Status Indicators
|
|
1611
|
+
|
|
1612
|
+
```javascript
|
|
1613
|
+
// via builder
|
|
1614
|
+
await sock.airich()
|
|
1615
|
+
.addText('Processing your request...')
|
|
1616
|
+
.addThinkingStatus('Searching the web...', 'WEB_SEARCH')
|
|
1617
|
+
.addThinkingStatus('Thinking deeply...', 'THINKING')
|
|
1618
|
+
.addProgressStatus('Almost done — 80%', true)
|
|
1619
|
+
.addProgressStatus('Done!', false)
|
|
1620
|
+
.send(jid)
|
|
1621
|
+
|
|
1622
|
+
// Task queue
|
|
1623
|
+
await sock.airich()
|
|
1624
|
+
.setTitle('Job Queue')
|
|
1625
|
+
.addTask({ taskId: 'task-1', title: 'Fetch data', subtitle: 'Calling API', status: 'DONE' })
|
|
1626
|
+
.addTask({ taskId: 'task-2', title: 'Process result', status: 'RUNNING' })
|
|
1627
|
+
.addTask({ taskId: 'task-3', title: 'Send response', status: 'PENDING' })
|
|
1628
|
+
.send(jid)
|
|
1629
|
+
```
|
|
1630
|
+
|
|
1631
|
+
---
|
|
1632
|
+
|
|
1633
|
+
##### Dividers & Spacers
|
|
1634
|
+
|
|
1635
|
+
```javascript
|
|
1636
|
+
await sock.airich()
|
|
1637
|
+
.setTitle('Layout Test')
|
|
1638
|
+
.addText('*Section A*')
|
|
1639
|
+
.addDivider() // horizontal line
|
|
1640
|
+
.addText('*Section B*')
|
|
1641
|
+
.addDivider('DOT') // dotted divider
|
|
1642
|
+
.addText('*Section C*')
|
|
1643
|
+
.addSpacer(3) // 3-line gap
|
|
1644
|
+
.addText('*Section D*')
|
|
1645
|
+
.send(jid)
|
|
1646
|
+
```
|
|
1647
|
+
|
|
1648
|
+
---
|
|
1649
|
+
|
|
1650
|
+
##### LaTeX
|
|
1651
|
+
|
|
1652
|
+
```javascript
|
|
1653
|
+
// via sendMessage
|
|
1654
|
+
await sock.sendMessage(jid, {
|
|
1655
|
+
aiRich: {
|
|
1656
|
+
latexText: 'The quadratic formula:',
|
|
1657
|
+
latex: [
|
|
1658
|
+
{ latexExpression: 'x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}', url: 'https://example.com/formula.png', width: 400, height: 80 }
|
|
1659
|
+
]
|
|
1660
|
+
}
|
|
1661
|
+
}, { quoted: message })
|
|
1662
|
+
|
|
1663
|
+
// via builder
|
|
1664
|
+
await sock.airich()
|
|
1665
|
+
.addText("Einstein's famous equation:")
|
|
1666
|
+
.addLatex({ expression: 'E = mc^2', imageUrl: 'https://example.com/emc2.png', width: 300, height: 60 })
|
|
1667
|
+
.send(jid)
|
|
1668
|
+
|
|
1669
|
+
// via shorthand
|
|
1670
|
+
await sock.sendLatex(jid, [
|
|
1671
|
+
{ latexExpression: 'E = mc^2', url: 'https://example.com/emc2.png', width: 300, height: 60 }
|
|
1672
|
+
], quoted, { text: 'Mass-energy equivalence:' })
|
|
1673
|
+
```
|
|
1674
|
+
|
|
1675
|
+
> Note: LaTeX requires a pre-rendered image URL. WhatsApp does not render LaTeX client-side.
|
|
1676
|
+
|
|
1677
|
+
---
|
|
1678
|
+
|
|
1679
|
+
##### Post & Product Cards
|
|
1680
|
+
|
|
1681
|
+
```javascript
|
|
1682
|
+
await sock.airich()
|
|
1683
|
+
.addPost({
|
|
1684
|
+
title: 'NexusBot v2.2.7 🚀',
|
|
1685
|
+
username: 'nexustechpro2',
|
|
1686
|
+
subtitle: 'GitHub',
|
|
1687
|
+
thumbnail_url: 'https://example.com/thumb.jpg',
|
|
1688
|
+
post_url: 'https://github.com/nexustechpro2',
|
|
1689
|
+
post_caption: 'New release — faster, smarter, better.',
|
|
1690
|
+
source_app: 'instagram',
|
|
1691
|
+
likes_count: 2048,
|
|
1692
|
+
comments_count: 128,
|
|
1693
|
+
is_verified: true
|
|
1694
|
+
})
|
|
1695
|
+
.addProduct({
|
|
1696
|
+
title: 'NexusBot Premium',
|
|
1697
|
+
brand: 'zervonex',
|
|
1698
|
+
price: '$9.99/mo',
|
|
1699
|
+
sale_price: '$4.99/mo',
|
|
1700
|
+
product_url: 'https://github.com/nexustechpro2',
|
|
1701
|
+
image_url: 'https://example.com/product.jpg'
|
|
1702
|
+
})
|
|
1703
|
+
.send(jid)
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
---
|
|
1707
|
+
|
|
1708
|
+
##### Map
|
|
1709
|
+
|
|
1710
|
+
```javascript
|
|
1711
|
+
await sock.airich()
|
|
1712
|
+
.addText('Our location:')
|
|
1713
|
+
.addMap([{
|
|
1714
|
+
latitude: 6.5244,
|
|
1715
|
+
longitude: 3.3792,
|
|
1716
|
+
name: 'Lagos, Nigeria',
|
|
1717
|
+
address: 'Lagos Island, Lagos State'
|
|
1718
|
+
}])
|
|
1719
|
+
.send(jid)
|
|
1720
|
+
```
|
|
1721
|
+
|
|
1722
|
+
---
|
|
1723
|
+
|
|
1724
|
+
##### Generating Placeholder
|
|
1725
|
+
|
|
1726
|
+
```javascript
|
|
1727
|
+
// Imagine placeholder (generation state)
|
|
1728
|
+
await sock.airich()
|
|
1729
|
+
.addText('Generating your image...')
|
|
1730
|
+
.addImagine({ mediaType: 'image', status: 'GENERATING', estimatedMs: 5000 })
|
|
1731
|
+
.send(jid)
|
|
1732
|
+
|
|
1733
|
+
// Standalone generation message with itemId for later edit
|
|
1734
|
+
const { msg, responseId, itemId } = await sock.sendRichGeneration(jid, {
|
|
1735
|
+
text: 'Generating...',
|
|
1736
|
+
mediaType: 'video',
|
|
1737
|
+
status: 'GENERATING',
|
|
1738
|
+
estimatedMs: 8000
|
|
1739
|
+
})
|
|
1740
|
+
|
|
1741
|
+
// Later — edit that same message with the finished result
|
|
1742
|
+
await sock.airich()
|
|
1743
|
+
.setResponseId(responseId)
|
|
1744
|
+
.addText('Here is your video!')
|
|
1745
|
+
.addImagine({ mediaType: 'video', url: 'https://example.com/result.mp4', status: 'READY' })
|
|
1746
|
+
.sendEdit(jid, msg.key.id)
|
|
1747
|
+
```
|
|
1748
|
+
|
|
1749
|
+
---
|
|
1750
|
+
|
|
1751
|
+
##### Load From / Edit
|
|
1752
|
+
|
|
1753
|
+
```javascript
|
|
1754
|
+
// Load an existing AIRich message back into the builder for editing
|
|
1755
|
+
const r = sock.airich()
|
|
1756
|
+
r.loadFrom(receivedMessage.message)
|
|
1757
|
+
r.addText('Additional content added!')
|
|
1758
|
+
await r.send(jid)
|
|
1759
|
+
|
|
1760
|
+
// Edit a sent AIRich message
|
|
1761
|
+
const sent = await sock.airich().addText('Original text').send(jid)
|
|
1762
|
+
await sock.airich()
|
|
1763
|
+
.addText('Updated text')
|
|
1764
|
+
.sendEdit(jid, sent.key.id)
|
|
1765
|
+
```
|
|
1766
|
+
|
|
1767
|
+
---
|
|
1768
|
+
|
|
1769
|
+
##### Capture & Relay
|
|
1770
|
+
|
|
1771
|
+
```javascript
|
|
1772
|
+
// Capture a received AIRich message for forwarding
|
|
1773
|
+
const captured = sock.captureAiRich(msg.message)
|
|
1774
|
+
|
|
1775
|
+
// Relay it to another jid
|
|
1776
|
+
if (captured) await sock.relayAiRich(targetJid, captured)
|
|
1777
|
+
```
|
|
1778
|
+
|
|
1779
|
+
---
|
|
1780
|
+
|
|
1781
|
+
##### Full Combo Example
|
|
1782
|
+
|
|
1783
|
+
```javascript
|
|
1784
|
+
// via sendMessage — everything in one object
|
|
1785
|
+
await sock.sendMessage(jid, {
|
|
1786
|
+
aiRich: {
|
|
1787
|
+
parts: [
|
|
1788
|
+
{ type: 'text', content: '## String Reversal' },
|
|
1789
|
+
{ type: 'code', language: 'javascript', content: `const reverse = s => s.split('').reverse().join('')` },
|
|
1790
|
+
{ type: 'text', content: 'Performance:' },
|
|
1791
|
+
{ type: 'table', table: ['Benchmarks', ['Method', 'Ops/sec'], ['split.reverse.join', '1.2M'], ['manual loop', '2.1M']] },
|
|
1792
|
+
{ type: 'sources', sources: [{ url: 'https://jsperf.app', displayName: 'JSPerf', subtitle: 'jsperf.app' }] }
|
|
1793
|
+
],
|
|
1794
|
+
footer: '_zervonex_'
|
|
1795
|
+
}
|
|
1796
|
+
}, { quoted: message })
|
|
1797
|
+
|
|
1798
|
+
// via builder — full combo
|
|
1799
|
+
await sock.airich()
|
|
1800
|
+
.setTitle('zervonex Bot')
|
|
1801
|
+
.setFooter('Powered by @zervonex/baileys latest')
|
|
1802
|
+
.addText('*Welcome to zervonex!*')
|
|
1803
|
+
.addDivider()
|
|
1804
|
+
.addCode('python', 'print("Hello from zervonex")')
|
|
1805
|
+
.addTable([
|
|
1806
|
+
['Plan', 'Price', 'Sessions'],
|
|
1807
|
+
['Basic', 'Free', '1'],
|
|
1808
|
+
['Pro', '$9/mo', '10'],
|
|
1809
|
+
['Enterprise', 'Custom', 'Unlimited']
|
|
1810
|
+
])
|
|
1811
|
+
.addTask({ taskId: 't1', title: 'Bot online', status: 'DONE' })
|
|
1812
|
+
.addMetadata('zervonex • v2.2.7 • 2026')
|
|
1813
|
+
.addSuggest(['View commands', 'Get support', 'Upgrade plan'])
|
|
1814
|
+
.addFooterAction({ cta_text: '📖 View Dashboard', cta_type: 'OPEN_URL', cta_url: 'https://github.com/nexustechpro2' })
|
|
1815
|
+
.addFOAText('_Reply with any message to continue_')
|
|
1816
|
+
.send(jid)
|
|
1817
|
+
|
|
1818
|
+
// via shorthand
|
|
1819
|
+
await sock.sendRichMessage(jid, {
|
|
1820
|
+
text: 'Hello from sendRichMessage!',
|
|
1821
|
+
code: 'console.log("works!")',
|
|
1822
|
+
language: 'javascript',
|
|
1823
|
+
footer: '_zervonex_'
|
|
1824
|
+
}, quoted)
|
|
1825
|
+
```
|
|
1826
|
+
|
|
1827
|
+
---
|
|
1828
|
+
|
|
1829
|
+
##### `aiRich` Options Reference
|
|
1830
|
+
|
|
1831
|
+
| Key | Type | Description |
|
|
1832
|
+
|-----|------|-------------|
|
|
1833
|
+
| `text` | `string` | Single markdown text block |
|
|
1834
|
+
| `texts` | `string[]` | Multiple text blocks in order |
|
|
1835
|
+
| `code` | `string \| { language, code }` | Single code block |
|
|
1836
|
+
| `codes` | `Array` | Multiple code blocks |
|
|
1837
|
+
| `language` | `string` | Default language for `code`/`codes` |
|
|
1838
|
+
| `table` | `Array` | `[title, headers[], ...rows[]]` |
|
|
1839
|
+
| `headers` + `rows` | `Array` | Alternative table format |
|
|
1840
|
+
| `images` | `Array` | Grid images with `url`, `sourceUrl` |
|
|
1841
|
+
| `sources` | `Array` | Search source cards |
|
|
1842
|
+
| `reels` | `Array` | Horizontal reel cards |
|
|
1843
|
+
| `latex` | `Array` | LaTeX expression objects |
|
|
1844
|
+
| `latexText` | `string` | Text shown above latex |
|
|
1845
|
+
| `parts` | `Array` | Composite ordered parts array |
|
|
1846
|
+
| `header` | `string` | Text prepended before content |
|
|
1847
|
+
| `footer` | `string` | Text appended after content |
|
|
1848
|
+
| `botJid` | `string` | Custom bot JID |
|
|
1849
|
+
| `responseId` | `string` | Custom response UUID |
|
|
1850
|
+
| `forwarded` | `boolean` | Set `false` to disable forwarded context |
|
|
1851
|
+
| `rawSections` | `Array` | Raw unified response sections (advanced) |
|
|
1852
|
+
| `rawSubmessages` | `Array` | Matching submessages for `rawSections` |
|
|
1853
|
+
|
|
1854
|
+
---
|
|
1855
|
+
|
|
1856
|
+
### Shorthand Wrappers
|
|
1857
|
+
|
|
1858
|
+
```javascript
|
|
1859
|
+
await sock.sendText(jid, 'Hello!', options)
|
|
1860
|
+
await sock.sendImage(jid, { url: './image.jpg' }, 'Caption', options)
|
|
1861
|
+
await sock.sendVideo(jid, buffer, 'Caption', options)
|
|
1862
|
+
await sock.sendDocument(jid, { url: './file.pdf' }, 'Caption', options)
|
|
1863
|
+
await sock.sendAudio(jid, { url: './audio.mp3' }, options)
|
|
1864
|
+
await sock.sendLocation(jid, { degreesLatitude: 24.12, degreesLongitude: 55.11, name: 'Place' }, options)
|
|
1865
|
+
await sock.sendPoll(jid, 'Question?', ['A', 'B', 'C'], false, options)
|
|
1866
|
+
await sock.sendReaction(jid, message.key, '💖', options)
|
|
1867
|
+
await sock.sendSticker(jid, { url: './sticker.webp' }, options)
|
|
1868
|
+
await sock.sendContact(jid, { vcard }, options)
|
|
1869
|
+
await sock.sendForward(jid, message, { force: true })
|
|
1870
|
+
|
|
1871
|
+
// ── AI Rich Messages ──────────────────────────────────────────────────────────
|
|
1872
|
+
await sock.sendCodeBlock(jid, code, quoted, { language, title, footer })
|
|
1873
|
+
await sock.sendCodeBlockV2(jid, code, quoted, { language, title, text, footer })
|
|
1874
|
+
await sock.sendTable(jid, title, headers, rows, quoted, { headerText, footer })
|
|
1875
|
+
await sock.sendTableV2(jid, tableArray, quoted, { headerText, text, footer })
|
|
1876
|
+
await sock.sendList(jid, title, items, quoted, { footer })
|
|
1877
|
+
await sock.sendLink(jid, text, links, quoted, { headerText, footer, botJid })
|
|
1878
|
+
await sock.sendLinkV2(jid, text, links, quoted, { headerText, footer, searchEngine })
|
|
1879
|
+
await sock.sendLatex(jid, expressions, quoted, { text, headerText, footer })
|
|
1880
|
+
await sock.sendRichMessage(jid, data, quoted)
|
|
1881
|
+
await sock.sendAlbumMessage(jid, items, quoted)
|
|
1882
|
+
await sock.sendGroupStatusMessage(jid, content)
|
|
1883
|
+
await sock.sendRichGeneration(jid, { text, mediaType, status, estimatedMs })
|
|
1884
|
+
await sock.sendUnifiedResponse(jid, sections, submessages, options)
|
|
1885
|
+
await sock.sendVerticalAlbumMessage(jid, { items: [...] })
|
|
1886
|
+
await sock.sendGridImageMessage(jid, { imageUrls: [...] })
|
|
1887
|
+
await sock.sendVideoGridMessage(jid, { videos: [...] })
|
|
1888
|
+
await sock.sendA2UIMessage(jid, { bloksWidget, nativeFlowMessage })
|
|
1889
|
+
await sock.sendA2UICommandMenu(jid, { title, rows, buttons, imageMessage })
|
|
1890
|
+
```
|
|
1891
|
+
|
|
1892
|
+
---
|
|
1893
|
+
|
|
1894
|
+
## ✏️ Message Modifications
|
|
1895
|
+
|
|
1896
|
+
```javascript
|
|
1897
|
+
// Edit
|
|
1898
|
+
await sock.sendMessage(jid, { text: 'Updated text', edit: originalMessage.key })
|
|
1899
|
+
|
|
1900
|
+
// Delete for everyone
|
|
1901
|
+
const sent = await sock.sendMessage(jid, { text: 'hello' })
|
|
1902
|
+
await sock.sendMessage(jid, { delete: sent.key })
|
|
1903
|
+
|
|
1904
|
+
// Pin (time in seconds: 86400=24h, 604800=7d, 2592000=30d)
|
|
1905
|
+
await sock.sendMessage(jid, { pin: { type: 1, time: 86400, key: message.key } })
|
|
1906
|
+
|
|
1907
|
+
// Unpin
|
|
1908
|
+
await sock.sendMessage(jid, { pin: { type: 0, time: 0, key: message.key } })
|
|
1909
|
+
```
|
|
1910
|
+
|
|
1911
|
+
---
|
|
1912
|
+
|
|
1913
|
+
## 📥 Media Download
|
|
1914
|
+
|
|
1915
|
+
```javascript
|
|
1916
|
+
import { downloadMediaMessage, getContentType } from '@zervonex/baileys'
|
|
1917
|
+
|
|
1918
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
1919
|
+
const msg = messages[0]
|
|
1920
|
+
if (!msg.message) return
|
|
1921
|
+
|
|
1922
|
+
const type = getContentType(msg.message)
|
|
1923
|
+
|
|
1924
|
+
if (type === 'imageMessage') {
|
|
1925
|
+
const buffer = await downloadMediaMessage(
|
|
1926
|
+
msg,
|
|
1927
|
+
'buffer',
|
|
1928
|
+
{},
|
|
1929
|
+
{ logger, reuploadRequest: sock.updateMediaMessage }
|
|
1930
|
+
)
|
|
1931
|
+
fs.writeFileSync('./downloaded.jpg', buffer)
|
|
1932
|
+
}
|
|
1933
|
+
})
|
|
1934
|
+
|
|
1935
|
+
// Re-upload expired media
|
|
1936
|
+
await sock.updateMediaMessage(msg)
|
|
1937
|
+
```
|
|
1938
|
+
|
|
1939
|
+
---
|
|
1940
|
+
|
|
1941
|
+
## 👥 Group Management
|
|
1942
|
+
|
|
1943
|
+
```javascript
|
|
1944
|
+
// Create group
|
|
1945
|
+
const group = await sock.groupCreate('Group Name', ['1234567890@s.whatsapp.net'])
|
|
1946
|
+
|
|
1947
|
+
// Add / Remove / Promote / Demote
|
|
1948
|
+
await sock.groupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'add')
|
|
1949
|
+
await sock.groupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'remove')
|
|
1950
|
+
await sock.groupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'promote')
|
|
1951
|
+
await sock.groupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'demote')
|
|
1952
|
+
|
|
1953
|
+
// Update group info
|
|
1954
|
+
await sock.groupUpdateSubject(groupJid, 'New Group Name')
|
|
1955
|
+
await sock.groupUpdateDescription(groupJid, 'New description')
|
|
1956
|
+
|
|
1957
|
+
// Settings
|
|
1958
|
+
await sock.groupSettingUpdate(groupJid, 'announcement') // only admins can send
|
|
1959
|
+
await sock.groupSettingUpdate(groupJid, 'not_announcement') // everyone can send
|
|
1960
|
+
await sock.groupSettingUpdate(groupJid, 'locked') // only admins edit info
|
|
1961
|
+
await sock.groupSettingUpdate(groupJid, 'unlocked') // everyone edits info
|
|
1962
|
+
|
|
1963
|
+
// Metadata
|
|
1964
|
+
const metadata = await sock.groupMetadata(groupJid)
|
|
1965
|
+
|
|
1966
|
+
// Invite link
|
|
1967
|
+
const code = await sock.groupInviteCode(groupJid)
|
|
1968
|
+
console.log(`https://chat.whatsapp.com/${code}`)
|
|
1969
|
+
|
|
1970
|
+
await sock.groupRevokeInvite(groupJid) // revoke invite link
|
|
1971
|
+
await sock.groupRevokeInviteV4(groupJid, '1234567890@s.whatsapp.net') // revoke a specific user's pending invite
|
|
1972
|
+
await sock.groupAcceptInvite('INVITE_CODE') // join group
|
|
1973
|
+
await sock.groupLeave(groupJid) // leave group
|
|
1974
|
+
```
|
|
1975
|
+
|
|
1976
|
+
### AI Groups
|
|
1977
|
+
|
|
1978
|
+
WhatsApp AI Groups are a special group type with Meta AI built-in as a participant.
|
|
1979
|
+
|
|
1980
|
+
```javascript
|
|
1981
|
+
// Create an AI group
|
|
1982
|
+
const group = await sock.aiGroupCreate('AI Study Group', ['1234567890@s.whatsapp.net'])
|
|
1983
|
+
|
|
1984
|
+
// Get AI group metadata
|
|
1985
|
+
const metadata = await sock.aiGroupMetadata(groupJid)
|
|
1986
|
+
|
|
1987
|
+
// Add the Meta AI bot to an existing AI group
|
|
1988
|
+
await sock.aiGroupAddBot(groupJid)
|
|
1989
|
+
|
|
1990
|
+
// Add / Remove / Promote / Demote participants
|
|
1991
|
+
await sock.aiGroupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'add')
|
|
1992
|
+
await sock.aiGroupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'remove')
|
|
1993
|
+
await sock.aiGroupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'promote')
|
|
1994
|
+
await sock.aiGroupParticipantsUpdate(groupJid, ['1234567890@s.whatsapp.net'], 'demote')
|
|
1995
|
+
|
|
1996
|
+
// Update subject
|
|
1997
|
+
await sock.aiGroupUpdateSubject(groupJid, 'New AI Group Name')
|
|
1998
|
+
|
|
1999
|
+
// Invite link
|
|
2000
|
+
const code = await sock.aiGroupInviteCode(groupJid)
|
|
2001
|
+
await sock.aiGroupRevokeInvite(groupJid)
|
|
2002
|
+
await sock.aiGroupAcceptInvite('INVITE_CODE')
|
|
2003
|
+
|
|
2004
|
+
// Leave
|
|
2005
|
+
await sock.aiGroupLeave(groupJid)
|
|
2006
|
+
|
|
2007
|
+
// Settings (announcement, not_announcement, locked, unlocked)
|
|
2008
|
+
await sock.aiGroupSettingUpdate(groupJid, 'announcement')
|
|
2009
|
+
|
|
2010
|
+
// Ephemeral messages
|
|
2011
|
+
await sock.aiGroupToggleEphemeral(groupJid, 86400) // 24h
|
|
2012
|
+
await sock.aiGroupToggleEphemeral(groupJid, 0) // disable
|
|
2013
|
+
```
|
|
2014
|
+
|
|
2015
|
+
---
|
|
2016
|
+
|
|
2017
|
+
## 📱 User Operations
|
|
2018
|
+
|
|
2019
|
+
```javascript
|
|
2020
|
+
// Check if number exists on WhatsApp
|
|
2021
|
+
const [result] = await sock.onWhatsApp('1234567890')
|
|
2022
|
+
if (result?.exists) console.log(result.jid)
|
|
2023
|
+
|
|
2024
|
+
// Profile picture
|
|
2025
|
+
const url = await sock.profilePictureUrl(jid, 'image') // 'image' = HD
|
|
2026
|
+
await sock.updateProfilePicture(jid, { url: './profile.jpg' })
|
|
2027
|
+
await sock.removeProfilePicture(jid)
|
|
2028
|
+
|
|
2029
|
+
// Status & name
|
|
2030
|
+
const status = await sock.fetchStatus(jid)
|
|
2031
|
+
await sock.updateProfileStatus('Available 24/7')
|
|
2032
|
+
await sock.updateProfileName('My Bot')
|
|
2033
|
+
|
|
2034
|
+
// Business profile
|
|
2035
|
+
const biz = await sock.getBusinessProfile(jid)
|
|
2036
|
+
|
|
2037
|
+
// Presence
|
|
2038
|
+
await sock.presenceSubscribe(jid)
|
|
2039
|
+
await sock.sendPresenceUpdate('composing', jid) // available | unavailable | composing | recording | paused
|
|
2040
|
+
|
|
2041
|
+
// Read messages
|
|
2042
|
+
await sock.readMessages([message.key])
|
|
2043
|
+
|
|
2044
|
+
// Block / Unblock
|
|
2045
|
+
await sock.updateBlockStatus(jid, 'block')
|
|
2046
|
+
await sock.updateBlockStatus(jid, 'unblock')
|
|
2047
|
+
|
|
2048
|
+
// Blocklist
|
|
2049
|
+
const blocked = await sock.fetchBlocklist()
|
|
2050
|
+
```
|
|
2051
|
+
|
|
2052
|
+
### Usernames
|
|
2053
|
+
|
|
2054
|
+
```javascript
|
|
2055
|
+
// Check if a username is available
|
|
2056
|
+
const result = await sock.checkUsername('zervonex')
|
|
2057
|
+
// { available: true, username: 'zervonex', session_id: '...' }
|
|
2058
|
+
// { available: false, suggestions: ['zervonex1', 'zervonex_'], ... }
|
|
2059
|
+
|
|
2060
|
+
// Check multiple usernames at once
|
|
2061
|
+
const results = await sock.checkUsernameMulti(['zervonex', 'zervonex'])
|
|
2062
|
+
|
|
2063
|
+
// Set your username
|
|
2064
|
+
await sock.setUsername('zervonex')
|
|
2065
|
+
|
|
2066
|
+
// Set with options
|
|
2067
|
+
await sock.setUsername('zervonex', { pin: '1234' })
|
|
2068
|
+
|
|
2069
|
+
// Check availability then set in one call
|
|
2070
|
+
await sock.checkAndSetUsername('zervonex')
|
|
2071
|
+
|
|
2072
|
+
// Get your current username
|
|
2073
|
+
const username = await sock.getMyUsername()
|
|
2074
|
+
|
|
2075
|
+
// Delete your username
|
|
2076
|
+
await sock.deleteUsername()
|
|
2077
|
+
|
|
2078
|
+
// Set a PIN on your username
|
|
2079
|
+
await sock.setUsernamePin('1234')
|
|
2080
|
+
|
|
2081
|
+
// Find a user by their @username
|
|
2082
|
+
const user = await sock.findUserByUsername('zervonex')
|
|
2083
|
+
// { jid: '1234567890@s.whatsapp.net', contact: true }
|
|
2084
|
+
|
|
2085
|
+
// Find a user with PIN-protected username
|
|
2086
|
+
const user = await sock.findUserByUsername('zervonex', '1234')
|
|
2087
|
+
|
|
2088
|
+
// Fetch usernames of multiple contacts
|
|
2089
|
+
const list = await sock.fetchContactUsernames('1234567890@s.whatsapp.net', '0987654321@s.whatsapp.net')
|
|
2090
|
+
|
|
2091
|
+
// Get username suggestions from WhatsApp
|
|
2092
|
+
const suggestions = await sock.getUsernameRecommendations()
|
|
2093
|
+
```
|
|
2094
|
+
|
|
2095
|
+
---
|
|
2096
|
+
|
|
2097
|
+
## 💬 Check Number Status
|
|
2098
|
+
|
|
2099
|
+
```javascript
|
|
2100
|
+
// Via socket instance
|
|
2101
|
+
const result = await sock.checkStatusWA('1234567890')
|
|
2102
|
+
|
|
2103
|
+
// Or direct import (no socket needed)
|
|
2104
|
+
import { checkStatusWA } from '@zervonex/baileys'
|
|
2105
|
+
const result = await checkStatusWA('1234567890')
|
|
2106
|
+
|
|
2107
|
+
// Response examples:
|
|
2108
|
+
// Active number
|
|
2109
|
+
{ number: '+1234567890', status: 'active', isBanned: false, isNeedOfficialWa: false, banInfo: null }
|
|
2110
|
+
|
|
2111
|
+
// Banned number
|
|
2112
|
+
{
|
|
2113
|
+
number: '+1234567890',
|
|
2114
|
+
status: 'banned',
|
|
2115
|
+
isBanned: true,
|
|
2116
|
+
isNeedOfficialWa: false,
|
|
2117
|
+
banInfo: {
|
|
2118
|
+
banType: 'temporary', // 'temporary' | 'permanent'
|
|
2119
|
+
violationType: '2',
|
|
2120
|
+
violationReason: 'Type 2',
|
|
2121
|
+
canAppeal: true, // false if permanent
|
|
2122
|
+
appealToken: 'xxxxx',
|
|
2123
|
+
banTime: 1716840000,
|
|
2124
|
+
banDate: '2024-05-28T00:00:00.000Z',
|
|
2125
|
+
appealStatus: 'PENDING',
|
|
2126
|
+
appealCreatedAt: '2024-05-27T00:00:00.000Z'
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
// Blocked by custom screen (needs official WhatsApp)
|
|
2131
|
+
{ number: '+1234567890', status: 'blocked', isBanned: false, isNeedOfficialWa: true, banInfo: null }
|
|
2132
|
+
|
|
2133
|
+
// Rate limited
|
|
2134
|
+
{ number: '+1234567890', status: 'rate_limited', isBanned: false, isNeedOfficialWa: false, banInfo: null }
|
|
2135
|
+
|
|
2136
|
+
// Usage example
|
|
2137
|
+
import { checkStatusWA } from '@zervonex/baileys'
|
|
2138
|
+
const check = await checkStatusWA('1234567890')
|
|
2139
|
+
if (check.isBanned) {
|
|
2140
|
+
console.log(`Banned: ${check.banInfo.banType}`)
|
|
2141
|
+
if (check.banInfo.canAppeal) console.log(`Appeal token: ${check.banInfo.appealToken}`)
|
|
2142
|
+
} else {
|
|
2143
|
+
console.log(`Status: ${check.status}`)
|
|
2144
|
+
}
|
|
2145
|
+
```
|
|
2146
|
+
|
|
2147
|
+
---
|
|
2148
|
+
|
|
2149
|
+
## 🔒 Privacy Controls
|
|
2150
|
+
|
|
2151
|
+
```javascript
|
|
2152
|
+
const settings = await sock.fetchPrivacySettings()
|
|
2153
|
+
|
|
2154
|
+
// last seen: 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
2155
|
+
await sock.updateLastSeenPrivacy('contacts')
|
|
2156
|
+
|
|
2157
|
+
// online: 'all' | 'match_last_seen'
|
|
2158
|
+
await sock.updateOnlinePrivacy('all')
|
|
2159
|
+
|
|
2160
|
+
// profile picture: 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
2161
|
+
await sock.updateProfilePicturePrivacy('contacts')
|
|
2162
|
+
|
|
2163
|
+
// status: 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
2164
|
+
await sock.updateStatusPrivacy('contacts')
|
|
2165
|
+
|
|
2166
|
+
// read receipts: 'all' | 'none'
|
|
2167
|
+
await sock.updateReadReceiptsPrivacy('all')
|
|
2168
|
+
|
|
2169
|
+
// groups add: 'all' | 'contacts' | 'contact_blacklist'
|
|
2170
|
+
await sock.updateGroupsAddPrivacy('contacts')
|
|
2171
|
+
```
|
|
2172
|
+
|
|
2173
|
+
### Reporting
|
|
2174
|
+
|
|
2175
|
+
```javascript
|
|
2176
|
+
// ── Report Spam (works on any JID — contact or group) ─────────────────────────
|
|
2177
|
+
// Rich report with full message metadata. Needs at least one received message stored.
|
|
2178
|
+
await sock.reportSpam(jid)
|
|
2179
|
+
|
|
2180
|
+
// With options
|
|
2181
|
+
await sock.reportSpam(jid, {
|
|
2182
|
+
spamFlow: 'ACCOUNT_INFO_REPORT', // report flow type
|
|
2183
|
+
maxMessages: 5, // max messages to include in report
|
|
2184
|
+
messages: [...] // optional — manual message list, skips auto-lookup
|
|
2185
|
+
})
|
|
2186
|
+
|
|
2187
|
+
// ── Report Contact (contacts only) ────────────────────────────────────────────
|
|
2188
|
+
// Simple report — also blocks the contact automatically after reporting
|
|
2189
|
+
await sock.reportContact(jid)
|
|
2190
|
+
|
|
2191
|
+
// With specific message keys
|
|
2192
|
+
await sock.reportContact(jid, [message.key, message2.key])
|
|
2193
|
+
|
|
2194
|
+
// ── Report Group (groups only) ────────────────────────────────────────────────
|
|
2195
|
+
// Simple report — also leaves the group automatically after reporting
|
|
2196
|
+
await sock.reportGroup(groupJid)
|
|
2197
|
+
|
|
2198
|
+
// With specific message keys
|
|
2199
|
+
await sock.reportGroup(groupJid, [message.key, message2.key])
|
|
2200
|
+
```
|
|
2201
|
+
|
|
2202
|
+
| Method | Works On | Auto-Blocks | Auto-Leaves | Detailed Report |
|
|
2203
|
+
|--------|----------|-------------|-------------|-----------------|
|
|
2204
|
+
| `reportSpam` | Contacts & Groups | ❌ | ❌ | ✅ |
|
|
2205
|
+
| `reportContact` | Contacts only | ✅ | ❌ | ❌ |
|
|
2206
|
+
| `reportGroup` | Groups only | ❌ | ✅ | ❌ |
|
|
2207
|
+
|
|
2208
|
+
> `reportSpam` requires at least one message to have been received from the JID first — it pulls stored reporting metadata automatically.
|
|
2209
|
+
|
|
2210
|
+
### Reporting Info Store
|
|
2211
|
+
|
|
2212
|
+
```javascript
|
|
2213
|
+
// Get stored reporting info for a JID (used internally by reportSpam)
|
|
2214
|
+
const info = sock.getStoredReportingInfo(jid)
|
|
2215
|
+
const limited = sock.getStoredReportingInfo(jid, 3) // max 3 entries
|
|
2216
|
+
|
|
2217
|
+
// Clear stored reporting info for a JID
|
|
2218
|
+
sock.clearStoredReportingInfo(jid)
|
|
2219
|
+
|
|
2220
|
+
// Access available spam flow types
|
|
2221
|
+
console.log(sock.SPAM_FLOWS)
|
|
2222
|
+
```
|
|
2223
|
+
|
|
2224
|
+
### Extended Privacy (MEX-based)
|
|
2225
|
+
|
|
2226
|
+
```javascript
|
|
2227
|
+
// Update your About/bio text (with optional emoji)
|
|
2228
|
+
await sock.updateTextStatus('Available for chats', '👋')
|
|
2229
|
+
|
|
2230
|
+
// Get About text of multiple contacts
|
|
2231
|
+
const statuses = await sock.getTextStatusList(['1234567890@s.whatsapp.net'])
|
|
2232
|
+
|
|
2233
|
+
// Fetch profile picture info for a user
|
|
2234
|
+
const info = await sock.fetchUserPictureInfo('1234567890@s.whatsapp.net')
|
|
2235
|
+
|
|
2236
|
+
// Set profile picture via MEX
|
|
2237
|
+
await sock.setProfilePictureMex(imageBase64)
|
|
2238
|
+
|
|
2239
|
+
// Trusted devices
|
|
2240
|
+
const devices = await sock.getTrustedDevices()
|
|
2241
|
+
await sock.addTrustedDevice('device_id', 'My Laptop')
|
|
2242
|
+
await sock.untrustTrustedDevice('device_id')
|
|
2243
|
+
await sock.deleteTrustedDevice('device_id')
|
|
2244
|
+
|
|
2245
|
+
// Multi-account
|
|
2246
|
+
await sock.addMultiAccountLink('1234567890')
|
|
2247
|
+
await sock.revokeMultiAccount('1234567890@s.whatsapp.net')
|
|
2248
|
+
|
|
2249
|
+
// Check if contacts/businesses are valid WA users
|
|
2250
|
+
const contacts = await sock.contactIntegrityQuery(['1234567890@s.whatsapp.net'])
|
|
2251
|
+
const businesses = await sock.bizIntegrityQuery(['1234567890@s.whatsapp.net'])
|
|
2252
|
+
|
|
2253
|
+
// Link / unlink Facebook or Instagram profile
|
|
2254
|
+
await sock.linkedProfilesSet([{ type: 'FB', username: 'myprofile' }])
|
|
2255
|
+
await sock.linkedProfilesRemove(['FB'])
|
|
2256
|
+
await sock.linkedProfilesUpdate([{ type: 'FB', showOnProfile: true }])
|
|
2257
|
+
|
|
2258
|
+
// Migrate blocklist to LID system
|
|
2259
|
+
await sock.migrateBlocklistLid(['1234567890@s.whatsapp.net'])
|
|
2260
|
+
|
|
2261
|
+
// Notify group members of your push name
|
|
2262
|
+
await sock.notifyPushName(groupJid, [{ jid: '1234567890@s.whatsapp.net', pushName: 'John' }])
|
|
2263
|
+
```
|
|
2264
|
+
|
|
2265
|
+
---
|
|
2266
|
+
|
|
2267
|
+
## 💬 Chat Operations
|
|
2268
|
+
|
|
2269
|
+
```javascript
|
|
2270
|
+
const lastMsg = await getLastMessageInChat(jid) // implement with your store
|
|
2271
|
+
|
|
2272
|
+
// Archive / Unarchive
|
|
2273
|
+
await sock.chatModify({ archive: true, lastMessages: [lastMsg] }, jid)
|
|
2274
|
+
|
|
2275
|
+
// Mute (ms) / Unmute
|
|
2276
|
+
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
|
|
2277
|
+
await sock.chatModify({ mute: null }, jid)
|
|
2278
|
+
|
|
2279
|
+
// Pin / Unpin
|
|
2280
|
+
await sock.chatModify({ pin: true }, jid)
|
|
2281
|
+
await sock.chatModify({ pin: false }, jid)
|
|
2282
|
+
|
|
2283
|
+
// Delete chat
|
|
2284
|
+
await sock.chatModify({ delete: true, lastMessages: [{ key: lastMsg.key, messageTimestamp: lastMsg.messageTimestamp }] }, jid)
|
|
2285
|
+
|
|
2286
|
+
// Mark read / unread
|
|
2287
|
+
await sock.chatModify({ markRead: true }, jid)
|
|
2288
|
+
await sock.chatModify({ markRead: false }, jid)
|
|
2289
|
+
```
|
|
2290
|
+
|
|
2291
|
+
---
|
|
2292
|
+
|
|
2293
|
+
## 📢 Newsletter / Channels
|
|
2294
|
+
|
|
2295
|
+
```javascript
|
|
2296
|
+
// ── Create & Manage ───────────────────────────────────────────────────────────
|
|
2297
|
+
|
|
2298
|
+
// Create a channel
|
|
2299
|
+
const channel = await sock.newsletterCreate('Channel Name', 'Channel description')
|
|
2300
|
+
console.log(channel.id) // newsletter jid
|
|
2301
|
+
|
|
2302
|
+
// Fetch channel metadata
|
|
2303
|
+
const meta = await sock.newsletterMetadata('invite', 'INVITE_CODE') // by invite code
|
|
2304
|
+
const meta2 = await sock.newsletterMetadata('jid', newsletterJid) // by jid
|
|
2305
|
+
|
|
2306
|
+
// Update channel info
|
|
2307
|
+
await sock.newsletterUpdate(newsletterJid, { name: 'New Name' })
|
|
2308
|
+
await sock.newsletterUpdate(newsletterJid, { description: 'New description' })
|
|
2309
|
+
await sock.newsletterUpdate(newsletterJid, { picture: buffer })
|
|
2310
|
+
|
|
2311
|
+
// Shorthand update helpers
|
|
2312
|
+
await sock.newsletterUpdateName(newsletterJid, 'New Name')
|
|
2313
|
+
await sock.newsletterUpdateDescription(newsletterJid, 'New description')
|
|
2314
|
+
await sock.newsletterUpdatePicture(newsletterJid, buffer)
|
|
2315
|
+
await sock.newsletterRemovePicture(newsletterJid)
|
|
2316
|
+
|
|
2317
|
+
// Update reaction settings — 'ALL' | 'BASIC' | 'NONE' | 'BLOCKLIST'
|
|
2318
|
+
await sock.newsletterUpdateReactions(newsletterJid, 'ALL')
|
|
2319
|
+
|
|
2320
|
+
// Delete channel
|
|
2321
|
+
await sock.newsletterDelete(newsletterJid)
|
|
2322
|
+
|
|
2323
|
+
// Change channel owner
|
|
2324
|
+
await sock.newsletterChangeOwner(newsletterJid, newOwnerJid)
|
|
2325
|
+
|
|
2326
|
+
// Demote an admin
|
|
2327
|
+
await sock.newsletterDemote(newsletterJid, userJid)
|
|
2328
|
+
|
|
2329
|
+
// ── Follow / Unfollow ─────────────────────────────────────────────────────────
|
|
2330
|
+
|
|
2331
|
+
await sock.newsletterFollow(newsletterJid)
|
|
2332
|
+
await sock.newsletterUnfollow(newsletterJid)
|
|
2333
|
+
|
|
2334
|
+
// Get all subscribed channels
|
|
2335
|
+
const subscribed = await sock.newsletterSubscribed()
|
|
2336
|
+
|
|
2337
|
+
// Subscribe to live updates for a channel
|
|
2338
|
+
const sub = await sock.subscribeNewsletterUpdates(newsletterJid)
|
|
2339
|
+
console.log(sub.duration) // how long the subscription lasts
|
|
2340
|
+
|
|
2341
|
+
// ── Mute / Unmute ─────────────────────────────────────────────────────────────
|
|
2342
|
+
|
|
2343
|
+
await sock.newsletterMute(newsletterJid)
|
|
2344
|
+
await sock.newsletterUnmute(newsletterJid)
|
|
2345
|
+
|
|
2346
|
+
// Fine-grained mute control
|
|
2347
|
+
await sock.newsletterUpdateUserSetting(newsletterJid, 'FOLLOWER_NOTIFICATIONS', true) // mute follower activity
|
|
2348
|
+
await sock.newsletterUpdateUserSetting(newsletterJid, 'ADMIN_NOTIFICATIONS', false) // unmute admin activity
|
|
2349
|
+
|
|
2350
|
+
// ── Admin Management ──────────────────────────────────────────────────────────
|
|
2351
|
+
|
|
2352
|
+
// Get admin count
|
|
2353
|
+
const count = await sock.newsletterAdminCount(newsletterJid)
|
|
2354
|
+
|
|
2355
|
+
// Get admin info
|
|
2356
|
+
const adminInfo = await sock.newsletterAdminInfo(newsletterJid)
|
|
2357
|
+
console.log(adminInfo.adminCount, adminInfo.adminProfile, adminInfo.adminProfilesEnabled)
|
|
2358
|
+
|
|
2359
|
+
// Get admin capabilities
|
|
2360
|
+
const capabilities = await sock.newsletterAdminCapabilities(newsletterJid)
|
|
2361
|
+
|
|
2362
|
+
// Check if you can post status
|
|
2363
|
+
const { canPost, canPostMusic, capabilities: caps } = await sock.newsletterCanPostStatus(newsletterJid)
|
|
2364
|
+
|
|
2365
|
+
// Admin invites
|
|
2366
|
+
await sock.newsletterCreateAdminInvite(newsletterJid, userJid)
|
|
2367
|
+
await sock.newsletterRevokeAdminInvite(newsletterJid, userJid)
|
|
2368
|
+
await sock.newsletterAcceptAdminInvite(newsletterJid)
|
|
2369
|
+
|
|
2370
|
+
// List pending admin invites
|
|
2371
|
+
const pending = await sock.newsletterPendingAdminInvites(newsletterJid)
|
|
2372
|
+
// [{ id, phoneNumber }, ...]
|
|
2373
|
+
|
|
2374
|
+
// ── Followers & Subscribers ───────────────────────────────────────────────────
|
|
2375
|
+
|
|
2376
|
+
const followers = await sock.newsletterFollowers(newsletterJid, { count: 50 })
|
|
2377
|
+
const subscribers = await sock.newsletterSubscribers(newsletterJid)
|
|
2378
|
+
// [{ id, phoneNumber, displayName, username, role, followTime }, ...]
|
|
2379
|
+
|
|
2380
|
+
// ── Messages ──────────────────────────────────────────────────────────────────
|
|
2381
|
+
|
|
2382
|
+
// Fetch recent messages
|
|
2383
|
+
const messages = await sock.newsletterFetchMessages(newsletterJid, 20)
|
|
2384
|
+
|
|
2385
|
+
// Fetch with pagination
|
|
2386
|
+
const older = await sock.newsletterFetchMessages(newsletterJid, 20, /* since */ undefined, /* after */ lastServerId)
|
|
2387
|
+
|
|
2388
|
+
// Fetch message updates (reactions, view counts, etc.)
|
|
2389
|
+
const updates = await sock.newsletterFetchMessageUpdates(newsletterJid, { count: 20 })
|
|
2390
|
+
const paged = await sock.newsletterFetchMessageUpdates(newsletterJid, { count: 20, before: serverId })
|
|
2391
|
+
|
|
2392
|
+
// Pin / unpin messages
|
|
2393
|
+
await sock.newsletterPinMessages(newsletterJid, serverId)
|
|
2394
|
+
await sock.newsletterPinMessages(newsletterJid, [serverId1, serverId2])
|
|
2395
|
+
await sock.newsletterUnpinMessages(newsletterJid, serverId)
|
|
2396
|
+
|
|
2397
|
+
// Label AI-generated content
|
|
2398
|
+
await sock.newsletterLabelAiContent(newsletterJid, serverId)
|
|
2399
|
+
|
|
2400
|
+
// Label paid partnership
|
|
2401
|
+
await sock.newsletterLabelPaidPartnership(newsletterJid, serverId)
|
|
2402
|
+
|
|
2403
|
+
// ── Reactions ─────────────────────────────────────────────────────────────────
|
|
2404
|
+
|
|
2405
|
+
// Single reaction on a message
|
|
2406
|
+
await sock.newsletterReactMessage(newsletterJid, serverId, '❤️')
|
|
2407
|
+
|
|
2408
|
+
// Remove a reaction
|
|
2409
|
+
await sock.newsletterReactMessage(newsletterJid, serverId, null)
|
|
2410
|
+
|
|
2411
|
+
// Bulk reactions — single emoji, 10 times
|
|
2412
|
+
await sock.newsletterBulkReactions(newsletterJid, serverId, '❤️', 10)
|
|
2413
|
+
|
|
2414
|
+
// Bulk reactions — cycle through multiple emojis (❤️ 🔥 ❤️ 🔥...), 20 total
|
|
2415
|
+
await sock.newsletterBulkReactions(newsletterJid, serverId, ['❤️', '🔥'], 20)
|
|
2416
|
+
|
|
2417
|
+
// Bulk reactions — random emoji each time, 20 total
|
|
2418
|
+
await sock.newsletterBulkReactions(newsletterJid, serverId, ['❤️', '🔥', '😂'], 20, { mode: 'random' })
|
|
2419
|
+
|
|
2420
|
+
// Bulk reactions — 10 of EACH emoji (30 total)
|
|
2421
|
+
await sock.newsletterBulkReactions(newsletterJid, serverId, ['❤️', '🔥', '😂'], 10, { mode: 'each' })
|
|
2422
|
+
|
|
2423
|
+
// Fake reactions (local events only, not sent to server)
|
|
2424
|
+
await sock.newsletterBulkReactions(newsletterJid, serverId, ['❤️', '🔥'], 100, { fake: true })
|
|
2425
|
+
|
|
2426
|
+
// Custom delay between reactions (default: 100ms)
|
|
2427
|
+
await sock.newsletterBulkReactions(newsletterJid, serverId, '🔥', 50, { delayMs: 200 })
|
|
2428
|
+
|
|
2429
|
+
// Get who reacted to a message
|
|
2430
|
+
const reactionSenders = await sock.newsletterReactionSenders(newsletterJid, serverId)
|
|
2431
|
+
|
|
2432
|
+
// ── Poll Votes ────────────────────────────────────────────────────────────────
|
|
2433
|
+
|
|
2434
|
+
// Vote on a poll
|
|
2435
|
+
await sock.newsletterSendPollVote(newsletterJid, serverId, 'Option A')
|
|
2436
|
+
await sock.newsletterSendPollVote(newsletterJid, serverId, ['Option A', 'Option B']) // multi-vote
|
|
2437
|
+
|
|
2438
|
+
// Get poll voters
|
|
2439
|
+
const voters = await sock.newsletterPollVoters(newsletterJid, serverId, { limit: 100 })
|
|
2440
|
+
const forOption = await sock.newsletterPollVoters(newsletterJid, serverId, { voteHash: 'abc123' })
|
|
2441
|
+
|
|
2442
|
+
// ── Questions & Responses ─────────────────────────────────────────────────────
|
|
2443
|
+
|
|
2444
|
+
// Fetch responses to a question status
|
|
2445
|
+
const responses = await sock.newsletterQuestionResponses(newsletterJid, serverId, { count: 20 })
|
|
2446
|
+
const filtered = await sock.newsletterQuestionResponses(newsletterJid, serverId, { filter: 'starred' })
|
|
2447
|
+
const searched = await sock.newsletterQuestionResponses(newsletterJid, serverId, { searchText: 'hello' })
|
|
2448
|
+
|
|
2449
|
+
// Update response state — e.g. star, reply
|
|
2450
|
+
await sock.newsletterQuestionResponseState(newsletterJid, serverId, responseServerId, 'STARRED')
|
|
2451
|
+
|
|
2452
|
+
// ── Status Publishing ─────────────────────────────────────────────────────────
|
|
2453
|
+
|
|
2454
|
+
// Send a text status
|
|
2455
|
+
await sock.newsletterSendStatus(newsletterJid, { text: 'Hello from channel!' })
|
|
2456
|
+
|
|
2457
|
+
// Send an image status
|
|
2458
|
+
await sock.newsletterSendStatus(newsletterJid, { image: buffer, caption: 'Caption here' })
|
|
2459
|
+
|
|
2460
|
+
// Send a video status
|
|
2461
|
+
await sock.newsletterSendStatus(newsletterJid, { video: buffer, caption: 'Caption here' })
|
|
2462
|
+
|
|
2463
|
+
// Send an audio status
|
|
2464
|
+
await sock.newsletterSendStatus(newsletterJid, { audio: buffer })
|
|
2465
|
+
|
|
2466
|
+
// Send a question on top of media
|
|
2467
|
+
await sock.newsletterSendStatus(newsletterJid, { image: buffer, question: true })
|
|
2468
|
+
|
|
2469
|
+
// Send a question response (text reply to a question)
|
|
2470
|
+
await sock.newsletterSendStatus(newsletterJid, { text: 'My answer' }, {
|
|
2471
|
+
interactionType: 'question_response',
|
|
2472
|
+
parentServerId: questionServerId
|
|
2473
|
+
})
|
|
2474
|
+
|
|
2475
|
+
// Send a question reshare (reshare a question with media)
|
|
2476
|
+
await sock.newsletterSendStatus(newsletterJid, { image: buffer }, {
|
|
2477
|
+
interactionType: 'question_reshare',
|
|
2478
|
+
parentServerId: questionServerId,
|
|
2479
|
+
responseServerId: responseServerId
|
|
2480
|
+
})
|
|
2481
|
+
|
|
2482
|
+
// Mark status as AI-generated
|
|
2483
|
+
await sock.newsletterSendStatus(newsletterJid, { text: 'AI content' }, { aiContent: true })
|
|
2484
|
+
|
|
2485
|
+
// Send without status attribution
|
|
2486
|
+
await sock.newsletterSendStatus(newsletterJid, { text: 'No attribution' }, { statusAttribution: false })
|
|
2487
|
+
|
|
2488
|
+
// Access the server id from the result
|
|
2489
|
+
const sent = await sock.newsletterSendStatus(newsletterJid, { text: 'Hello' })
|
|
2490
|
+
console.log(sent.newsletterStatusServerId) // use this for reactions, pins, etc.
|
|
2491
|
+
|
|
2492
|
+
// ── Status Management ─────────────────────────────────────────────────────────
|
|
2493
|
+
|
|
2494
|
+
// React to a status
|
|
2495
|
+
await sock.newsletterReactStatus(newsletterJid, serverId, '❤️')
|
|
2496
|
+
|
|
2497
|
+
// Remove a status reaction
|
|
2498
|
+
await sock.newsletterReactStatus(newsletterJid, serverId, null)
|
|
2499
|
+
|
|
2500
|
+
// Revoke / delete a status
|
|
2501
|
+
await sock.newsletterRevokeStatus(newsletterJid, statusId)
|
|
2502
|
+
|
|
2503
|
+
// Fetch published statuses
|
|
2504
|
+
const statuses = await sock.newsletterFetchStatus(newsletterJid, { count: 20 })
|
|
2505
|
+
const before = await sock.newsletterFetchStatus(newsletterJid, { count: 20, before: serverId })
|
|
2506
|
+
const after = await sock.newsletterFetchStatus(newsletterJid, { count: 20, after: serverId })
|
|
2507
|
+
|
|
2508
|
+
// Fetch status updates (counts, reactions, etc.)
|
|
2509
|
+
const statusUpdates = await sock.newsletterFetchStatusUpdates(newsletterJid, { count: 20 })
|
|
2510
|
+
|
|
2511
|
+
// ── Add-ons ───────────────────────────────────────────────────────────────────
|
|
2512
|
+
|
|
2513
|
+
// Get your own reactions/votes across all channels
|
|
2514
|
+
const myAddOns = await sock.newsletterMyAddOns()
|
|
2515
|
+
const myStatusAddOns = await sock.newsletterStatusMyAddOns()
|
|
2516
|
+
|
|
2517
|
+
// Filter by channel
|
|
2518
|
+
const filtered = await sock.newsletterMyAddOns({ jid: newsletterJid })
|
|
2519
|
+
|
|
2520
|
+
// ── Analytics & Insights ──────────────────────────────────────────────────────
|
|
2521
|
+
|
|
2522
|
+
const insights = await sock.newsletterInsights(newsletterJid)
|
|
2523
|
+
const custom = await sock.newsletterInsights(newsletterJid, { metrics: ['NET_FOLLOWS', 'UNFOLLOWS', 'IMPRESSIONS'] })
|
|
2524
|
+
|
|
2525
|
+
// ── Enforcements & Reports ────────────────────────────────────────────────────
|
|
2526
|
+
|
|
2527
|
+
// Get enforcements (violations, suspensions, etc.)
|
|
2528
|
+
const enforcements = await sock.newsletterEnforcements(newsletterJid)
|
|
2529
|
+
const { adminProfiles, profilePictureDeletions, suspensions, violatingMessages, geoSuspensions } = enforcements
|
|
2530
|
+
|
|
2531
|
+
// Get all your channel reports
|
|
2532
|
+
const reports = await sock.newsletterReports()
|
|
2533
|
+
|
|
2534
|
+
// Appeal a report
|
|
2535
|
+
await sock.newsletterAppealReport(reportId, 'REASON_HERE')
|
|
2536
|
+
|
|
2537
|
+
// ── Discovery ─────────────────────────────────────────────────────────────────
|
|
2538
|
+
|
|
2539
|
+
// Browse recommended channels
|
|
2540
|
+
const recommended = await sock.newsletterRecommended({ limit: 20 })
|
|
2541
|
+
|
|
2542
|
+
// Browse by country
|
|
2543
|
+
const local = await sock.newsletterRecommended({ countryCodes: ['NG', 'US'] })
|
|
2544
|
+
|
|
2545
|
+
// Search channels
|
|
2546
|
+
const results = await sock.newsletterDirectorySearch('football', { limit: 20 })
|
|
2547
|
+
|
|
2548
|
+
// Browse directory
|
|
2549
|
+
const directory = await sock.newsletterDirectoryList({ view: 'RECOMMENDED', limit: 20 })
|
|
2550
|
+
const byCountry = await sock.newsletterDirectoryList({ countryCodes: ['NG'], categories: ['SPORTS'] })
|
|
2551
|
+
|
|
2552
|
+
// Browse categories
|
|
2553
|
+
const categories = await sock.newsletterDirectoryCategories({ perCategoryLimit: 10 })
|
|
2554
|
+
|
|
2555
|
+
// Find similar channels
|
|
2556
|
+
const similar = await sock.newsletterSimilar(newsletterJid, { limit: 20 })
|
|
2557
|
+
```
|
|
2558
|
+
|
|
2559
|
+
---
|
|
2560
|
+
|
|
2561
|
+
## 🔧 Builder API
|
|
2562
|
+
|
|
2563
|
+
All builders can be used as a fluent chain. Call `.send(jid)` to send, or `.build(jid)` to get the proto message without sending.
|
|
2564
|
+
|
|
2565
|
+
### AIRich Builder
|
|
2566
|
+
|
|
2567
|
+
```javascript
|
|
2568
|
+
const r = sock.airich() // create a new builder
|
|
2569
|
+
r.setTitle('Title') // shown in message metadata
|
|
2570
|
+
r.setFooter('© zervonex') // shown below content
|
|
2571
|
+
r.setBotJid('867051314767696@bot') // custom bot JID
|
|
2572
|
+
r.setResponseId('my-id') // fix response ID (disables auto-refresh)
|
|
2573
|
+
r.setContextInfo({ ... }) // custom contextInfo fields
|
|
2574
|
+
|
|
2575
|
+
// Content methods — all chainable, all accept { id, replace, insertAt } opts
|
|
2576
|
+
r.addText('hello **world**')
|
|
2577
|
+
r.addCode('javascript', 'console.log("hi")')
|
|
2578
|
+
r.addTable([['Header1', 'Header2'], ['R1C1', 'R1C2']])
|
|
2579
|
+
r.addImage('https://example.com/image.jpg')
|
|
2580
|
+
r.addVideo('https://example.com/video.mp4')
|
|
2581
|
+
r.addReels([{ creator, avatar_url, thumbnail_url, reels_url }])
|
|
2582
|
+
r.addPost({ title, username, thumbnail_url, post_url, source_app, likes_count, is_verified })
|
|
2583
|
+
r.addProduct({ title, brand, price, sale_price, product_url, image_url })
|
|
2584
|
+
r.addSource([{ title, url, favicon }])
|
|
2585
|
+
r.addMap([{ latitude, longitude, name, address }])
|
|
2586
|
+
r.addWidget(ctas, title) // ctas: [{ label, tool_call_id, kind, toast }]
|
|
2587
|
+
r.addFooterAction({ cta_text, cta_type, cta_url })
|
|
2588
|
+
r.addMetadata('small info text')
|
|
2589
|
+
r.addFOAText('# Heading\n## Subheading')
|
|
2590
|
+
r.addTip('Tip callout text')
|
|
2591
|
+
r.addDivider() // or addDivider('DOT') for dotted line
|
|
2592
|
+
r.addSpacer(2) // spacing: number of blank lines
|
|
2593
|
+
r.addThinkingStatus('title', 'THINKING') // icons: THINKING | WEB_SEARCH | META_SEARCH
|
|
2594
|
+
r.addProgressStatus('title', true) // true = in progress, false = done
|
|
2595
|
+
r.addTask({ taskId, title, subtitle, status }) // status: PENDING | RUNNING | DONE
|
|
2596
|
+
r.addLatex({ expression, imageUrl, width, height, fontHeight, padding })
|
|
2597
|
+
r.addGenerating('GENERATING') // image generation placeholder
|
|
2598
|
+
r.addInlineImage('url', 'center') // alignment: center | left | right
|
|
2599
|
+
r.addSuggest(['Pill 1', 'Pill 2'], false) // false = action row, true = hscroll
|
|
2600
|
+
r.addSection(rawSectionObject) // raw section for advanced use
|
|
2601
|
+
r.addEmbeddedScreen(screenObject) // embedded tabbed panel
|
|
2602
|
+
r.addRawSections(sections, submessages) // escape hatch — raw unified sections + submessages
|
|
2603
|
+
|
|
2604
|
+
// Special methods
|
|
2605
|
+
r.loadFrom(msg) // load existing AIRich message for editing
|
|
2606
|
+
await r.send(jid, opts) // send
|
|
2607
|
+
await r.sendEdit(jid, targetId) // edit a previously sent message
|
|
2608
|
+
// Standalone
|
|
2609
|
+
await sock.sendRichGeneration(jid, { text, mediaType, url, status, estimatedMs, itemId, responseId })
|
|
2610
|
+
await sock.sendUnifiedResponse(jid, sections, submessages, options)
|
|
2611
|
+
```
|
|
2612
|
+
|
|
2613
|
+
**Named node IDs** — update specific content after adding:
|
|
2614
|
+
|
|
2615
|
+
```javascript
|
|
2616
|
+
const r = sock.airich()
|
|
2617
|
+
r.addText('Loading...', { id: 'status' })
|
|
2618
|
+
r.addCode('js', '// placeholder', { id: 'code' })
|
|
2619
|
+
|
|
2620
|
+
// Later, replace a specific node by id
|
|
2621
|
+
r.addText('Done!', { replace: 'status' })
|
|
2622
|
+
r.addCode('js', 'console.log("real code")', { replace: 'code' })
|
|
2623
|
+
|
|
2624
|
+
await r.send(jid)
|
|
2625
|
+
```
|
|
2626
|
+
|
|
2627
|
+
---
|
|
2628
|
+
|
|
2629
|
+
### Button Builder
|
|
2630
|
+
|
|
2631
|
+
```javascript
|
|
2632
|
+
const b = sock.button()
|
|
2633
|
+
|
|
2634
|
+
// Header / body / footer
|
|
2635
|
+
b.setTitle('Menu')
|
|
2636
|
+
b.setSubtitle('Choose an option')
|
|
2637
|
+
b.setBody('What would you like to do?')
|
|
2638
|
+
b.setFooter('© zervonex')
|
|
2639
|
+
|
|
2640
|
+
// Media header (pick one)
|
|
2641
|
+
b.setImage('https://example.com/image.jpg')
|
|
2642
|
+
b.setVideo('https://example.com/video.mp4')
|
|
2643
|
+
b.setDocument('https://example.com/file.pdf', 'file.pdf')
|
|
2644
|
+
b.setLocation(6.5244, 3.3792, 'Lagos')
|
|
2645
|
+
|
|
2646
|
+
// Native-flow buttons (chainable)
|
|
2647
|
+
b.reply('Quick Reply', 'reply_id')
|
|
2648
|
+
b.url('Visit Website', 'https://zervonex.com')
|
|
2649
|
+
b.call('Call Us', '+2341234567890')
|
|
2650
|
+
b.copy('Copy Code', 'NEXUS2025')
|
|
2651
|
+
b.openWebview('Open App', 'https://app.zervonex.com')
|
|
2652
|
+
b.catalog('View Catalog')
|
|
2653
|
+
b.flow('Start Flow', 'flow_id_here')
|
|
2654
|
+
b.remind('Set Reminder')
|
|
2655
|
+
b.cancelReminder('Cancel Reminder')
|
|
2656
|
+
b.address('Share Address')
|
|
2657
|
+
b.sendLocation('Share Location')
|
|
2658
|
+
b.reviewAndPay('Review & Pay')
|
|
2659
|
+
b.reviewOrder('Review Order')
|
|
2660
|
+
b.orderDetails('Order Details')
|
|
2661
|
+
b.paymentStatus('Payment Status')
|
|
2662
|
+
b.transactionDetails('Transaction Details')
|
|
2663
|
+
b.select('Choose Option', [{ title: 'Section', rows: [{ title: 'Option 1', id: 'opt1' }] }])
|
|
2664
|
+
|
|
2665
|
+
// Bloks widget (advanced UI with checkboxes, inputs etc)
|
|
2666
|
+
b.setBloksWidget([{ __type__: 'Column', id: 'root', children: [{ __type__: 'Text', text: 'Hello' }] }])
|
|
2667
|
+
|
|
2668
|
+
// Message-level params
|
|
2669
|
+
b.setLimitedTimeOffer(Date.now() + 3600000)
|
|
2670
|
+
b.setBottomSheet({ title: 'Select' })
|
|
2671
|
+
b.setTapTargetConfiguration({ dismissible: true })
|
|
2672
|
+
|
|
2673
|
+
// Legacy buttons (mode: 'legacy')
|
|
2674
|
+
b.legacyButton('Button 1', 'btn1_id')
|
|
2675
|
+
b.legacyButton('Button 2', 'btn2_id')
|
|
2676
|
+
|
|
2677
|
+
// Template buttons (mode: 'template')
|
|
2678
|
+
b.templateReply('Quick Reply', 'reply_id')
|
|
2679
|
+
b.templateUrl('Visit', 'https://zervonex.com')
|
|
2680
|
+
b.templateCall('Call', '+2341234567890')
|
|
2681
|
+
|
|
2682
|
+
// Convert to a carousel card
|
|
2683
|
+
const card = b.toCard()
|
|
2684
|
+
|
|
2685
|
+
await b.send(jid)
|
|
2686
|
+
```
|
|
2687
|
+
|
|
2688
|
+
---
|
|
2689
|
+
|
|
2690
|
+
### Carousel Builder
|
|
2691
|
+
|
|
2692
|
+
```javascript
|
|
2693
|
+
const c = sock.carousel()
|
|
2694
|
+
|
|
2695
|
+
c.setCaption('Our Products')
|
|
2696
|
+
c.setFooter('Powered by zervonex')
|
|
2697
|
+
c.setCardType('HSCROLL_CARDS') // 'HSCROLL_CARDS' (default) | 'ALBUM_IMAGE'
|
|
2698
|
+
|
|
2699
|
+
// Add cards — pass a Button builder instance or a raw card object
|
|
2700
|
+
c.card(sock.button().setBody('Card 1').reply('Select', 'card1').url('Learn More', 'https://example.com'))
|
|
2701
|
+
c.card(sock.button().setImage('https://example.com/img.jpg').setBody('Card 2').reply('Select', 'card2'))
|
|
2702
|
+
|
|
2703
|
+
// Max 10 cards
|
|
2704
|
+
await c.send(jid)
|
|
2705
|
+
```
|
|
2706
|
+
|
|
2707
|
+
---
|
|
2708
|
+
|
|
2709
|
+
### Album Builder
|
|
2710
|
+
|
|
2711
|
+
```javascript
|
|
2712
|
+
const a = sock.album()
|
|
2713
|
+
|
|
2714
|
+
// Add items — URLs, Buffers, or file paths
|
|
2715
|
+
a.image('https://example.com/1.jpg', 'Caption for photo 1')
|
|
2716
|
+
a.image(buffer, 'Caption for photo 2')
|
|
2717
|
+
a.video('https://example.com/video.mp4', 'Caption for video')
|
|
2718
|
+
a.add([ // add multiple at once
|
|
2719
|
+
{ image: { url: 'https://example.com/3.jpg' }, caption: 'Photo 3' },
|
|
2720
|
+
{ video: { url: 'https://example.com/4.mp4' }, caption: 'Video 2' }
|
|
2721
|
+
])
|
|
2722
|
+
|
|
2723
|
+
a.setDelay(1500) // ms between each item send (default: 1500)
|
|
2724
|
+
|
|
2725
|
+
// Requires at least 2 items
|
|
2726
|
+
await a.send(jid)
|
|
2727
|
+
```
|
|
2728
|
+
|
|
2729
|
+
### VerticalAlbum Builder
|
|
2730
|
+
|
|
2731
|
+
Sends a full-width stacked media album using the AIRich unified response format. Unlike the standard Album builder (which sends individual messages), this renders all items in a single rich message.
|
|
2732
|
+
|
|
2733
|
+
```javascript
|
|
2734
|
+
await sock.sendMessage(jid, {
|
|
2735
|
+
verticalAlbumMessage: [
|
|
2736
|
+
{ type: 'image', image: { url: 'https://example.com/1.jpg' } },
|
|
2737
|
+
{ type: 'video', video: { url: 'https://example.com/2.mp4' }, duration: 10 },
|
|
2738
|
+
{ type: 'image', image: { url: 'https://example.com/3.jpg' }, width: 1280, height: 720 }
|
|
2739
|
+
]
|
|
2740
|
+
})
|
|
2741
|
+
|
|
2742
|
+
// via shorthand
|
|
2743
|
+
await sock.sendVerticalAlbumMessage(jid, {
|
|
2744
|
+
items: [
|
|
2745
|
+
{ type: 'image', image: { url: 'https://example.com/1.jpg' } },
|
|
2746
|
+
{ type: 'video', video: { url: 'https://example.com/2.mp4' } }
|
|
2747
|
+
]
|
|
2748
|
+
})
|
|
2749
|
+
```
|
|
2750
|
+
|
|
2751
|
+
---
|
|
2752
|
+
|
|
2753
|
+
### GridImage Builder
|
|
2754
|
+
|
|
2755
|
+
Sends a grid of images using the GRID_IMAGE protocol submessage type.
|
|
2756
|
+
|
|
2757
|
+
```javascript
|
|
2758
|
+
await sock.sendMessage(jid, {
|
|
2759
|
+
gridImageMessage: {
|
|
2760
|
+
imageUrls: [
|
|
2761
|
+
{ url: 'https://example.com/1.jpg', width: 600, height: 400 },
|
|
2762
|
+
{ url: 'https://example.com/2.jpg', width: 600, height: 400 },
|
|
2763
|
+
{ url: 'https://example.com/3.jpg', width: 600, height: 400 }
|
|
2764
|
+
]
|
|
2765
|
+
}
|
|
2766
|
+
})
|
|
2767
|
+
|
|
2768
|
+
// via shorthand
|
|
2769
|
+
await sock.sendGridImageMessage(jid, {
|
|
2770
|
+
imageUrls: [
|
|
2771
|
+
'https://example.com/1.jpg',
|
|
2772
|
+
'https://example.com/2.jpg'
|
|
2773
|
+
]
|
|
2774
|
+
})
|
|
2775
|
+
```
|
|
2776
|
+
|
|
2777
|
+
---
|
|
2778
|
+
|
|
2779
|
+
### VideoGrid Builder
|
|
2780
|
+
|
|
2781
|
+
Sends a grid of videos using GenAIVideoPrimitive with full delivery metadata support.
|
|
2782
|
+
|
|
2783
|
+
```javascript
|
|
2784
|
+
await sock.sendMessage(jid, {
|
|
2785
|
+
videoGridMessage: {
|
|
2786
|
+
videos: [
|
|
2787
|
+
{
|
|
2788
|
+
url: 'https://example.com/1.mp4',
|
|
2789
|
+
title: 'Video 1',
|
|
2790
|
+
thumbnailUrl: 'https://example.com/thumb1.jpg',
|
|
2791
|
+
creator: 'Creator Name',
|
|
2792
|
+
likes: 1200,
|
|
2793
|
+
isVerified: true
|
|
2794
|
+
},
|
|
2795
|
+
{
|
|
2796
|
+
url: 'https://example.com/2.mp4',
|
|
2797
|
+
title: 'Video 2',
|
|
2798
|
+
thumbnailUrl: 'https://example.com/thumb2.jpg'
|
|
2799
|
+
}
|
|
2800
|
+
]
|
|
2801
|
+
}
|
|
2802
|
+
})
|
|
2803
|
+
|
|
2804
|
+
// via shorthand
|
|
2805
|
+
await sock.sendVideoGridMessage(jid, {
|
|
2806
|
+
videos: [
|
|
2807
|
+
{ url: 'https://example.com/1.mp4', title: 'Clip 1' },
|
|
2808
|
+
{ url: 'https://example.com/2.mp4', title: 'Clip 2' }
|
|
2809
|
+
]
|
|
2810
|
+
})
|
|
2811
|
+
```
|
|
2812
|
+
|
|
2813
|
+
---
|
|
2814
|
+
|
|
2815
|
+
### A2UI Builder
|
|
2816
|
+
|
|
2817
|
+
Sends a WhatsApp A2UI bloksWidget interactive message. Use the command menu preset or build a fully custom component tree.
|
|
2818
|
+
|
|
2819
|
+
```javascript
|
|
2820
|
+
// Generic A2UI envelope
|
|
2821
|
+
await sock.sendA2UIMessage(jid, {
|
|
2822
|
+
bloksWidget: {
|
|
2823
|
+
type: 'im_a2ui',
|
|
2824
|
+
data: JSON.stringify({ version: 'v0.9', createSurface: { /* ... */ } })
|
|
2825
|
+
},
|
|
2826
|
+
nativeFlowMessage: { buttons: [{ name: 'single_select', buttonParamsJson: '...' }] }
|
|
2827
|
+
})
|
|
2828
|
+
|
|
2829
|
+
// Command menu preset
|
|
2830
|
+
await sock.sendA2UICommandMenu(jid, {
|
|
2831
|
+
title: 'NexusBot Menu',
|
|
2832
|
+
rows: [
|
|
2833
|
+
['!help', 'Show all commands'],
|
|
2834
|
+
['!ping', 'Check bot status'],
|
|
2835
|
+
['!ai', 'Ask AI a question']
|
|
2836
|
+
],
|
|
2837
|
+
buttons: [
|
|
2838
|
+
{ text: 'GitHub', url: 'https://github.com/nexustechpro2' }
|
|
2839
|
+
],
|
|
2840
|
+
footer: 'Powered by zervonex'
|
|
2841
|
+
})
|
|
2842
|
+
```
|
|
2843
|
+
|
|
2844
|
+
**A2UI row format:** `[command, description]` or `{ title, description, id }`
|
|
2845
|
+
|
|
2846
|
+
**A2UI button format:** `{ text, url }` or `{ label, url }`
|
|
2847
|
+
|
|
2848
|
+
---
|
|
2849
|
+
|
|
2850
|
+
### Poll Builder
|
|
2851
|
+
|
|
2852
|
+
```javascript
|
|
2853
|
+
const p = sock.poll()
|
|
2854
|
+
|
|
2855
|
+
p.name('What is your favorite color?')
|
|
2856
|
+
p.options(['Red', 'Blue', 'Green', 'Yellow'])
|
|
2857
|
+
p.addOption('Purple') // add one more
|
|
2858
|
+
p.multiSelect(2) // allow selecting up to 2 (0 = unlimited)
|
|
2859
|
+
p.hideVoter() // hide who voted
|
|
2860
|
+
p.announcement() // for announcement groups
|
|
2861
|
+
|
|
2862
|
+
// Quiz mode
|
|
2863
|
+
p.quiz('Blue') // marks as quiz with correct answer
|
|
2864
|
+
|
|
2865
|
+
// Timed poll
|
|
2866
|
+
p.setEndTime(Math.floor(Date.now() / 1000) + 3600) // ends in 1 hour
|
|
2867
|
+
p.hideParticipantName() // hide voter names
|
|
2868
|
+
p.allowAddOption() // allow participants to add options
|
|
2869
|
+
|
|
2870
|
+
await p.send(jid)
|
|
2871
|
+
```
|
|
2872
|
+
|
|
2873
|
+
---
|
|
2874
|
+
|
|
2875
|
+
### Event Builder
|
|
2876
|
+
|
|
2877
|
+
```javascript
|
|
2878
|
+
const e = sock.event()
|
|
2879
|
+
|
|
2880
|
+
e.setName('NexusTech Conference 2026')
|
|
2881
|
+
e.setDescription('Annual developer meetup')
|
|
2882
|
+
e.setLocation({ degreesLatitude: 6.5244, degreesLongitude: 3.3792, name: 'Lagos, Nigeria' })
|
|
2883
|
+
e.setJoinLink('https://meet.example.com/nexusconf')
|
|
2884
|
+
e.setStartTime(Math.floor(Date.now() / 1000) + 86400)
|
|
2885
|
+
e.setEndTime(Math.floor(Date.now() / 1000) + 172800)
|
|
2886
|
+
e.setCanceled(false)
|
|
2887
|
+
e.setReminder(3600) // remind 1 hour before (sets hasReminder + reminderOffsetSec)
|
|
2888
|
+
e.setScheduledCall(true) // marks as a scheduled call event
|
|
2889
|
+
|
|
2890
|
+
await e.send(jid)
|
|
2891
|
+
```
|
|
2892
|
+
|
|
2893
|
+
---
|
|
2894
|
+
|
|
2895
|
+
### Payment Builder
|
|
2896
|
+
|
|
2897
|
+
```javascript
|
|
2898
|
+
const pay = sock.payment()
|
|
2899
|
+
|
|
2900
|
+
pay.setCurrency('NGN')
|
|
2901
|
+
pay.setAmount(10000000) // amount × 1000
|
|
2902
|
+
pay.setFrom('1234567890@s.whatsapp.net')
|
|
2903
|
+
pay.setNote('Payment for order #123')
|
|
2904
|
+
pay.setExpiry(Date.now() + 86400000)
|
|
2905
|
+
|
|
2906
|
+
await pay.send(jid)
|
|
2907
|
+
```
|
|
2908
|
+
|
|
2909
|
+
---
|
|
2910
|
+
|
|
2911
|
+
### Order Builder
|
|
2912
|
+
|
|
2913
|
+
```javascript
|
|
2914
|
+
const ord = sock.order()
|
|
2915
|
+
|
|
2916
|
+
ord.from({
|
|
2917
|
+
orderId: 'ORDER_001',
|
|
2918
|
+
itemCount: 3,
|
|
2919
|
+
totalAmount1000: 45000000,
|
|
2920
|
+
totalCurrencyCode: 'NGN',
|
|
2921
|
+
orderTitle: 'My Order',
|
|
2922
|
+
message: 'Thank you for your order',
|
|
2923
|
+
thumbnail: 'https://example.com/product.jpg'
|
|
2924
|
+
})
|
|
2925
|
+
|
|
2926
|
+
await ord.send(jid)
|
|
2927
|
+
```
|
|
2928
|
+
|
|
2929
|
+
---
|
|
2930
|
+
|
|
2931
|
+
## 🛠 Utility Methods
|
|
2932
|
+
|
|
2933
|
+
```javascript
|
|
2934
|
+
// Refresh stale contacts (triggers WA to re-push contact data)
|
|
2935
|
+
await sock.requestContactRefresh(['1234567890@s.whatsapp.net', '0987654321@s.whatsapp.net'])
|
|
2936
|
+
|
|
2937
|
+
// Fetch message history on demand
|
|
2938
|
+
await sock.fetchMessageHistory(50, oldestMessageKey, oldestMessageTimestamp)
|
|
2939
|
+
|
|
2940
|
+
// Request a placeholder message to be resent (for unavailable encrypted messages)
|
|
2941
|
+
await sock.requestPlaceholderResend(messageKey)
|
|
2942
|
+
|
|
2943
|
+
// Capture an AIRich message for forwarding
|
|
2944
|
+
const captured = sock.captureAiRich(msg.message)
|
|
2945
|
+
// { submessages, sections, contextInfo, messageType }
|
|
2946
|
+
|
|
2947
|
+
// Relay a captured AIRich message to another jid
|
|
2948
|
+
if (captured) await sock.relayAiRich(targetJid, captured)
|
|
2949
|
+
```
|
|
2950
|
+
|
|
2951
|
+
---
|
|
2952
|
+
|
|
2953
|
+
## 📦 Exported Utilities
|
|
2954
|
+
|
|
2955
|
+
Everything exported from `@zervonex/baileys` that you can import directly:
|
|
2956
|
+
|
|
2957
|
+
```javascript
|
|
2958
|
+
import {
|
|
2959
|
+
// Connection
|
|
2960
|
+
makeWASocket,
|
|
2961
|
+
useMultiFileAuthState,
|
|
2962
|
+
useKeyvAuthState,
|
|
2963
|
+
makeCacheableSignalKeyStore,
|
|
2964
|
+
Browsers,
|
|
2965
|
+
DisconnectReason,
|
|
2966
|
+
|
|
2967
|
+
// Message generation
|
|
2968
|
+
generateWAMessage,
|
|
2969
|
+
generateWAMessageFromContent,
|
|
2970
|
+
generateWAMessageContent,
|
|
2971
|
+
generateMessageIDV2,
|
|
2972
|
+
|
|
2973
|
+
// Media
|
|
2974
|
+
downloadMediaMessage,
|
|
2975
|
+
downloadContentFromMessage,
|
|
2976
|
+
prepareWAMessageMedia,
|
|
2977
|
+
|
|
2978
|
+
// Message utils
|
|
2979
|
+
getContentType,
|
|
2980
|
+
normalizeMessageContent,
|
|
2981
|
+
extractMessageContent,
|
|
2982
|
+
getAggregateVotesInPollMessage,
|
|
2983
|
+
|
|
2984
|
+
// JID utils
|
|
2985
|
+
jidDecode,
|
|
2986
|
+
jidNormalizedUser,
|
|
2987
|
+
areJidsSameUser,
|
|
2988
|
+
isJidGroup,
|
|
2989
|
+
isJidNewsletterGroup,
|
|
2990
|
+
isJidUser,
|
|
2991
|
+
isLidUser,
|
|
2992
|
+
isJidBroadcast,
|
|
2993
|
+
isJidStatusBroadcast,
|
|
2994
|
+
|
|
2995
|
+
// Types / Enums
|
|
2996
|
+
WAMessageStubType,
|
|
2997
|
+
WAMessageStatus,
|
|
2998
|
+
WAMessageAddressingMode,
|
|
2999
|
+
resolveStubType, // resolveStubType(stubType) → name string
|
|
3000
|
+
WA_STUB_TYPE_NAMES, // { 196: 'SUPPORT_AI_EDUCATION', 225: 'SCHEDULED_MESSAGE_CREATED', ... }
|
|
3001
|
+
AIProvenanceType, // { NONE: 0, CREATED_WITH_GEN_AI: 1, EDITED_WITH_GEN_AI: 2 }
|
|
3002
|
+
DeviceCapabilityLevel, // { NONE: 0, INFRA: 1, FULL: 2 }
|
|
3003
|
+
|
|
3004
|
+
// Rich message helpers
|
|
3005
|
+
tokenizeCode, // tokenizeCode(code, language) → { codeBlocks, unified_codeBlock }
|
|
3006
|
+
extractIE, // extractIE(text, extraEntities?) → { text, inline_entities }
|
|
3007
|
+
waitAllPromises, // deep async resolver
|
|
3008
|
+
generateVerificationMetadata, // bot signature metadata
|
|
3009
|
+
// AIRich utilities
|
|
3010
|
+
hasVerifiableProofs,
|
|
3011
|
+
wrapToBotForwardedMessage,
|
|
3012
|
+
attachBotVerificationProofs,
|
|
3013
|
+
buildImaginePrimitive,
|
|
3014
|
+
prepareRichGenerationMessage,
|
|
3015
|
+
extractVerificationMetadata
|
|
3016
|
+
|
|
3017
|
+
// Status checker
|
|
3018
|
+
checkStatusWA,
|
|
3019
|
+
} from '@zervonex/baileys'
|
|
3020
|
+
```
|
|
3021
|
+
|
|
3022
|
+
---
|
|
3023
|
+
|
|
3024
|
+
## 📡 Events Reference
|
|
3025
|
+
|
|
3026
|
+
| Event | Fields | Description |
|
|
3027
|
+
|-------|--------|-------------|
|
|
3028
|
+
| `connection.update` | `connection`, `qr`, `lastDisconnect`, `isNewLogin` | Connection state changed |
|
|
3029
|
+
| `creds.update` | partial `AuthenticationCreds` | Auth credentials updated |
|
|
3030
|
+
| `messaging-history.set` | `chats`, `contacts`, `messages`, `syncType`, `isLatest` | Initial history loaded |
|
|
3031
|
+
| `messages.upsert` | `messages[]`, `type` | New message(s) received |
|
|
3032
|
+
| `messages.update` | `[{ key, update }]` | Message status/content updated |
|
|
3033
|
+
| `messages.delete` | `keys[]` or `{ jid, all }` | Message(s) deleted |
|
|
3034
|
+
| `messages.reaction` | `[{ reaction, key }]` | Reaction added/removed |
|
|
3035
|
+
| `messages.media-update` | `[{ key, media?, error? }]` | Media upload status updated |
|
|
3036
|
+
| `message-receipt.update` | `[{ key, receipt }]` | Read/delivered receipts |
|
|
3037
|
+
| `chats.set` | `{ chats[], isLatest }` | Initial chat list loaded |
|
|
3038
|
+
| `chats.upsert` | `Chat[]` | New chat(s) appeared |
|
|
3039
|
+
| `chats.update` | `Partial<Chat>[]` | Chat metadata updated |
|
|
3040
|
+
| `chats.delete` | `string[]` | Chat(s) deleted |
|
|
3041
|
+
| `contacts.set` | `{ contacts[] }` | Initial contacts loaded |
|
|
3042
|
+
| `contacts.upsert` | `Contact[]` | New contact(s) added |
|
|
3043
|
+
| `contacts.update` | `Partial<Contact>[]` | Contact info updated |
|
|
3044
|
+
| `groups.upsert` | `GroupMetadata[]` | New group created/joined |
|
|
3045
|
+
| `groups.update` | `Partial<GroupMetadata>[]` | Group metadata changed |
|
|
3046
|
+
| `group-participants.update` | `{ id, author, authorPn, participants, action }` | Member added/removed/promoted/demoted |
|
|
3047
|
+
| `blocklist.set` | `{ blocklist[] }` | Initial blocklist loaded |
|
|
3048
|
+
| `blocklist.update` | `{ blocklist[], type }` | Block/unblock event |
|
|
3049
|
+
| `presence.update` | `{ id, presences }` | User presence changed |
|
|
3050
|
+
| `call` | `WACallEvent[]` | Incoming/outgoing call |
|
|
3051
|
+
| `labels.edit` | `Label` | Label created/updated |
|
|
3052
|
+
| `labels.association` | `[{ association, type }]` | Message/chat label assigned/removed |
|
|
3053
|
+
| `settings.update` | `{ setting, value }` | Account setting changed (theme, AI thread rename, device capabilities, etc.) |
|
|
3054
|
+
|
|
3055
|
+
**`group-participants.update` fields:**
|
|
3056
|
+
|
|
3057
|
+
| Field | Type | Description |
|
|
3058
|
+
|-------|------|-------------|
|
|
3059
|
+
| `id` | `string` | Group JID |
|
|
3060
|
+
| `author` | `string` | JID of who performed the action |
|
|
3061
|
+
| `authorPn` | `string` | Phone number of the actor (PN format) |
|
|
3062
|
+
| `participants` | `string[]` | JIDs of affected participants |
|
|
3063
|
+
| `action` | `string` | `add` \| `remove` \| `promote` \| `demote` |
|
|
3064
|
+
|
|
3065
|
+
---
|
|
3066
|
+
|
|
3067
|
+
## 🤖 Meta AI Messages
|
|
3068
|
+
|
|
3069
|
+
Meta AI bot messages (`msmsg` encrypted responses) are now automatically decrypted when received. They arrive as regular messages in `messages.upsert` once decrypted:
|
|
3070
|
+
|
|
3071
|
+
```javascript
|
|
3072
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
3073
|
+
for (const msg of messages) {
|
|
3074
|
+
if (!msg.message) continue
|
|
3075
|
+
|
|
3076
|
+
// Meta AI responses appear as regular extendedTextMessage or other content
|
|
3077
|
+
const content = extractMessageContent(msg.message)
|
|
3078
|
+
if (content?.extendedTextMessage?.text) {
|
|
3079
|
+
console.log('Message (possibly Meta AI):', content.extendedTextMessage.text)
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
})
|
|
3083
|
+
```
|
|
3084
|
+
|
|
3085
|
+
If decryption fails (e.g. missing message secret), the message is gracefully NACKed and logged — it won't crash your session.
|
|
3086
|
+
|
|
3087
|
+
---
|
|
3088
|
+
|
|
3089
|
+
## 🎯 Best Practices
|
|
3090
|
+
|
|
3091
|
+
### Reconnection
|
|
3092
|
+
|
|
3093
|
+
```javascript
|
|
3094
|
+
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
3095
|
+
if (connection === 'close') {
|
|
3096
|
+
const code = lastDisconnect?.error?.output?.statusCode
|
|
3097
|
+
const shouldReconnect = code !== DisconnectReason.loggedOut
|
|
3098
|
+
if (shouldReconnect) connectToWhatsApp()
|
|
3099
|
+
else console.log('Logged out — clear session and re-authenticate')
|
|
3100
|
+
}
|
|
3101
|
+
})
|
|
3102
|
+
```
|
|
3103
|
+
|
|
3104
|
+
### Cache Group Metadata
|
|
3105
|
+
|
|
3106
|
+
```javascript
|
|
3107
|
+
import NodeCache from '@cacheable/node-cache'
|
|
3108
|
+
|
|
3109
|
+
const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
|
|
3110
|
+
|
|
3111
|
+
const sock = makeWASocket({
|
|
3112
|
+
cachedGroupMetadata: async (jid) => groupCache.get(jid)
|
|
3113
|
+
})
|
|
3114
|
+
|
|
3115
|
+
sock.ev.on('groups.update', async ([event]) => {
|
|
3116
|
+
const metadata = await sock.groupMetadata(event.id)
|
|
3117
|
+
groupCache.set(event.id, metadata)
|
|
3118
|
+
})
|
|
3119
|
+
```
|
|
3120
|
+
|
|
3121
|
+
### Rate Limiting
|
|
3122
|
+
|
|
3123
|
+
```javascript
|
|
3124
|
+
const queue = []
|
|
3125
|
+
let sending = false
|
|
3126
|
+
|
|
3127
|
+
const queueMessage = (jid, content) => {
|
|
3128
|
+
queue.push({ jid, content })
|
|
3129
|
+
if (!sending) processQueue()
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
const processQueue = async () => {
|
|
3133
|
+
sending = true
|
|
3134
|
+
while (queue.length > 0) {
|
|
3135
|
+
const { jid, content } = queue.shift()
|
|
3136
|
+
await sock.sendMessage(jid, content)
|
|
3137
|
+
await new Promise(r => setTimeout(r, 1000))
|
|
3138
|
+
}
|
|
3139
|
+
sending = false
|
|
3140
|
+
}
|
|
3141
|
+
```
|
|
3142
|
+
|
|
3143
|
+
### Error Handling
|
|
3144
|
+
|
|
3145
|
+
```javascript
|
|
3146
|
+
try {
|
|
3147
|
+
await sock.sendMessage(jid, { text: 'Hello' })
|
|
3148
|
+
} catch (error) {
|
|
3149
|
+
if (error.output?.statusCode === 401) console.log('Unauthorized')
|
|
3150
|
+
else console.error('Send failed:', error)
|
|
3151
|
+
}
|
|
3152
|
+
```
|
|
3153
|
+
|
|
3154
|
+
### Poll Decryption
|
|
3155
|
+
|
|
3156
|
+
```javascript
|
|
3157
|
+
import { getAggregateVotesInPollMessage } from '@zervonex/baileys'
|
|
3158
|
+
|
|
3159
|
+
sock.ev.on('messages.update', async (event) => {
|
|
3160
|
+
for (const { key, update } of event) {
|
|
3161
|
+
if (update.pollUpdates) {
|
|
3162
|
+
const pollCreation = await getMessage(key)
|
|
3163
|
+
if (pollCreation) {
|
|
3164
|
+
const result = getAggregateVotesInPollMessage({
|
|
3165
|
+
message: pollCreation,
|
|
3166
|
+
pollUpdates: update.pollUpdates
|
|
3167
|
+
})
|
|
3168
|
+
console.log('Poll votes:', result)
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
})
|
|
3173
|
+
```
|
|
3174
|
+
|
|
3175
|
+
---
|
|
3176
|
+
|
|
3177
|
+
## ⚠️ Disclaimer
|
|
3178
|
+
|
|
3179
|
+
This project is **not** affiliated with WhatsApp or Meta. Use responsibly:
|
|
3180
|
+
|
|
3181
|
+
- Follow WhatsApp's Terms of Service
|
|
3182
|
+
- Do not spam or send unsolicited messages
|
|
3183
|
+
- Respect user privacy
|
|
3184
|
+
- Be aware of WhatsApp's rate limits
|
|
3185
|
+
- This library is for legitimate automation purposes only
|
|
3186
|
+
|
|
3187
|
+
---
|
|
3188
|
+
|
|
3189
|
+
## 🙏 Acknowledgments
|
|
3190
|
+
|
|
3191
|
+
- [WhiskeySockets](https://github.com/WhiskeySockets) for the original Baileys library
|
|
3192
|
+
- All contributors and the open-source community
|
|
3193
|
+
|
|
3194
|
+
---
|
|
3195
|
+
|
|
3196
|
+
<div align="center">
|
|
3197
|
+
|
|
3198
|
+
**Made with ❤️ by [nexustechpro2](https://github.com/nexustechpro2)**
|
|
3199
|
+
|
|
3200
|
+
⭐ **Star us on GitHub!** ⭐
|
|
3201
|
+
|
|
3202
|
+
[GitHub](https://github.com/nexustechpro2/baileys) • [NPM](https://www.npmjs.com/package/@zervonex/baileys)
|
|
3203
|
+
|
|
3204
|
+
</div>
|