easy-connect-wpp 1.3.5 → 1.3.7

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 ADDED
@@ -0,0 +1,864 @@
1
+ # easy-connect-wpp
2
+
3
+ Unofficial WhatsApp Client for Node.js powered by Baileys. Build scalable, event-driven WhatsApp integrations with full message support and automated reconnection.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/easy-connect-wpp.svg)](https://www.npmjs.com/package/easy-connect-wpp)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
+ [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
8
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
9
+
10
+ ## ⚠️ Disclaimer
11
+
12
+ This is an **unofficial** WhatsApp client library. It is not affiliated with WhatsApp Inc. or Meta Platforms. Use at your own risk and ensure compliance with WhatsApp's Terms of Service.
13
+
14
+ ## Features
15
+
16
+ ✨ **Unofficial WhatsApp Client** — Reverse-engineered Baileys library
17
+ 🚀 **Automatic Initialization** — Quick setup with QR code or pairing code
18
+ 🎧 **Event-Driven Architecture** — Familiar callback pattern for all events
19
+ 📨 **Full Message Support** — Text, images, videos, audio, documents, location, contacts, reactions
20
+ ✅ **Type-Safe** — Full TypeScript support with comprehensive type definitions
21
+ 🔄 **Auto-Reconnect** — Automatic reconnection with exponential backoff
22
+ 👥 **Group Management** — Create, update, and manage WhatsApp groups
23
+ 📊 **Session Management** — Persistent session storage and restoration
24
+ 🛡️ **License Validation** — Built-in license verification system
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install easy-connect-wpp
30
+ ```
31
+
32
+ ### Prerequisites
33
+
34
+ - **Node.js** 18+
35
+ - **Valid WhatsApp Account** (with verified phone number)
36
+ - **Modern Browser** (for QR code scanning)
37
+
38
+ ## Quick Start
39
+
40
+ ```typescript
41
+ import { SessionManager } from 'easy-connect-wpp';
42
+ import { Session } from 'easy-connect-wpp/models/session';
43
+
44
+ // 1. Create session
45
+ const session: Session = {
46
+ session: 'my_session',
47
+ phoneNumber: '5511999999999',
48
+ licensePath: './license.json',
49
+ syncFullHistory: false,
50
+ pairingCode: false, // set to true for pairing code authentication
51
+ qrCode: true,
52
+ qrPrintTerminal: true,
53
+ };
54
+
55
+ const manager = new SessionManager();
56
+
57
+ // 2. Register listeners
58
+ manager.onQrCode((qrCode) => {
59
+ console.log('Scan QR code:', qrCode);
60
+ });
61
+
62
+ manager.onPairingCode((code) => {
63
+ console.log('Pairing code:', code);
64
+ });
65
+
66
+ manager.onMessage(async (message) => {
67
+ console.log(`Message from ${message.from}: ${message.content.conversation}`);
68
+ });
69
+
70
+ manager.onConnectionStatus((status) => {
71
+ console.log(`Connection status: ${status}`);
72
+ });
73
+
74
+ // 3. Create session
75
+ await manager.createSession(session);
76
+ ```
77
+
78
+ ## API Reference
79
+
80
+ ### SessionManager Constructor
81
+
82
+ ```typescript
83
+ const manager = new SessionManager();
84
+ ```
85
+
86
+ ### Session Configuration
87
+
88
+ ```typescript
89
+ interface Session {
90
+ session: string; // Unique session identifier
91
+ phoneNumber: string; // WhatsApp phone number (with country code)
92
+ licensePath: string; // Path to license.json file
93
+ syncFullHistory?: boolean; // Sync full chat history (default: false)
94
+ pairingCode?: boolean; // Use pairing code instead of QR (default: false)
95
+ qrCode?: boolean; // Enable QR code (default: true)
96
+ qrPrintTerminal?: boolean; // Print QR in terminal (default: false)
97
+ maxRetries?: number; // Max reconnection attempts (default: 10)
98
+ version?: [number, number, number]; // WA version override (optional)
99
+ }
100
+ ```
101
+
102
+ ### Methods
103
+
104
+ #### `createSession(session: Session): Promise<void>`
105
+
106
+ Initialize and connect WhatsApp session.
107
+
108
+ ```typescript
109
+ await manager.createSession(session);
110
+ ```
111
+
112
+ ### Sending Messages
113
+
114
+ #### `sendText(identifier: string, message: string): Promise<Response>`
115
+
116
+ Send a text message.
117
+
118
+ ```typescript
119
+ const phone = '5511999999999';
120
+ const message = 'Hello!';
121
+ const response = await manager.sendText(phone, message);
122
+ if (response.status === 200) {
123
+ console.log('Message sent:', response.id);
124
+ }
125
+ ```
126
+
127
+ #### `sendTextEdit(identifier: string, message: string, messageId: string): Promise<Response>`
128
+
129
+ Edit a previously sent text message.
130
+
131
+ ```typescript
132
+ const phone = '5511999999999';
133
+ const message = 'Hello (edited)';
134
+ const messageId = '3AF91FDF7463FFB0CFCA';
135
+ const response = await manager.sendTextEdit(phone, message, messageId);
136
+ if (response.status === 200) {
137
+ console.log('Message edited:', response.id);
138
+ }
139
+ ```
140
+
141
+ #### `sendTextReply(identifier: string, message: string, options: Option): Promise<Response>`
142
+
143
+ Send a reply to a specific message.
144
+
145
+ ```typescript
146
+ const phone = '5511999999999';
147
+ const message = 'Thanks!';
148
+ const options = {
149
+ content: JSON.stringify({
150
+ id: 'original_message_id',
151
+ fromMe: false,
152
+ remoteJid: 'sender@s.whatsapp.net',
153
+ content: originalMessageContent,
154
+ }),
155
+ };
156
+ const response = await manager.sendTextReply(phone, message, options);
157
+ if (response.status === 200) {
158
+ console.log('Reply sent:', response.id);
159
+ }
160
+ ```
161
+
162
+ #### `sendTextStatus(identifiers: string[], message: string, backgroundColor?: string): Promise<Response>`
163
+
164
+ Send a text status to multiple contacts.
165
+
166
+ ```typescript
167
+ const phones = ['5511999999999', '5511988888888'];
168
+ const message = 'My status!';
169
+ const backgroundColor = '#25D366';
170
+ const response = await manager.sendTextStatus(phones, message, backgroundColor);
171
+ if (response.status === 200) {
172
+ console.log('Status sent');
173
+ }
174
+ ```
175
+
176
+ #### `sendImage(identifier: string, content: string, option: ImageOption): Promise<Response>`
177
+
178
+ Send an image with optional caption.
179
+
180
+ ```typescript
181
+ const phone = '5511999999999';
182
+ const content = 'https://example.com/image.jpg';
183
+ const option = { caption: 'Check this out!' };
184
+ const response = await manager.sendImage(phone, content, option);
185
+ if (response.status === 200) {
186
+ console.log('Image sent:', response.id);
187
+ }
188
+ ```
189
+
190
+ #### `sendVideo(identifier: string, content: string, option: VideoOption): Promise<Response>`
191
+
192
+ Send a video with optional caption.
193
+
194
+ ```typescript
195
+ const phone = '5511999999999';
196
+ const content = 'https://example.com/video.mp4';
197
+ const option = { caption: 'My video', ptv: false };
198
+ const response = await manager.sendVideo(phone, content, option);
199
+ if (response.status === 200) {
200
+ console.log('Video sent:', response.id);
201
+ }
202
+ ```
203
+
204
+ #### `sendAudio(identifier: string, content: string, option?: AudioOption): Promise<Response>`
205
+
206
+ Send an audio file.
207
+
208
+ ```typescript
209
+ const phone = '5511999999999';
210
+ const content = 'https://example.com/audio.mp3';
211
+ const option = { mimetype: 'audio/mpeg' };
212
+ const response = await manager.sendAudio(phone, content, option);
213
+ if (response.status === 200) {
214
+ console.log('Audio sent:', response.id);
215
+ }
216
+ ```
217
+
218
+ #### `sendVoice(identifier: string, content: string, option?: AudioOption): Promise<Response>`
219
+
220
+ Send a voice message.
221
+
222
+ ```typescript
223
+ const phone = '5511999999999';
224
+ const content = 'https://example.com/voice.ogg';
225
+ const response = await manager.sendVoice(phone, content);
226
+ if (response.status === 200) {
227
+ console.log('Voice sent:', response.id);
228
+ }
229
+ ```
230
+
231
+ #### `sendDocument(identifier: string, content: string, option: FileOption): Promise<Response>`
232
+
233
+ Send a document with optional filename.
234
+
235
+ ```typescript
236
+ const phone = '5511999999999';
237
+ const content = 'https://example.com/document.pdf';
238
+ const option = { filename: 'Report.pdf', caption: 'Here is your report' };
239
+ const response = await manager.sendDocument(phone, content, option);
240
+ if (response.status === 200) {
241
+ console.log('Document sent:', response.id);
242
+ }
243
+ ```
244
+
245
+ #### `sendLocation(identifier: string, latitude: number, longitude: number): Promise<Response>`
246
+
247
+ Send a location.
248
+
249
+ ```typescript
250
+ const phone = '5511999999999';
251
+ const latitude = -23.5505;
252
+ const longitude = -46.6333;
253
+ const response = await manager.sendLocation(phone, latitude, longitude);
254
+ if (response.status === 200) {
255
+ console.log('Location sent:', response.id);
256
+ }
257
+ ```
258
+
259
+ #### `sendContact(identifier: string, contactName: string, contactPhone: string, contactPhotoUrl?: string): Promise<Response>`
260
+
261
+ Send a contact card.
262
+
263
+ ```typescript
264
+ const phone = '5511999999999';
265
+ const contactName = 'John Doe';
266
+ const contactPhone = '5511988888888';
267
+ const contactPhotoUrl = null;
268
+ const response = await manager.sendContact(phone, contactName, contactPhone, contactPhotoUrl);
269
+ if (response.status === 200) {
270
+ console.log('Contact sent:', response.id);
271
+ }
272
+ ```
273
+
274
+ #### `sendForward(identifier: string, options: Option): Promise<Response>`
275
+
276
+ Forward a message.
277
+
278
+ ```typescript
279
+ const phone = '5511999999999';
280
+ const options = {
281
+ content: JSON.stringify({
282
+ id: 'original_message_id',
283
+ fromMe: false,
284
+ remoteJid: 'sender@s.whatsapp.net',
285
+ content: messageContent,
286
+ }),
287
+ };
288
+ const response = await manager.sendForward(phone, options);
289
+ if (response.status === 200) {
290
+ console.log('Message forwarded:', response.id);
291
+ }
292
+ ```
293
+
294
+ #### `sendReaction(identifier: string, reaction: string, messageId: string): Promise<Response>`
295
+
296
+ Send a reaction emoji to a message.
297
+
298
+ ```typescript
299
+ const phone = '5511999999999';
300
+ const reaction = '👍';
301
+ const messageId = '3AF91FDF7463FFB0CFCA';
302
+ const response = await manager.sendReaction(phone, reaction, messageId);
303
+ if (response.status === 200) {
304
+ console.log('Reaction sent:', response.id);
305
+ }
306
+ ```
307
+
308
+ #### `deleteMessageForEveryone(identifier: string, messageId: string): Promise<Response>`
309
+
310
+ Delete a message for everyone.
311
+
312
+ ```typescript
313
+ const phone = '5511999999999';
314
+ const messageId = '3AF91FDF7463FFB0CFCA';
315
+ const response = await manager.deleteMessageForEveryone(phone, messageId);
316
+ if (response.status === 200) {
317
+ console.log('Message deleted for everyone');
318
+ }
319
+ ```
320
+
321
+ #### `deleteMessageForMe(identifier: string, messageId: string): Promise<Response>`
322
+
323
+ Delete a message only for you.
324
+
325
+ ```typescript
326
+ const phone = '5511999999999';
327
+ const messageId = '3AF91FDF7463FFB0CFCA';
328
+ const response = await manager.deleteMessageForMe(phone, messageId);
329
+ if (response.status === 200) {
330
+ console.log('Message deleted for you');
331
+ }
332
+ ```
333
+
334
+ #### `markReadAll(identifier: string): Promise<Response>`
335
+
336
+ Mark all messages in a chat as read.
337
+
338
+ ```typescript
339
+ const phone = '5511999999999';
340
+ const response = await manager.markReadAll(phone);
341
+ if (response.status === 200) {
342
+ console.log('All messages marked as read');
343
+ }
344
+ ```
345
+
346
+ #### `setPresence(identifier: string, type: 'unavailable' | 'available' | 'composing' | 'recording' | 'paused'): Promise<Response>`
347
+
348
+ Set presence status (typing indicator).
349
+
350
+ ```typescript
351
+ const phone = '5511999999999';
352
+ const type = 'composing';
353
+ const response = await manager.setPresence(phone, type);
354
+ if (response.status === 200) {
355
+ console.log('Presence updated');
356
+ }
357
+ ```
358
+
359
+ ### Group Management
360
+
361
+ #### `groupCreate(name: string, description: string, type?: 'group' | 'community'): Promise<Response>`
362
+
363
+ Create a group or community.
364
+
365
+ ```typescript
366
+ const name = 'My Group';
367
+ const description = 'Group description';
368
+ const type = 'group';
369
+ const result = await manager.groupCreate(name, description, type);
370
+ if (result.status === 200) {
371
+ console.log('Group created:', result.content.id);
372
+ }
373
+ ```
374
+
375
+ #### `groupUpdate(identifier: string, name: string, description: string, type?: 'group' | 'community'): Promise<Response>`
376
+
377
+ Update group name and description.
378
+
379
+ ```typescript
380
+ const groupId = 'group_id_here';
381
+ const name = 'New Name';
382
+ const description = 'New Description';
383
+ const response = await manager.groupUpdate(groupId, name, description, 'group');
384
+ if (response.status === 200) {
385
+ console.log('Group updated');
386
+ }
387
+ ```
388
+
389
+ #### `groupUpdateSettings(identifier: string, type: 'group' | 'community', setting: 'announcement' | 'not_announcement' | 'locked' | 'unlocked'): Promise<Response>`
390
+
391
+ Update group settings.
392
+
393
+ ```typescript
394
+ const groupId = 'group_id_here';
395
+ const type = 'group';
396
+ const setting = 'announcement';
397
+ const response = await manager.groupUpdateSettings(groupId, type, setting);
398
+ if (response.status === 200) {
399
+ console.log('Settings updated');
400
+ }
401
+ ```
402
+
403
+ #### `groupParticipantAdd(identifier: string, participant: string): Promise<Response>`
404
+
405
+ Add a participant to a group.
406
+
407
+ ```typescript
408
+ const groupId = 'group_id_here';
409
+ const participant = '5511999999999';
410
+ const response = await manager.groupParticipantAdd(groupId, participant);
411
+ if (response.status === 200) {
412
+ console.log('Participant added');
413
+ }
414
+ ```
415
+
416
+ #### `groupParticipantRemove(identifier: string, participant: string): Promise<Response>`
417
+
418
+ Remove a participant from a group.
419
+
420
+ ```typescript
421
+ const groupId = 'group_id_here';
422
+ const participant = '5511999999999';
423
+ const response = await manager.groupParticipantRemove(groupId, participant);
424
+ if (response.status === 200) {
425
+ console.log('Participant removed');
426
+ }
427
+ ```
428
+
429
+ #### `getGroupMetadata(identifier: string): Promise<Response>`
430
+
431
+ Get group information.
432
+
433
+ ```typescript
434
+ const groupId = 'group_id_here';
435
+ const response = await manager.getGroupMetadata(groupId);
436
+ if (response.status === 200) {
437
+ const metadata = response.content;
438
+ console.log('Group name:', metadata.subject);
439
+ }
440
+ ```
441
+
442
+ #### `getGroupInviteCode(identifier: string): Promise<Response>`
443
+
444
+ Get group invite code and link.
445
+
446
+ ```typescript
447
+ const groupId = 'group_id_here';
448
+ const response = await manager.getGroupInviteCode(groupId);
449
+ if (response.status === 200) {
450
+ const { code, url } = response.content;
451
+ console.log('Invite link:', url);
452
+ }
453
+ ```
454
+
455
+ ### Media Management
456
+
457
+ #### `downloadMedia(options: Option): Promise<Response>`
458
+
459
+ Download media from WhatsApp (returns buffer).
460
+
461
+ ```typescript
462
+ const options = { content: JSON.stringify(messageObject) };
463
+ const response = await manager.downloadMedia(options);
464
+ if (response.status === 200) {
465
+ const buffer = response.content;
466
+ console.log('Media downloaded:', buffer.length, 'bytes');
467
+ }
468
+ ```
469
+
470
+ #### `downloadMediaAndSave(options: Option, directory: string): Promise<Response>`
471
+
472
+ Download media and save to file.
473
+
474
+ ```typescript
475
+ const options = { content: JSON.stringify(messageObject) };
476
+ const directory = './downloads/media.jpg';
477
+ const response = await manager.downloadMediaAndSave(options, directory);
478
+ if (response.status === 200) {
479
+ console.log('Media saved to:', directory);
480
+ }
481
+ ```
482
+
483
+ ### Profile Management
484
+
485
+ #### `getPicture(identifier: string): Promise<Response>`
486
+
487
+ Get profile picture URL.
488
+
489
+ ```typescript
490
+ const phone = '5511999999999';
491
+ const response = await manager.getPicture(phone);
492
+ if (response.status === 200) {
493
+ const picUrl = response.content;
494
+ console.log('Profile picture:', picUrl);
495
+ }
496
+ ```
497
+
498
+ #### `updateProfilePicture(identifier: string, content: string): Promise<Response>`
499
+
500
+ Update profile picture from URL, buffer, or stream.
501
+
502
+ ```typescript
503
+ const phone = '5511999999999';
504
+ const content = 'https://example.com/profile.jpg';
505
+ const response = await manager.updateProfilePicture(phone, content);
506
+ if (response.status === 200) {
507
+ console.log('Profile picture updated');
508
+ }
509
+ ```
510
+
511
+ #### `removeProfilePicture(identifier: string): Promise<Response>`
512
+
513
+ Remove profile picture.
514
+
515
+ ```typescript
516
+ const phone = '5511999999999';
517
+ const response = await manager.removeProfilePicture(phone);
518
+ if (response.status === 200) {
519
+ console.log('Profile picture removed');
520
+ }
521
+ ```
522
+
523
+ #### `onWhatsApp(identifier: string): Promise<Response>`
524
+
525
+ Check if a phone number is registered on WhatsApp.
526
+
527
+ ```typescript
528
+ const phone = '5511999999999';
529
+ const response = await manager.onWhatsApp(phone);
530
+ if (response.exists) {
531
+ console.log('Number is on WhatsApp');
532
+ } else {
533
+ console.log('Number not found on WhatsApp');
534
+ }
535
+ ```
536
+
537
+ ### Event Listeners
538
+
539
+ #### `onMessage(callback: (message: EventResponse) => void): void`
540
+
541
+ Listen for incoming messages.
542
+
543
+ ```typescript
544
+ manager.onMessage((message) => {
545
+ console.log(`Type: ${message.type}`);
546
+ console.log(`From: ${message.from}`);
547
+ console.log(`IsGroup: ${message.isgroup}`);
548
+
549
+ if (message.type === 'conversation') {
550
+ console.log(`Text: ${message.content.conversation}`);
551
+ } else if (message.type === 'imageMessage') {
552
+ console.log(`Image caption: ${message.content.imageMessage?.caption}`);
553
+ }
554
+ });
555
+ ```
556
+
557
+ #### `onMessageAck(callback: (ack: any) => void): void`
558
+
559
+ Listen for message acknowledgments.
560
+
561
+ ```typescript
562
+ manager.onMessageAck((ack) => {
563
+ // Status: PENDING (1), SERVER_ACK (2), DELIVERY_ACK (3), READ (4), PLAYED (5)
564
+ console.log(`Message ${ack.id}: ${ack.status}`);
565
+ });
566
+ ```
567
+
568
+ #### `onMessageUpdate(callback: (message: any) => void): void`
569
+
570
+ Listen for message updates.
571
+
572
+ ```typescript
573
+ manager.onMessageUpdate((message) => {
574
+ console.log('Message updated:', message);
575
+ });
576
+ ```
577
+
578
+ #### `onConnectionStatus(callback: (status: ConnectionState) => void): void`
579
+
580
+ Listen for connection changes.
581
+
582
+ ```typescript
583
+ manager.onConnectionStatus((status) => {
584
+ console.log(`Connection: ${status}`);
585
+ // ConnectionState: NOT_LOGGED, CONNECTING, CONNECTED, DISCONNECTED
586
+ });
587
+ ```
588
+
589
+ #### `onQrCode(callback: (qr: string) => void): void`
590
+
591
+ Listen for QR code updates.
592
+
593
+ ```typescript
594
+ manager.onQrCode((qr) => {
595
+ console.log('New QR code generated');
596
+ // Display in UI
597
+ });
598
+ ```
599
+
600
+ #### `onPairingCode(callback: (code: string) => void): void`
601
+
602
+ Listen for pairing code updates.
603
+
604
+ ```typescript
605
+ manager.onPairingCode((code) => {
606
+ console.log(`Pairing code: ${code}`);
607
+ });
608
+ ```
609
+
610
+ #### `onChatsUpsert(callback: (chats: any) => void): void`
611
+
612
+ Listen for chat updates.
613
+
614
+ ```typescript
615
+ manager.onChatsUpsert((chats) => {
616
+ console.log('Chats updated:', chats);
617
+ });
618
+ ```
619
+
620
+ #### `onContactsUpsert(callback: (contacts: any) => void): void`
621
+
622
+ Listen for contact updates.
623
+
624
+ ```typescript
625
+ manager.onContactsUpsert((contacts) => {
626
+ console.log('Contacts updated:', contacts);
627
+ });
628
+ ```
629
+
630
+ #### `onGroupsUpsert(callback: (groups: any) => void): void`
631
+
632
+ Listen for group updates.
633
+
634
+ ```typescript
635
+ manager.onGroupsUpsert((groups) => {
636
+ console.log('Groups updated:', groups);
637
+ });
638
+ ```
639
+
640
+ #### `onGroupParticipantsUpdate(callback: (event: any) => void): void`
641
+
642
+ Listen for group participant changes.
643
+
644
+ ```typescript
645
+ manager.onGroupParticipantsUpdate((event) => {
646
+ console.log(`${event.action}: ${event.participants}`);
647
+ });
648
+ ```
649
+
650
+ #### `onBlocklistUpdate(callback: (event: any) => void): void`
651
+
652
+ Listen for blocklist changes.
653
+
654
+ ```typescript
655
+ manager.onBlocklistUpdate((event) => {
656
+ console.log('Blocklist updated:', event);
657
+ });
658
+ ```
659
+
660
+ #### `onCall(callback: (calls: any) => void): void`
661
+
662
+ Listen for incoming calls.
663
+
664
+ ```typescript
665
+ manager.onCall((calls) => {
666
+ console.log('Call received:', calls);
667
+ });
668
+ ```
669
+
670
+ ## Complete Example
671
+
672
+ ```typescript
673
+ import { SessionManager } from 'easy-connect-wpp';
674
+ import { Session } from 'easy-connect-wpp/models/session';
675
+
676
+ async function main() {
677
+ const session: Session = {
678
+ session: 'my_session',
679
+ phoneNumber: '5511999999999',
680
+ licensePath: './license.json',
681
+ qrCode: true,
682
+ qrPrintTerminal: true,
683
+ };
684
+
685
+ const manager = new SessionManager();
686
+
687
+ // Handle messages
688
+ manager.onMessage(async (message) => {
689
+ if (message.type === 'conversation') {
690
+ console.log(`📨 ${message.from}: ${message.content.conversation}`);
691
+
692
+ // Reply
693
+ await manager.sendText(message.from, 'Thanks! 👋');
694
+ } else if (message.type === 'imageMessage') {
695
+ console.log(`📸 Image received from ${message.from}`);
696
+
697
+ // Send reaction
698
+ await manager.sendReaction(message.from, '👍', message.id);
699
+ }
700
+ });
701
+
702
+ // Handle acknowledgments
703
+ manager.onMessageAck((ack) => {
704
+ console.log(`✔️ Message ${ack.id}: ${ack.status}`);
705
+ });
706
+
707
+ // Handle QR code
708
+ manager.onQrCode((qr) => {
709
+ console.log('📱 Scan QR code to login');
710
+ // Display in UI or use terminal
711
+ });
712
+
713
+ // Connection status
714
+ manager.onConnectionStatus((status) => {
715
+ console.log(`🔌 ${status}`);
716
+ });
717
+
718
+ // Graceful shutdown
719
+ process.on('SIGINT', async () => {
720
+ console.log('\n👋 Closing...');
721
+ await manager.logout();
722
+ process.exit(0);
723
+ });
724
+
725
+ // Create session and connect
726
+ await manager.createSession(session);
727
+ console.log('🚀 Running...');
728
+ }
729
+
730
+ main().catch(console.error);
731
+ ```
732
+
733
+ ## Authentication Methods
734
+
735
+ ### QR Code (Recommended)
736
+
737
+ ```typescript
738
+ const session: Session = {
739
+ session: 'my_session',
740
+ phoneNumber: '5511999999999',
741
+ licensePath: './license.json',
742
+ qrCode: true,
743
+ qrPrintTerminal: true,
744
+ pairingCode: false,
745
+ };
746
+
747
+ manager.onQrCode((qr) => {
748
+ // Display QR in UI or mobile app
749
+ });
750
+
751
+ await manager.createSession(session);
752
+ ```
753
+
754
+ ### Pairing Code
755
+
756
+ ```typescript
757
+ const session: Session = {
758
+ session: 'my_session',
759
+ phoneNumber: '5511999999999',
760
+ licensePath: './license.json',
761
+ pairingCode: true,
762
+ qrCode: false,
763
+ };
764
+
765
+ manager.onPairingCode((code) => {
766
+ console.log(`Enter code in WhatsApp: ${code}`);
767
+ });
768
+
769
+ await manager.createSession(session);
770
+ ```
771
+
772
+ ## License
773
+
774
+ This library requires a valid license file. Place your `license.json` in the specified path.
775
+
776
+ ```typescript
777
+ licensePath: './license.json';
778
+ ```
779
+
780
+ ## Error Handling
781
+
782
+ All methods return a `Response` object:
783
+
784
+ ```typescript
785
+ const response = await manager.sendText('5511999999999', 'Hello');
786
+
787
+ if (response.status === 200) {
788
+ console.log('Success:', response.content);
789
+ } else {
790
+ console.error('Error:', response.message);
791
+ }
792
+ ```
793
+
794
+ ### Common Error Codes
795
+
796
+ - **400** — Bad request or invalid parameters
797
+ - **401** — Unauthorized (invalid license)
798
+ - **404** — Phone not found on WhatsApp
799
+ - **500** — Internal server error
800
+
801
+ ## Best Practices
802
+
803
+ 1. **Session Management** — Create one manager per phone number
804
+ 2. **Error Handling** — Always check response.status
805
+ 3. **Rate Limiting** — Avoid sending too many messages in short time
806
+ 4. **Graceful Shutdown** — Call logout() before exit
807
+ 5. **Event Processing** — Keep listeners fast, use queues for heavy work
808
+ 6. **License Validation** — Ensure license.json is valid and accessible
809
+ 7. **Connection Monitoring** — Listen to onConnectionStatus events
810
+
811
+ ## Troubleshooting
812
+
813
+ ### QR Code Not Appearing
814
+
815
+ - Ensure `qrCode: true` in session config
816
+ - Check terminal output or UI integration
817
+ - Verify browser environment for QR display
818
+
819
+ ### Session Not Persisting
820
+
821
+ - Check `tokens/instance-${phoneNumber}/` directory exists
822
+ - Verify write permissions
823
+ - Ensure session name is consistent
824
+
825
+ ### Messages Not Sending
826
+
827
+ - Validate recipient phone number format
828
+ - Check connection status before sending
829
+ - Verify license is valid
830
+
831
+ ### Reconnection Issues
832
+
833
+ - Check network connectivity
834
+ - Review max retries setting
835
+ - Monitor onConnectionStatus events
836
+
837
+ ## Performance Tips
838
+
839
+ 1. **Reuse instances** — One SessionManager per phone number
840
+ 2. **Batch messages** — Send multiple messages efficiently
841
+ 3. **Monitor events** — Use onConnectionStatus to detect disconnections
842
+ 4. **Cache metadata** — Store group/contact info locally
843
+ 5. **Clean shutdown** — Proper logout frees resources
844
+
845
+ ## Disclaimer
846
+
847
+ This library is **not affiliated with WhatsApp Inc. or Meta Platforms**. It's a reverse-engineered implementation based on Baileys. Users are responsible for compliance with WhatsApp's Terms of Service. Use at your own risk.
848
+
849
+ ## Related Projects
850
+
851
+ - [Baileys](https://github.com/WhiskeySockets/Baileys) — The underlying protocol implementation
852
+ - [easy-connect-official-wpp-rc](https://www.npmjs.com/package/easy-connect-official-wpp-rc) — Official WhatsApp Cloud API client
853
+
854
+ ## License
855
+
856
+ ISC
857
+
858
+ ## Support
859
+
860
+ For issues and questions:
861
+
862
+ - Check existing GitHub issues
863
+ - Review example usage in repository
864
+ - Consult the logging system for debugging