@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.
Files changed (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3203 -2
  3. package/WAProto/WAProtoCompile.js +291 -0
  4. package/WAProto/fetcher.js +69 -0
  5. package/WAProto/index.js +88 -0
  6. package/WAProto/parser.js +313 -0
  7. package/engine-requirements.js +10 -0
  8. package/lib/Builders/AIRich.js +590 -0
  9. package/lib/Builders/base.js +130 -0
  10. package/lib/Builders/builders.js +448 -0
  11. package/lib/Builders/index.js +3 -0
  12. package/lib/Defaults/index.js +225 -0
  13. package/lib/Defaults/phonenumber-mcc.json +223 -0
  14. package/lib/Signal/index.js +2 -0
  15. package/lib/Signal/libsignal.js +523 -0
  16. package/lib/Signal/lid-mapping.js +283 -0
  17. package/lib/Socket/Client/index.js +2 -0
  18. package/lib/Socket/Client/types.js +10 -0
  19. package/lib/Socket/Client/websocket.js +84 -0
  20. package/lib/Socket/business.js +152 -0
  21. package/lib/Socket/chats.js +855 -0
  22. package/lib/Socket/communities.js +147 -0
  23. package/lib/Socket/groups.js +294 -0
  24. package/lib/Socket/index.js +15 -0
  25. package/lib/Socket/messages-recv.js +904 -0
  26. package/lib/Socket/messages-send.js +693 -0
  27. package/lib/Socket/mex.js +34 -0
  28. package/lib/Socket/newsletter.js +752 -0
  29. package/lib/Socket/nexus-handler.js +55 -0
  30. package/lib/Socket/registration.js +155 -0
  31. package/lib/Socket/socket.js +798 -0
  32. package/lib/Socket/spam-report.js +65 -0
  33. package/lib/Socket/username.js +82 -0
  34. package/lib/Store/index.js +6 -0
  35. package/lib/Store/make-cache-manager-store.js +81 -0
  36. package/lib/Store/make-in-memory-store.js +425 -0
  37. package/lib/Store/make-ordered-dictionary.js +82 -0
  38. package/lib/Store/object-repository.js +31 -0
  39. package/lib/Store/reporting-info-store.js +38 -0
  40. package/lib/Types/Auth.js +2 -0
  41. package/lib/Types/Bussines.js +2 -0
  42. package/lib/Types/Call.js +2 -0
  43. package/lib/Types/Chat.js +8 -0
  44. package/lib/Types/Contact.js +2 -0
  45. package/lib/Types/Events.js +2 -0
  46. package/lib/Types/GroupMetadata.js +2 -0
  47. package/lib/Types/Label.js +25 -0
  48. package/lib/Types/LabelAssociation.js +7 -0
  49. package/lib/Types/Message.js +15 -0
  50. package/lib/Types/Newsletter.js +100 -0
  51. package/lib/Types/Product.js +2 -0
  52. package/lib/Types/Signal.js +2 -0
  53. package/lib/Types/Socket.js +14 -0
  54. package/lib/Types/State.js +26 -0
  55. package/lib/Types/USync.js +2 -0
  56. package/lib/Types/index.js +30 -0
  57. package/lib/Utils/auth-utils.js +142 -0
  58. package/lib/Utils/baileys-event-stream.js +33 -0
  59. package/lib/Utils/bot-capabilities.js +40 -0
  60. package/lib/Utils/bot-planning-replay.js +44 -0
  61. package/lib/Utils/browser-utils.js +26 -0
  62. package/lib/Utils/business.js +75 -0
  63. package/lib/Utils/chat-utils.js +316 -0
  64. package/lib/Utils/companion-reg-client-utils.js +20 -0
  65. package/lib/Utils/consumer-application.js +38 -0
  66. package/lib/Utils/crypto.js +52 -0
  67. package/lib/Utils/decode-wa-message.js +197 -0
  68. package/lib/Utils/event-buffer.js +273 -0
  69. package/lib/Utils/extras.js +186 -0
  70. package/lib/Utils/generics.js +195 -0
  71. package/lib/Utils/history.js +51 -0
  72. package/lib/Utils/identity-change-handler.js +19 -0
  73. package/lib/Utils/index.js +39 -0
  74. package/lib/Utils/key-store.js +3 -0
  75. package/lib/Utils/link-preview.js +51 -0
  76. package/lib/Utils/logger.js +2 -0
  77. package/lib/Utils/lt-hash.js +3 -0
  78. package/lib/Utils/make-mutex.js +16 -0
  79. package/lib/Utils/message-composer.js +59 -0
  80. package/lib/Utils/message-retry-manager.js +48 -0
  81. package/lib/Utils/messages-media.js +520 -0
  82. package/lib/Utils/messages.js +742 -0
  83. package/lib/Utils/meta-ai-msmsg.js +122 -0
  84. package/lib/Utils/meta-compositing.js +75 -0
  85. package/lib/Utils/modern-messages.js +235 -0
  86. package/lib/Utils/native-flow.js +55 -0
  87. package/lib/Utils/noise-handler.js +161 -0
  88. package/lib/Utils/pre-key-manager.js +76 -0
  89. package/lib/Utils/process-message.js +399 -0
  90. package/lib/Utils/reporting-utils.js +171 -0
  91. package/lib/Utils/signal.js +167 -0
  92. package/lib/Utils/spam-report-utils.js +142 -0
  93. package/lib/Utils/sync-action-utils.js +33 -0
  94. package/lib/Utils/tc-token-utils.js +102 -0
  95. package/lib/Utils/use-multi-file-auth-state.js +307 -0
  96. package/lib/Utils/validate-connection.js +181 -0
  97. package/lib/WABinary/constants.js +1321 -0
  98. package/lib/WABinary/decode.js +152 -0
  99. package/lib/WABinary/encode.js +140 -0
  100. package/lib/WABinary/generic-utils.js +179 -0
  101. package/lib/WABinary/index.js +6 -0
  102. package/lib/WABinary/jid-utils.js +235 -0
  103. package/lib/WABinary/types.js +4 -0
  104. package/lib/WAM/BinaryInfo.js +10 -0
  105. package/lib/WAM/constants.js +22853 -0
  106. package/lib/WAM/encode.js +150 -0
  107. package/lib/WAM/index.js +3 -0
  108. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +30 -0
  109. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +48 -0
  110. package/lib/WAUSync/Protocols/USyncContactProtocol.js +23 -0
  111. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +28 -0
  112. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +15 -0
  113. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +24 -0
  114. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +9 -0
  115. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +21 -0
  116. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +19 -0
  117. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +19 -0
  118. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +22 -0
  119. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +16 -0
  120. package/lib/WAUSync/Protocols/index.js +12 -0
  121. package/lib/WAUSync/USyncQuery.js +100 -0
  122. package/lib/WAUSync/USyncUser.js +20 -0
  123. package/lib/WAUSync/index.js +3 -0
  124. package/lib/index.js +68 -0
  125. package/package.json +216 -5
package/README.md CHANGED
@@ -1,3 +1,3204 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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>