@zervonex/baileys 0.0.0-stage → 3.0.2

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