wa-multi-mongodb 3.10.8 → 3.11.0

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,1246 +1,1302 @@
1
- # WhatsApp Multi MongoDB - Multi Session WhatsApp with MongoDB
2
-
3
- ## ⚠️ Important Note
4
- This repository is a modified version of [@mimamch/wa-multi-session](https://github.com/mimamch/wa-multi-session) with MongoDB session management integration. The original repository uses file-based session storage, while this version uses MongoDB for better scalability and session management.
5
-
6
- Lightweight library for WhatsApp with MongoDB integration. No Selenium or browser required.
7
-
8
- Built on [Baileys](https://github.com/WhiskeySockets/Baileys) Library.
9
-
10
- ## Features
11
- - Multi-session WhatsApp (multiple numbers simultaneously)
12
- - State (auth) storage in MongoDB instead of files
13
- - Automatic loading of all sessions from the database at startup
14
- - No need to scan QR again as long as MongoDB data is preserved
15
- - Automatic timeout handling for long-running operations
16
- - Auto-reconnect when connection is lost
17
- - Better group chat support
18
- - Automatic retry for failed message deliveries
19
- - Automatic group chat detection (v3.9.0+)
20
- - Hybrid caching system for group metadata (v3.9.4+)
21
- - Message deletion for self and others (v3.9.5+)
22
- - Custom browser configuration (v3.10.4+)
23
- - LID ↔ PN conversion utilities (v3.10.4+)
24
- - Proxy support for WebSocket and media connections (v3.10.8+)
25
-
26
- ## Installation
27
-
28
- Install package using npm:
29
-
30
- ```bash
31
- npm install wa-multi-mongodb@latest
32
- ```
33
-
34
- Then import into your code:
35
-
36
- ```typescript
37
- // Using ES modules
38
- import * as whatsapp from "wa-multi-mongodb";
39
-
40
- // Or using CommonJS
41
- const whatsapp = require("wa-multi-mongodb");
42
- ```
43
-
44
- ## Environment Setup
45
-
46
- For secure MongoDB URI management, we recommend using environment variables:
47
-
48
- 1. Create a `.env` file in your project root (copy from `.env.example`):
49
- ```
50
- # MongoDB Configuration
51
- MONGODB_URI=mongodb://username:password@hostname:port/database
52
-
53
- # Optional database settings
54
- WA_DB_NAME=wa_session
55
- WA_COLLECTION_NAME=auth
56
- ```
57
-
58
- 2. Install and use the dotenv package:
59
- ```javascript
60
- // Load environment variables
61
- require('dotenv').config();
62
-
63
- // Use in your code
64
- const MONGODB_URI = process.env.MONGODB_URI;
65
- if (!MONGODB_URI) {
66
- console.error('Error: MONGODB_URI not found in environment variables');
67
- process.exit(1);
68
- }
69
-
70
- // Initialize WhatsApp with MongoDB
71
- await whatsapp.setMongoURI(MONGODB_URI);
72
- ```
73
-
74
- 3. Make sure to add `.env` to your `.gitignore` file to prevent exposing sensitive credentials
75
-
76
- ## MongoDB Configuration
77
-
78
- ### Setup MongoDB Connection
79
- 1. Make sure MongoDB is running (local/cloud)
80
- 2. Configure the connection using one of these methods:
81
-
82
- **Using environment variables (recommended):**
83
- ```javascript
84
- require('dotenv').config();
85
- await whatsapp.setMongoURI(process.env.MONGODB_URI);
86
- ```
87
-
88
- **Directly in code (not recommended for production):**
89
- ```javascript
90
- await whatsapp.setMongoURI("mongodb+srv://username:password@host/db?options");
91
- ```
92
-
93
- 3. Optionally customize the database and collection names:
94
- ```javascript
95
- // Default values are "wa_session" and "auth"
96
- whatsapp.setMongoDBNames("custom_database_name", "custom_collection_name");
97
- ```
98
-
99
- ## Basic Usage
100
-
101
- ### Session Management
102
-
103
- ```javascript
104
- // Start a new session with QR Code
105
- const session = await whatsapp.startSession("mysession");
106
-
107
- // Start with options
108
- await whatsapp.startSession("mysession2", {
109
- printQR: true,
110
- onConnected: () => console.log("Connected!"),
111
- onDisconnected: () => console.log("Disconnected!"),
112
- onQRUpdated: (qr) => {
113
- console.log("New QR:", qr);
114
- // QR data is raw and ready for frontend use
115
- // You can display this in React, Vue, Angular, etc.
116
- }
117
- });
118
-
119
- // Start with custom browser configuration (v3.10.4+)
120
- // Display: "Safari (Mac OS)" in WhatsApp Linked Devices
121
- await whatsapp.startSession("mysession3", {
122
- printQR: true,
123
- browserType: "macOS", // Options: "ubuntu", "macOS", "windows", "appropriate"
124
- browserName: "Safari", // Valid: Chrome, Safari, Firefox, Edge, Opera, IE, Desktop
125
- onConnected: () => console.log("Connected with custom browser!"),
126
- });
127
-
128
- // Start session with Pairing Code (v3.9.6+)
129
- await whatsapp.startSessionWithPairingCode("mysession4", "6281234567890", {
130
- onConnected: () => console.log("Pairing session connected!"),
131
- onDisconnected: () => console.log("Pairing session disconnected!"),
132
- onPairingCode: (code) => {
133
- console.log("Pairing code:", code);
134
- // Enter this code in your WhatsApp app: Settings > Linked Devices > Link a Device > Link with phone number
135
- }
136
- });
137
-
138
- // Pairing code with valid browser config - displays "Edge (Windows)"
139
- // ⚠️ IMPORTANT: Pairing code ONLY works with valid browser configurations!
140
- await whatsapp.startSessionWithPairingCode("mysession5", "6281234567890", {
141
- browserType: "windows",
142
- browserName: "Edge", // Must be valid: Chrome, Safari, Firefox, Edge, Opera, IE, Desktop
143
- onPairingCode: (code) => console.log("Code:", code),
144
- });
145
-
146
- // Get all active sessions
147
- const sessions = await whatsapp.getAllSession();
148
-
149
- // Get data for a specific session
150
- const sessionData = whatsapp.getSession("mysession");
151
-
152
- // Load all saved sessions from MongoDB
153
- await whatsapp.loadSessionsFromMongo();
154
-
155
- // Session Management Utilities (v3.9.6+)
156
- // Get session status with detailed information
157
- const status = await whatsapp.getSessionStatus("mysession");
158
- console.log("Session status:", status);
159
- // Returns: { exists: true, connected: true, sessionType: 'qr' | 'pairing' }
160
-
161
- // Manual reconnection for any session
162
- try {
163
- const reconnected = await whatsapp.reconnect("mysession");
164
- console.log("Reconnection successful:", reconnected);
165
- } catch (error) {
166
- console.error("Reconnection failed:", error);
167
- }
168
-
169
- // Get all pairing code sessions
170
- const pairingSessions = whatsapp.getPairingCodeSessions();
171
- console.log("Pairing code sessions:", pairingSessions);
172
-
173
- // Bulk reconnect all pairing code sessions
174
- await whatsapp.reconnectAllPairingCodeSessions();
175
- ```
176
-
177
- ### Custom Browser Configuration (v3.10.4+)
178
-
179
- Customize how your session appears in WhatsApp's "Linked Devices" list.
180
-
181
- **Display Format in WhatsApp**: `browserName (OsName)` - e.g., "Safari (Mac OS)"
182
-
183
- #### Valid browserName Values
184
-
185
- These are recognized by WhatsApp and will display correctly:
186
-
187
- | browserName | Description |
188
- |-------------|-------------|
189
- | `"Chrome"` | Google Chrome (default) |
190
- | `"Safari"` | Apple Safari |
191
- | `"Firefox"` | Mozilla Firefox |
192
- | `"Edge"` | Microsoft Edge |
193
- | `"Opera"` | Opera Browser |
194
- | `"IE"` | Internet Explorer |
195
- | `"Desktop"` | Generic Desktop App |
196
-
197
- #### browserType Options
198
-
199
- | browserType | OS Name Displayed | OS Version |
200
- |-------------|-------------------|------------|
201
- | `"ubuntu"` | Ubuntu | 22.04.4 |
202
- | `"macOS"` | Mac OS | 14.4.1 |
203
- | `"windows"` | Windows | 10.0.22631 |
204
- | `"appropriate"` | Auto-detect | Based on platform |
205
-
206
- #### Usage Examples
207
-
208
- ```javascript
209
- // Safari on macOS → displays as "Safari (Mac OS)"
210
- await whatsapp.startSession("session1", {
211
- printQR: true,
212
- browserType: "macOS",
213
- browserName: "Safari",
214
- });
215
-
216
- // Chrome on Windows → displays as "Chrome (Windows)"
217
- await whatsapp.startSession("session2", {
218
- printQR: true,
219
- browserType: "windows",
220
- browserName: "Chrome",
221
- });
222
-
223
- // Firefox on Ubuntu → displays as "Firefox (Ubuntu)"
224
- await whatsapp.startSession("session3", {
225
- printQR: true,
226
- browserType: "ubuntu",
227
- browserName: "Firefox",
228
- });
229
-
230
- // Edge on Windows → displays as "Edge (Windows)"
231
- await whatsapp.startSession("session4", {
232
- printQR: true,
233
- browserType: "windows",
234
- browserName: "Edge",
235
- });
236
-
237
- // Desktop app on macOS → displays as "Desktop (Mac OS)"
238
- await whatsapp.startSession("session5", {
239
- printQR: true,
240
- browserType: "macOS",
241
- browserName: "Desktop",
242
- });
243
-
244
- // Custom name (fallback to Chrome) → displays as "Chrome (My Bot App)"
245
- await whatsapp.startSession("session6", {
246
- printQR: true,
247
- browserType: "windows",
248
- browserName: "My Bot App",
249
- });
250
-
251
- // Custom name with Safari → displays as "Safari (My Bot App)"
252
- await whatsapp.startSession("session7", {
253
- printQR: true,
254
- browserType: "macOS",
255
- browserName: "My Bot App",
256
- displayBrowser: "Safari", // Choose which browser type to display
257
- });
258
-
259
- // Custom name with Firefox → displays as "Firefox (Device Bot)"
260
- await whatsapp.startSession("session8", {
261
- printQR: true,
262
- browserType: "ubuntu",
263
- browserName: "Device Bot",
264
- displayBrowser: "Firefox",
265
- });
266
- ```
267
-
268
- #### displayBrowser Parameter (v3.10.5+)
269
-
270
- When using a custom `browserName`, you can now choose which browser type to display using the `displayBrowser` parameter:
271
-
272
- | displayBrowser | Custom Name Example | Display Result |
273
- |----------------|---------------------|----------------|
274
- | `"Chrome"` (default) | "My Bot" | Chrome (My Bot) |
275
- | `"Safari"` | "My Bot" | Safari (My Bot) |
276
- | `"Firefox"` | "My Bot" | Firefox (My Bot) |
277
- | `"Edge"` | "My Bot" | Edge (My Bot) |
278
- | `"Opera"` | "My Bot" | Opera (My Bot) |
279
- | `"Desktop"` | "My Bot" | Desktop (My Bot) |
280
-
281
- > **Note**: `displayBrowser` is only used when `browserName` is a custom name (not a valid browser type like Chrome, Safari, etc.).
282
-
283
- > [!WARNING]
284
- > **Custom browserName and displayBrowser are NOT supported for Pairing Code sessions!**
285
- >
286
- > WhatsApp server validates browser configuration strictly during pairing code authentication. You MUST use valid browser configurations for pairing code:
287
- >
288
- > | browserType | browserName | Display | Pairing Code |
289
- > |-------------|-------------|---------|--------------|
290
- > | `"windows"` | `"Chrome"` | Chrome (Windows) | ✅ Works |
291
- > | `"macOS"` | `"Safari"` | Safari (Mac OS) | ✅ Works |
292
- > | `"windows"` | `"Edge"` | Edge (Windows) | ✅ Works |
293
- > | `"ubuntu"` | `"Firefox"` | Firefox (Ubuntu) | ✅ Works |
294
- > | `"windows"` | `"My Bot"` | Chrome (My Bot) | Fails |
295
- >
296
- > Custom names (like "My Bot App") only work with **QR Code** authentication.
297
-
298
- ### Proxy Support (v3.10.8+)
299
-
300
- You can use a proxy for WebSocket connections and media upload/download. **No additional dependencies are included** - install your preferred proxy agent package if needed.
301
-
302
- #### Install Proxy Agent (User's Choice)
303
-
304
- ```bash
305
- # For HTTP/HTTPS proxy
306
- npm install https-proxy-agent
307
-
308
- # For SOCKS4/SOCKS5 proxy
309
- npm install socks-proxy-agent
310
- ```
311
-
312
- #### Usage Examples
313
-
314
- ```javascript
315
- // Using HTTPS proxy
316
- import { HttpsProxyAgent } from 'https-proxy-agent';
317
-
318
- const proxyAgent = new HttpsProxyAgent('http://proxy.example.com:8080');
319
- // With authentication: new HttpsProxyAgent('http://user:pass@proxy.example.com:8080');
320
-
321
- await whatsapp.startSession("mysession", {
322
- printQR: true,
323
- agent: proxyAgent, // Proxy for WebSocket connection
324
- fetchAgent: proxyAgent, // Proxy for media upload/download (optional, defaults to agent)
325
- });
326
-
327
- // Using SOCKS5 proxy
328
- import { SocksProxyAgent } from 'socks-proxy-agent';
329
-
330
- const socksAgent = new SocksProxyAgent('socks5://127.0.0.1:1080');
331
- // With authentication: new SocksProxyAgent('socks5://user:pass@127.0.0.1:1080');
332
-
333
- await whatsapp.startSessionWithPairingCode("mysession", "6281234567890", {
334
- browserType: "windows",
335
- browserName: "Chrome",
336
- agent: socksAgent,
337
- });
338
- ```
339
-
340
- | Option | Type | Description |
341
- |--------|------|-------------|
342
- | `agent` | `Agent` | Proxy agent for WebSocket connection |
343
- | `fetchAgent` | `Agent` | Proxy agent for media upload/download (defaults to `agent`) |
344
-
345
- > **Note**: Proxy is optional. If not provided, direct connection is used.
346
-
347
-
348
-
349
- ### Sending Messages
350
-
351
- ```javascript
352
- // Send text message
353
- await whatsapp.sendTextMessage({
354
- sessionId: "mysession",
355
- to: "6281234567890", // always include country code
356
- text: "Hello from wa-multi-mongodb!"
357
- // isGroup parameter is optional (v3.9.0+)
358
- // The library will automatically detect if the destination is a group
359
- });
360
-
361
- // Send to a group (automatic detection in v3.9.0+)
362
- await whatsapp.sendTextMessage({
363
- sessionId: "mysession",
364
- to: "120363152682073800", // group ID
365
- text: "Hello group!"
366
- // No need for isGroup: true parameter in v3.9.0+
367
- });
368
-
369
- // Send to a group (compatible with older versions)
370
- await whatsapp.sendTextMessage({
371
- sessionId: "mysession",
372
- to: "120363152682073800", // group ID
373
- text: "Hello group!",
374
- isGroup: true // still works but optional in v3.9.0+
375
- });
376
-
377
- // Send media (unified function)
378
- await whatsapp.sendMedia({
379
- sessionId: "mysession",
380
- to: "6281234567890",
381
- type: "image", // options: image, video, pdf, doc, docx, xls, xlsx, zip, mp3
382
- media: fs.readFileSync("./image.jpg"), // or URL string
383
- caption: "Image caption",
384
- fileName: "image.jpg", // required for documents
385
- // isGroup parameter is optional (v3.9.0+)
386
- });
387
-
388
- // Send voice note
389
- await whatsapp.sendVoiceNote({
390
- sessionId: "mysession",
391
- to: "6281234567890",
392
- media: fs.readFileSync("./audio.mp3"),
393
- // isGroup parameter is optional (v3.9.0+)
394
- });
395
-
396
- // Mark message as read
397
- await whatsapp.readMessage({
398
- sessionId: "mysession",
399
- key: msg.key,
400
- });
401
-
402
- // Send typing indicator
403
- await whatsapp.sendTyping({
404
- sessionId: "mysession",
405
- to: "6281234567890", // or group ID
406
- duration: 3000, // milliseconds
407
- // isGroup parameter is optional (v3.9.0+)
408
- });
409
-
410
- // Delete message (v3.9.5+)
411
- // Delete own message for everyone
412
- await whatsapp.deleteMessage({
413
- sessionId: "mysession",
414
- key: messageObject.key, // message key from received or sent message
415
- });
416
-
417
- // Delete someone else's message (requires admin permissions in groups)
418
- await whatsapp.deleteMessage({
419
- sessionId: "mysession",
420
- key: {
421
- remoteJid: "120363152682073800@g.us", // group ID with @g.us
422
- fromMe: false,
423
- id: "MESSAGE_ID",
424
- participant: "SENDER_JID" // required for group messages
425
- }
426
- });
427
-
428
- // Auto-delete message after delay (helper function example)
429
- function autoDeleteMessage(sessionId, message, delayMs = 3000) {
430
- setTimeout(async () => {
431
- try {
432
- await whatsapp.deleteMessage({
433
- sessionId: sessionId,
434
- key: message.key
435
- });
436
- } catch (error) {
437
- console.error("Error auto-deleting message:", error);
438
- }
439
- }, delayMs);
440
- }
441
-
442
- // Send text message with mention (v3.9.8+)
443
- // Mention one user in a group
444
- await whatsapp.sendTextMessageWithMention({
445
- sessionId: "mysession",
446
- to: "6281234567890@g.us", // group JID
447
- text: "Halo @6281234567890, selamat datang di grup!",
448
- mentions: ["6281234567890@s.whatsapp.net"], // JID to mention
449
- isGroup: true
450
- });
451
-
452
- // Mention multiple users in a group
453
- await whatsapp.sendTextMessageWithMention({
454
- sessionId: "mysession",
455
- to: "6281234567890@g.us",
456
- text: "Halo @6281234567890 dan @6289876543210, ada yang bisa saya bantu?",
457
- mentions: [
458
- "6281234567890@s.whatsapp.net",
459
- "6289876543210@s.whatsapp.net"
460
- ],
461
- isGroup: true
462
- });
463
-
464
- // Mention in private chat (less common but supported)
465
- await whatsapp.sendTextMessageWithMention({
466
- sessionId: "mysession",
467
- to: "6281234567890",
468
- text: "Halo @6281234567890, ini adalah pesan pribadi dengan mention",
469
- mentions: ["6281234567890@s.whatsapp.net"]
470
- });
471
-
472
- // Alternative: Use sendTextMessage with mentions property
473
- // You can also use the regular sendTextMessage with mentions
474
- const session = whatsapp.getSession("mysession");
475
- if (session) {
476
- await session.sendMessage(
477
- "6281234567890@g.us",
478
- {
479
- text: "Halo @6281234567890, ini pesan dengan mention!",
480
- mentions: ["6281234567890@s.whatsapp.net"]
481
- },
482
- {
483
- quoted: null // or message to quote
484
- }
485
- );
486
- }
487
- ```
488
-
489
- ### Event Listeners
490
-
491
- ```javascript
492
- // Incoming messages
493
- whatsapp.onMessageReceived((msg) => {
494
- console.log(`Message from ${msg.key.remoteJid}:`, msg);
495
- });
496
-
497
- // QR code updates
498
- whatsapp.onQRUpdated(({ sessionId, qr }) => {
499
- console.log(`QR Code for ${sessionId}:`, qr);
500
- // You can display this QR in a UI or save it to a file
501
- });
502
-
503
- // Connection events
504
- whatsapp.onConnected((sessionId) => {
505
- console.log(`Session ${sessionId} connected`);
506
- });
507
-
508
- whatsapp.onDisconnected((sessionId) => {
509
- console.log(`Session ${sessionId} disconnected`);
510
- });
511
- ```
512
-
513
- ### Handling Media in Incoming Messages
514
-
515
- ```javascript
516
- whatsapp.onMessageReceived(async (msg) => {
517
- if (msg.message?.imageMessage) {
518
- await msg.saveImage("./saved-image.jpg");
519
- }
520
-
521
- if (msg.message?.videoMessage) {
522
- await msg.saveVideo("./saved-video.mp4");
523
- }
524
-
525
- if (msg.message?.documentMessage) {
526
- await msg.saveDocument("./saved-document"); // extension will be added automatically
527
- }
528
-
529
- if (msg.message?.audioMessage) {
530
- await msg.saveAudio("./saved-audio.mp3");
531
- }
532
- });
533
- ```
534
-
535
- ### Group Metadata Caching (v3.9.4+)
536
-
537
- The library now implements a hybrid caching system for group metadata using both in-memory (NodeCache) and persistent storage (MongoDB). This significantly improves performance for applications that frequently use group metadata information.
538
-
539
- ```javascript
540
- // Configure cache settings (optional, has default values)
541
- whatsapp.setGroupCacheConfig({
542
- stdTTL: 10 * 60, // Time-to-live in seconds (10 minutes)
543
- checkperiod: 120 // Check for expired keys every 2 minutes
544
- });
545
-
546
- // Get group metadata (automatically uses cache if available)
547
- const metadata = await whatsapp.getGroupMetadata(sessionId, groupJid);
548
- console.log(`Group name: ${metadata.subject}`);
549
- console.log(`Participants: ${metadata.participants.length}`);
550
- console.log(`Created on: ${new Date(metadata.creation * 1000).toLocaleString()}`);
551
-
552
- // Force fetch fresh data from server and update cache
553
- const freshData = await whatsapp.getGroupMetadata(sessionId, groupJid, true);
554
-
555
- // Clear cache for specific group in a specific session
556
- await whatsapp.clearGroupMetadataCache(sessionId, groupJid);
557
-
558
- // Clear all group metadata cache for a specific session
559
- await whatsapp.clearSessionGroupMetadataCache(sessionId);
560
-
561
- // Clear all cached group metadata for all sessions
562
- whatsapp.clearAllGroupMetadataCache();
563
- ```
564
-
565
- Benefits of the hybrid caching system:
566
- 1. Significantly reduces WhatsApp API calls for group metadata
567
- 2. Improves response time for group-related features
568
- 3. Persistent cache in MongoDB survives application restarts
569
- 4. In-memory cache provides ultra-fast access for frequently used groups
570
- 5. Automatic cache invalidation on group updates (members, settings, etc.)
571
- 6. **Full multi-session support** - each session has isolated cache for group metadata
572
- 7. Automatic cleanup when sessions are deleted or invalidated
573
-
574
- #### Multi-Session Caching Architecture
575
-
576
- The group metadata cache system is designed to support multiple WhatsApp sessions running simultaneously without any cache collision:
577
-
578
- - Each session maintains its own isolated cache for group metadata
579
- - Cache keys combine both session ID and group ID to ensure separation
580
- - MongoDB storage includes session information for persistent separation
581
- - Cache cleanup happens automatically when sessions are deleted or invalidated
582
- - Memory and database efficiency through shared infrastructure
583
-
584
- This approach ensures that in multi-session environments:
585
- - Session A and Session B can both cache metadata for the same group ID without conflicts
586
- - Each session gets its own view of its accessible groups
587
- - Cache invalidation in one session doesn't affect other sessions
588
-
589
- ## Utility Functions
590
-
591
- ```javascript
592
- // Create a delay
593
- import { createDelay } from "wa-multi-mongodb";
594
- await createDelay(2000); // wait 2 seconds
595
-
596
- // Execute with timeout
597
- import { withTimeout } from "wa-multi-mongodb";
598
- try {
599
- const result = await withTimeout(
600
- functionThatMightTakeTooLong(),
601
- 10000, // timeout in ms
602
- "Operation timed out" // error message if timeout occurs
603
- );
604
- } catch (error) {
605
- console.error(error.message);
606
- }
607
-
608
- // Attempt to reconnect a session
609
- import { reconnect } from "wa-multi-mongodb";
610
- try {
611
- const reconnected = await reconnect("mysession");
612
- console.log("Reconnect successful:", reconnected);
613
- } catch (error) {
614
- console.error("Reconnect failed:", error);
615
- }
616
- ```
617
-
618
- ## LID PN Conversion Utilities (v3.10.4+)
619
-
620
- WhatsApp has introduced LID (Linked ID) as a new anonymous identifier format to enhance user privacy. These utility functions help you convert between LID and Phone Number (PN) formats.
621
-
622
- ### Understanding LID and PN
623
-
624
- | Format | Description | Example |
625
- |--------|-------------|---------|
626
- | **LID** | Anonymous identifier (new format) | `1524746986546@lid` |
627
- | **PN/JID** | Phone number based identifier (traditional) | `6281234567890@s.whatsapp.net` |
628
-
629
- ### Converting LID to Phone Number
630
-
631
- ```javascript
632
- // Get phone number from LID
633
- const result = await whatsapp.getPNForLID("mysession", "1524746986546@lid");
634
- if (result.success && result.pn) {
635
- console.log(`Phone number: ${result.pn}`);
636
- } else {
637
- console.log("Phone number not found:", result.error);
638
- }
639
-
640
- // Returns: { success: boolean, lid: string, pn: string | null, error?: string }
641
- ```
642
-
643
- ### Converting Phone Number to LID
644
-
645
- ```javascript
646
- // Get LID from phone number
647
- const result = await whatsapp.getLIDForPN("mysession", "6281234567890");
648
- if (result.success && result.lid) {
649
- console.log(`LID: ${result.lid}`);
650
- } else {
651
- console.log("LID not found:", result.error);
652
- }
653
-
654
- // Returns: { success: boolean, pn: string, lid: string | null, error?: string }
655
- ```
656
-
657
- ### Smart Conversion (Auto-detect Format)
658
-
659
- ```javascript
660
- // Automatically convert any JID to phone number
661
- const phoneNumber = await whatsapp.toPhoneNumber("mysession", anyJid);
662
- if (phoneNumber) {
663
- console.log(`Phone: ${phoneNumber}`);
664
- }
665
-
666
- // Automatically convert any JID to LID
667
- const lid = await whatsapp.toLID("mysession", "6281234567890@s.whatsapp.net");
668
- if (lid) {
669
- console.log(`LID: ${lid}`);
670
- }
671
- ```
672
-
673
- ### Get All Known LID Mappings
674
-
675
- ```javascript
676
- // Get all LID-PN mappings for a session
677
- const mappings = await whatsapp.getAllLIDMappings("mysession");
678
- for (const { lid, pn } of mappings) {
679
- console.log(`${lid} => ${pn}`);
680
- }
681
- ```
682
-
683
- ### Format Detection Helpers
684
-
685
- ```javascript
686
- // Check if JID is in LID format
687
- if (whatsapp.isLIDFormat("1524746986546@lid")) {
688
- console.log("This is an LID");
689
- }
690
-
691
- // Check if JID is in PN format
692
- if (whatsapp.isPNFormat("6281234567890@s.whatsapp.net")) {
693
- console.log("This is a phone number JID");
694
- }
695
- ```
696
-
697
- ### Important Notes on LID Conversion
698
-
699
- > ⚠️ **Limitations**:
700
- > - `getPNForLID` may return `null` for new contacts or when WhatsApp hasn't provided the LID-PN mapping
701
- > - LID mappings are only available for contacts that have already interacted with your session
702
- > - WhatsApp is increasingly focusing on privacy, so not all LIDs have known phone numbers
703
-
704
- | Function | Description |
705
- |----------|-------------|
706
- | `getPNForLID(sessionId, lid)` | Convert LID to phone number |
707
- | `getLIDForPN(sessionId, pn)` | Convert phone number to LID |
708
- | `toPhoneNumber(sessionId, jid)` | Smart convert any JID to PN |
709
- | `toLID(sessionId, jid)` | Smart convert any JID to LID |
710
- | `getAllLIDMappings(sessionId)` | Get all known LID-PN mappings |
711
- | `isLIDFormat(jid)` | Check if JID is in LID format |
712
- | `isPNFormat(jid)` | Check if JID is in PN format |
713
-
714
- ## Complete Example: Auto-Reconnect Application
715
-
716
-
717
- ```javascript
718
- import * as whatsapp from "wa-multi-mongodb";
719
- import { withTimeout } from "wa-multi-mongodb";
720
- require('dotenv').config();
721
-
722
- // Store connection status
723
- const sessionStatus = {};
724
-
725
- // Function to check and reconnect if disconnected
726
- async function checkAndReconnect(sessionId) {
727
- if (sessionStatus[sessionId] === 'disconnected') {
728
- try {
729
- const reconnected = await whatsapp.reconnect(sessionId);
730
- if (reconnected) {
731
- sessionStatus[sessionId] = 'connected';
732
- console.log(`Session ${sessionId} reconnected`);
733
- }
734
- } catch (error) {
735
- console.error(`Error during reconnect: ${error.message}`);
736
- }
737
- }
738
- }
739
-
740
- async function startApp() {
741
- // MongoDB Configuration
742
- await whatsapp.setMongoURI(process.env.MONGODB_URI);
743
-
744
- // Event listeners
745
- whatsapp.onQRUpdated(({ sessionId, qr }) => {
746
- console.log(`QR Code for session ${sessionId}:`, qr);
747
- });
748
-
749
- whatsapp.onConnected((sessionId) => {
750
- console.log(`Session ${sessionId} connected!`);
751
- sessionStatus[sessionId] = 'connected';
752
- });
753
-
754
- whatsapp.onDisconnected((sessionId) => {
755
- console.log(`Session ${sessionId} disconnected!`);
756
- sessionStatus[sessionId] = 'disconnected';
757
-
758
- // Try to reconnect after a few seconds
759
- setTimeout(() => checkAndReconnect(sessionId), 10000);
760
- });
761
-
762
- // Message handler with error handling and group detection
763
- whatsapp.onMessageReceived(async (msg) => {
764
- try {
765
- if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
766
-
767
- const messageContent = msg.message?.conversation ||
768
- msg.message?.extendedTextMessage?.text ||
769
- "";
770
-
771
- // Detect if message is from a group
772
- const isGroup = msg.key.remoteJid.endsWith('@g.us');
773
-
774
- // Using group metadata cache (v3.9.4+)
775
- if (isGroup) {
776
- const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid);
777
- console.log(`Message from group: ${metadata.subject} with ${metadata.participants.length} members`);
778
- }
779
-
780
- // Mark message as read
781
- try {
782
- await whatsapp.readMessage({
783
- sessionId: msg.sessionId,
784
- key: msg.key,
785
- });
786
- } catch (error) {
787
- if (error.message.includes('Connection Closed')) {
788
- sessionStatus[msg.sessionId] = 'disconnected';
789
- setTimeout(() => checkAndReconnect(msg.sessionId), 5000);
790
- }
791
- }
792
-
793
- // Reply to messages containing "hello"
794
- if (messageContent.toLowerCase().includes("hello")) {
795
- // Show typing indicator (works in both private and group chats since v3.9.1+)
796
- await whatsapp.sendTyping({
797
- sessionId: msg.sessionId,
798
- to: msg.key.remoteJid,
799
- duration: 2000,
800
- });
801
-
802
- // Use different timeouts for groups vs private chats
803
- const timeoutMs = isGroup ? 60000 : 30000;
804
-
805
- try {
806
- await withTimeout(
807
- whatsapp.sendTextMessage({
808
- sessionId: msg.sessionId,
809
- to: msg.key.remoteJid,
810
- text: "Hello! How can I help you?",
811
- answering: msg,
812
- }),
813
- timeoutMs,
814
- "Message sending timed out"
815
- );
816
- } catch (error) {
817
- console.error("Error sending message:", error.message);
818
- }
819
- }
820
-
821
- // Example command to get group info
822
- if (messageContent === "!groupinfo" && isGroup) {
823
- try {
824
- // Force fetch fresh data
825
- const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid, true);
826
-
827
- const adminList = metadata.participants
828
- .filter(p => p.admin)
829
- .map(p => p.id.split('@')[0])
830
- .join(", ");
831
-
832
- const infoText = `*Group Info*\n` +
833
- `Name: ${metadata.subject}\n` +
834
- `Description: ${metadata.desc || 'None'}\n` +
835
- `Members: ${metadata.participants.length}\n` +
836
- `Admins: ${adminList}\n` +
837
- `Created: ${new Date(metadata.creation * 1000).toLocaleString()}`;
838
-
839
- await whatsapp.sendTextMessage({
840
- sessionId: msg.sessionId,
841
- to: msg.key.remoteJid,
842
- text: infoText
843
- });
844
- } catch (error) {
845
- console.error("Error getting group info:", error.message);
846
- }
847
- }
848
- } catch (error) {
849
- // Prevent application crash
850
- console.error("Error processing message:", error.message);
851
- }
852
- });
853
-
854
- // Load all sessions from MongoDB
855
- await whatsapp.loadSessionsFromMongo();
856
-
857
- // Create a main session if it doesn't exist
858
- const mainSession = "main_session";
859
- const existingSessions = await whatsapp.getAllSession();
860
- if (!existingSessions.includes(mainSession)) {
861
- await whatsapp.startSession(mainSession);
862
- } else {
863
- sessionStatus[mainSession] = 'connected';
864
- }
865
-
866
- // Check connections periodically
867
- setInterval(() => {
868
- Object.keys(sessionStatus).forEach(sid => {
869
- checkAndReconnect(sid);
870
- });
871
- }, 5 * 60 * 1000); // check every 5 minutes
872
- }
873
-
874
- startApp().catch(err => {
875
- console.error("Failed to start application:", err);
876
- process.exit(1);
877
- });
878
- ```
879
-
880
- ## Complete Example: Pairing Code with Auto-Reconnect (v3.9.6+)
881
-
882
- ```javascript
883
- import * as whatsapp from "wa-multi-mongodb";
884
- require('dotenv').config();
885
-
886
- // Store connection status
887
- const sessionStatus = {};
888
-
889
- async function startPairingApp() {
890
- // MongoDB Configuration
891
- await whatsapp.setMongoURI(process.env.MONGODB_URI);
892
-
893
- // Event listeners for pairing code sessions
894
- whatsapp.onConnected((sessionId) => {
895
- console.log(`Pairing session ${sessionId} connected!`);
896
- sessionStatus[sessionId] = 'connected';
897
- });
898
-
899
- whatsapp.onDisconnected(async (sessionId) => {
900
- console.log(`Pairing session ${sessionId} disconnected!`);
901
- sessionStatus[sessionId] = 'disconnected';
902
-
903
- // Check if it's a pairing code session
904
- const status = await whatsapp.getSessionStatus(sessionId);
905
- if (status.sessionType === 'pairing') {
906
- console.log(`Attempting to reconnect pairing session ${sessionId}...`);
907
-
908
- // Auto-reconnect after 5 seconds
909
- setTimeout(async () => {
910
- try {
911
- const reconnected = await whatsapp.reconnect(sessionId);
912
- if (reconnected) {
913
- console.log(`Pairing session ${sessionId} reconnected successfully!`);
914
- sessionStatus[sessionId] = 'connected';
915
- }
916
- } catch (error) {
917
- console.error(`Failed to reconnect pairing session ${sessionId}:`, error);
918
- }
919
- }, 5000);
920
- }
921
- });
922
-
923
- // Message handler
924
- whatsapp.onMessageReceived(async (msg) => {
925
- if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
926
-
927
- const messageContent = msg.message?.conversation ||
928
- msg.message?.extendedTextMessage?.text ||
929
- "";
930
-
931
- console.log(`Message from ${msg.key.remoteJid}: ${messageContent}`);
932
-
933
- // Auto-reply example
934
- if (messageContent.toLowerCase().includes("ping")) {
935
- await whatsapp.sendTextMessage({
936
- sessionId: msg.sessionId,
937
- to: msg.key.remoteJid,
938
- text: "Pong! Message received from pairing session.",
939
- answering: msg
940
- });
941
- }
942
- });
943
-
944
- // Load existing sessions from MongoDB
945
- await whatsapp.loadSessionsFromMongo();
946
-
947
- // Start a new pairing code session
948
- const pairingSessionId = "pairing_session_1";
949
- const yourPhoneNumber = "6281234567890"; // Replace with your phone number
950
-
951
- try {
952
- await whatsapp.startSessionWithPairingCode(pairingSessionId, yourPhoneNumber, {
953
- onConnected: () => {
954
- console.log("Pairing session connected successfully!");
955
- sessionStatus[pairingSessionId] = 'connected';
956
- },
957
- onDisconnected: () => {
958
- console.log("Pairing session disconnected!");
959
- sessionStatus[pairingSessionId] = 'disconnected';
960
- },
961
- onPairingCode: (code) => {
962
- console.log("\n" + "=".repeat(50));
963
- console.log("📱 PAIRING CODE:", code);
964
- console.log("=".repeat(50));
965
- console.log("1. Open WhatsApp on your phone");
966
- console.log("2. Go to Settings > Linked Devices");
967
- console.log("3. Tap 'Link a Device'");
968
- console.log("4. Tap 'Link with phone number instead'");
969
- console.log("5. Enter the pairing code above");
970
- console.log("=".repeat(50) + "\n");
971
- }
972
- });
973
-
974
- sessionStatus[pairingSessionId] = 'connecting';
975
- } catch (error) {
976
- console.error("Error starting pairing session:", error);
977
- }
978
-
979
- // Periodic health check for pairing sessions
980
- setInterval(async () => {
981
- const pairingSessions = whatsapp.getPairingCodeSessions();
982
- console.log(`Active pairing sessions: ${pairingSessions.length}`);
983
-
984
- // Check each pairing session status
985
- for (const sessionId of pairingSessions) {
986
- const status = await whatsapp.getSessionStatus(sessionId);
987
- console.log(`Session ${sessionId}: ${status.connected ? 'Connected' : 'Disconnected'}`);
988
-
989
- if (!status.connected && sessionStatus[sessionId] === 'connected') {
990
- console.log(`Detected disconnection for ${sessionId}, attempting reconnect...`);
991
- try {
992
- await whatsapp.reconnect(sessionId);
993
- } catch (error) {
994
- console.error(`Reconnect failed for ${sessionId}:`, error);
995
- }
996
- }
997
- }
998
- }, 30000); // Check every 30 seconds
999
-
1000
- // Bulk reconnect utility
1001
- setInterval(async () => {
1002
- try {
1003
- await whatsapp.reconnectAllPairingCodeSessions();
1004
- console.log("Bulk reconnect completed for all pairing sessions");
1005
- } catch (error) {
1006
- console.error("Bulk reconnect failed:", error);
1007
- }
1008
- }, 10 * 60 * 1000); // Every 10 minutes
1009
-
1010
- console.log("Pairing code application started!");
1011
- }
1012
-
1013
- startPairingApp().catch(err => {
1014
- console.error("Failed to start pairing application:", err);
1015
- process.exit(1);
1016
- });
1017
- ```
1018
-
1019
- ## Frontend Integration Example: QR Code Display (v3.9.6+)
1020
-
1021
- ```javascript
1022
- // React.js example for QR code display
1023
- import React, { useState, useEffect } from 'react';
1024
- import QRCode from 'qrcode';
1025
- import * as whatsapp from "wa-multi-mongodb";
1026
-
1027
- function WhatsAppQRComponent() {
1028
- const [qrDataURL, setQrDataURL] = useState('');
1029
- const [sessionStatus, setSessionStatus] = useState('disconnected');
1030
-
1031
- useEffect(() => {
1032
- // Initialize WhatsApp connection
1033
- const initWhatsApp = async () => {
1034
- await whatsapp.setMongoURI(process.env.REACT_APP_MONGODB_URI);
1035
-
1036
- // Start session with simplified QR callback
1037
- await whatsapp.startSession("frontend_session", {
1038
- printQR: false, // Don't print in terminal
1039
- onQRUpdated: async (qr) => {
1040
- // QR data is raw and ready for frontend use
1041
- try {
1042
- const qrDataURL = await QRCode.toDataURL(qr);
1043
- setQrDataURL(qrDataURL);
1044
- } catch (error) {
1045
- console.error('Error generating QR code:', error);
1046
- }
1047
- },
1048
- onConnected: () => {
1049
- setSessionStatus('connected');
1050
- setQrDataURL(''); // Clear QR when connected
1051
- },
1052
- onDisconnected: () => {
1053
- setSessionStatus('disconnected');
1054
- }
1055
- });
1056
- };
1057
-
1058
- initWhatsApp().catch(console.error);
1059
- }, []);
1060
-
1061
- return (
1062
- <div className="whatsapp-qr">
1063
- <h2>WhatsApp Connection</h2>
1064
- <div className="status">
1065
- Status: <span className={sessionStatus}>{sessionStatus}</span>
1066
- </div>
1067
-
1068
- {qrDataURL && (
1069
- <div className="qr-container">
1070
- <p>Scan this QR code with WhatsApp:</p>
1071
- <img src={qrDataURL} alt="WhatsApp QR Code" />
1072
- </div>
1073
- )}
1074
-
1075
- {sessionStatus === 'connected' && (
1076
- <div className="connected">
1077
- <p>✅ WhatsApp connected successfully!</p>
1078
- </div>
1079
- )}
1080
- </div>
1081
- );
1082
- }
1083
-
1084
- export default WhatsAppQRComponent;
1085
- ```
1086
-
1087
- ## Best Practices for Group Chats
1088
-
1089
- 1. **Auto Group Detection**: Since v3.9.0, the library automatically detects if a chat is a group based on its JID format
1090
- 2. **Typing Indicators**: Typing indicators now work in both private and group chats (v3.9.1+)
1091
- 3. **Longer Timeouts**: Use longer timeouts when sending media to groups (60+ seconds)
1092
- 4. **Handle Errors**: Implement retry mechanisms for failed group messages
1093
- 5. **Announcement Channels**: Groups with announcement channels may trigger `MessageCounterError` (handled automatically in v3.9.1+)
1094
- 6. **Retry Strategy**: For announcement channel groups, the library will automatically retry sending messages up to 3 times with increasing delays
1095
- 7. **Group Metadata Caching**: Use the hybrid caching system (v3.9.4+) to improve performance when working with groups
1096
- 8. **New `sendTextMessageWithMention` Function**: Comprehensive mention functionality for WhatsApp messages (v3.9.8+)
1097
-
1098
- ## WhatsApp Limitations
1099
-
1100
- 1. **Media Transfer**: Large media files to groups may take longer or timeout
1101
- 2. **Connection Stability**: Auto-reconnect may be needed in production apps
1102
- 3. **Announcement Channels**: Some groups with announcement channels may still fail after multiple retries
1103
-
1104
- ## Changelog
1105
-
1106
- ### v3.10.4 (latest)
1107
- - **Custom Browser Configuration**: Added ability to customize browser type and name for WhatsApp connection
1108
- - New `browserType` option: Choose from "ubuntu" (default), "macOS", "windows", or "appropriate"
1109
- - New `browserName` option: Customize the app name displayed in WhatsApp's "Linked Devices" list
1110
- - Works with both `startSession()` and `startSessionWithPairingCode()` methods
1111
- - Default behavior unchanged (Ubuntu browser with "Chrome" name)
1112
- - **LID ↔ PN Conversion Utilities**: Added comprehensive utilities for converting between LID (Linked ID) and Phone Number formats
1113
- - New `getPNForLID(sessionId, lid)` function to convert LID to phone number
1114
- - New `getLIDForPN(sessionId, pn)` function to convert phone number to LID
1115
- - New `toPhoneNumber(sessionId, jid)` smart conversion function (auto-detects format)
1116
- - New `toLID(sessionId, jid)` smart conversion function (auto-detects format)
1117
- - New `getAllLIDMappings(sessionId)` function to get all known LID-PN mappings
1118
- - New `isLIDFormat(jid)` and `isPNFormat(jid)` helper functions
1119
- - Uses Baileys' internal `signalRepository.lidMapping` for conversions
1120
-
1121
-
1122
- ### v3.10.2
1123
- - **Fixed Group JID Validation**: Resolved issue with group chat validation
1124
- - Fixed `isValidJid()` function to properly validate group JIDs without requiring dash (-) character
1125
- - Some WhatsApp group IDs don't use dash format, validation now accepts all valid group formats
1126
- - Error "Invalid JID format: [group-id]@g.us" has been resolved
1127
-
1128
- ### v3.10.1
1129
- - **Using Baileys New Version (7.x.x)**: Update & support function with latest baileys version
1130
- - **Added @lid Format Support**: Full support for WhatsApp's new @lid identifier format
1131
- - Updated `phoneToJid()` function to handle both @s.whatsapp.net and @lid formats
1132
- - Enhanced all message sending functions with JID validation:
1133
- - `sendTextMessage()`
1134
- - `sendTextMessageWithMention()`
1135
- - `sendMedia()`
1136
- - `sendVoiceNote()`
1137
- - `sendSticker()`
1138
- - `sendTyping()`
1139
- - No breaking changes - existing @s.whatsapp.net format continues to work
1140
- - Automatic detection and handling of @lid format to prevent 404 errors
1141
- - Added comprehensive error handling for invalid JID formats
1142
-
1143
- ### v3.9.8
1144
- ### Added
1145
- - **New `sendTextMessageWithMention` Function**: Comprehensive mention functionality for WhatsApp messages
1146
- - Support for mentioning single or multiple users in group chats
1147
- - Automatic JID format validation and conversion
1148
- - Full retry mechanism with error handling for mention messages
1149
- - Support for quoted messages with mentions
1150
- - Compatible with both group and private chat mentions
1151
- - Enhanced timeout handling for mention messages
1152
-
1153
- ### v3.9.7
1154
- - **Enhanced Message Processing for Group Chats**: Fixed issues with group message handling and improved message processing architecture
1155
- - **Multiple Message Processing**: Event handler `messages.upsert` now processes all messages in array instead of only the first message
1156
- - **Improved Message Filtering**: Added intelligent filtering to skip protocol messages and empty messages while preserving valid group messages
1157
- - **Enhanced Group Message Support**: Better detection and processing of group messages with participant information
1158
- - **Group vs Private Chat Detection**: Better differentiation between group and private messages
1159
- - **Improved Error Recovery**: Better error handling without changing existing error patterns
1160
-
1161
- ### v3.9.6
1162
- - **Enhanced Pairing Code Support**: Added comprehensive pairing code session management with auto-reconnect capabilities
1163
- - New `startSessionWithPairingCode()` function for creating sessions using pairing codes
1164
- - Intelligent session tracking system that preserves pairing code session data across disconnections
1165
- - Enhanced auto-reconnect mechanism that differentiates between QR code and pairing code sessions
1166
- - Session persistence in MongoDB for pairing code sessions to enable seamless reconnection
1167
- - **New Utility Functions for Session Management**:
1168
- - `reconnect(sessionId)` - Manual reconnection for any session type
1169
- - `reconnectAllPairingCodeSessions()` - Bulk reconnection for all tracked pairing code sessions
1170
- - `getPairingCodeSessions()` - Get list of all pairing code session IDs
1171
- - `getSessionStatus(sessionId)` - Get detailed session status information including session type
1172
- - **QR Data Raw for Frontend Integration**: Simplified QR handling optimized for frontend development
1173
- - Cleaned up QR callback to provide only essential QR data raw for frontend processing
1174
- - Removed unnecessary QR string complexity from callbacks for better performance
1175
- - QR data can be directly used with any frontend QR code library (React, Vue, Angular, etc.)
1176
- - Terminal QR display handled automatically via `printQR` option
1177
- - **Breaking Changes**:
1178
- - Simplified `onQRUpdated` callback signature: removed `qrString` parameter, now only provides raw QR data
1179
- - Session-level `onQRUpdated` option simplified from `(qr, qrString)` to `(qr)` only
1180
- - **Enhanced Session Persistence**: Pairing code sessions maintain authentication state in MongoDB during disconnections
1181
- - **Improved Error Handling**: Better error recovery and automatic session restoration for pairing code sessions
1182
-
1183
- ### v3.9.5
1184
- - New `deleteMessage()` function for deleting messages
1185
- - Support for deleting both own messages and others' messages (requires admin permissions in groups)
1186
- - Auto-delete message utility function example
1187
-
1188
- ### v3.9.4
1189
- - Updated baileys dependency to v6.7.18
1190
- - Added hybrid caching system for group metadata (NodeCache + MongoDB)
1191
- - Improved group operations performance with automatic caching
1192
- - New functions for group metadata management:
1193
- - `getGroupMetadata()` - Get metadata with automatic caching
1194
- - `setGroupCacheConfig()` - Configure cache TTL and check periods
1195
- - `clearGroupMetadataCache()` - Clear specific group metadata
1196
- - `clearAllGroupMetadataCache()` - Clear all cached group metadata
1197
-
1198
- ### v3.9.3
1199
- - Updated QR code implementation for better display in terminal
1200
- - Replaced deprecated `printQRInTerminal` option with `qrcode` library implementation
1201
- - Added support for latest Baileys version
1202
-
1203
- ### v3.9.2
1204
- - Updated Baileys dependency to v6.7.17 for improved stability and compatibility
1205
-
1206
- ### v3.9.1
1207
- - Added special handling for `MessageCounterError` in group chats with announcement channels
1208
- - Implemented automatic retry mechanism for messages to announcement channels
1209
- - Enhanced error reporting for group chat issues
1210
- - Fixed typing indicators to work properly in group chats
1211
-
1212
- ### v3.9.0
1213
- - Added automatic group chat detection - no need to specify `isGroup: true` parameter
1214
- - Improved message sending reliability for group chats
1215
- - Enhanced error handling with better timeout management
1216
- - Implemented automatic format detection for group IDs
1217
-
1218
- ### v3.8.1
1219
- - Updated baileys to v6.7.16
1220
- - Improved MongoDB integration
1221
- - Enhanced error handling and connection stability
1222
-
1223
- ### v3.8.0
1224
- - Package renamed from wa-multi-session to wa-multi-mongodb
1225
- - Added MongoDB session management
1226
- - Fixed connection and authentication issues
1227
-
1228
- ### v3.7.0
1229
- - Upgraded to baileys v6.7.9
1230
- - Fixed phone number validation
1231
- - Removed registered phone number validation requirement
1232
-
1233
- ## Links
1234
-
1235
- - [GitHub Repository](https://github.com/wahdalo/wa-multi-mongodb)
1236
- - [Issue Tracker](https://github.com/wahdalo/wa-multi-mongodb/issues)
1237
- - [Original wa-multi-session](https://github.com/mimamch/wa-multi-session)
1238
- - [Baileys Library](https://github.com/WhiskeySockets/Baileys)
1239
-
1240
- ## Author
1241
-
1242
- - [@wahdalo](https://github.com/wahdalo)
1243
-
1244
- ## License
1245
-
1246
- ISC
1
+ # WhatsApp Multi MongoDB - Multi Session WhatsApp with MongoDB
2
+
3
+ ## ⚠️ Important Note
4
+ This repository is a modified version of [@mimamch/wa-multi-session](https://github.com/mimamch/wa-multi-session) with MongoDB session management integration. The original repository uses file-based session storage, while this version uses MongoDB for better scalability and session management.
5
+
6
+ Lightweight library for WhatsApp with MongoDB integration. No Selenium or browser required.
7
+
8
+ Built on [Baileys](https://github.com/WhiskeySockets/Baileys) Library.
9
+
10
+ ## Features
11
+ - Multi-session WhatsApp (multiple numbers simultaneously)
12
+ - State (auth) storage in MongoDB instead of files
13
+ - Automatic loading of all sessions from the database at startup
14
+ - No need to scan QR again as long as MongoDB data is preserved
15
+ - Automatic timeout handling for long-running operations
16
+ - Auto-reconnect when connection is lost
17
+ - Better group chat support
18
+ - Automatic retry for failed message deliveries
19
+ - Automatic group chat detection (v3.9.0+)
20
+ - Hybrid caching system for group metadata (v3.9.4+)
21
+ - Message deletion for self and others (v3.9.5+)
22
+ - Custom browser configuration (v3.10.4+)
23
+ - LID ↔ PN conversion utilities (v3.10.4+)
24
+ - Proxy support for WebSocket and media connections (v3.10.8+)
25
+ - Download incoming media messages directly as Buffer with session-aware reupload support (v3.10.8+)
26
+
27
+ ## Installation
28
+
29
+ Install package using npm:
30
+
31
+ ```bash
32
+ npm install wa-multi-mongodb@latest
33
+ ```
34
+
35
+ Then import into your code:
36
+
37
+ ```typescript
38
+ // Using ES modules
39
+ import * as whatsapp from "wa-multi-mongodb";
40
+
41
+ // Or using CommonJS
42
+ const whatsapp = require("wa-multi-mongodb");
43
+ ```
44
+
45
+ ## Environment Setup
46
+
47
+ For secure MongoDB URI management, we recommend using environment variables:
48
+
49
+ 1. Create a `.env` file in your project root (copy from `.env.example`):
50
+ ```
51
+ # MongoDB Configuration
52
+ MONGODB_URI=mongodb://username:password@hostname:port/database
53
+
54
+ # Optional database settings
55
+ WA_DB_NAME=wa_session
56
+ WA_COLLECTION_NAME=auth
57
+ ```
58
+
59
+ 2. Install and use the dotenv package:
60
+ ```javascript
61
+ // Load environment variables
62
+ require('dotenv').config();
63
+
64
+ // Use in your code
65
+ const MONGODB_URI = process.env.MONGODB_URI;
66
+ if (!MONGODB_URI) {
67
+ console.error('Error: MONGODB_URI not found in environment variables');
68
+ process.exit(1);
69
+ }
70
+
71
+ // Initialize WhatsApp with MongoDB
72
+ await whatsapp.setMongoURI(MONGODB_URI);
73
+ ```
74
+
75
+ 3. Make sure to add `.env` to your `.gitignore` file to prevent exposing sensitive credentials
76
+
77
+ ## MongoDB Configuration
78
+
79
+ ### Setup MongoDB Connection
80
+ 1. Make sure MongoDB is running (local/cloud)
81
+ 2. Configure the connection using one of these methods:
82
+
83
+ **Using environment variables (recommended):**
84
+ ```javascript
85
+ require('dotenv').config();
86
+ await whatsapp.setMongoURI(process.env.MONGODB_URI);
87
+ ```
88
+
89
+ **Directly in code (not recommended for production):**
90
+ ```javascript
91
+ await whatsapp.setMongoURI("mongodb+srv://username:password@host/db?options");
92
+ ```
93
+
94
+ 3. Optionally customize the database and collection names:
95
+ ```javascript
96
+ // Default values are "wa_session" and "auth"
97
+ whatsapp.setMongoDBNames("custom_database_name", "custom_collection_name");
98
+ ```
99
+
100
+ ## Basic Usage
101
+
102
+ ### Session Management
103
+
104
+ ```javascript
105
+ // Start a new session with QR Code
106
+ const session = await whatsapp.startSession("mysession");
107
+
108
+ // Start with options
109
+ await whatsapp.startSession("mysession2", {
110
+ printQR: true,
111
+ onConnected: () => console.log("Connected!"),
112
+ onDisconnected: () => console.log("Disconnected!"),
113
+ onQRUpdated: (qr) => {
114
+ console.log("New QR:", qr);
115
+ // QR data is raw and ready for frontend use
116
+ // You can display this in React, Vue, Angular, etc.
117
+ }
118
+ });
119
+
120
+ // Start with custom browser configuration (v3.10.4+)
121
+ // Display: "Safari (Mac OS)" in WhatsApp Linked Devices
122
+ await whatsapp.startSession("mysession3", {
123
+ printQR: true,
124
+ browserType: "macOS", // Options: "ubuntu", "macOS", "windows", "appropriate"
125
+ browserName: "Safari", // Valid: Chrome, Safari, Firefox, Edge, Opera, IE, Desktop
126
+ onConnected: () => console.log("Connected with custom browser!"),
127
+ });
128
+
129
+ // Start session with Pairing Code (v3.9.6+)
130
+ await whatsapp.startSessionWithPairingCode("mysession4", "6281234567890", {
131
+ onConnected: () => console.log("Pairing session connected!"),
132
+ onDisconnected: () => console.log("Pairing session disconnected!"),
133
+ onPairingCode: (code) => {
134
+ console.log("Pairing code:", code);
135
+ // Enter this code in your WhatsApp app: Settings > Linked Devices > Link a Device > Link with phone number
136
+ }
137
+ });
138
+
139
+ // Pairing code with valid browser config - displays "Edge (Windows)"
140
+ // ⚠️ IMPORTANT: Pairing code ONLY works with valid browser configurations!
141
+ await whatsapp.startSessionWithPairingCode("mysession5", "6281234567890", {
142
+ browserType: "windows",
143
+ browserName: "Edge", // Must be valid: Chrome, Safari, Firefox, Edge, Opera, IE, Desktop
144
+ onPairingCode: (code) => console.log("Code:", code),
145
+ });
146
+
147
+ // Get all active sessions
148
+ const sessions = await whatsapp.getAllSession();
149
+
150
+ // Get data for a specific session
151
+ const sessionData = whatsapp.getSession("mysession");
152
+
153
+ // Load all saved sessions from MongoDB
154
+ await whatsapp.loadSessionsFromMongo();
155
+
156
+ // Session Management Utilities (v3.9.6+)
157
+ // Get session status with detailed information
158
+ const status = await whatsapp.getSessionStatus("mysession");
159
+ console.log("Session status:", status);
160
+ // Returns: { exists: true, connected: true, sessionType: 'qr' | 'pairing' }
161
+
162
+ // Manual reconnection for any session
163
+ try {
164
+ const reconnected = await whatsapp.reconnect("mysession");
165
+ console.log("Reconnection successful:", reconnected);
166
+ } catch (error) {
167
+ console.error("Reconnection failed:", error);
168
+ }
169
+
170
+ // Get all pairing code sessions
171
+ const pairingSessions = whatsapp.getPairingCodeSessions();
172
+ console.log("Pairing code sessions:", pairingSessions);
173
+
174
+ // Bulk reconnect all pairing code sessions
175
+ await whatsapp.reconnectAllPairingCodeSessions();
176
+ ```
177
+
178
+ ### Custom Browser Configuration (v3.10.4+)
179
+
180
+ Customize how your session appears in WhatsApp's "Linked Devices" list.
181
+
182
+ **Display Format in WhatsApp**: `browserName (OsName)` - e.g., "Safari (Mac OS)"
183
+
184
+ #### Valid browserName Values
185
+
186
+ These are recognized by WhatsApp and will display correctly:
187
+
188
+ | browserName | Description |
189
+ |-------------|-------------|
190
+ | `"Chrome"` | Google Chrome (default) |
191
+ | `"Safari"` | Apple Safari |
192
+ | `"Firefox"` | Mozilla Firefox |
193
+ | `"Edge"` | Microsoft Edge |
194
+ | `"Opera"` | Opera Browser |
195
+ | `"IE"` | Internet Explorer |
196
+ | `"Desktop"` | Generic Desktop App |
197
+
198
+ #### browserType Options
199
+
200
+ | browserType | OS Name Displayed | OS Version |
201
+ |-------------|-------------------|------------|
202
+ | `"ubuntu"` | Ubuntu | 22.04.4 |
203
+ | `"macOS"` | Mac OS | 14.4.1 |
204
+ | `"windows"` | Windows | 10.0.22631 |
205
+ | `"appropriate"` | Auto-detect | Based on platform |
206
+
207
+ #### Usage Examples
208
+
209
+ ```javascript
210
+ // Safari on macOS → displays as "Safari (Mac OS)"
211
+ await whatsapp.startSession("session1", {
212
+ printQR: true,
213
+ browserType: "macOS",
214
+ browserName: "Safari",
215
+ });
216
+
217
+ // Chrome on Windows → displays as "Chrome (Windows)"
218
+ await whatsapp.startSession("session2", {
219
+ printQR: true,
220
+ browserType: "windows",
221
+ browserName: "Chrome",
222
+ });
223
+
224
+ // Firefox on Ubuntu → displays as "Firefox (Ubuntu)"
225
+ await whatsapp.startSession("session3", {
226
+ printQR: true,
227
+ browserType: "ubuntu",
228
+ browserName: "Firefox",
229
+ });
230
+
231
+ // Edge on Windows → displays as "Edge (Windows)"
232
+ await whatsapp.startSession("session4", {
233
+ printQR: true,
234
+ browserType: "windows",
235
+ browserName: "Edge",
236
+ });
237
+
238
+ // Desktop app on macOS → displays as "Desktop (Mac OS)"
239
+ await whatsapp.startSession("session5", {
240
+ printQR: true,
241
+ browserType: "macOS",
242
+ browserName: "Desktop",
243
+ });
244
+
245
+ // Custom name (fallback to Chrome) → displays as "Chrome (My Bot App)"
246
+ await whatsapp.startSession("session6", {
247
+ printQR: true,
248
+ browserType: "windows",
249
+ browserName: "My Bot App",
250
+ });
251
+
252
+ // Custom name with Safari → displays as "Safari (My Bot App)"
253
+ await whatsapp.startSession("session7", {
254
+ printQR: true,
255
+ browserType: "macOS",
256
+ browserName: "My Bot App",
257
+ displayBrowser: "Safari", // Choose which browser type to display
258
+ });
259
+
260
+ // Custom name with Firefox → displays as "Firefox (Device Bot)"
261
+ await whatsapp.startSession("session8", {
262
+ printQR: true,
263
+ browserType: "ubuntu",
264
+ browserName: "Device Bot",
265
+ displayBrowser: "Firefox",
266
+ });
267
+ ```
268
+
269
+ #### displayBrowser Parameter (v3.10.5+)
270
+
271
+ When using a custom `browserName`, you can now choose which browser type to display using the `displayBrowser` parameter:
272
+
273
+ | displayBrowser | Custom Name Example | Display Result |
274
+ |----------------|---------------------|----------------|
275
+ | `"Chrome"` (default) | "My Bot" | Chrome (My Bot) |
276
+ | `"Safari"` | "My Bot" | Safari (My Bot) |
277
+ | `"Firefox"` | "My Bot" | Firefox (My Bot) |
278
+ | `"Edge"` | "My Bot" | Edge (My Bot) |
279
+ | `"Opera"` | "My Bot" | Opera (My Bot) |
280
+ | `"Desktop"` | "My Bot" | Desktop (My Bot) |
281
+
282
+ > **Note**: `displayBrowser` is only used when `browserName` is a custom name (not a valid browser type like Chrome, Safari, etc.).
283
+
284
+ > [!WARNING]
285
+ > **Custom browserName and displayBrowser are NOT supported for Pairing Code sessions!**
286
+ >
287
+ > WhatsApp server validates browser configuration strictly during pairing code authentication. You MUST use valid browser configurations for pairing code:
288
+ >
289
+ > | browserType | browserName | Display | Pairing Code |
290
+ > |-------------|-------------|---------|--------------|
291
+ > | `"windows"` | `"Chrome"` | Chrome (Windows) | ✅ Works |
292
+ > | `"macOS"` | `"Safari"` | Safari (Mac OS) | ✅ Works |
293
+ > | `"windows"` | `"Edge"` | Edge (Windows) | ✅ Works |
294
+ > | `"ubuntu"` | `"Firefox"` | Firefox (Ubuntu) | Works |
295
+ > | `"windows"` | `"My Bot"` | Chrome (My Bot) | ❌ Fails |
296
+ >
297
+ > Custom names (like "My Bot App") only work with **QR Code** authentication.
298
+
299
+ ### Proxy Support (v3.10.8+)
300
+
301
+ You can use a proxy for WebSocket connections and media upload/download. **No additional dependencies are included** - install your preferred proxy agent package if needed.
302
+
303
+ #### Install Proxy Agent (User's Choice)
304
+
305
+ ```bash
306
+ # For HTTP/HTTPS proxy
307
+ npm install https-proxy-agent
308
+
309
+ # For SOCKS4/SOCKS5 proxy
310
+ npm install socks-proxy-agent
311
+ ```
312
+
313
+ #### Usage Examples
314
+
315
+ ```javascript
316
+ // Using HTTPS proxy
317
+ import { HttpsProxyAgent } from 'https-proxy-agent';
318
+
319
+ const proxyAgent = new HttpsProxyAgent('http://proxy.example.com:8080');
320
+ // With authentication: new HttpsProxyAgent('http://user:pass@proxy.example.com:8080');
321
+
322
+ await whatsapp.startSession("mysession", {
323
+ printQR: true,
324
+ agent: proxyAgent, // Proxy for WebSocket connection
325
+ fetchAgent: proxyAgent, // Proxy for media upload/download (optional, defaults to agent)
326
+ });
327
+
328
+ // Using SOCKS5 proxy
329
+ import { SocksProxyAgent } from 'socks-proxy-agent';
330
+
331
+ const socksAgent = new SocksProxyAgent('socks5://127.0.0.1:1080');
332
+ // With authentication: new SocksProxyAgent('socks5://user:pass@127.0.0.1:1080');
333
+
334
+ await whatsapp.startSessionWithPairingCode("mysession", "6281234567890", {
335
+ browserType: "windows",
336
+ browserName: "Chrome",
337
+ agent: socksAgent,
338
+ });
339
+ ```
340
+
341
+ | Option | Type | Description |
342
+ |--------|------|-------------|
343
+ | `agent` | `Agent` | Proxy agent for WebSocket connection |
344
+ | `fetchAgent` | `Agent` | Proxy agent for media upload/download (defaults to `agent`) |
345
+
346
+ > **Note**: Proxy is optional. If not provided, direct connection is used.
347
+
348
+
349
+
350
+ ### Sending Messages
351
+
352
+ ```javascript
353
+ // Send text message
354
+ await whatsapp.sendTextMessage({
355
+ sessionId: "mysession",
356
+ to: "6281234567890", // always include country code
357
+ text: "Hello from wa-multi-mongodb!"
358
+ // isGroup parameter is optional (v3.9.0+)
359
+ // The library will automatically detect if the destination is a group
360
+ });
361
+
362
+ // Send to a group (automatic detection in v3.9.0+)
363
+ await whatsapp.sendTextMessage({
364
+ sessionId: "mysession",
365
+ to: "120363152682073800", // group ID
366
+ text: "Hello group!"
367
+ // No need for isGroup: true parameter in v3.9.0+
368
+ });
369
+
370
+ // Send to a group (compatible with older versions)
371
+ await whatsapp.sendTextMessage({
372
+ sessionId: "mysession",
373
+ to: "120363152682073800", // group ID
374
+ text: "Hello group!",
375
+ isGroup: true // still works but optional in v3.9.0+
376
+ });
377
+
378
+ // Send media (unified function)
379
+ await whatsapp.sendMedia({
380
+ sessionId: "mysession",
381
+ to: "6281234567890",
382
+ type: "image", // options: image, video, pdf, doc, docx, xls, xlsx, zip, mp3
383
+ media: fs.readFileSync("./image.jpg"), // or URL string
384
+ caption: "Image caption",
385
+ fileName: "image.jpg", // required for documents
386
+ // isGroup parameter is optional (v3.9.0+)
387
+ });
388
+
389
+ // Send voice note
390
+ await whatsapp.sendVoiceNote({
391
+ sessionId: "mysession",
392
+ to: "6281234567890",
393
+ media: fs.readFileSync("./audio.mp3"),
394
+ // isGroup parameter is optional (v3.9.0+)
395
+ });
396
+
397
+ // Mark message as read
398
+ await whatsapp.readMessage({
399
+ sessionId: "mysession",
400
+ key: msg.key,
401
+ });
402
+
403
+ // Send typing indicator
404
+ await whatsapp.sendTyping({
405
+ sessionId: "mysession",
406
+ to: "6281234567890", // or group ID
407
+ duration: 3000, // milliseconds
408
+ // isGroup parameter is optional (v3.9.0+)
409
+ });
410
+
411
+ // Delete message (v3.9.5+)
412
+ // Delete own message for everyone
413
+ await whatsapp.deleteMessage({
414
+ sessionId: "mysession",
415
+ key: messageObject.key, // message key from received or sent message
416
+ });
417
+
418
+ // Delete someone else's message (requires admin permissions in groups)
419
+ await whatsapp.deleteMessage({
420
+ sessionId: "mysession",
421
+ key: {
422
+ remoteJid: "120363152682073800@g.us", // group ID with @g.us
423
+ fromMe: false,
424
+ id: "MESSAGE_ID",
425
+ participant: "SENDER_JID" // required for group messages
426
+ }
427
+ });
428
+
429
+ // Auto-delete message after delay (helper function example)
430
+ function autoDeleteMessage(sessionId, message, delayMs = 3000) {
431
+ setTimeout(async () => {
432
+ try {
433
+ await whatsapp.deleteMessage({
434
+ sessionId: sessionId,
435
+ key: message.key
436
+ });
437
+ } catch (error) {
438
+ console.error("Error auto-deleting message:", error);
439
+ }
440
+ }, delayMs);
441
+ }
442
+
443
+ // Send text message with mention (v3.9.8+)
444
+ // Mention one user in a group
445
+ await whatsapp.sendTextMessageWithMention({
446
+ sessionId: "mysession",
447
+ to: "6281234567890@g.us", // group JID
448
+ text: "Halo @6281234567890, selamat datang di grup!",
449
+ mentions: ["6281234567890@s.whatsapp.net"], // JID to mention
450
+ isGroup: true
451
+ });
452
+
453
+ // Mention multiple users in a group
454
+ await whatsapp.sendTextMessageWithMention({
455
+ sessionId: "mysession",
456
+ to: "6281234567890@g.us",
457
+ text: "Halo @6281234567890 dan @6289876543210, ada yang bisa saya bantu?",
458
+ mentions: [
459
+ "6281234567890@s.whatsapp.net",
460
+ "6289876543210@s.whatsapp.net"
461
+ ],
462
+ isGroup: true
463
+ });
464
+
465
+ // Mention in private chat (less common but supported)
466
+ await whatsapp.sendTextMessageWithMention({
467
+ sessionId: "mysession",
468
+ to: "6281234567890",
469
+ text: "Halo @6281234567890, ini adalah pesan pribadi dengan mention",
470
+ mentions: ["6281234567890@s.whatsapp.net"]
471
+ });
472
+
473
+ // Alternative: Use sendTextMessage with mentions property
474
+ // You can also use the regular sendTextMessage with mentions
475
+ const session = whatsapp.getSession("mysession");
476
+ if (session) {
477
+ await session.sendMessage(
478
+ "6281234567890@g.us",
479
+ {
480
+ text: "Halo @6281234567890, ini pesan dengan mention!",
481
+ mentions: ["6281234567890@s.whatsapp.net"]
482
+ },
483
+ {
484
+ quoted: null // or message to quote
485
+ }
486
+ );
487
+ }
488
+ ```
489
+
490
+ ### Event Listeners
491
+
492
+ ```javascript
493
+ // Incoming messages
494
+ whatsapp.onMessageReceived((msg) => {
495
+ console.log(`Message from ${msg.key.remoteJid}:`, msg);
496
+ });
497
+
498
+ // QR code updates
499
+ whatsapp.onQRUpdated(({ sessionId, qr }) => {
500
+ console.log(`QR Code for ${sessionId}:`, qr);
501
+ // You can display this QR in a UI or save it to a file
502
+ });
503
+
504
+ // Connection events
505
+ whatsapp.onConnected((sessionId) => {
506
+ console.log(`Session ${sessionId} connected`);
507
+ });
508
+
509
+ whatsapp.onDisconnected((sessionId) => {
510
+ console.log(`Session ${sessionId} disconnected`);
511
+ });
512
+ ```
513
+
514
+ ### Handling Media in Incoming Messages
515
+
516
+ For simple file saving, incoming media messages include helper methods such as `saveImage`, `saveVideo`, `saveDocument`, and `saveAudio`.
517
+
518
+ ```javascript
519
+ whatsapp.onMessageReceived(async (msg) => {
520
+ if (msg.message?.imageMessage) {
521
+ await msg.saveImage("./saved-image.jpg");
522
+ }
523
+
524
+ if (msg.message?.videoMessage) {
525
+ await msg.saveVideo("./saved-video.mp4");
526
+ }
527
+
528
+ if (msg.message?.documentMessage) {
529
+ await msg.saveDocument("./saved-document"); // extension will be added automatically
530
+ }
531
+
532
+ if (msg.message?.audioMessage) {
533
+ await msg.saveAudio("./saved-audio.mp3");
534
+ }
535
+ });
536
+ ```
537
+
538
+ #### Download Media as Buffer (v3.10.8+)
539
+
540
+ Use `downloadMediaMessage` when you need the raw media `Buffer` instead of saving directly to disk. This is useful for uploading media to cloud storage, forwarding it to another service, processing it in memory, or returning it from an API endpoint.
541
+
542
+ ```javascript
543
+ whatsapp.onMessageReceived(async (msg) => {
544
+ const hasMedia =
545
+ msg.message?.imageMessage ||
546
+ msg.message?.videoMessage ||
547
+ msg.message?.documentMessage ||
548
+ msg.message?.audioMessage ||
549
+ msg.message?.stickerMessage;
550
+
551
+ if (!hasMedia) return;
552
+
553
+ try {
554
+ const buffer = await whatsapp.downloadMediaMessage({
555
+ sessionId: "mysession",
556
+ message: msg,
557
+ });
558
+
559
+ console.log("Downloaded media size:", buffer.length);
560
+ // Example: upload buffer to S3, save to your database, or process it in memory
561
+ } catch (error) {
562
+ console.error("Failed to download media:", error);
563
+ }
564
+ });
565
+ ```
566
+
567
+ Parameters:
568
+
569
+ | Parameter | Type | Required | Description |
570
+ |-----------|------|----------|-------------|
571
+ | `sessionId` | `string` | Yes | Active WhatsApp session ID used to download and reupload expired media if needed |
572
+ | `message` | `any` | Yes | Incoming Baileys message object from `onMessageReceived` |
573
+ | `key` | `any` | No | Reserved optional message key parameter |
574
+
575
+ Returns: `Promise<Buffer>` containing the downloaded media bytes.
576
+
577
+ Notes:
578
+
579
+ - The session must be active, otherwise `sessionNotFound` is thrown.
580
+ - The message must contain downloadable media content.
581
+ - Expired WhatsApp media can be reuploaded automatically through the active session's `updateMediaMessage` handler.
582
+
583
+ ### Group Metadata Caching (v3.9.4+)
584
+
585
+ The library now implements a hybrid caching system for group metadata using both in-memory (NodeCache) and persistent storage (MongoDB). This significantly improves performance for applications that frequently use group metadata information.
586
+
587
+ ```javascript
588
+ // Configure cache settings (optional, has default values)
589
+ whatsapp.setGroupCacheConfig({
590
+ stdTTL: 10 * 60, // Time-to-live in seconds (10 minutes)
591
+ checkperiod: 120 // Check for expired keys every 2 minutes
592
+ });
593
+
594
+ // Get group metadata (automatically uses cache if available)
595
+ const metadata = await whatsapp.getGroupMetadata(sessionId, groupJid);
596
+ console.log(`Group name: ${metadata.subject}`);
597
+ console.log(`Participants: ${metadata.participants.length}`);
598
+ console.log(`Created on: ${new Date(metadata.creation * 1000).toLocaleString()}`);
599
+
600
+ // Force fetch fresh data from server and update cache
601
+ const freshData = await whatsapp.getGroupMetadata(sessionId, groupJid, true);
602
+
603
+ // Clear cache for specific group in a specific session
604
+ await whatsapp.clearGroupMetadataCache(sessionId, groupJid);
605
+
606
+ // Clear all group metadata cache for a specific session
607
+ await whatsapp.clearSessionGroupMetadataCache(sessionId);
608
+
609
+ // Clear all cached group metadata for all sessions
610
+ whatsapp.clearAllGroupMetadataCache();
611
+ ```
612
+
613
+ Benefits of the hybrid caching system:
614
+ 1. Significantly reduces WhatsApp API calls for group metadata
615
+ 2. Improves response time for group-related features
616
+ 3. Persistent cache in MongoDB survives application restarts
617
+ 4. In-memory cache provides ultra-fast access for frequently used groups
618
+ 5. Automatic cache invalidation on group updates (members, settings, etc.)
619
+ 6. **Full multi-session support** - each session has isolated cache for group metadata
620
+ 7. Automatic cleanup when sessions are deleted or invalidated
621
+
622
+ #### Multi-Session Caching Architecture
623
+
624
+ The group metadata cache system is designed to support multiple WhatsApp sessions running simultaneously without any cache collision:
625
+
626
+ - Each session maintains its own isolated cache for group metadata
627
+ - Cache keys combine both session ID and group ID to ensure separation
628
+ - MongoDB storage includes session information for persistent separation
629
+ - Cache cleanup happens automatically when sessions are deleted or invalidated
630
+ - Memory and database efficiency through shared infrastructure
631
+
632
+ This approach ensures that in multi-session environments:
633
+ - Session A and Session B can both cache metadata for the same group ID without conflicts
634
+ - Each session gets its own view of its accessible groups
635
+ - Cache invalidation in one session doesn't affect other sessions
636
+
637
+ ## Utility Functions
638
+
639
+ ```javascript
640
+ // Create a delay
641
+ import { createDelay } from "wa-multi-mongodb";
642
+ await createDelay(2000); // wait 2 seconds
643
+
644
+ // Execute with timeout
645
+ import { withTimeout } from "wa-multi-mongodb";
646
+ try {
647
+ const result = await withTimeout(
648
+ functionThatMightTakeTooLong(),
649
+ 10000, // timeout in ms
650
+ "Operation timed out" // error message if timeout occurs
651
+ );
652
+ } catch (error) {
653
+ console.error(error.message);
654
+ }
655
+
656
+ // Attempt to reconnect a session
657
+ import { reconnect } from "wa-multi-mongodb";
658
+ try {
659
+ const reconnected = await reconnect("mysession");
660
+ console.log("Reconnect successful:", reconnected);
661
+ } catch (error) {
662
+ console.error("Reconnect failed:", error);
663
+ }
664
+ ```
665
+
666
+ ## LID PN Conversion Utilities (v3.10.4+)
667
+
668
+ WhatsApp has introduced LID (Linked ID) as a new anonymous identifier format to enhance user privacy. These utility functions help you convert between LID and Phone Number (PN) formats.
669
+
670
+ ### Understanding LID and PN
671
+
672
+ | Format | Description | Example |
673
+ |--------|-------------|---------|
674
+ | **LID** | Anonymous identifier (new format) | `1524746986546@lid` |
675
+ | **PN/JID** | Phone number based identifier (traditional) | `6281234567890@s.whatsapp.net` |
676
+
677
+ ### Converting LID to Phone Number
678
+
679
+ ```javascript
680
+ // Get phone number from LID
681
+ const result = await whatsapp.getPNForLID("mysession", "1524746986546@lid");
682
+ if (result.success && result.pn) {
683
+ console.log(`Phone number: ${result.pn}`);
684
+ } else {
685
+ console.log("Phone number not found:", result.error);
686
+ }
687
+
688
+ // Returns: { success: boolean, lid: string, pn: string | null, error?: string }
689
+ ```
690
+
691
+ ### Converting Phone Number to LID
692
+
693
+ ```javascript
694
+ // Get LID from phone number
695
+ const result = await whatsapp.getLIDForPN("mysession", "6281234567890");
696
+ if (result.success && result.lid) {
697
+ console.log(`LID: ${result.lid}`);
698
+ } else {
699
+ console.log("LID not found:", result.error);
700
+ }
701
+
702
+ // Returns: { success: boolean, pn: string, lid: string | null, error?: string }
703
+ ```
704
+
705
+ ### Smart Conversion (Auto-detect Format)
706
+
707
+ ```javascript
708
+ // Automatically convert any JID to phone number
709
+ const phoneNumber = await whatsapp.toPhoneNumber("mysession", anyJid);
710
+ if (phoneNumber) {
711
+ console.log(`Phone: ${phoneNumber}`);
712
+ }
713
+
714
+ // Automatically convert any JID to LID
715
+ const lid = await whatsapp.toLID("mysession", "6281234567890@s.whatsapp.net");
716
+ if (lid) {
717
+ console.log(`LID: ${lid}`);
718
+ }
719
+ ```
720
+
721
+ ### Get All Known LID Mappings
722
+
723
+ ```javascript
724
+ // Get all LID-PN mappings for a session
725
+ const mappings = await whatsapp.getAllLIDMappings("mysession");
726
+ for (const { lid, pn } of mappings) {
727
+ console.log(`${lid} => ${pn}`);
728
+ }
729
+ ```
730
+
731
+ ### Format Detection Helpers
732
+
733
+ ```javascript
734
+ // Check if JID is in LID format
735
+ if (whatsapp.isLIDFormat("1524746986546@lid")) {
736
+ console.log("This is an LID");
737
+ }
738
+
739
+ // Check if JID is in PN format
740
+ if (whatsapp.isPNFormat("6281234567890@s.whatsapp.net")) {
741
+ console.log("This is a phone number JID");
742
+ }
743
+ ```
744
+
745
+ ### Important Notes on LID Conversion
746
+
747
+ > ⚠️ **Limitations**:
748
+ > - `getPNForLID` may return `null` for new contacts or when WhatsApp hasn't provided the LID-PN mapping
749
+ > - LID mappings are only available for contacts that have already interacted with your session
750
+ > - WhatsApp is increasingly focusing on privacy, so not all LIDs have known phone numbers
751
+
752
+ | Function | Description |
753
+ |----------|-------------|
754
+ | `getPNForLID(sessionId, lid)` | Convert LID to phone number |
755
+ | `getLIDForPN(sessionId, pn)` | Convert phone number to LID |
756
+ | `toPhoneNumber(sessionId, jid)` | Smart convert any JID to PN |
757
+ | `toLID(sessionId, jid)` | Smart convert any JID to LID |
758
+ | `getAllLIDMappings(sessionId)` | Get all known LID-PN mappings |
759
+ | `isLIDFormat(jid)` | Check if JID is in LID format |
760
+ | `isPNFormat(jid)` | Check if JID is in PN format |
761
+
762
+ ## Complete Example: Auto-Reconnect Application
763
+
764
+
765
+ ```javascript
766
+ import * as whatsapp from "wa-multi-mongodb";
767
+ import { withTimeout } from "wa-multi-mongodb";
768
+ require('dotenv').config();
769
+
770
+ // Store connection status
771
+ const sessionStatus = {};
772
+
773
+ // Function to check and reconnect if disconnected
774
+ async function checkAndReconnect(sessionId) {
775
+ if (sessionStatus[sessionId] === 'disconnected') {
776
+ try {
777
+ const reconnected = await whatsapp.reconnect(sessionId);
778
+ if (reconnected) {
779
+ sessionStatus[sessionId] = 'connected';
780
+ console.log(`Session ${sessionId} reconnected`);
781
+ }
782
+ } catch (error) {
783
+ console.error(`Error during reconnect: ${error.message}`);
784
+ }
785
+ }
786
+ }
787
+
788
+ async function startApp() {
789
+ // MongoDB Configuration
790
+ await whatsapp.setMongoURI(process.env.MONGODB_URI);
791
+
792
+ // Event listeners
793
+ whatsapp.onQRUpdated(({ sessionId, qr }) => {
794
+ console.log(`QR Code for session ${sessionId}:`, qr);
795
+ });
796
+
797
+ whatsapp.onConnected((sessionId) => {
798
+ console.log(`Session ${sessionId} connected!`);
799
+ sessionStatus[sessionId] = 'connected';
800
+ });
801
+
802
+ whatsapp.onDisconnected((sessionId) => {
803
+ console.log(`Session ${sessionId} disconnected!`);
804
+ sessionStatus[sessionId] = 'disconnected';
805
+
806
+ // Try to reconnect after a few seconds
807
+ setTimeout(() => checkAndReconnect(sessionId), 10000);
808
+ });
809
+
810
+ // Message handler with error handling and group detection
811
+ whatsapp.onMessageReceived(async (msg) => {
812
+ try {
813
+ if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
814
+
815
+ const messageContent = msg.message?.conversation ||
816
+ msg.message?.extendedTextMessage?.text ||
817
+ "";
818
+
819
+ // Detect if message is from a group
820
+ const isGroup = msg.key.remoteJid.endsWith('@g.us');
821
+
822
+ // Using group metadata cache (v3.9.4+)
823
+ if (isGroup) {
824
+ const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid);
825
+ console.log(`Message from group: ${metadata.subject} with ${metadata.participants.length} members`);
826
+ }
827
+
828
+ // Mark message as read
829
+ try {
830
+ await whatsapp.readMessage({
831
+ sessionId: msg.sessionId,
832
+ key: msg.key,
833
+ });
834
+ } catch (error) {
835
+ if (error.message.includes('Connection Closed')) {
836
+ sessionStatus[msg.sessionId] = 'disconnected';
837
+ setTimeout(() => checkAndReconnect(msg.sessionId), 5000);
838
+ }
839
+ }
840
+
841
+ // Reply to messages containing "hello"
842
+ if (messageContent.toLowerCase().includes("hello")) {
843
+ // Show typing indicator (works in both private and group chats since v3.9.1+)
844
+ await whatsapp.sendTyping({
845
+ sessionId: msg.sessionId,
846
+ to: msg.key.remoteJid,
847
+ duration: 2000,
848
+ });
849
+
850
+ // Use different timeouts for groups vs private chats
851
+ const timeoutMs = isGroup ? 60000 : 30000;
852
+
853
+ try {
854
+ await withTimeout(
855
+ whatsapp.sendTextMessage({
856
+ sessionId: msg.sessionId,
857
+ to: msg.key.remoteJid,
858
+ text: "Hello! How can I help you?",
859
+ answering: msg,
860
+ }),
861
+ timeoutMs,
862
+ "Message sending timed out"
863
+ );
864
+ } catch (error) {
865
+ console.error("Error sending message:", error.message);
866
+ }
867
+ }
868
+
869
+ // Example command to get group info
870
+ if (messageContent === "!groupinfo" && isGroup) {
871
+ try {
872
+ // Force fetch fresh data
873
+ const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid, true);
874
+
875
+ const adminList = metadata.participants
876
+ .filter(p => p.admin)
877
+ .map(p => p.id.split('@')[0])
878
+ .join(", ");
879
+
880
+ const infoText = `*Group Info*\n` +
881
+ `Name: ${metadata.subject}\n` +
882
+ `Description: ${metadata.desc || 'None'}\n` +
883
+ `Members: ${metadata.participants.length}\n` +
884
+ `Admins: ${adminList}\n` +
885
+ `Created: ${new Date(metadata.creation * 1000).toLocaleString()}`;
886
+
887
+ await whatsapp.sendTextMessage({
888
+ sessionId: msg.sessionId,
889
+ to: msg.key.remoteJid,
890
+ text: infoText
891
+ });
892
+ } catch (error) {
893
+ console.error("Error getting group info:", error.message);
894
+ }
895
+ }
896
+ } catch (error) {
897
+ // Prevent application crash
898
+ console.error("Error processing message:", error.message);
899
+ }
900
+ });
901
+
902
+ // Load all sessions from MongoDB
903
+ await whatsapp.loadSessionsFromMongo();
904
+
905
+ // Create a main session if it doesn't exist
906
+ const mainSession = "main_session";
907
+ const existingSessions = await whatsapp.getAllSession();
908
+ if (!existingSessions.includes(mainSession)) {
909
+ await whatsapp.startSession(mainSession);
910
+ } else {
911
+ sessionStatus[mainSession] = 'connected';
912
+ }
913
+
914
+ // Check connections periodically
915
+ setInterval(() => {
916
+ Object.keys(sessionStatus).forEach(sid => {
917
+ checkAndReconnect(sid);
918
+ });
919
+ }, 5 * 60 * 1000); // check every 5 minutes
920
+ }
921
+
922
+ startApp().catch(err => {
923
+ console.error("Failed to start application:", err);
924
+ process.exit(1);
925
+ });
926
+ ```
927
+
928
+ ## Complete Example: Pairing Code with Auto-Reconnect (v3.9.6+)
929
+
930
+ ```javascript
931
+ import * as whatsapp from "wa-multi-mongodb";
932
+ require('dotenv').config();
933
+
934
+ // Store connection status
935
+ const sessionStatus = {};
936
+
937
+ async function startPairingApp() {
938
+ // MongoDB Configuration
939
+ await whatsapp.setMongoURI(process.env.MONGODB_URI);
940
+
941
+ // Event listeners for pairing code sessions
942
+ whatsapp.onConnected((sessionId) => {
943
+ console.log(`Pairing session ${sessionId} connected!`);
944
+ sessionStatus[sessionId] = 'connected';
945
+ });
946
+
947
+ whatsapp.onDisconnected(async (sessionId) => {
948
+ console.log(`Pairing session ${sessionId} disconnected!`);
949
+ sessionStatus[sessionId] = 'disconnected';
950
+
951
+ // Check if it's a pairing code session
952
+ const status = await whatsapp.getSessionStatus(sessionId);
953
+ if (status.sessionType === 'pairing') {
954
+ console.log(`Attempting to reconnect pairing session ${sessionId}...`);
955
+
956
+ // Auto-reconnect after 5 seconds
957
+ setTimeout(async () => {
958
+ try {
959
+ const reconnected = await whatsapp.reconnect(sessionId);
960
+ if (reconnected) {
961
+ console.log(`Pairing session ${sessionId} reconnected successfully!`);
962
+ sessionStatus[sessionId] = 'connected';
963
+ }
964
+ } catch (error) {
965
+ console.error(`Failed to reconnect pairing session ${sessionId}:`, error);
966
+ }
967
+ }, 5000);
968
+ }
969
+ });
970
+
971
+ // Message handler
972
+ whatsapp.onMessageReceived(async (msg) => {
973
+ if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
974
+
975
+ const messageContent = msg.message?.conversation ||
976
+ msg.message?.extendedTextMessage?.text ||
977
+ "";
978
+
979
+ console.log(`Message from ${msg.key.remoteJid}: ${messageContent}`);
980
+
981
+ // Auto-reply example
982
+ if (messageContent.toLowerCase().includes("ping")) {
983
+ await whatsapp.sendTextMessage({
984
+ sessionId: msg.sessionId,
985
+ to: msg.key.remoteJid,
986
+ text: "Pong! Message received from pairing session.",
987
+ answering: msg
988
+ });
989
+ }
990
+ });
991
+
992
+ // Load existing sessions from MongoDB
993
+ await whatsapp.loadSessionsFromMongo();
994
+
995
+ // Start a new pairing code session
996
+ const pairingSessionId = "pairing_session_1";
997
+ const yourPhoneNumber = "6281234567890"; // Replace with your phone number
998
+
999
+ try {
1000
+ await whatsapp.startSessionWithPairingCode(pairingSessionId, yourPhoneNumber, {
1001
+ onConnected: () => {
1002
+ console.log("Pairing session connected successfully!");
1003
+ sessionStatus[pairingSessionId] = 'connected';
1004
+ },
1005
+ onDisconnected: () => {
1006
+ console.log("Pairing session disconnected!");
1007
+ sessionStatus[pairingSessionId] = 'disconnected';
1008
+ },
1009
+ onPairingCode: (code) => {
1010
+ console.log("\n" + "=".repeat(50));
1011
+ console.log("📱 PAIRING CODE:", code);
1012
+ console.log("=".repeat(50));
1013
+ console.log("1. Open WhatsApp on your phone");
1014
+ console.log("2. Go to Settings > Linked Devices");
1015
+ console.log("3. Tap 'Link a Device'");
1016
+ console.log("4. Tap 'Link with phone number instead'");
1017
+ console.log("5. Enter the pairing code above");
1018
+ console.log("=".repeat(50) + "\n");
1019
+ }
1020
+ });
1021
+
1022
+ sessionStatus[pairingSessionId] = 'connecting';
1023
+ } catch (error) {
1024
+ console.error("Error starting pairing session:", error);
1025
+ }
1026
+
1027
+ // Periodic health check for pairing sessions
1028
+ setInterval(async () => {
1029
+ const pairingSessions = whatsapp.getPairingCodeSessions();
1030
+ console.log(`Active pairing sessions: ${pairingSessions.length}`);
1031
+
1032
+ // Check each pairing session status
1033
+ for (const sessionId of pairingSessions) {
1034
+ const status = await whatsapp.getSessionStatus(sessionId);
1035
+ console.log(`Session ${sessionId}: ${status.connected ? 'Connected' : 'Disconnected'}`);
1036
+
1037
+ if (!status.connected && sessionStatus[sessionId] === 'connected') {
1038
+ console.log(`Detected disconnection for ${sessionId}, attempting reconnect...`);
1039
+ try {
1040
+ await whatsapp.reconnect(sessionId);
1041
+ } catch (error) {
1042
+ console.error(`Reconnect failed for ${sessionId}:`, error);
1043
+ }
1044
+ }
1045
+ }
1046
+ }, 30000); // Check every 30 seconds
1047
+
1048
+ // Bulk reconnect utility
1049
+ setInterval(async () => {
1050
+ try {
1051
+ await whatsapp.reconnectAllPairingCodeSessions();
1052
+ console.log("Bulk reconnect completed for all pairing sessions");
1053
+ } catch (error) {
1054
+ console.error("Bulk reconnect failed:", error);
1055
+ }
1056
+ }, 10 * 60 * 1000); // Every 10 minutes
1057
+
1058
+ console.log("Pairing code application started!");
1059
+ }
1060
+
1061
+ startPairingApp().catch(err => {
1062
+ console.error("Failed to start pairing application:", err);
1063
+ process.exit(1);
1064
+ });
1065
+ ```
1066
+
1067
+ ## Frontend Integration Example: QR Code Display (v3.9.6+)
1068
+
1069
+ ```javascript
1070
+ // React.js example for QR code display
1071
+ import React, { useState, useEffect } from 'react';
1072
+ import QRCode from 'qrcode';
1073
+ import * as whatsapp from "wa-multi-mongodb";
1074
+
1075
+ function WhatsAppQRComponent() {
1076
+ const [qrDataURL, setQrDataURL] = useState('');
1077
+ const [sessionStatus, setSessionStatus] = useState('disconnected');
1078
+
1079
+ useEffect(() => {
1080
+ // Initialize WhatsApp connection
1081
+ const initWhatsApp = async () => {
1082
+ await whatsapp.setMongoURI(process.env.REACT_APP_MONGODB_URI);
1083
+
1084
+ // Start session with simplified QR callback
1085
+ await whatsapp.startSession("frontend_session", {
1086
+ printQR: false, // Don't print in terminal
1087
+ onQRUpdated: async (qr) => {
1088
+ // QR data is raw and ready for frontend use
1089
+ try {
1090
+ const qrDataURL = await QRCode.toDataURL(qr);
1091
+ setQrDataURL(qrDataURL);
1092
+ } catch (error) {
1093
+ console.error('Error generating QR code:', error);
1094
+ }
1095
+ },
1096
+ onConnected: () => {
1097
+ setSessionStatus('connected');
1098
+ setQrDataURL(''); // Clear QR when connected
1099
+ },
1100
+ onDisconnected: () => {
1101
+ setSessionStatus('disconnected');
1102
+ }
1103
+ });
1104
+ };
1105
+
1106
+ initWhatsApp().catch(console.error);
1107
+ }, []);
1108
+
1109
+ return (
1110
+ <div className="whatsapp-qr">
1111
+ <h2>WhatsApp Connection</h2>
1112
+ <div className="status">
1113
+ Status: <span className={sessionStatus}>{sessionStatus}</span>
1114
+ </div>
1115
+
1116
+ {qrDataURL && (
1117
+ <div className="qr-container">
1118
+ <p>Scan this QR code with WhatsApp:</p>
1119
+ <img src={qrDataURL} alt="WhatsApp QR Code" />
1120
+ </div>
1121
+ )}
1122
+
1123
+ {sessionStatus === 'connected' && (
1124
+ <div className="connected">
1125
+ <p>✅ WhatsApp connected successfully!</p>
1126
+ </div>
1127
+ )}
1128
+ </div>
1129
+ );
1130
+ }
1131
+
1132
+ export default WhatsAppQRComponent;
1133
+ ```
1134
+
1135
+ ## Best Practices for Group Chats
1136
+
1137
+ 1. **Auto Group Detection**: Since v3.9.0, the library automatically detects if a chat is a group based on its JID format
1138
+ 2. **Typing Indicators**: Typing indicators now work in both private and group chats (v3.9.1+)
1139
+ 3. **Longer Timeouts**: Use longer timeouts when sending media to groups (60+ seconds)
1140
+ 4. **Handle Errors**: Implement retry mechanisms for failed group messages
1141
+ 5. **Announcement Channels**: Groups with announcement channels may trigger `MessageCounterError` (handled automatically in v3.9.1+)
1142
+ 6. **Retry Strategy**: For announcement channel groups, the library will automatically retry sending messages up to 3 times with increasing delays
1143
+ 7. **Group Metadata Caching**: Use the hybrid caching system (v3.9.4+) to improve performance when working with groups
1144
+ 8. **New `sendTextMessageWithMention` Function**: Comprehensive mention functionality for WhatsApp messages (v3.9.8+)
1145
+
1146
+ ## WhatsApp Limitations
1147
+
1148
+ 1. **Media Transfer**: Large media files to groups may take longer or timeout
1149
+ 2. **Connection Stability**: Auto-reconnect may be needed in production apps
1150
+ 3. **Announcement Channels**: Some groups with announcement channels may still fail after multiple retries
1151
+
1152
+ ## Changelog
1153
+
1154
+ ### v3.11.0 (latest)
1155
+ - **New `downloadMediaMessage` Function**: Download incoming WhatsApp media messages directly as a `Buffer`
1156
+ - Supports images, videos, documents, audio, stickers, and other Baileys-supported media messages
1157
+ - Uses the active session for media reupload requests when WhatsApp media links have expired
1158
+ - Useful for cloud uploads, custom storage, media processing, forwarding workflows, and API responses
1159
+ - Throws clear `WhatsappError` messages when the session is missing, message is empty, or media download fails
1160
+ - **Proxy Support**: Added proxy support for WebSocket and media connections
1161
+
1162
+ ### v3.10.4
1163
+ - **Custom Browser Configuration**: Added ability to customize browser type and name for WhatsApp connection
1164
+ - New `browserType` option: Choose from "ubuntu" (default), "macOS", "windows", or "appropriate"
1165
+ - New `browserName` option: Customize the app name displayed in WhatsApp's "Linked Devices" list
1166
+ - Works with both `startSession()` and `startSessionWithPairingCode()` methods
1167
+ - Default behavior unchanged (Ubuntu browser with "Chrome" name)
1168
+ - **LID PN Conversion Utilities**: Added comprehensive utilities for converting between LID (Linked ID) and Phone Number formats
1169
+ - New `getPNForLID(sessionId, lid)` function to convert LID to phone number
1170
+ - New `getLIDForPN(sessionId, pn)` function to convert phone number to LID
1171
+ - New `toPhoneNumber(sessionId, jid)` smart conversion function (auto-detects format)
1172
+ - New `toLID(sessionId, jid)` smart conversion function (auto-detects format)
1173
+ - New `getAllLIDMappings(sessionId)` function to get all known LID-PN mappings
1174
+ - New `isLIDFormat(jid)` and `isPNFormat(jid)` helper functions
1175
+ - Uses Baileys' internal `signalRepository.lidMapping` for conversions
1176
+
1177
+
1178
+ ### v3.10.2
1179
+ - **Fixed Group JID Validation**: Resolved issue with group chat validation
1180
+ - Fixed `isValidJid()` function to properly validate group JIDs without requiring dash (-) character
1181
+ - Some WhatsApp group IDs don't use dash format, validation now accepts all valid group formats
1182
+ - Error "Invalid JID format: [group-id]@g.us" has been resolved
1183
+
1184
+ ### v3.10.1
1185
+ - **Using Baileys New Version (7.x.x)**: Update & support function with latest baileys version
1186
+ - **Added @lid Format Support**: Full support for WhatsApp's new @lid identifier format
1187
+ - Updated `phoneToJid()` function to handle both @s.whatsapp.net and @lid formats
1188
+ - Enhanced all message sending functions with JID validation:
1189
+ - `sendTextMessage()`
1190
+ - `sendTextMessageWithMention()`
1191
+ - `sendMedia()`
1192
+ - `sendVoiceNote()`
1193
+ - `sendSticker()`
1194
+ - `sendTyping()`
1195
+ - No breaking changes - existing @s.whatsapp.net format continues to work
1196
+ - Automatic detection and handling of @lid format to prevent 404 errors
1197
+ - Added comprehensive error handling for invalid JID formats
1198
+
1199
+ ### v3.9.8
1200
+ ### Added
1201
+ - **New `sendTextMessageWithMention` Function**: Comprehensive mention functionality for WhatsApp messages
1202
+ - Support for mentioning single or multiple users in group chats
1203
+ - Automatic JID format validation and conversion
1204
+ - Full retry mechanism with error handling for mention messages
1205
+ - Support for quoted messages with mentions
1206
+ - Compatible with both group and private chat mentions
1207
+ - Enhanced timeout handling for mention messages
1208
+
1209
+ ### v3.9.7
1210
+ - **Enhanced Message Processing for Group Chats**: Fixed issues with group message handling and improved message processing architecture
1211
+ - **Multiple Message Processing**: Event handler `messages.upsert` now processes all messages in array instead of only the first message
1212
+ - **Improved Message Filtering**: Added intelligent filtering to skip protocol messages and empty messages while preserving valid group messages
1213
+ - **Enhanced Group Message Support**: Better detection and processing of group messages with participant information
1214
+ - **Group vs Private Chat Detection**: Better differentiation between group and private messages
1215
+ - **Improved Error Recovery**: Better error handling without changing existing error patterns
1216
+
1217
+ ### v3.9.6
1218
+ - **Enhanced Pairing Code Support**: Added comprehensive pairing code session management with auto-reconnect capabilities
1219
+ - New `startSessionWithPairingCode()` function for creating sessions using pairing codes
1220
+ - Intelligent session tracking system that preserves pairing code session data across disconnections
1221
+ - Enhanced auto-reconnect mechanism that differentiates between QR code and pairing code sessions
1222
+ - Session persistence in MongoDB for pairing code sessions to enable seamless reconnection
1223
+ - **New Utility Functions for Session Management**:
1224
+ - `reconnect(sessionId)` - Manual reconnection for any session type
1225
+ - `reconnectAllPairingCodeSessions()` - Bulk reconnection for all tracked pairing code sessions
1226
+ - `getPairingCodeSessions()` - Get list of all pairing code session IDs
1227
+ - `getSessionStatus(sessionId)` - Get detailed session status information including session type
1228
+ - **QR Data Raw for Frontend Integration**: Simplified QR handling optimized for frontend development
1229
+ - Cleaned up QR callback to provide only essential QR data raw for frontend processing
1230
+ - Removed unnecessary QR string complexity from callbacks for better performance
1231
+ - QR data can be directly used with any frontend QR code library (React, Vue, Angular, etc.)
1232
+ - Terminal QR display handled automatically via `printQR` option
1233
+ - **Breaking Changes**:
1234
+ - Simplified `onQRUpdated` callback signature: removed `qrString` parameter, now only provides raw QR data
1235
+ - Session-level `onQRUpdated` option simplified from `(qr, qrString)` to `(qr)` only
1236
+ - **Enhanced Session Persistence**: Pairing code sessions maintain authentication state in MongoDB during disconnections
1237
+ - **Improved Error Handling**: Better error recovery and automatic session restoration for pairing code sessions
1238
+
1239
+ ### v3.9.5
1240
+ - New `deleteMessage()` function for deleting messages
1241
+ - Support for deleting both own messages and others' messages (requires admin permissions in groups)
1242
+ - Auto-delete message utility function example
1243
+
1244
+ ### v3.9.4
1245
+ - Updated baileys dependency to v6.7.18
1246
+ - Added hybrid caching system for group metadata (NodeCache + MongoDB)
1247
+ - Improved group operations performance with automatic caching
1248
+ - New functions for group metadata management:
1249
+ - `getGroupMetadata()` - Get metadata with automatic caching
1250
+ - `setGroupCacheConfig()` - Configure cache TTL and check periods
1251
+ - `clearGroupMetadataCache()` - Clear specific group metadata
1252
+ - `clearAllGroupMetadataCache()` - Clear all cached group metadata
1253
+
1254
+ ### v3.9.3
1255
+ - Updated QR code implementation for better display in terminal
1256
+ - Replaced deprecated `printQRInTerminal` option with `qrcode` library implementation
1257
+ - Added support for latest Baileys version
1258
+
1259
+ ### v3.9.2
1260
+ - Updated Baileys dependency to v6.7.17 for improved stability and compatibility
1261
+
1262
+ ### v3.9.1
1263
+ - Added special handling for `MessageCounterError` in group chats with announcement channels
1264
+ - Implemented automatic retry mechanism for messages to announcement channels
1265
+ - Enhanced error reporting for group chat issues
1266
+ - Fixed typing indicators to work properly in group chats
1267
+
1268
+ ### v3.9.0
1269
+ - Added automatic group chat detection - no need to specify `isGroup: true` parameter
1270
+ - Improved message sending reliability for group chats
1271
+ - Enhanced error handling with better timeout management
1272
+ - Implemented automatic format detection for group IDs
1273
+
1274
+ ### v3.8.1
1275
+ - Updated baileys to v6.7.16
1276
+ - Improved MongoDB integration
1277
+ - Enhanced error handling and connection stability
1278
+
1279
+ ### v3.8.0
1280
+ - Package renamed from wa-multi-session to wa-multi-mongodb
1281
+ - Added MongoDB session management
1282
+ - Fixed connection and authentication issues
1283
+
1284
+ ### v3.7.0
1285
+ - Upgraded to baileys v6.7.9
1286
+ - Fixed phone number validation
1287
+ - Removed registered phone number validation requirement
1288
+
1289
+ ## Links
1290
+
1291
+ - [GitHub Repository](https://github.com/wahdalo/wa-multi-mongodb)
1292
+ - [Issue Tracker](https://github.com/wahdalo/wa-multi-mongodb/issues)
1293
+ - [Original wa-multi-session](https://github.com/mimamch/wa-multi-session)
1294
+ - [Baileys Library](https://github.com/WhiskeySockets/Baileys)
1295
+
1296
+ ## Author
1297
+
1298
+ - [@wahdalo](https://github.com/wahdalo)
1299
+
1300
+ ## License
1301
+
1302
+ ISC