@crysnovax/baileys 2.5.0 → 2.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,20 +1,3 @@
1
- <p align="center">
2
- <img src="https://readme-typing-svg.demolab.com?font=Fira+Code&weight=700&size=40&duration=3000&pause=800&color=10B981&center=true&vCenter=true&width=600&lines=%F0%9F%91%8B+Hey%2C+I'm+CRYSNOVA;%F0%9F%92%BB+Full+Stack+Developer;%F0%9F%9A%80+Building+the+Future;%F0%9F%94%A5+Open+Source+Lover" alt="Typing Animation" />
3
- </p>
4
-
5
- <p align="center">
6
- <img src="https://img.shields.io/github/followers/crysnovax?style=for-the-badge&logo=github&color=10b981&labelColor=0a0f0a" />
7
- <img src="https://img.shields.io/github/stars/crysnovax?style=for-the-badge&logo=github&color=10b981&labelColor=0a0f0a" />
8
- <img src="https://komarev.com/ghpvc/?username=crysnovax&style=for-the-badge&color=10b981&label=PROFILE+VIEWS" />
9
- </p>
10
-
11
- <br />
12
-
13
- <div align="center">
14
- <img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="700">
15
- </div>
16
-
17
- <br />
18
1
 
19
2
  <h2 align="center">
20
3
  <img src="https://media2.giphy.com/media/QssGEmpkyEOhBCb7e1/giphy.gif?cid=ecf05e47a0n3gi1bfqntqmob8g9aid1oyj2wr3ds3mg700bl&rid=giphy.gif" width="28" />
@@ -64,254 +47,841 @@ const crysnova = {
64
47
 
65
48
  | 🚀 Project | ⭐ Stars | 📝 Description |
66
49
  |-----------|---------|---------------|
67
- | **CRYSNOVA AI** | [![Stars](https://img.shields.io/github/stars/crysnovax/CRYSNOVA_AI?style=flat&color=10b981)](https://github.com/crysnovax/CRYSNOVA_AI) | 250+ Command WhatsApp Bot with AI Integration |
50
+ | **CRYSNOVA AI** | [![Stars](https://img.shields.io/github/stars/crysnovax/CRYSNOVA_AI?style=flat&color=10b981)](https://github.com/crysnovax/CRYSNOVA_AI) | 550+ Command WhatsApp Bot with AI Integration |
68
51
  | **API Gateway** | [![Stars](https://img.shields.io/github/stars/crysnovax/API?style=flat&color=10b981)](https://github.com/crysnovax/API) | Nexray Endpoints Unified API Gateway |
69
52
  | **Economy Engine** | [![Stars](https://img.shields.io/github/stars/crysnovax?style=flat&color=10b981)](https://github.com/crysnovax) | Realistic Virtual Economy with Banking System |
70
53
 
71
54
  </div>
72
55
 
73
- <br />
74
56
 
75
- <h2 align="center">
76
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
77
- GitHub Stats
78
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
79
- </h2>
80
57
 
81
- <div align="center">
82
- <a href="https://github.com/crysnovax">
83
- <img height="180em" src="https://github-readme-stats.vercel.app/api?username=crysnovax&show_icons=true&theme=dark&title_color=10b981&icon_color=10b981&text_color=e2f5e8&bg_color=0a0f0a&hide_border=true&count_private=true&include_all_commits=true" />
84
- </a>
85
- <a href="https://github.com/crysnovax">
86
- <img height="180em" src="https://github-readme-stats.vercel.app/api/top-langs/?username=crysnovax&layout=compact&theme=dark&title_color=10b981&text_color=e2f5e8&bg_color=0a0f0a&hide_border=true&langs_count=8" />
87
- </a>
88
- </div>
58
+ <p align="center">
59
+ <img src="https://readme-typing-svg.demolab.com?font=Fira+Code&weight=700&size=32&duration=3000&pause=800&color=10B981&center=true&vCenter=true&width=650&lines=%F0%9F%9A%80+%40crysnovax%2Fbailey%3B+WhatsApp+API+for+Node.js%3B+Rich+Messages+%7C+Meta+AI+Style%3B+Production+Ready+%E2%9C%85" alt="Typing Animation" />
60
+ </p>
61
+
62
+ <p align="center">
63
+ <img src="https://img.shields.io/npm/v/@crysnovax/bailey?style=for-the-badge&logo=npm&color=10b981&labelColor=0a0f0a" />
64
+ <img src="https://img.shields.io/github/stars/crysnovax/baileys?style=for-the-badge&logo=github&color=10b981&labelColor=0a0f0a" />
65
+ <img src="https://img.shields.io/badge/License-MIT-10b981?style=for-the-badge&labelColor=0a0f0a" />
66
+ <img src="https://img.shields.io/badge/Node.js-%3E%3D18-10b981?style=for-the-badge&logo=node.js&labelColor=0a0f0a" />
67
+ </p>
89
68
 
90
69
  <br />
91
70
 
92
71
  <div align="center">
93
- <a href="https://github.com/crysnovax">
94
- <img src="https://github-readme-streak-stats.herokuapp.com/?user=crysnovax&theme=dark&ring=10b981&fire=10b981&currStreakLabel=10b981&sideNums=10b981&sideLabels=e2f5e8&dates=6aa886&background=0a0f0a&hide_border=true" />
95
- </a>
72
+ <img src="https://user-images.githubusercontent.com/74038190/212284100-561aa473-3905-4a80-b561-0d28506553ee.gif" width="700">
96
73
  </div>
97
74
 
98
75
  <br />
99
76
 
100
- <div align="center">
101
- <img src="https://github-profile-trophy.vercel.app/?username=crysnovax&theme=darkhub&no-frame=true&no-bg=true&margin-w=15&column=7&title_color=10b981" />
102
- </div>
77
+ ## Table of Contents
78
+
79
+ | # | Section | Description |
80
+ |---|---------|-------------|
81
+ | 1 | [Overview](#overview) | What this package is and what sets it apart |
82
+ | 2 | [Installation](#installation) | NPM, GitHub, ESM & CJS imports |
83
+ | 3 | [Quick Start](#quick-start) | Minimal working connection example |
84
+ | 4 | [Authentication](#authentication) | Auth states, pairing codes, SQLite |
85
+ | 5 | [Sending Messages](#sending-messages) | Text, mentions, reactions, contacts, locations, events, polls, forward, edit |
86
+ | 6 | [Media Messages](#media-messages) | Images, videos, audio, documents, stickers, albums |
87
+ | 7 | [Interactive Messages](#interactive-messages) | Buttons, lists, native flows, carousels, hydrated templates |
88
+ | 8 | [Rich Content](#rich-content) | Code blocks, tables, inline entities, rich response arrays |
89
+ | 9 | [Meta AI Features](#meta-ai-features) | Meta typing, meta compositing, replay planning |
90
+ | 10 | [Welcome Flow](#welcome-flow) | Auto-greet new contacts with FAQ menus |
91
+ | 11 | [Payment Messages](#payment-messages) | Invites, invoices, orders, payment requests |
92
+ | 12 | [Message Options](#message-options) | AI icon, ephemeral, spoilers, view once, raw, and more |
93
+ | 13 | [Newsletter Management](#newsletter-management) | Create, update, follow, react, delete newsletters |
94
+ | 14 | [Group Management](#group-management) | Create, settings, participants, invites, metadata |
95
+ | 15 | [Community Management](#community-management) | Communities, subgroups, linked groups |
96
+ | 16 | [Profile & Business](#profile--business) | Profile pictures, business catalog, products, quick replies |
97
+ | 17 | [Privacy & Security](#privacy--security) | Last seen, online, status, read receipts, calls |
98
+ | 18 | [Events Reference](#events-reference) | Full list of socket event listeners |
99
+ | 19 | [Image Processing](#image-processing) | Sharp, NAPI-RS, Jimp auto-detection |
100
+ | 20 | [Condition of Use](#condition-of-use) | Channel follow agreement |
101
+ | 21 | [Credits](#credits) | Attribution and enhancements |
102
+
103
+ ---
104
+
105
+ ## Overview
106
+
107
+ `@crysnovax/bailey` is a powerful, production-ready WhatsApp API wrapper for Node.js, built on top of the Baileys protocol. It extends the core with rich messaging capabilities, Meta AI-style compositing, and a streamlined developer experience.
108
+
109
+ ### What Sets It Apart
110
+
111
+ | Feature | Status | Notes |
112
+ |---------|--------|-------|
113
+ | Rich Messages | ✅ | Code blocks, tables, inline entities, carousel cards |
114
+ | Meta AI Style | ✅ | Live thinking indicators without "edited" badges |
115
+ | Welcome Flow | ✅ | Auto-greet new contacts with interactive FAQ menus |
116
+ | No Obfuscation | ✅ | Fully readable, auditable source code |
117
+ | Newsletter Ready | ✅ | Full media support, quoting, quiz polls |
118
+ | Image Processing | ✅ | Auto-detects `sharp`, `@napi-rs/image`, or `jimp` |
119
+ | Safe FFmpeg | ✅ | Uses `spawn` instead of `exec` |
120
+ | In-Memory Store | ✅ | Reintroduced with minimal ESM adaptation |
121
+
122
+ ---
123
+
124
+ ## Installation
125
+
126
+ ```bash
127
+ # NPM
128
+ npm install @crysnovax/bailey
129
+
130
+ # GitHub
131
+ npm install github:crysnovax/baileys
132
+ ```
103
133
 
104
- <br />
134
+ ### Import (ESM & CJS)
105
135
 
106
- <h2 align="center">
107
- <img src="https://media.giphy.com/media/LnQjpWaON8nhr21vNW/giphy.gif" width="28" />
108
- Let's Connect
109
- <img src="https://media.giphy.com/media/LnQjpWaON8nhr21vNW/giphy.gif" width="28" />
110
- </h2>
136
+ ```javascript
137
+ // ESM
138
+ import { makeWASocket } from '@crysnovax/bailey'
111
139
 
112
- <p align="center">
113
- <a href="https://whatsapp.com/channel/0029Vb6pe77K0IBn48HLKb38">
114
- <img src="https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white&labelColor=0a0f0a&color=10b981" />
115
- </a>
116
- <a href="https://youtube.com/@crysnovax">
117
- <img src="https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge&logo=youtube&logoColor=white&labelColor=0a0f0a&color=10b981" />
118
- </a>
119
- <a href="https://discord.com/users/crysnovadesigns">
120
- <img src="https://img.shields.io/badge/Discord-crysnovadesigns-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=0a0f0a&color=10b981" />
121
- </a>
122
- <a href="https://github.com/crysnovax">
123
- <img src="https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white&labelColor=0a0f0a&color=10b981" />
124
- </a>
125
- <a href="mailto:crysnovax@gmail.com">
126
- <img src="https://img.shields.io/badge/Email-D14836?style=for-the-badge&logo=gmail&logoColor=white&labelColor=0a0f0a&color=10b981" />
127
- </a>
128
- </p>
140
+ // CJS (Node.js 24+)
141
+ const { makeWASocket } = require('@crysnovax/bailey')
142
+ ```
129
143
 
130
- <br />
144
+ ---
131
145
 
132
- <div align="center">
133
- <img src="https://quotes-github-readme.vercel.app/api?type=horizontal&theme=dark&quote=Code+is+like+humor.+When+you+have+to+explain+it,+it's+bad.&author=Cory+House" />
134
- </div>
146
+ ## Quick Start
135
147
 
136
- <br />
148
+ ```javascript
149
+ import { makeWASocket, delay, DisconnectReason, useMultiFileAuthState } from '@crysnovax/bailey'
150
+ import { Boom } from '@hapi/boom'
151
+ import pino from 'pino'
137
152
 
138
- <h2 align="center">⚠️ Condition of Use</h2>
153
+ const myPhoneNumber = '6288888888888'
154
+ const logger = pino({ level: 'silent' })
139
155
 
140
- <p align="center">
141
- By using <b>@crysnovax/bailey</b> you agree to the following condition:<br/><br/>
142
- This fork will automatically follow the two official Crysnovax WhatsApp channels<br/>
143
- on first connection. This happens once and will not repeat on reconnects.<br/><br/>
144
- <b>The channels are:</b><br/>
145
- 📢 <a href="https://whatsapp.com/channel/120363402922206865">Crysnovax Channel 1</a><br/>
146
- 📢 <a href="https://whatsapp.com/channel/120363423670814885">Crysnovax Channel 2</a><br/><br/>
147
- This is how you stay updated with new features, patches, and releases.<br/>
148
- If you do not agree to this condition, do not use this fork.
149
- </p>
156
+ const connectToWhatsApp = async () => {
157
+ const { state, saveCreds } = await useMultiFileAuthState('session')
150
158
 
151
- <br />
159
+ const sock = makeWASocket({
160
+ logger,
161
+ auth: state
162
+ })
152
163
 
153
- <h2 align="center">
154
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
155
- Welcome Flow — Startup Template
156
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
157
- </h2>
164
+ sock.ev.on('creds.update', saveCreds)
158
165
 
159
- <p align="center">
160
- Meta Business-style greeting template fires automatically on first message<br/>
161
- from any new contact with an interactive FAQ menu. Once per contact, never repeats.
162
- </p>
166
+ sock.ev.on('connection.update', async (update) => {
167
+ const { connection, lastDisconnect } = update
163
168
 
164
- <br />
169
+ if (connection === 'connecting' && !sock.authState.creds.registered) {
170
+ await delay(1500)
171
+ const code = await sock.requestPairingCode(myPhoneNumber)
172
+ console.log('Pairing code:', code)
173
+ }
174
+ else if (connection === 'close') {
175
+ const shouldReconnect = new Boom(lastDisconnect?.error)?.output?.statusCode !== DisconnectReason.loggedOut
176
+ console.log('Connection closed, reconnecting:', shouldReconnect)
177
+ if (shouldReconnect) connectToWhatsApp()
178
+ }
179
+ else if (connection === 'open') {
180
+ console.log('Connected to WhatsApp')
181
+ }
182
+ })
165
183
 
166
- **Basic setup drop it in and it works:**
184
+ sock.ev.on('messages.upsert', async ({ messages }) => {
185
+ for (const msg of messages) {
186
+ if (!msg.message) continue
187
+ await sock.sendMessage(msg.key.remoteJid, { text: 'Hello world!' })
188
+ }
189
+ })
190
+ }
167
191
 
168
- ```js
169
- import { createWelcomeFlow } from '@crysnovax/bailey'
192
+ connectToWhatsApp()
193
+ ```
170
194
 
171
- const welcome = createWelcomeFlow(sock, {
172
- greeting: '👋 Welcome! How can I help you today?',
173
- footer: 'Powered by MyBot',
174
- buttonText: '📋 Choose an option',
175
- sectionTitle: 'How can we help?',
176
- faqs: [
177
- { id: 'order', title: '📦 Track my order', description: 'Check order status' },
178
- { id: 'billing', title: '💳 Billing & payments', description: 'Payment issues & invoices' },
179
- { id: 'support', title: '🛠️ Technical support', description: 'Get help with a problem' },
180
- { id: 'human', title: '📞 Talk to a human', description: 'Connect with support staff' },
181
- ]
195
+ ---
196
+
197
+ ## Authentication
198
+
199
+ ### Multi-File Auth State (Recommended)
200
+
201
+ ```javascript
202
+ import { useMultiFileAuthState } from '@crysnovax/bailey'
203
+
204
+ const { state, saveCreds } = await useMultiFileAuthState('session')
205
+ ```
206
+
207
+ ### Single-File Auth State (Experimental)
208
+
209
+ ```javascript
210
+ import { useSingleFileAuthState } from '@crysnovax/bailey'
211
+
212
+ const { state, saveCreds } = await useSingleFileAuthState('session.json')
213
+ // Already includes internal caching — no need for makeCacheableSignalKeyStore
214
+ ```
215
+
216
+ ### SQLite Auth State (Experimental)
217
+
218
+ ```javascript
219
+ import { useSqliteAuthState } from '@crysnovax/bailey'
220
+
221
+ const { state, saveCreds } = await useSqliteAuthState('session.db')
222
+ ```
223
+
224
+ ### Custom Pairing Code
225
+
226
+ ```javascript
227
+ const phoneNumber = '6281111111111'
228
+ const customCode = 'STARFALL'
229
+
230
+ await sock.requestPairingCode(phoneNumber, customCode)
231
+ console.log('Pairing code:', customCode)
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Sending Messages
237
+
238
+ ### Text & Mentions
239
+
240
+ ```javascript
241
+ // Plain text
242
+ sock.sendMessage(jid, { text: 'Hello!' }, { quoted: message })
243
+
244
+ // With link preview
245
+ const url = 'https://www.npmjs.com/package/@crysnovax/bailey'
246
+ sock.sendMessage(jid, {
247
+ text: url + ' Check it out!',
248
+ linkPreview: {
249
+ 'matched-text': url,
250
+ title: '@crysnovax/bailey',
251
+ description: 'WhatsApp API for Node.js',
252
+ previewType: 0,
253
+ jpegThumbnail: fs.readFileSync('./thumb.jpg')
254
+ }
182
255
  })
183
256
 
184
- welcome.listen() // start
257
+ // Large link preview with favicon
258
+ import { prepareWAMessageMedia } from '@crysnovax/bailey'
259
+
260
+ const { imageMessage: image } = await prepareWAMessageMedia(
261
+ { image: { url: './thumb.jpg' } },
262
+ { upload: sock.waUploadToServer, mediaTypeOverride: 'thumbnail-link' }
263
+ )
264
+
265
+ image.height = 720
266
+ image.width = 480
267
+
268
+ sock.sendMessage(jid, {
269
+ text: url + ' Check it out!',
270
+ linkPreview: {
271
+ 'matched-text': url,
272
+ title: '@crysnovax/bailey',
273
+ description: 'WhatsApp API for Node.js',
274
+ previewType: 0,
275
+ jpegThumbnail: fs.readFileSync('./thumb.jpg'),
276
+ highQualityThumbnail: image,
277
+ linkPreviewMetadata: {
278
+ linkMediaDuration: 0,
279
+ socialMediaPostType: 1 // 0=NONE, 1=REEL, 2=LIVE, 3=LONG, 4=IMAGE, 5=CAROUSEL
280
+ }
281
+ },
282
+ favicon: { url: './favicon.ico' }
283
+ })
284
+
285
+ // Mention specific users
286
+ sock.sendMessage(jid, {
287
+ text: 'Hello @628123456789',
288
+ mentions: ['628123456789@s.whatsapp.net']
289
+ })
290
+
291
+ // Mention all group participants
292
+ sock.sendMessage(jid, {
293
+ text: 'Hello @all',
294
+ mentionAll: true
295
+ })
185
296
  ```
186
297
 
187
- <br />
298
+ ### Reactions & Pins
299
+
300
+ ```javascript
301
+ // Reaction
302
+ sock.sendMessage(jid, {
303
+ react: { key: message.key, text: '✨' }
304
+ })
188
305
 
189
- **Handle FAQ replies + greet callback:**
306
+ // Pin message (86400=1d, 604800=7d, 2592000=30d)
307
+ sock.sendMessage(jid, {
308
+ pin: message.key,
309
+ time: 86400,
310
+ type: 1 // 1=pin, 2=unpin
311
+ })
190
312
 
191
- ```js
192
- const welcome = createWelcomeFlow(sock, {
193
- greeting: '👋 Hi there! What brings you here today?',
194
- faqs: [
195
- { id: 'pricing', title: '💰 Pricing', description: 'Plans and costs' },
196
- { id: 'demo', title: '🎥 Request demo', description: 'See it in action' },
197
- { id: 'support', title: '🛠️ Support', description: 'Get help' },
313
+ // Keep chat (disappearing messages only)
314
+ sock.sendMessage(jid, {
315
+ keep: message.key,
316
+ type: 1 // 1=keep, 2=remove
317
+ })
318
+ ```
319
+
320
+ ### Contacts & Locations
321
+
322
+ ```javascript
323
+ // Contact card
324
+ const vcard = 'BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nORG:Company;\nTEL;type=CELL;type=VOICE;waid=628123456789:+62 8123 4567 89\nEND:VCARD'
325
+
326
+ sock.sendMessage(jid, {
327
+ contacts: {
328
+ displayName: 'John Doe',
329
+ contacts: [{ vcard }]
330
+ }
331
+ })
332
+
333
+ // Location
334
+ sock.sendMessage(jid, {
335
+ location: {
336
+ degreesLatitude: 24.121231,
337
+ degreesLongitude: 55.1121221,
338
+ name: 'I am here'
339
+ }
340
+ })
341
+
342
+ // Group invite
343
+ const inviteCode = groupUrl.split('chat.whatsapp.com/')[1]?.split('?')[0]
344
+
345
+ sock.sendMessage(jid, {
346
+ groupInvite: {
347
+ inviteCode,
348
+ inviteExpiration: Date.now() + 86400000,
349
+ text: 'Join our group!',
350
+ jid: groupJid,
351
+ subject: groupName
352
+ }
353
+ })
354
+ ```
355
+
356
+ ### Events & Polls
357
+
358
+ ```javascript
359
+ // Calendar event
360
+ sock.sendMessage(jid, {
361
+ event: {
362
+ name: 'Meet & Mingle Party',
363
+ description: 'A fun gathering to connect and chat.',
364
+ call: 'audio', // or 'video'
365
+ startDate: new Date(Date.now() + 3600000),
366
+ endDate: new Date(Date.now() + 28800000),
367
+ isCancelled: false,
368
+ isScheduleCall: false,
369
+ extraGuestsAllowed: false,
370
+ location: {
371
+ name: 'Jakarta',
372
+ degreesLatitude: -6.2,
373
+ degreesLongitude: 106.8
374
+ }
375
+ }
376
+ })
377
+
378
+ // Poll
379
+ sock.sendMessage(jid, {
380
+ poll: {
381
+ name: 'Voting time',
382
+ values: ['Yes', 'No'],
383
+ selectableCount: 1,
384
+ toAnnouncementGroup: false,
385
+ endDate: new Date(Date.now() + 28800000),
386
+ hideVoter: false,
387
+ canAddOption: false
388
+ }
389
+ })
390
+
391
+ // Quiz (newsletter only)
392
+ sock.sendMessage('1211111111111@newsletter', {
393
+ poll: {
394
+ name: 'Quiz',
395
+ values: ['Yes', 'No'],
396
+ correctAnswer: 'Yes',
397
+ pollType: 1
398
+ }
399
+ })
400
+
401
+ // Poll result
402
+ sock.sendMessage(jid, {
403
+ pollResult: {
404
+ name: 'Poll Result',
405
+ votes: [
406
+ { name: 'Nice', voteCount: 10 },
407
+ { name: 'Nah', voteCount: 2 }
198
408
  ],
409
+ pollType: 0
410
+ }
411
+ })
412
+
413
+ // Poll update
414
+ sock.sendMessage(jid, {
415
+ pollUpdate: {
416
+ metadata: {},
417
+ key: message.key,
418
+ vote: { enclv: buffer, encPayload: buffer }
419
+ }
420
+ })
421
+ ```
422
+
423
+ ### Forward & Edit
424
+
425
+ ```javascript
426
+ // Forward
427
+ sock.sendMessage(jid, {
428
+ forward: message,
429
+ force: true
430
+ })
431
+
432
+ // Delete
433
+ sock.sendMessage(jid, { delete: message.key })
434
+
435
+ // Edit text
436
+ sock.sendMessage(jid, {
437
+ text: 'Updated text!',
438
+ edit: message.key
439
+ })
440
+
441
+ // Edit media caption
442
+ sock.sendMessage(jid, {
443
+ caption: 'Updated caption!',
444
+ edit: message.key
445
+ })
446
+ ```
447
+
448
+ ---
449
+
450
+ ## Media Messages
451
+
452
+ ### Images & Videos
453
+
454
+ ```javascript
455
+ // Image
456
+ sock.sendMessage(jid, {
457
+ image: { url: './image.jpg' },
458
+ caption: 'Check this out!'
459
+ })
460
+
461
+ // Video
462
+ sock.sendMessage(jid, {
463
+ video: { url: './video.mp4' },
464
+ gifPlayback: false, // true = send as GIF
465
+ ptv: false, // true = send as PTV
466
+ caption: 'Watch this!'
467
+ })
468
+
469
+ // Status mention (multiple jids)
470
+ sock.sendMessage([jidA, jidB, jidC], {
471
+ text: 'Hello!'
472
+ })
473
+ ```
474
+
475
+ ### Audio & Documents
476
+
477
+ ```javascript
478
+ // Audio
479
+ sock.sendMessage(jid, {
480
+ audio: { url: './audio.mp3' },
481
+ ptt: false // true = voice note
482
+ })
483
+
484
+ // Document
485
+ sock.sendMessage(jid, {
486
+ document: { url: './file.pdf' },
487
+ mimetype: 'application/pdf',
488
+ caption: 'My document'
489
+ })
490
+ ```
491
+
492
+ ### Stickers & Albums
493
+
494
+ ```javascript
495
+ // Sticker
496
+ sock.sendMessage(jid, {
497
+ sticker: { url: './sticker.webp' }
498
+ })
499
+
500
+ // Album (images + videos)
501
+ sock.sendMessage(jid, {
502
+ album: [
503
+ { image: { url: './img1.jpg' }, caption: 'First image' },
504
+ { video: { url: './vid1.mp4' }, caption: 'First video' },
505
+ { image: { url: './img2.jpg' }, caption: 'Second image' }
506
+ ]
507
+ })
508
+
509
+ // Sticker pack
510
+ sock.sendMessage(jid, {
511
+ cover: { url: './cover.webp' },
512
+ stickers: [
513
+ { data: { url: './sticker1.webp' } },
514
+ { data: { url: './sticker2.webp' } }
515
+ ],
516
+ name: 'My Sticker Pack',
517
+ publisher: 'CRYSNOVA',
518
+ description: '@crysnovax/bailey'
519
+ })
520
+ ```
521
+
522
+ ---
523
+
524
+ ## Interactive Messages
525
+
526
+ ### Buttons & Lists
527
+
528
+ ```javascript
529
+ // Buttons
530
+ sock.sendMessage(jid, {
531
+ text: 'Choose an option!',
532
+ footer: '@crysnovax/bailey',
533
+ buttons: [
534
+ { text: 'Sign Up', id: '#SignUp' }
535
+ ]
536
+ })
199
537
 
200
- // Fires after greeting is sent
201
- onGreet: async (jid, message) => {
202
- console.log(`Greeted new contact: ${jid}`)
538
+ // Buttons with media and native flow
539
+ sock.sendMessage(jid, {
540
+ image: { url: './image.jpg' },
541
+ caption: 'Interactive buttons!',
542
+ footer: '@crysnovax/bailey',
543
+ buttons: [
544
+ { text: 'Rating', id: '#Rating' },
545
+ {
546
+ text: 'Select',
547
+ sections: [
548
+ {
549
+ title: 'Section 1',
550
+ rows: [
551
+ { header: '', title: 'Secret Ingredient', description: '', id: '#SecretIngredient' }
552
+ ]
553
+ },
554
+ {
555
+ title: 'Section 2',
556
+ highlight_label: 'Popular',
557
+ rows: [
558
+ { header: '', title: 'Coupon', description: '', id: '#CouponCode' }
559
+ ]
560
+ }
561
+ ]
562
+ }
563
+ ]
564
+ })
565
+
566
+ // List (private chat only)
567
+ sock.sendMessage(jid, {
568
+ text: 'List menu!',
569
+ footer: '@crysnovax/bailey',
570
+ buttonText: 'Select',
571
+ title: 'Hello',
572
+ sections: [
573
+ {
574
+ title: 'Menu 1',
575
+ rows: [
576
+ { title: 'AI', description: '', rowId: '#AI' }
577
+ ]
203
578
  },
579
+ {
580
+ title: 'Menu 2',
581
+ rows: [
582
+ { title: 'Search', description: '', rowId: '#Search' }
583
+ ]
584
+ }
585
+ ]
586
+ })
587
+ ```
204
588
 
205
- // Fires when user picks a FAQ option
206
- onFaqReply: async (jid, faqId, message) => {
207
- switch (faqId) {
208
- case 'pricing':
209
- await sock.sendMessage(jid, { text: '💰 Our plans start at $9/month...' })
210
- break
211
- case 'demo':
212
- await sock.sendMessage(jid, { text: '🎥 Book a demo here: https://...' })
213
- break
214
- case 'support':
215
- await sock.sendMessage(jid, { text: '🛠️ Describe your issue and we\'ll help!' })
216
- break
589
+ ### Native Flows & Carousels
590
+
591
+ ```javascript
592
+ // Native flow with options
593
+ sock.sendMessage(jid, {
594
+ image: { url: './image.jpg' },
595
+ caption: 'Interactive!',
596
+ footer: '@crysnovax/bailey',
597
+ optionText: 'Select Options',
598
+ optionTitle: 'Select Options',
599
+ offerText: 'New Coupon!',
600
+ offerCode: 'SAVE20',
601
+ offerUrl: 'https://example.com',
602
+ offerExpiration: Date.now() + 3600000,
603
+ nativeFlow: [
604
+ { text: 'Greeting', id: '#Greeting', icon: 'review' },
605
+ { text: 'Call', call: '628123456789' },
606
+ { text: 'Copy', copy: '@crysnovax/bailey' },
607
+ { text: 'Source', url: 'https://example.com', useWebview: true },
608
+ {
609
+ text: 'Select',
610
+ sections: [
611
+ {
612
+ title: 'Section 1',
613
+ rows: [
614
+ { header: '', title: 'Coupon', description: '', id: '#CouponCode' }
615
+ ]
217
616
  }
617
+ ],
618
+ icon: 'default'
218
619
  }
620
+ ],
621
+ interactiveAsTemplate: false
219
622
  })
220
623
 
221
- welcome.listen()
624
+ // Carousel with cards
625
+ sock.sendMessage(jid, {
626
+ text: 'Carousel!',
627
+ footer: '@crysnovax/bailey',
628
+ cards: [
629
+ {
630
+ image: { url: './img1.jpg' },
631
+ caption: 'Image 1',
632
+ footer: 'Pinterest',
633
+ nativeFlow: [
634
+ { text: 'Source', url: 'https://example.com', useWebview: true }
635
+ ]
636
+ },
637
+ {
638
+ image: { url: './img2.jpg' },
639
+ caption: 'Image 2',
640
+ footer: 'Pinterest',
641
+ offerText: 'New Coupon!',
642
+ offerCode: 'SAVE20',
643
+ offerUrl: 'https://example.com',
644
+ offerExpiration: Date.now() + 3600000,
645
+ nativeFlow: [
646
+ { text: 'Source', url: 'https://example.com' }
647
+ ]
648
+ }
649
+ ]
650
+ })
651
+
652
+ // Native flow with audio footer
653
+ sock.sendMessage(jid, {
654
+ text: 'Music in footer!',
655
+ audioFooter: { url: './audio.mp3' },
656
+ nativeFlow: [
657
+ { text: 'Good, next', id: '#Next', icon: 'review' },
658
+ { text: 'Skip', id: '#Skip', icon: 'default' }
659
+ ]
660
+ })
222
661
  ```
223
662
 
224
- <br />
663
+ ### Hydrated Templates
225
664
 
226
- **Persist seen contacts across restarts:**
665
+ ```javascript
666
+ sock.sendMessage(jid, {
667
+ title: 'Hello',
668
+ image: { url: './image.jpg' },
669
+ caption: 'Template!',
670
+ footer: '@crysnovax/bailey',
671
+ templateButtons: [
672
+ { text: 'Tap Here', id: '#Order' },
673
+ { text: 'Source', url: 'https://example.com' },
674
+ { text: 'Call', call: '628123456789' }
675
+ ]
676
+ })
677
+ ```
227
678
 
228
- ```js
229
- const welcome = createWelcomeFlow(sock, {
230
- greeting: '👋 Welcome!',
231
- faqs: [...],
232
- persistPath: './data/greeted-contacts.json' // saves + loads automatically
679
+ ---
680
+
681
+ ## Rich Content
682
+
683
+ ### Code Blocks
684
+
685
+ ```javascript
686
+ // Built-in tokenizer
687
+ sock.sendMessage(jid, {
688
+ disclaimerText: 'Code Block',
689
+ headerText: '## Example Usage',
690
+ contentText: '---',
691
+ code: 'console.log("Hello, World!")',
692
+ language: 'javascript',
693
+ footerText: 'Pretty simple, right?'
694
+ })
695
+
696
+ // Supported languages: css, html, javascript, typescript, python, golang, rust, c, c#, c++, bash, bat, powershell
697
+
698
+ // Manual tokenization
699
+ import { tokenizeCode } from '@crysnovax/bailey'
700
+
701
+ const language = 'javascript'
702
+ const code = 'console.log("Hello, World!")'
703
+
704
+ sock.sendMessage(jid, {
705
+ disclaimerText: 'Tokenized Code',
706
+ richResponse: [
707
+ { text: 'Example Usage' },
708
+ { language, code: tokenizeCode(code, language) },
709
+ { text: 'Pretty simple, right?' }
710
+ ]
233
711
  })
234
712
  ```
235
713
 
236
- <br />
714
+ ### Tables & Inline Entities
237
715
 
238
- **Control methods:**
716
+ ```javascript
717
+ // Table message
718
+ sock.sendMessage(jid, {
719
+ disclaimerText: 'Table',
720
+ headerText: '## Comparison',
721
+ contentText: '---',
722
+ title: 'Runtime Comparison',
723
+ table: [
724
+ ['', 'Node.js', 'Bun', 'Deno'],
725
+ ['Engine', 'V8', 'JavaScriptCore', 'V8'],
726
+ ['Performance', '4/5', '5/5', '4/5']
727
+ ],
728
+ noHeading: false,
729
+ footerText: 'Does this help?'
730
+ })
239
731
 
240
- ```js
241
- welcome.listen() // start listening
242
- welcome.stop() // stop listening
243
- welcome.reset(jid) // force re-greet one contact next message
244
- welcome.resetAll() // clear all seen contacts
245
- welcome.hasGreeted(jid) // check if contact was already greeted → boolean
732
+ // Inline entities (links)
733
+ sock.sendMessage(jid, {
734
+ disclaimerText: 'Inline Entities',
735
+ headerText: '## Check Out!',
736
+ contentText: '---',
737
+ links: [
738
+ { text: '1. Google', title: 'Search Engine', url: 'https://google.com' },
739
+ { text: '2. YouTube', title: 'Streaming', url: 'https://youtube.com' }
740
+ ],
741
+ footerText: '---'
742
+ })
246
743
  ```
247
744
 
248
- <br />
745
+ ### Rich Response Arrays
249
746
 
250
- **Full config reference:**
747
+ ```javascript
748
+ // Full rich response with mixed content
749
+ sock.sendMessage(jid, {
750
+ disclaimerText: 'Rich Response',
751
+ richResponse: [
752
+ { text: 'Example Usage' },
753
+ {
754
+ language: 'javascript',
755
+ code: [
756
+ { highlightType: 0, codeContent: 'console.log("Hello, World!")' }
757
+ ]
758
+ },
759
+ { text: 'Pretty simple, right?\n' },
760
+ { text: 'Comparison table:' },
761
+ {
762
+ title: 'Runtime Comparison',
763
+ table: [
764
+ { isHeading: true, items: ['', 'Node.js', 'Bun', 'Deno'] },
765
+ { isHeading: false, items: ['Engine', 'V8', 'JavaScriptCore', 'V8'] },
766
+ { isHeading: false, items: ['Performance', '4/5', '5/5', '4/5'] }
767
+ ]
768
+ },
769
+ { text: 'Does this help clarify?' }
770
+ ]
771
+ })
772
+ ```
251
773
 
252
- | Option | Type | Default | Description |
253
- |--------|------|---------|-------------|
254
- | `greeting` | `string` | `'👋 Welcome!...'` | Body text of the welcome message |
255
- | `footer` | `string` | `'Powered by @crysnovax/bailey'` | Footer text |
256
- | `buttonText` | `string` | `'📋 Choose an option'` | List button label |
257
- | `sectionTitle` | `string` | `'How can we help?'` | Section header in the list |
258
- | `faqs` | `Array` | 4 default items | `{ id, title, description }` objects |
259
- | `typingDelayMs` | `number` | `1200` | Typing indicator duration before greeting |
260
- | `persistPath` | `string\|null` | `null` | JSON file path to persist seen JIDs |
261
- | `ignoreGroups` | `boolean` | `true` | Skip group chats |
262
- | `ignoreNewsletter` | `boolean` | `true` | Skip newsletter messages |
263
- | `ignoreBroadcast` | `boolean` | `true` | Skip broadcast messages |
264
- | `onGreet` | `async fn` | `null` | Called after greeting is sent |
265
- | `onFaqReply` | `async fn` | `null` | Called when user selects a FAQ option |
774
+ ---
266
775
 
267
- <br />
268
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
269
- </h2>
776
+ ## Meta AI Features
270
777
 
271
- <p align="center">
272
- Live Meta AI-style reasoning feed — each step visibly completes in real time,<br/>
273
- then the final rich message lands clean. <b>No "edited" badge. Ever.</b>
274
- </p>
778
+ ### Meta Typing Indicator
275
779
 
276
- <br />
780
+ Show a live thinking indicator that you control. Delete it manually when ready — no "edited" badge ever appears.
781
+
782
+ ```javascript
783
+ import { metaTyping, buildSteps, PlanningStepStatus } from '@crysnovax/bailey'
784
+
785
+ const placeholder = await metaTyping(sock, jid, {
786
+ description: 'Thinking…',
787
+ steps: buildSteps(['Reading your message…', 'Writing response…'])
788
+ })
789
+
790
+ // Do your work here…
791
+
792
+ // Delete the indicator cleanly
793
+ await sock.sendMessage(jid, { delete: placeholder.key })
794
+
795
+ // Send the real message
796
+ await sock.sendMessage(jid, { text: 'Here is your answer!' })
797
+ ```
798
+
799
+ ### Meta Compositing
800
+
801
+ Full flow: indicator shows → auto-deletes → clean final message lands. Works with every rich content type.
802
+
803
+ ```javascript
804
+ import { sendMetaComposited, PlanningStepStatus } from '@crysnovax/bailey'
805
+
806
+ // With code block
807
+ await sendMetaComposited(
808
+ sock, jid,
809
+ { code: 'const x = 1 + 1', language: 'javascript' },
810
+ {
811
+ thinkingMs: 3000,
812
+ description: 'Analyzing…',
813
+ steps: [
814
+ { title: 'Reading context…', status: PlanningStepStatus.DONE },
815
+ { title: 'Writing code…', status: PlanningStepStatus.IN_PROGRESS }
816
+ ]
817
+ }
818
+ )
819
+
820
+ // With table
821
+ await sendMetaComposited(
822
+ sock, jid,
823
+ {
824
+ title: 'Comparison',
825
+ table: [
826
+ ['Feature', 'Baileys', 'Crysnovax'],
827
+ ['Rich Messages', '❌', '✅'],
828
+ ['Meta Compositing', '❌', '✅']
829
+ ]
830
+ },
831
+ { thinkingMs: 2500, description: 'Building table…' }
832
+ )
833
+
834
+ // With rich response array
835
+ await sendMetaComposited(
836
+ sock, jid,
837
+ {
838
+ richResponse: [
839
+ { text: 'Here is your result:' },
840
+ { code: 'console.log("hello")', language: 'javascript' },
841
+ { text: 'Run it with `node index.js`' }
842
+ ]
843
+ },
844
+ { thinkingMs: 2000 }
845
+ )
846
+ ```
277
847
 
278
- **`replayPlanning`** full live flow: all steps IN_PROGRESS → each flips DONE → delete → final message.
848
+ ### Replay Planning
279
849
 
280
- ```js
850
+ Live Meta AI-style reasoning feed — each step visibly completes in real time, then the final rich message lands clean.
851
+
852
+ ```javascript
281
853
  import { replayPlanning, mixedSteps } from '@crysnovax/bailey'
282
854
 
283
855
  await replayPlanning(
284
- sock, jid,
856
+ sock, jid,
285
857
 
286
- // Steps — status is managed automatically, don't pass it
287
- mixedSteps([
288
- { title: 'Understanding your question…', type: 'reasoning' },
289
- { title: 'Searching for data…', type: 'search' },
290
- { title: 'Writing the answer…' }
291
- ]),
858
+ // Steps — status managed automatically
859
+ mixedSteps([
860
+ { title: 'Understanding your question…', type: 'reasoning' },
861
+ { title: 'Searching for data…', type: 'search' },
862
+ { title: 'Writing the answer…' }
863
+ ]),
292
864
 
293
- // Final rich message — any richResponse content
294
- { code: 'const answer = 42', language: 'javascript' },
865
+ // Final rich message
866
+ { code: 'const answer = 42', language: 'javascript' },
295
867
 
296
- // Options
297
- {
298
- description: 'Thinking…', // label on the bubble
299
- stepDelayMs: 900, // ms between each step completing
300
- finalPauseMs: 600, // ms to hold after all steps done
301
- }
868
+ // Options
869
+ {
870
+ description: 'Thinking…',
871
+ stepDelayMs: 900,
872
+ finalPauseMs: 600
873
+ }
302
874
  )
303
875
  ```
304
876
 
305
- <br />
306
-
307
- **Step type helpers** — each renders a different visual in the Meta bubble.
877
+ **Step type helpers:**
308
878
 
309
- ```js
879
+ ```javascript
310
880
  import {
311
- buildReasoningSteps, // isReasoning: true — "thinking" visual
312
- buildSearchSteps, // isEnhancedSearch: true — "searching" visual
313
- mixedSteps, // mix any combination
314
- buildSteps // plain steps (from meta-compositing)
881
+ buildReasoningSteps, // isReasoning: true
882
+ buildSearchSteps, // isEnhancedSearch: true
883
+ mixedSteps, // mix any combination
884
+ buildSteps // plain steps
315
885
  } from '@crysnovax/bailey'
316
886
 
317
887
  // All reasoning
@@ -322,145 +892,720 @@ buildSearchSteps(['Searching the web…', 'Reading top results…'])
322
892
 
323
893
  // Mixed — most realistic Meta AI look
324
894
  mixedSteps([
325
- { title: 'Reading your message…', type: 'reasoning' },
326
- { title: 'Searching sources…', type: 'search' },
327
- { title: 'Composing response…' }
895
+ { title: 'Reading your message…', type: 'reasoning' },
896
+ { title: 'Searching sources…', type: 'search' },
897
+ { title: 'Composing response…' }
328
898
  ])
329
899
  ```
330
900
 
331
- <br />
332
-
333
- **`replayPlanningOnly`** — run the animation without sending a final message. You control what comes next.
901
+ **Replay planning only (no final message):**
334
902
 
335
- ```js
903
+ ```javascript
336
904
  import { replayPlanningOnly, buildSearchSteps } from '@crysnovax/bailey'
337
905
 
338
- await replayPlanningOnly(sock, jid,
339
- buildSearchSteps(['Looking up prices…', 'Comparing results…']),
340
- { stepDelayMs: 1200 }
906
+ await replayPlanningOnly(
907
+ sock, jid,
908
+ buildSearchSteps(['Looking up prices…', 'Comparing results…']),
909
+ { stepDelayMs: 1200 }
341
910
  )
342
911
 
343
912
  // Send whatever you want after — no badge, no trace
344
913
  await sock.sendMessage(jid, { text: 'Here are the results!' })
345
914
  ```
346
915
 
347
- <br />
348
-
349
- **Options reference**
916
+ **Options reference:**
350
917
 
351
918
  | Option | Type | Default | Description |
352
919
  |--------|------|---------|-------------|
353
920
  | `description` | `string` | `'Thinking…'` | Top label on the indicator bubble |
354
- | `placeholderText` | `string` | `''` | Body text shown in bubble while steps run |
355
- | `stepDelayMs` | `number` | `900` | Ms between each step flipping to DONE |
356
- | `finalPauseMs` | `number` | `600` | Ms to hold after all steps complete before cleanup |
357
- | `abortOnDisconnect` | `boolean` | `true` | Stops the loop cleanly if socket closes mid-replay |
358
- | `sendOptions` | `object` | `{}` | Extra options passed to the final `sendMessage` call |
921
+ | `placeholderText` | `string` | `''` | Body text while steps run |
922
+ | `stepDelayMs` | `number` | `900` | Ms between each step completing |
923
+ | `finalPauseMs` | `number` | `600` | Ms to hold after all steps done |
924
+ | `abortOnDisconnect` | `boolean` | `true` | Stops cleanly if socket closes |
925
+ | `sendOptions` | `object` | `{}` | Extra options for final `sendMessage` |
359
926
 
360
- <br />
927
+ ---
361
928
 
362
- <h2 align="center">
363
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
364
- Meta Compositing & Meta Typing
365
- <img src="https://media.giphy.com/media/W5eoZHPpUx9sapR0eu/giphy.gif" width="28" />
366
- </h2>
929
+ ## Welcome Flow
367
930
 
368
- <p align="center">
369
- Send rich messages with a Meta AI-style thinking indicator — no <b>"edited"</b> badge, ever.<br/>
370
- The placeholder shows, then silently deletes, then the final message lands clean.
371
- </p>
931
+ Auto-greet new contacts with an interactive FAQ menu. Fires once per contact, never repeats.
372
932
 
373
- <br />
933
+ ### Basic Setup
374
934
 
375
- **`metaTyping`** — show the thinking indicator only. You control what happens next.
935
+ ```javascript
936
+ import { createWelcomeFlow } from '@crysnovax/bailey'
376
937
 
377
- ```js
378
- import { metaTyping, buildSteps, PlanningStepStatus } from '@crysnovax/bailey'
938
+ const welcome = createWelcomeFlow(sock, {
939
+ greeting: 'Welcome! How can I help you today?',
940
+ footer: 'Powered by MyBot',
941
+ buttonText: 'Choose an option',
942
+ sectionTitle: 'How can we help?',
943
+ faqs: [
944
+ { id: 'order', title: 'Track my order', description: 'Check order status' },
945
+ { id: 'billing', title: 'Billing & payments', description: 'Payment issues' },
946
+ { id: 'support', title: 'Technical support', description: 'Get help' },
947
+ { id: 'human', title: 'Talk to a human', description: 'Connect with staff' }
948
+ ]
949
+ })
379
950
 
380
- const placeholder = await metaTyping(sock, jid, {
381
- description: 'Thinking…',
382
- steps: buildSteps(['Reading your message…', 'Writing response…'])
951
+ welcome.listen() // start
952
+ ```
953
+
954
+ ### With Callbacks
955
+
956
+ ```javascript
957
+ const welcome = createWelcomeFlow(sock, {
958
+ greeting: 'Hi there! What brings you here today?',
959
+ faqs: [
960
+ { id: 'pricing', title: 'Pricing', description: 'Plans and costs' },
961
+ { id: 'demo', title: 'Request demo', description: 'See it in action' },
962
+ { id: 'support', title: 'Support', description: 'Get help' }
963
+ ],
964
+
965
+ onGreet: async (jid, message) => {
966
+ console.log(`Greeted new contact: ${jid}`)
967
+ },
968
+
969
+ onFaqReply: async (jid, faqId, message) => {
970
+ switch (faqId) {
971
+ case 'pricing':
972
+ await sock.sendMessage(jid, { text: 'Our plans start at $9/month…' })
973
+ break
974
+ case 'demo':
975
+ await sock.sendMessage(jid, { text: 'Book a demo here: https://…' })
976
+ break
977
+ case 'support':
978
+ await sock.sendMessage(jid, { text: 'Describe your issue and we will help!' })
979
+ break
980
+ }
981
+ }
383
982
  })
384
983
 
385
- // Delete it yourself whenever ready
386
- await sock.sendMessage(jid, { delete: placeholder.key })
984
+ welcome.listen()
387
985
  ```
388
986
 
389
- <br />
987
+ ### Persist Across Restarts
988
+
989
+ ```javascript
990
+ const welcome = createWelcomeFlow(sock, {
991
+ greeting: 'Welcome!',
992
+ faqs: [...],
993
+ persistPath: './data/greeted-contacts.json'
994
+ })
995
+ ```
390
996
 
391
- **`sendMetaComposited`** full flow: indicator → auto-delete → clean final message.
997
+ ### Control Methods
392
998
 
393
- Works with every rich content type: `code`, `table`, `text`, `expressions` (LaTeX), `items` (reels carousel), or the full `richResponse` array.
999
+ ```javascript
1000
+ welcome.listen() // start listening
1001
+ welcome.stop() // stop listening
1002
+ welcome.reset(jid) // force re-greet one contact
1003
+ welcome.resetAll() // clear all seen contacts
1004
+ welcome.hasGreeted(jid) // check if greeted → boolean
1005
+ ```
394
1006
 
395
- ```js
396
- import { sendMetaComposited, PlanningStepStatus } from '@crysnovax/bailey'
1007
+ ### Config Reference
397
1008
 
398
- // With a code block
399
- await sendMetaComposited(sock, jid,
400
- { code: 'const x = 1 + 1', language: 'javascript' },
401
- {
402
- thinkingMs: 3000,
403
- description: 'Analyzing…',
404
- steps: [
405
- { title: 'Reading context…', status: PlanningStepStatus.DONE },
406
- { title: 'Writing code…', status: PlanningStepStatus.IN_PROGRESS }
407
- ]
1009
+ | Option | Type | Default | Description |
1010
+ |--------|------|---------|-------------|
1011
+ | `greeting` | `string` | `'Welcome!…'` | Body text of welcome message |
1012
+ | `footer` | `string` | `'Powered by @crysnovax/bailey'` | Footer text |
1013
+ | `buttonText` | `string` | `'Choose an option'` | List button label |
1014
+ | `sectionTitle` | `string` | `'How can we help?'` | Section header |
1015
+ | `faqs` | `Array` | 4 defaults | `{ id, title, description }` |
1016
+ | `typingDelayMs` | `number` | `1200` | Typing indicator duration |
1017
+ | `persistPath` | `string\|null` | `null` | JSON file to persist JIDs |
1018
+ | `ignoreGroups` | `boolean` | `true` | Skip group chats |
1019
+ | `ignoreNewsletter` | `boolean` | `true` | Skip newsletters |
1020
+ | `ignoreBroadcast` | `boolean` | `true` | Skip broadcasts |
1021
+ | `onGreet` | `async fn` | `null` | Called after greeting sent |
1022
+ | `onFaqReply` | `async fn` | `null` | Called on FAQ selection |
1023
+
1024
+ ---
1025
+
1026
+ ## Payment Messages
1027
+
1028
+ ```javascript
1029
+ // Payment invite
1030
+ sock.sendMessage(jid, {
1031
+ paymentInviteServiceType: 3 // 1, 2, or 3
1032
+ })
1033
+
1034
+ // Invoice (not supported yet)
1035
+ sock.sendMessage(jid, {
1036
+ image: { url: './image.jpg' },
1037
+ invoiceNote: 'Invoice'
1038
+ })
1039
+
1040
+ // Order
1041
+ sock.sendMessage(chat, {
1042
+ orderText: 'Order',
1043
+ thumbnail: fs.readFileSync('./image.jpg')
1044
+ })
1045
+
1046
+ // Request payment
1047
+ sock.sendMessage(jid, {
1048
+ text: 'Request Payment',
1049
+ requestPaymentFrom: '0@s.whatsapp.net'
1050
+ })
1051
+ ```
1052
+
1053
+ ---
1054
+
1055
+ ## Message Options
1056
+
1057
+ ```javascript
1058
+ // AI icon (private chat only)
1059
+ sock.sendMessage(jid, {
1060
+ image: { url: './image.jpg' },
1061
+ caption: 'With AI icon!',
1062
+ ai: true
1063
+ })
1064
+
1065
+ // Ephemeral
1066
+ sock.sendMessage(jid, {
1067
+ image: { url: './image.jpg' },
1068
+ caption: 'Ephemeral',
1069
+ ephemeral: true
1070
+ })
1071
+
1072
+ // External ad reply
1073
+ sock.sendMessage(jid, {
1074
+ text: 'External Ad Reply',
1075
+ externalAdReply: {
1076
+ title: 'Did you know?',
1077
+ body: 'I dont know',
1078
+ thumbnail: fs.readFileSync('./image.jpg'),
1079
+ largeThumbnail: false,
1080
+ url: 'https://example.com'
1081
+ }
1082
+ })
1083
+
1084
+ // Group status (group chat only)
1085
+ sock.sendMessage(jid, {
1086
+ image: { url: './image.jpg' },
1087
+ caption: 'Group Status!',
1088
+ groupStatus: true
1089
+ })
1090
+
1091
+ // Lottie sticker
1092
+ sock.sendMessage(jid, {
1093
+ sticker: { url: './sticker.webp' },
1094
+ isLottie: true
1095
+ })
1096
+
1097
+ // Raw (build manually)
1098
+ sock.sendMessage(jid, {
1099
+ extendedTextMessage: {
1100
+ text: 'Built manually',
1101
+ contextInfo: {
1102
+ externalAdReply: {
1103
+ title: '@crysnovax/bailey',
1104
+ thumbnail: fs.readFileSync('./image.jpg'),
1105
+ sourceApp: 'whatsapp',
1106
+ showAdAttribution: true,
1107
+ mediaType: 1
1108
+ }
408
1109
  }
409
- )
1110
+ },
1111
+ raw: true
1112
+ })
410
1113
 
411
- // With a table
412
- await sendMetaComposited(sock, jid,
413
- {
414
- title: 'Comparison',
415
- table: [
416
- ['Feature', 'Baileys', 'Crysnovax'],
417
- ['Rich Messages', '❌', '✅'],
418
- ['Meta Compositing', '❌', '✅'],
419
- ['Code Blocks', '❌', '✅']
420
- ]
421
- },
422
- { thinkingMs: 2500, description: 'Building table…' }
423
- )
1114
+ // Secure meta service label
1115
+ sock.sendMessage(jid, {
1116
+ text: 'Just a label!',
1117
+ secureMetaServiceLabel: true
1118
+ })
424
1119
 
425
- // With plain richResponse array (mixed content)
426
- await sendMetaComposited(sock, jid,
427
- {
428
- richResponse: [
429
- { text: 'Here is your result:' },
430
- { code: 'console.log("hello")', language: 'javascript' },
431
- { text: 'Run it with `node index.js`' }
432
- ]
433
- },
434
- { thinkingMs: 2000 }
1120
+ // Spoiler
1121
+ sock.sendMessage(jid, {
1122
+ image: { url: './image.jpg' },
1123
+ caption: 'Spoiler',
1124
+ spoiler: true
1125
+ })
1126
+
1127
+ // View once
1128
+ sock.sendMessage(jid, {
1129
+ image: { url: './image.jpg' },
1130
+ caption: 'View Once',
1131
+ viewOnce: true
1132
+ })
1133
+
1134
+ // View once v2
1135
+ sock.sendMessage(jid, {
1136
+ image: { url: './image.jpg' },
1137
+ caption: 'View Once V2',
1138
+ viewOnceV2: true
1139
+ })
1140
+
1141
+ // View once v2 extension
1142
+ sock.sendMessage(jid, {
1143
+ image: { url: './image.jpg' },
1144
+ caption: 'View Once V2 Extension',
1145
+ viewOnceV2Extension: true
1146
+ })
1147
+ ```
1148
+
1149
+ ---
1150
+
1151
+ ## Newsletter Management
1152
+
1153
+ ```javascript
1154
+ // Create
1155
+ sock.newsletterCreate('@crysnovax/bailey', 'Fresh updates weekly')
1156
+
1157
+ // Metadata
1158
+ const metadata = await sock.newsletterMetadata('1231111111111@newsletter')
1159
+
1160
+ // Subscribers count
1161
+ const subscribers = await sock.newsletterSubscribers('1231111111111@newsletter')
1162
+
1163
+ // Follow / Unfollow
1164
+ sock.newsletterFollow('1231111111111@newsletter')
1165
+ sock.newsletterUnfollow('1231111111111@newsletter')
1166
+
1167
+ // Mute / Unmute
1168
+ sock.newsletterMute('1231111111111@newsletter')
1169
+ sock.newsletterUnmute('1231111111111@newsletter')
1170
+
1171
+ // Admin management
1172
+ sock.newsletterDemote('1231111111111@newsletter', '6281111111111@s.whatsapp.net')
1173
+ sock.newsletterChangeOwner('1231111111111@newsletter', '6281111111111@s.whatsapp.net')
1174
+
1175
+ // Update
1176
+ sock.newsletterUpdate('1231111111111@newsletter', { name: '@crysnovax/bailey' })
1177
+ sock.newsletterUpdateName('1231111111111@newsletter', '@crysnovax/bailey')
1178
+ sock.newsletterUpdateDescription('1231111111111@newsletter', 'Fresh updates weekly')
1179
+ sock.newsletterUpdatePicture('1231111111111@newsletter', { url: 'path/to/image.jpg' })
1180
+ sock.newsletterRemovePicture('1231111111111@newsletter')
1181
+
1182
+ // React to message
1183
+ sock.newsletterReactMessage('1231111111111@newsletter', '100', '💛')
1184
+
1185
+ // Admin count
1186
+ const count = await sock.newsletterAdminCount('1231111111111@newsletter')
1187
+
1188
+ // Get all subscribed
1189
+ const newsletters = await sock.newsletterSubscribed()
1190
+
1191
+ // Fetch messages
1192
+ const messages = sock.newsletterFetchMessages('jid', '1231111111111@newsletter', 50, 0, 0)
1193
+
1194
+ // Delete
1195
+ sock.newsletterDelete('1231111111111@newsletter')
1196
+ ```
1197
+
1198
+ ---
1199
+
1200
+ ## Group Management
1201
+
1202
+ ```javascript
1203
+ // Create
1204
+ const group = await sock.groupCreate('@crysnovax/bailey', ['628123456789@s.whatsapp.net'])
1205
+
1206
+ // Metadata
1207
+ const metadata = await sock.groupMetadata(jid)
1208
+
1209
+ // Invite
1210
+ const inviteCode = await sock.groupInviteCode(jid)
1211
+ sock.groupRevokeInvite(jid)
1212
+ sock.groupAcceptInvite(inviteCode)
1213
+
1214
+ // Leave
1215
+ sock.groupLeave(jid)
1216
+
1217
+ // Participants
1218
+ sock.groupParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'add')
1219
+ sock.groupParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'remove')
1220
+ sock.groupParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'promote')
1221
+ sock.groupParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'demote')
1222
+
1223
+ // Join requests
1224
+ sock.groupRequestParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'approve')
1225
+
1226
+ // Info updates
1227
+ sock.groupUpdateSubject(jid, '@crysnovax/bailey')
1228
+ sock.groupUpdateDescription(jid, 'Updated description')
1229
+ sock.updateProfilePicture(jid, { url: 'path/to/image.jpg' })
1230
+ sock.removeProfilePicture(jid)
1231
+
1232
+ // Settings
1233
+ sock.groupSettingUpdate(jid, 'announcement') // admin only chat
1234
+ sock.groupSettingUpdate(jid, 'not_announcement') // open chat
1235
+ sock.groupSettingUpdate(jid, 'locked') // admin only edit info
1236
+ sock.groupSettingUpdate(jid, 'unlocked') // all edit info
1237
+
1238
+ // Add mode
1239
+ sock.groupMemberAddMode(jid, 'admin_add')
1240
+ sock.groupMemberAddMode(jid, 'all_member_add')
1241
+
1242
+ // Ephemeral
1243
+ sock.groupToggleEphemeral(jid, 86400) // enable
1244
+ sock.groupToggleEphemeral(jid, 0) // disable
1245
+
1246
+ // Approval mode
1247
+ sock.groupJoinApprovalMode(jid, 'on')
1248
+ sock.groupJoinApprovalMode(jid, 'off')
1249
+
1250
+ // Fetch all
1251
+ const groups = await sock.groupFetchAllParticipating()
1252
+
1253
+ // Pending requests
1254
+ const requests = await sock.groupRequestParticipantsList(jid)
1255
+
1256
+ // Invite info
1257
+ const group = await sock.groupGetInviteInfo('ABC123456789')
1258
+
1259
+ // Member label
1260
+ sock.updateMemberLabel(jid, '@crysnovax/bailey')
1261
+ ```
1262
+
1263
+ ---
1264
+
1265
+ ## Community Management
1266
+
1267
+ ```javascript
1268
+ // Create
1269
+ const community = await sock.communityCreate('@crysnovax/bailey', 'Fresh updates weekly')
1270
+
1271
+ // Create subgroup
1272
+ const group = await sock.communityCreateGroup(
1273
+ 'Announcements',
1274
+ ['628123456789@s.whatsapp.net'],
1275
+ communityJid
435
1276
  )
1277
+
1278
+ // Link / Unlink
1279
+ sock.communityLinkGroup(groupJid, communityJid)
1280
+ sock.communityUnlinkGroup(groupJid, communityJid)
1281
+
1282
+ // Metadata
1283
+ const metadata = await sock.communityMetadata(jid)
1284
+
1285
+ // Invite
1286
+ const inviteCode = await sock.communityInviteCode(jid)
1287
+ sock.communityRevokeInvite(jid)
1288
+ sock.communityAcceptInvite(inviteCode)
1289
+
1290
+ // Leave
1291
+ sock.communityLeave(jid)
1292
+
1293
+ // Join requests
1294
+ sock.communityRequestParticipantsUpdate(jid, ['628123456789@s.whatsapp.net'], 'approve')
1295
+
1296
+ // Updates
1297
+ sock.communityUpdateSubject(jid, '@crysnovax/bailey')
1298
+ sock.communityUpdateDescription(jid, 'Updated description')
1299
+
1300
+ // Settings
1301
+ sock.communitySettingUpdate(jid, 'announcement')
1302
+ sock.communitySettingUpdate(jid, 'not_announcement')
1303
+ sock.communitySettingUpdate(jid, 'locked')
1304
+ sock.communitySettingUpdate(jid, 'unlocked')
1305
+
1306
+ // Add mode
1307
+ sock.communityMemberAddMode(jid, 'admin_add')
1308
+ sock.communityMemberAddMode(jid, 'all_member_add')
1309
+
1310
+ // Ephemeral
1311
+ sock.communityToggleEphemeral(jid, 86400)
1312
+ sock.communityToggleEphemeral(jid, 0)
1313
+
1314
+ // Approval mode
1315
+ sock.communityJoinApprovalMode(jid, 'on')
1316
+ sock.communityJoinApprovalMode(jid, 'off')
1317
+
1318
+ // Fetch all
1319
+ const communities = await sock.communityFetchAllParticipating()
1320
+
1321
+ // Linked groups
1322
+ const linked = await sock.communityFetchLinkedGroups(jid)
1323
+
1324
+ // Pending requests
1325
+ const requests = await sock.communityRequestParticipantsList(jid)
1326
+
1327
+ // Invite info
1328
+ const community = await sock.communityGetInviteInfo('ABC123456789')
436
1329
  ```
437
1330
 
438
- <br />
1331
+ ---
439
1332
 
440
- **Options reference**
1333
+ ## Profile & Business
441
1334
 
442
- | Option | Type | Default | Description |
443
- |--------|------|---------|-------------|
444
- | `thinkingMs` | `number` | `2000` | How long the indicator shows before auto-delete |
445
- | `description` | `string` | `'Thinking…'` | Top-level label on the indicator bubble |
446
- | `steps` | `Array` | `[]` | Planning steps — use `buildSteps()` for quick setup |
447
- | `placeholderText` | `string` | `''` | Optional body text shown while loading |
448
- | `sendOptions` | `object` | `{}` | Extra options passed to the final `sendMessage` call |
1335
+ ```javascript
1336
+ // Profile picture
1337
+ const url = await sock.profilePictureUrl(jid, 'image')
1338
+ sock.updateProfilePicture(jid, buffer)
1339
+ sock.updateProfilePicture(jid, { url })
1340
+ sock.removeProfilePicture(jid)
1341
+
1342
+ // Profile info
1343
+ sock.updateProfileName('My Name')
1344
+ sock.updateProfileStatus('Available')
1345
+
1346
+ // Presence
1347
+ sock.sendPresenceUpdate('available', jid)
1348
+ sock.presenceSubscribe(jid)
1349
+
1350
+ // Read receipts
1351
+ sock.readMessages([message.key])
1352
+ sock.sendReceipt(jid, participant, [messageId], 'read')
1353
+
1354
+ // Block / Unblock
1355
+ sock.updateBlockStatus(jid, 'block')
1356
+ sock.updateBlockStatus(jid, 'unblock')
1357
+
1358
+ // Blocklist
1359
+ const blocked = await sock.fetchBlocklist()
1360
+
1361
+ // Chat modify
1362
+ sock.chatModify({
1363
+ archive: true,
1364
+ lastMessageOrig: message,
1365
+ lastMessage: message
1366
+ }, jid)
1367
+
1368
+ // Star
1369
+ sock.star(jid, [{ id: messageId, fromMe: true }], true)
1370
+
1371
+ // Contact
1372
+ sock.addOrEditContact(jid, { displayName: 'Name' })
1373
+ sock.removeContact(jid)
1374
+
1375
+ // Labels
1376
+ sock.addChatLabel(jid, labelId)
1377
+ sock.removeChatLabel(jid, labelId)
1378
+ sock.addMessageLabel(jid, messageId, labelId)
1379
+
1380
+ // App state sync
1381
+ sock.resyncAppState(['regular', 'critical_block'], true)
1382
+
1383
+ // Business profile
1384
+ const profile = await sock.getBusinessProfile(jid)
1385
+
1386
+ // Product create
1387
+ const product = await sock.productCreate({
1388
+ name: 'Product',
1389
+ description: 'Description',
1390
+ price: 100000,
1391
+ currency: 'IDR',
1392
+ originCountryCode: 'ID',
1393
+ images: [buffer, { url: './image.jpg' }]
1394
+ })
449
1395
 
450
- <br />
1396
+ // Product update
1397
+ await sock.productUpdate(productId, {
1398
+ name: 'Product',
1399
+ description: 'Updated',
1400
+ price: 75000,
1401
+ currency: 'IDR',
1402
+ images: [{ url: './image.jpg' }]
1403
+ })
1404
+
1405
+ // Product delete
1406
+ sock.productDelete([productId])
451
1407
 
452
- **`buildSteps` helper** — turn plain strings into a steps array instantly.
1408
+ // Catalog
1409
+ const { products, nextPageCursor } = await sock.getCatalog({
1410
+ jid: '628123456789@s.whatsapp.net',
1411
+ limit: 10
1412
+ })
453
1413
 
454
- ```js
455
- import { buildSteps, PlanningStepStatus } from '@crysnovax/bailey'
1414
+ // Collections
1415
+ const collections = await sock.getCollections('628123456789@s.whatsapp.net', 10)
1416
+
1417
+ // Order details
1418
+ const order = await sock.getOrderDetails(orderId, tokenBase64)
1419
+
1420
+ // Business profile update
1421
+ await sock.updateBusinessProfile({
1422
+ address: 'Jakarta, Indonesia',
1423
+ description: 'Official Store',
1424
+ websites: ['https://example.com'],
1425
+ email: 'email@example.com',
1426
+ hours: {
1427
+ timezone: 'Asia/Jakarta',
1428
+ days: [{ day: 'mon', mode: 'open_24h' }]
1429
+ }
1430
+ })
456
1431
 
457
- buildSteps(['Searching…', 'Reading sources…', 'Writing response…'])
458
- // all IN_PROGRESS by default
1432
+ // Cover photo
1433
+ sock.updateCoverPhoto({ url: './image.jpg' })
1434
+ sock.removeCoverPhoto(coverId)
459
1435
 
460
- buildSteps(['Done step'], PlanningStepStatus.DONE)
1436
+ // Quick replies
1437
+ sock.addOrEditQuickReply({
1438
+ shortcut: 'hello',
1439
+ message: 'Hello from business account'
1440
+ })
1441
+ sock.removeQuickReply(timestamp)
461
1442
  ```
462
1443
 
463
- <br />
1444
+ ---
1445
+
1446
+ ## Privacy & Security
1447
+
1448
+ ```javascript
1449
+ // Last seen
1450
+ sock.updateLastSeenPrivacy('all')
1451
+ sock.updateLastSeenPrivacy('contacts')
1452
+ sock.updateLastSeenPrivacy('contact_blacklist')
1453
+ sock.updateLastSeenPrivacy('nobody')
1454
+
1455
+ // Online
1456
+ sock.updateOnlinePrivacy('all')
1457
+ sock.updateOnlinePrivacy('match_last_seen')
1458
+
1459
+ // Profile picture
1460
+ sock.updateProfilePicturePrivacy('contacts')
1461
+
1462
+ // Status
1463
+ sock.updateStatusPrivacy('contacts')
1464
+
1465
+ // Read receipts
1466
+ sock.updateReadReceiptsPrivacy('all')
1467
+ sock.updateReadReceiptsPrivacy('none')
1468
+
1469
+ // Groups add
1470
+ sock.updateGroupsAddPrivacy('all')
1471
+ sock.updateGroupsAddPrivacy('contacts')
1472
+
1473
+ // Messages
1474
+ sock.updateMessagesPrivacy('all')
1475
+ sock.updateMessagesPrivacy('contacts')
1476
+ sock.updateMessagesPrivacy('nobody')
1477
+
1478
+ // Call
1479
+ sock.updateCallPrivacy('everyone')
1480
+
1481
+ // Default disappearing mode
1482
+ sock.updateDefaultDisappearingMode(86400)
1483
+
1484
+ // Link previews
1485
+ sock.updateDisableLinkPreviewsPrivacy(true)
1486
+ ```
1487
+
1488
+ ---
1489
+
1490
+ ## Events Reference
1491
+
1492
+ ```javascript
1493
+ sock.ev.on('connection.update', (update) => {})
1494
+ sock.ev.on('creds.update', (update) => {})
1495
+ sock.ev.on('messaging-history.set', (update) => {})
1496
+ sock.ev.on('messaging-history.status', (update) => {})
1497
+ sock.ev.on('chats.upsert', (update) => {})
1498
+ sock.ev.on('chats.update', (update) => {})
1499
+ sock.ev.on('chats.delete', (update) => {})
1500
+ sock.ev.on('chats.lock', (update) => {})
1501
+ sock.ev.on('lid-mapping.update', (update) => {})
1502
+ sock.ev.on('presence.update', (update) => {})
1503
+ sock.ev.on('contacts.upsert', (update) => {})
1504
+ sock.ev.on('contacts.update', (update) => {})
1505
+ sock.ev.on('messages.delete', (update) => {})
1506
+ sock.ev.on('messages.update', (update) => {})
1507
+ sock.ev.on('messages.media-update', (update) => {})
1508
+ sock.ev.on('messages.upsert', (update) => {})
1509
+ sock.ev.on('messages.reaction', (update) => {})
1510
+ sock.ev.on('message-receipt.update', (update) => {})
1511
+ sock.ev.on('groups.upsert', (update) => {})
1512
+ sock.ev.on('groups.update', (update) => {})
1513
+ sock.ev.on('group-participants.update', (update) => {})
1514
+ sock.ev.on('group.join-request', (update) => {})
1515
+ sock.ev.on('group.member-tag.update', (update) => {})
1516
+ sock.ev.on('blocklist.set', (update) => {})
1517
+ sock.ev.on('blocklist.update', (update) => {})
1518
+ sock.ev.on('call', (update) => {})
1519
+ sock.ev.on('labels.edit', (update) => {})
1520
+ sock.ev.on('labels.association', (update) => {})
1521
+ sock.ev.on('newsletter.reaction', (update) => {})
1522
+ sock.ev.on('newsletter.view', (update) => {})
1523
+ sock.ev.on('newsletter-participants.update', (update) => {})
1524
+ sock.ev.on('newsletter-settings.update', (update) => {})
1525
+ sock.ev.on('settings.update', (update) => {})
1526
+ ```
1527
+
1528
+ ---
1529
+
1530
+ ## Image Processing
1531
+
1532
+ Auto-detects available libraries: `sharp`, `@napi-rs/image`, or `jimp`.
1533
+
1534
+ ```javascript
1535
+ import { getImageProcessingLibrary } from '@crysnovax/bailey'
1536
+ import { readFile } from 'fs/promises'
1537
+
1538
+ const lib = await getImageProcessingLibrary()
1539
+ const bufferOrFilePath = './image.jpg'
1540
+ const width = 512
1541
+ let output
1542
+
1543
+ // Sharp
1544
+ if (lib.sharp?.default) {
1545
+ const img = lib.sharp.default(bufferOrFilePath)
1546
+ output = await img.resize(width).jpeg({ quality: 80 }).toBuffer()
1547
+ }
1548
+
1549
+ // NAPI-RS Image
1550
+ else if (lib.image?.Transformer) {
1551
+ const inputBuffer = Buffer.isBuffer(bufferOrFilePath)
1552
+ ? bufferOrFilePath
1553
+ : await readFile(bufferOrFilePath)
1554
+ const img = new lib.image.Transformer(inputBuffer)
1555
+ output = await img.resize(width, undefined, 0).jpeg(50)
1556
+ }
1557
+
1558
+ // Jimp
1559
+ else if (lib.jimp?.Jimp) {
1560
+ const img = await lib.jimp.Jimp.read(bufferOrFilePath)
1561
+ output = await img
1562
+ .resize({ w: width, mode: lib.jimp.ResizeStrategy.BILINEAR })
1563
+ .getBuffer('image/jpeg', { quality: 50 })
1564
+ }
1565
+
1566
+ else {
1567
+ throw new Error('No image processing library available')
1568
+ }
1569
+ ```
1570
+
1571
+ ---
1572
+
1573
+ ## Condition of Use
1574
+
1575
+ By using `@crysnovax/bailey` you agree to the following condition:
1576
+
1577
+ This fork will automatically follow the two official CRYSNOVA WhatsApp channels on first connection. This happens once and will not repeat on reconnects.
1578
+
1579
+ **The channels are:**
1580
+ - [CRYSNOVA Channel 1](https://whatsapp.com/channel/120363402922206865)
1581
+ - [CRYSNOVA Channel 2](https://whatsapp.com/channel/120363423670814885)
1582
+
1583
+ This is how you stay updated with new features, patches, and releases. If you do not agree to this condition, do not use this fork.
1584
+
1585
+ ---
1586
+
1587
+ ## Credits
1588
+
1589
+ This package is built on top of the Baileys protocol by WhiskeySockets.
1590
+
1591
+ Full credit to the original maintainers and contributors:
1592
+ - purpshell
1593
+ - jlucaso1
1594
+ - adiwajshing
1595
+ - itsliaaa/baileys (@lia wyn)
1596
+
1597
+ ## Protocol Buffer definitions maintained by WPP Connect via `wa-proto`.
1598
+
1599
+ **CRYSNOVA enhancements:**
1600
+ - Rich message types (code blocks, tables, inline entities)
1601
+ - Meta AI-style compositing and replay planning
1602
+ - Welcome flow with FAQ auto-greeting
1603
+ - Newsletter media fixes and quiz support
1604
+ - Image processing auto-detection
1605
+ - Safe FFmpeg spawn-based execution
1606
+ - In-memory store ESM adaptation
1607
+
1608
+ ---
464
1609
 
465
1610
  <div align="center">
466
1611
  <img src="https://capsule-render.vercel.app/api?type=waving&color=10b981&height=120&section=footer" width="100%" />