@skyzopedia/baileys-pro 7.0.16 → 8.0.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 ADDED
@@ -0,0 +1,1354 @@
1
+ <div align='center'>Baileys - Typescript/Javascript WhatsApp Web API</div>
2
+
3
+ Then import the default function in your code:
4
+
5
+ ```ts
6
+ import makeWASocket from 'baileys'
7
+ ```
8
+
9
+ Links
10
+
11
+ · Discord
12
+ · Docs
13
+ · Support Channels:
14
+ · WhatsApp Channel: https://whatsapp.com/channel/0029VbBcgCK1SWstUXZnLh1o
15
+ · Telegram: t.me/Skyzopedia (Skyzopedia)
16
+
17
+ Index
18
+
19
+ · Connecting Account
20
+ · Connect with QR-CODE
21
+ · Connect with Pairing Code
22
+ · Receive Full History
23
+ · Important Notes About Socket Config
24
+ · Caching Group Metadata (Recommended)
25
+ · Improve Retry System & Decrypt Poll Votes
26
+ · Receive Notifications in Whatsapp App
27
+ · Save Auth Info
28
+ · Handling Events
29
+ · Example to Start
30
+ · Decrypt Poll Votes
31
+ · Summary of Events on First Connection
32
+ · Implementing a Data Store
33
+ · Whatsapp IDs Explain
34
+ · Utility Functions
35
+ · JID Conversion Utilities
36
+ · Sending Messages
37
+ · Non-Media Messages
38
+ · Text Message
39
+ · Quote Message
40
+ · Mention User
41
+ · Forward Messages
42
+ · Location Message
43
+ · Contact Message
44
+ · Reaction Message
45
+ · Pin Message
46
+ · Poll Message
47
+ · Sending with Link Preview
48
+ · Media Messages
49
+ · Gif Message
50
+ · Video Message
51
+ · Audio Message
52
+ · Image Message
53
+ · ViewOnce Message
54
+ · Modify Messages
55
+ · Delete Messages (for everyone)
56
+ · Edit Messages
57
+ · Manipulating Media Messages
58
+ · Thumbnail in Media Messages
59
+ · Downloading Media Messages
60
+ · Re-upload Media Message to Whatsapp
61
+ · Reject Call
62
+ · Send States in Chat
63
+ · Reading Messages
64
+ · Update Presence
65
+ · Modifying Chats
66
+ · Archive a Chat
67
+ · Mute/Unmute a Chat
68
+ · Mark a Chat Read/Unread
69
+ · Delete a Message for Me
70
+ · Delete a Chat
71
+ · Star/Unstar a Message
72
+ · Disappearing Messages
73
+ · User Querys
74
+ · Check If ID Exists in Whatsapp
75
+ · Query Chat History (groups too)
76
+ · Fetch Status
77
+ · Fetch Profile Picture (groups too)
78
+ · Fetch Bussines Profile (such as description or category)
79
+ · Fetch Someone's Presence (if they're typing or online)
80
+ · Change Profile
81
+ · Change Profile Status
82
+ · Change Profile Name
83
+ · Change Display Picture (groups too)
84
+ · Remove display picture (groups too)
85
+ · Groups
86
+ · Create a Group
87
+ · Add/Remove or Demote/Promote
88
+ · Change Subject (name)
89
+ · Change Description
90
+ · Change Settings
91
+ · Leave a Group
92
+ · Get Invite Code
93
+ · Revoke Invite Code
94
+ · Join Using Invitation Code
95
+ · Get Group Info by Invite Code
96
+ · Query Metadata (participants, name, description...)
97
+ · Join using groupInviteMessage
98
+ · Get Request Join List
99
+ · Approve/Reject Request Join
100
+ · Get All Participating Groups Metadata
101
+ · Toggle Ephemeral
102
+ · Change Add Mode
103
+ · Privacy
104
+ · Block/Unblock User
105
+ · Get Privacy Settings
106
+ · Get BlockList
107
+ · Update LastSeen Privacy
108
+ · Update Online Privacy
109
+ · Update Profile Picture Privacy
110
+ · Update Status Privacy
111
+ · Update Read Receipts Privacy
112
+ · Update Groups Add Privacy
113
+ · Update Default Disappearing Mode
114
+ · Broadcast Lists & Stories
115
+ · Send Broadcast & Stories
116
+ · Query a Broadcast List's Recipients & Name
117
+ · Writing Custom Functionality
118
+ · Enabling Debug Level in Baileys Logs
119
+ · How Whatsapp Communicate With Us
120
+ · Register a Callback for Websocket Events
121
+
122
+ ---
123
+
124
+ Connecting Account
125
+
126
+ WhatsApp provides a multi-device API that allows Baileys to be authenticated as a second WhatsApp client by scanning a QR code or Pairing Code with WhatsApp on your phone.
127
+
128
+ ```ts
129
+ import makeWASocket from 'baileys'
130
+
131
+ const sock = makeWASocket({
132
+ // can provide additional config here
133
+ browser: Browsers.ubuntu('My App'),
134
+ printQRInTerminal: true
135
+ })
136
+ ```
137
+
138
+ If the connection is successful, you will see a QR code printed on your terminal screen, scan it with WhatsApp on your phone and you'll be logged in!
139
+
140
+ Starting socket with Pairing Code
141
+
142
+ [!IMPORTANT]
143
+ Pairing Code isn't Mobile API, it's a method to connect Whatsapp Web without QR-CODE, you can connect only with one device, see here
144
+
145
+ The phone number can't have + or () or -, only numbers, you must provide country code
146
+
147
+ ```ts
148
+ import makeWASocket from 'baileys'
149
+
150
+ const sock = makeWASocket({
151
+ // can provide additional config here
152
+ printQRInTerminal: false //need to be false
153
+ })
154
+ // NOTE: WAIT TILL QR EVENT BEFORE REQUESTING THE PAIRING CODE
155
+ if (!sock.authState.creds.registered) {
156
+ const number = 'XXXXXXXXXXX'
157
+ const code = await sock.requestPairingCode(number)
158
+ console.log(code)
159
+ }
160
+ ```
161
+
162
+ Receive Full History
163
+
164
+ 1. Set syncFullHistory as true
165
+ 2. Baileys, by default, use chrome browser config
166
+ · If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config:
167
+
168
+ ```ts
169
+ const sock = makeWASocket({
170
+ ...otherOpts,
171
+ // can use Windows, Ubuntu here too
172
+ browser: Browsers.macOS('Desktop'),
173
+ syncFullHistory: true
174
+ })
175
+ ```
176
+
177
+ Important Notes About Socket Config
178
+
179
+ Caching Group Metadata (Recommended)
180
+
181
+ · If you use baileys for groups, we recommend you to set cachedGroupMetadata in socket config, you need to implement a cache like this:
182
+ ```ts
183
+ const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
184
+
185
+ const sock = makeWASocket({
186
+ cachedGroupMetadata: async (jid) => groupCache.get(jid)
187
+ })
188
+
189
+ sock.ev.on('groups.update', async ([event]) => {
190
+ const metadata = await sock.groupMetadata(event.id)
191
+ groupCache.set(event.id, metadata)
192
+ })
193
+
194
+ sock.ev.on('group-participants.update', async (event) => {
195
+ const metadata = await sock.groupMetadata(event.id)
196
+ groupCache.set(event.id, metadata)
197
+ })
198
+ ```
199
+
200
+ Improve Retry System & Decrypt Poll Votes
201
+
202
+ · If you want to improve sending message, retrying when error occurs and decrypt poll votes, you need to have a store and set getMessage config in socket like this:
203
+ ```ts
204
+ const sock = makeWASocket({
205
+ getMessage: async (key) => await getMessageFromStore(key)
206
+ })
207
+ ```
208
+
209
+ Receive Notifications in Whatsapp App
210
+
211
+ · If you want to receive notifications in whatsapp app, set markOnlineOnConnect to false
212
+ ```ts
213
+ const sock = makeWASocket({
214
+ markOnlineOnConnect: false
215
+ })
216
+ ```
217
+
218
+ Saving & Restoring Sessions
219
+
220
+ You obviously don't want to keep scanning the QR code every time you want to connect.
221
+
222
+ So, you can load the credentials to log back in:
223
+
224
+ ```ts
225
+ import makeWASocket, { useMultiFileAuthState } from 'baileys'
226
+
227
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
228
+
229
+ // will use the given state to connect
230
+ // so if valid credentials are available -- it'll connect without QR
231
+ const sock = makeWASocket({ auth: state })
232
+
233
+ // this will be called as soon as the credentials are updated
234
+ sock.ev.on('creds.update', saveCreds)
235
+ ```
236
+
237
+ [!IMPORTANT]
238
+ useMultiFileAuthState is a utility function to help save the auth state in a single folder, this function serves as a good guide to help write auth & key states for SQL/no-SQL databases, which I would recommend in any production grade system.
239
+
240
+ [!NOTE]
241
+ When a message is received/sent, due to signal sessions needing updating, the auth keys (authState.keys) will update. Whenever that happens, you must save the updated keys (authState.keys.set() is called). Not doing so will prevent your messages from reaching the recipient & cause other unexpected consequences. The useMultiFileAuthState function automatically takes care of that, but for any other serious implementation -- you will need to be very careful with the key state management.
242
+
243
+ Handling Events
244
+
245
+ · Baileys uses the EventEmitter syntax for events.
246
+ They're all nicely typed up,so you shouldn't have any issues with an Intellisense editor like VS Code.
247
+
248
+ You can listen to these events like this:
249
+
250
+ ```ts
251
+ const sock = makeWASocket()
252
+ sock.ev.on('messages.upsert', ({ messages }) => {
253
+ console.log('got messages', messages)
254
+ })
255
+ ```
256
+
257
+ Example to Start
258
+
259
+ [!NOTE]
260
+ This example includes basic auth storage too
261
+
262
+ ```ts
263
+ import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'baileys'
264
+ import { Boom } from '@hapi/boom'
265
+
266
+ async function connectToWhatsApp () {
267
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
268
+ const sock = makeWASocket({
269
+ // can provide additional config here
270
+ auth: state,
271
+ printQRInTerminal: true
272
+ })
273
+ sock.ev.on('connection.update', (update) => {
274
+ const { connection, lastDisconnect } = update
275
+ if(connection === 'close') {
276
+ const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
277
+ console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
278
+ // reconnect if not logged out
279
+ if(shouldReconnect) {
280
+ connectToWhatsApp()
281
+ }
282
+ } else if(connection === 'open') {
283
+ console.log('opened connection')
284
+ }
285
+ })
286
+ sock.ev.on('messages.upsert', async event => {
287
+ for (const m of event.messages) {
288
+ console.log(JSON.stringify(m, undefined, 2))
289
+
290
+ console.log('replying to', m.key.remoteJid)
291
+ await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
292
+ }
293
+ })
294
+
295
+ // to storage creds (session info) when it updates
296
+ sock.ev.on('creds.update', saveCreds)
297
+ }
298
+ // run in main file
299
+ connectToWhatsApp()
300
+ ```
301
+
302
+ [!IMPORTANT]
303
+ In messages.upsert it's recommended to use a loop like for (const message of event.messages) to handle all messages in array
304
+
305
+ Decrypt Poll Votes
306
+
307
+ · By default poll votes are encrypted and handled in messages.update
308
+ · That's a simple example
309
+
310
+ ```ts
311
+ sock.ev.on('messages.update', async event => {
312
+ for(const { key, update } of event) {
313
+ if(update.pollUpdates) {
314
+ const pollCreation = await getMessage(key)
315
+ if(pollCreation) {
316
+ console.log(
317
+ 'got poll update, aggregation: ',
318
+ getAggregateVotesInPollMessage({
319
+ message: pollCreation,
320
+ pollUpdates: update.pollUpdates,
321
+ })
322
+ )
323
+ }
324
+ }
325
+ }
326
+ })
327
+ ```
328
+
329
+ · getMessage is a store implementation (in your end)
330
+
331
+ Summary of Events on First Connection
332
+
333
+ 1. When you connect first time, connection.update will be fired requesting you to restart sock
334
+ 2. Then, history messages will be received in messaging-history.set
335
+
336
+ Implementing a Data Store
337
+
338
+ · Baileys does not come with a defacto storage for chats, contacts, or messages. However, a simple in-memory implementation has been provided. The store listens for chat updates, new messages, message updates, etc., to always have an up-to-date version of the data.
339
+
340
+ [!IMPORTANT]
341
+ I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM.
342
+
343
+ It can be used as follows:
344
+
345
+ ```ts
346
+ import makeWASocket, { makeInMemoryStore } from 'baileys'
347
+ // the store maintains the data of the WA connection in memory
348
+ // can be written out to a file & read from it
349
+ const store = makeInMemoryStore({ })
350
+ // can be read from a file
351
+ store.readFromFile('./baileys_store.json')
352
+ // saves the state to a file every 10s
353
+ setInterval(() => {
354
+ store.writeToFile('./baileys_store.json')
355
+ }, 10_000)
356
+
357
+ const sock = makeWASocket({ })
358
+ // will listen from this socket
359
+ // the store can listen from a new socket once the current socket outlives its lifetime
360
+ store.bind(sock.ev)
361
+
362
+ sock.ev.on('chats.upsert', () => {
363
+ // can use 'store.chats' however you want, even after the socket dies out
364
+ // 'chats' => a KeyedDB instance
365
+ console.log('got chats', store.chats.all())
366
+ })
367
+
368
+ sock.ev.on('contacts.upsert', () => {
369
+ console.log('got contacts', Object.values(store.contacts))
370
+ })
371
+ ```
372
+
373
+ The store also provides some simple functions such as loadMessages that utilize the store to speed up data retrieval.
374
+
375
+ Whatsapp IDs Explain
376
+
377
+ · id is the WhatsApp ID, called jid too, of the person or group you're sending the message to.
378
+ · It must be in the format [country code][phone number]@s.whatsapp.net
379
+ · Example for people: +19999999999@s.whatsapp.net.
380
+ · For groups, it must be in the format 123456789-123345@g.us .
381
+ · For broadcast lists, it's [timestamp of creation]@broadcast.
382
+ · For stories, the ID is status@broadcast.
383
+
384
+ Utility Functions
385
+
386
+ · getContentType, returns the content type for any message
387
+ · getDevice, returns the device from message
388
+ · makeCacheableSignalKeyStore, make auth store more fast
389
+ · downloadContentFromMessage, download content from any message
390
+
391
+ JID Conversion Utilities
392
+
393
+ Baileys provides helper methods to convert between standard JIDs (@s.whatsapp.net) and LID (Local ID) format (@lid). These are useful when working with different WhatsApp ID formats.
394
+
395
+ Convert to LID (@lid)
396
+
397
+ ```ts
398
+ const standardJid = '1234567890@s.whatsapp.net'
399
+ const lidJid = sock.toLid(standardJid)
400
+ // Result: '1234567890@lid'
401
+ ```
402
+
403
+ Convert from LID to Standard (@s.whatsapp.net)
404
+
405
+ ```ts
406
+ const lidJid = '1234567890@lid'
407
+ const standardJid = sock.toPn(lidJid)
408
+ // Result: '1234567890@s.whatsapp.net'
409
+ ```
410
+
411
+ [!NOTE]
412
+ These conversion utilities are helpful when interacting with systems or APIs that use different JID formats.
413
+
414
+ Sending Messages
415
+
416
+ ```ts
417
+ const jid: string
418
+ const content: AnyMessageContent
419
+ const options: MiscMessageGenerationOptions
420
+
421
+ await sock.sendMessage(jid, content, options)
422
+ ```
423
+
424
+ Non-Media Messages
425
+
426
+ Text Message
427
+
428
+ ```ts
429
+ await sock.sendMessage(jid, { text: 'hello word' })
430
+ ```
431
+
432
+ Quote Message (works with all types)
433
+
434
+ ```ts
435
+ await sock.sendMessage(jid, { text: 'hello word' }, { quoted: message })
436
+ ```
437
+
438
+ Mention User (works with most types)
439
+
440
+ · @number is to mention in text, it's optional
441
+
442
+ ```ts
443
+ await sock.sendMessage(
444
+ jid,
445
+ {
446
+ text: '@12345678901',
447
+ mentions: ['12345678901@s.whatsapp.net']
448
+ }
449
+ )
450
+ ```
451
+
452
+ Forward Messages
453
+
454
+ ```ts
455
+ const msg = getMessageFromStore() // implement this on your end
456
+ await sock.sendMessage(jid, { forward: msg }) // WA forward the message!
457
+ ```
458
+
459
+ Location Message
460
+
461
+ ```ts
462
+ await sock.sendMessage(
463
+ jid,
464
+ {
465
+ location: {
466
+ degreesLatitude: 24.121231,
467
+ degreesLongitude: 55.1121221
468
+ }
469
+ }
470
+ )
471
+ ```
472
+
473
+ Contact Message
474
+
475
+ ```ts
476
+ const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
477
+ + 'VERSION:3.0\n'
478
+ + 'FN:Jeff Singh\n' // full name
479
+ + 'ORG:Ashoka Uni;\n' // the organization of the contact
480
+ + 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number
481
+ + 'END:VCARD'
482
+
483
+ await sock.sendMessage(
484
+ jid,
485
+ {
486
+ contacts: {
487
+ displayName: 'Jeff',
488
+ contacts: [{ vcard }]
489
+ }
490
+ }
491
+ )
492
+ ```
493
+
494
+ Reaction Message
495
+
496
+ ```ts
497
+ await sock.sendMessage(
498
+ jid,
499
+ {
500
+ react: {
501
+ text: '💖', // use an empty string to remove the reaction
502
+ key: message.key
503
+ }
504
+ }
505
+ )
506
+ ```
507
+
508
+ Pin Message
509
+
510
+ · You need to pass the key of message, you can retrieve from store or use a key object
511
+ · Time can be:
512
+
513
+ Time Seconds
514
+ 24h 86.400
515
+ 7d 604.800
516
+ 30d 2.592.000
517
+
518
+ ```ts
519
+ await sock.sendMessage(
520
+ jid,
521
+ {
522
+ pin: {
523
+ type: 1, // 0 to remove
524
+ time: 86400
525
+ key: message.key
526
+ }
527
+ }
528
+ )
529
+ ```
530
+
531
+ Poll Message
532
+
533
+ ```ts
534
+ await sock.sendMessage(
535
+ jid,
536
+ {
537
+ poll: {
538
+ name: 'My Poll',
539
+ values: ['Option 1', 'Option 2', ...],
540
+ selectableCount: 1,
541
+ toAnnouncementGroup: false // or true
542
+ }
543
+ }
544
+ )
545
+ ```
546
+
547
+ Sending Messages with Link Previews
548
+
549
+ 1. By default, wa does not have link generation when sent from the web
550
+ 2. Baileys has a function to generate the content for these link previews
551
+ 3. To enable this function's usage, add link-preview-js as a dependency to your project with yarn add link-preview-js
552
+ 4. Send a link:
553
+
554
+ ```ts
555
+ await sock.sendMessage(
556
+ jid,
557
+ {
558
+ text: 'Hi, this was sent using https://github.com/whiskeysockets/baileys'
559
+ }
560
+ )
561
+ ```
562
+
563
+ Media Messages
564
+
565
+ Sending media (video, stickers, images) is easier & more efficient than ever.
566
+
567
+ [!NOTE]
568
+ In media messages, you can pass { stream: Stream } or { url: Url } or Buffer directly, you can see more here
569
+
570
+ · When specifying a media url, Baileys never loads the entire buffer into memory; it even encrypts the media as a readable stream.
571
+
572
+ [!TIP]
573
+ It's recommended to use Stream or Url to save memory
574
+
575
+ Gif Message
576
+
577
+ · Whatsapp doesn't support .gif files, that's why we send gifs as common .mp4 video with gifPlayback flag
578
+
579
+ ```ts
580
+ await sock.sendMessage(
581
+ jid,
582
+ {
583
+ video: fs.readFileSync('Media/ma_gif.mp4'),
584
+ caption: 'hello word',
585
+ gifPlayback: true
586
+ }
587
+ )
588
+ ```
589
+
590
+ Video Message
591
+
592
+ ```ts
593
+ await sock.sendMessage(
594
+ jid,
595
+ {
596
+ video: {
597
+ url: './Media/ma_gif.mp4'
598
+ },
599
+ caption: 'hello word',
600
+ ptv: false // if set to true, will send as a `video note`
601
+ }
602
+ )
603
+ ```
604
+
605
+ Audio Message
606
+
607
+ · To audio message work in all devices you need to convert with some tool like ffmpeg with this flags:
608
+ ```bash
609
+ codec: libopus //ogg file
610
+ ac: 1 //one channel
611
+ avoid_negative_ts
612
+ make_zero
613
+ ```
614
+ · Example:
615
+ ```bash
616
+ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
617
+ ```
618
+
619
+ ```ts
620
+ await sock.sendMessage(
621
+ jid,
622
+ {
623
+ audio: {
624
+ url: './Media/audio.mp3'
625
+ },
626
+ mimetype: 'audio/mp4'
627
+ }
628
+ )
629
+ ```
630
+
631
+ Image Message
632
+
633
+ ```ts
634
+ await sock.sendMessage(
635
+ jid,
636
+ {
637
+ image: {
638
+ url: './Media/ma_img.png'
639
+ },
640
+ caption: 'hello word'
641
+ }
642
+ )
643
+ ```
644
+
645
+ View Once Message
646
+
647
+ · You can send all messages above as viewOnce, you only need to pass viewOnce: true in content object
648
+
649
+ ```ts
650
+ await sock.sendMessage(
651
+ jid,
652
+ {
653
+ image: {
654
+ url: './Media/ma_img.png'
655
+ },
656
+ viewOnce: true, //works with video, audio too
657
+ caption: 'hello word'
658
+ }
659
+ )
660
+ ```
661
+
662
+ Modify Messages
663
+
664
+ Deleting Messages (for everyone)
665
+
666
+ ```ts
667
+ const msg = await sock.sendMessage(jid, { text: 'hello word' })
668
+ await sock.sendMessage(jid, { delete: msg.key })
669
+ ```
670
+
671
+ Note: deleting for oneself is supported via chatModify, see in this section
672
+
673
+ Editing Messages
674
+
675
+ · You can pass all editable contents here
676
+
677
+ ```ts
678
+ await sock.sendMessage(jid, {
679
+ text: 'updated text goes here',
680
+ edit: response.key,
681
+ });
682
+ ```
683
+
684
+ Manipulating Media Messages
685
+
686
+ Thumbnail in Media Messages
687
+
688
+ · For media messages, the thumbnail can be generated automatically for images & stickers provided you add jimp or sharp as a dependency in your project using yarn add jimp or yarn add sharp.
689
+ · Thumbnails for videos can also be generated automatically, though, you need to have ffmpeg installed on your system.
690
+
691
+ Downloading Media Messages
692
+
693
+ If you want to save the media you received
694
+
695
+ ```ts
696
+ import { createWriteStream } from 'fs'
697
+ import { downloadMediaMessage, getContentType } from 'baileys'
698
+
699
+ sock.ev.on('messages.upsert', async ({ messages }) => {
700
+ for (const m of messages) {
701
+ if (!m.message) return // if there is no text or media message
702
+ const messageType = getContentType(m) // get what type of message it is (text, image, video...)
703
+
704
+ // if the message is an image
705
+ if (messageType === 'imageMessage') {
706
+ // download the message
707
+ const stream = await downloadMediaMessage(
708
+ m,
709
+ 'stream', // can be 'buffer' too
710
+ { },
711
+ {
712
+ logger,
713
+ // pass this so that baileys can request a reupload of media
714
+ // that has been deleted
715
+ reuploadRequest: sock.updateMediaMessage
716
+ }
717
+ )
718
+ // save to file
719
+ const writeStream = createWriteStream('./my-download.jpeg')
720
+ stream.pipe(writeStream)
721
+ }
722
+ }
723
+ })
724
+ ```
725
+
726
+ Re-upload Media Message to Whatsapp
727
+
728
+ · WhatsApp automatically removes old media from their servers. For the device to access said media -- a re-upload is required by another device that has it. This can be accomplished using:
729
+
730
+ ```ts
731
+ await sock.updateMediaMessage(msg)
732
+ ```
733
+
734
+ Reject Call
735
+
736
+ · You can obtain callId and callFrom from call event
737
+
738
+ ```ts
739
+ await sock.rejectCall(callId, callFrom)
740
+ ```
741
+
742
+ Send States in Chat
743
+
744
+ Reading Messages
745
+
746
+ · A set of message keys must be explicitly marked read now.
747
+ · You cannot mark an entire 'chat' read as it were with Baileys Web.
748
+ This means you have to keep track of unread messages.
749
+
750
+ ```ts
751
+ const key: WAMessageKey
752
+ // can pass multiple keys to read multiple messages as well
753
+ await sock.readMessages([key])
754
+ ```
755
+
756
+ The message ID is the unique identifier of the message that you are marking as read.
757
+ On aWAMessage, the messageID can be accessed using messageID = message.key.id.
758
+
759
+ Update Presence
760
+
761
+ · presence can be one of these
762
+ · The presence expires after about 10 seconds.
763
+ · This lets the person/group with jid know whether you're online, offline, typing etc.
764
+
765
+ ```ts
766
+ await sock.sendPresenceUpdate('available', jid)
767
+ ```
768
+
769
+ [!NOTE]
770
+ If a desktop client is active, WA doesn't send push notifications to the device. If you would like to receive said notifications -- mark your Baileys client offline using sock.sendPresenceUpdate('unavailable')
771
+
772
+ Modifying Chats
773
+
774
+ WA uses an encrypted form of communication to send chat/app updates. This has been implemented mostly and you can send the following updates:
775
+
776
+ [!IMPORTANT]
777
+ If you mess up one of your updates, WA can log you out of all your devices and you'll have to log in again.
778
+
779
+ Archive a Chat
780
+
781
+ ```ts
782
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
783
+ await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
784
+ ```
785
+
786
+ Mute/Unmute a Chat
787
+
788
+ · Supported times:
789
+
790
+ Time Miliseconds
791
+ Remove null
792
+ 8h 86.400.000
793
+ 7d 604.800.000
794
+
795
+ ```ts
796
+ // mute for 8 hours
797
+ await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
798
+ // unmute
799
+ await sock.chatModify({ mute: null }, jid)
800
+ ```
801
+
802
+ Mark a Chat Read/Unread
803
+
804
+ ```ts
805
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
806
+ // mark it unread
807
+ await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
808
+ ```
809
+
810
+ Delete a Message for Me
811
+
812
+ ```ts
813
+ await sock.chatModify(
814
+ {
815
+ clear: {
816
+ messages: [
817
+ {
818
+ id: 'ATWYHDNNWU81732J',
819
+ fromMe: true,
820
+ timestamp: '1654823909'
821
+ }
822
+ ]
823
+ }
824
+ },
825
+ jid
826
+ )
827
+ ```
828
+
829
+ Delete a Chat
830
+
831
+ ```ts
832
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
833
+ await sock.chatModify({
834
+ delete: true,
835
+ lastMessages: [
836
+ {
837
+ key: lastMsgInChat.key,
838
+ messageTimestamp: lastMsgInChat.messageTimestamp
839
+ }
840
+ ]
841
+ },
842
+ jid
843
+ )
844
+ ```
845
+
846
+ Pin/Unpin a Chat
847
+
848
+ ```ts
849
+ await sock.chatModify({
850
+ pin: true // or `false` to unpin
851
+ },
852
+ jid
853
+ )
854
+ ```
855
+
856
+ Star/Unstar a Message
857
+
858
+ ```ts
859
+ await sock.chatModify({
860
+ star: {
861
+ messages: [
862
+ {
863
+ id: 'messageID',
864
+ fromMe: true // or `false`
865
+ }
866
+ ],
867
+ star: true // - true: Star Message; false: Unstar Message
868
+ }
869
+ },
870
+ jid
871
+ )
872
+ ```
873
+
874
+ Disappearing Messages
875
+
876
+ · Ephemeral can be:
877
+
878
+ Time Seconds
879
+ Remove 0
880
+ 24h 86.400
881
+ 7d 604.800
882
+ 90d 7.776.000
883
+
884
+ · You need to pass in Seconds, default is 7 days
885
+
886
+ ```ts
887
+ import { WA_DEFAULT_EPHEMERAL } from 'baileys'
888
+
889
+ // turn on disappearing messages
890
+ await sock.sendMessage(
891
+ jid,
892
+ // this is 1 week in seconds -- how long you want messages to appear for
893
+ { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
894
+ )
895
+
896
+ // will send as a disappearing message
897
+ await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
898
+
899
+ // turn off disappearing messages
900
+ await sock.sendMessage(
901
+ jid,
902
+ { disappearingMessagesInChat: false }
903
+ )
904
+ ```
905
+
906
+ User Querys
907
+
908
+ Check If ID Exists in Whatsapp
909
+
910
+ ```ts
911
+ const [result] = await sock.onWhatsApp(jid)
912
+ if (result.exists) console.log (`${jid} exists on WhatsApp, as jid: ${result.jid}`)
913
+ ```
914
+
915
+ Query Chat History (groups too)
916
+
917
+ · You need to have oldest message in chat
918
+
919
+ ```ts
920
+ const msg = await getOldestMessageInChat(jid)
921
+ await sock.fetchMessageHistory(
922
+ 50, //quantity (max: 50 per query)
923
+ msg.key,
924
+ msg.messageTimestamp
925
+ )
926
+ ```
927
+
928
+ · Messages will be received in messaging-history.set event
929
+
930
+ Fetch Status
931
+
932
+ ```ts
933
+ const status = await sock.fetchStatus(jid)
934
+ console.log('status: ' + status)
935
+ ```
936
+
937
+ Fetch Profile Picture (groups too)
938
+
939
+ · To get the display picture of some person/group
940
+
941
+ ```ts
942
+ // for low res picture
943
+ const ppUrl = await sock.profilePictureUrl(jid)
944
+ console.log(ppUrl)
945
+
946
+ // for high res picture
947
+ const ppUrl = await sock.profilePictureUrl(jid, 'image')
948
+ ```
949
+
950
+ Fetch Bussines Profile (such as description or category)
951
+
952
+ ```ts
953
+ const profile = await sock.getBusinessProfile(jid)
954
+ console.log('business description: ' + profile.description + ', category: ' + profile.category)
955
+ ```
956
+
957
+ Fetch Someone's Presence (if they're typing or online)
958
+
959
+ ```ts
960
+ // the presence update is fetched and called here
961
+ sock.ev.on('presence.update', console.log)
962
+
963
+ // request updates for a chat
964
+ await sock.presenceSubscribe(jid)
965
+ ```
966
+
967
+ Change Profile
968
+
969
+ Change Profile Status
970
+
971
+ ```ts
972
+ await sock.updateProfileStatus('Hello World!')
973
+ ```
974
+
975
+ Change Profile Name
976
+
977
+ ```ts
978
+ await sock.updateProfileName('My name')
979
+ ```
980
+
981
+ Change Display Picture (groups too)
982
+
983
+ · To change your display picture or a group's
984
+
985
+ [!NOTE]
986
+ Like media messages, you can pass { stream: Stream } or { url: Url } or Buffer directly, you can see more here
987
+
988
+ ```ts
989
+ await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
990
+ ```
991
+
992
+ Remove display picture (groups too)
993
+
994
+ ```ts
995
+ await sock.removeProfilePicture(jid)
996
+ ```
997
+
998
+ Groups
999
+
1000
+ · To change group properties you need to be admin
1001
+
1002
+ Create a Group
1003
+
1004
+ ```ts
1005
+ // title & participants
1006
+ const group = await sock.groupCreate('My Fab Group', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
1007
+ console.log('created group with id: ' + group.gid)
1008
+ await sock.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
1009
+ ```
1010
+
1011
+ Add/Remove or Demote/Promote
1012
+
1013
+ ```ts
1014
+ // id & people to add to the group (will throw error if it fails)
1015
+ await sock.groupParticipantsUpdate(
1016
+ jid,
1017
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1018
+ 'add' // replace this parameter with 'remove' or 'demote' or 'promote'
1019
+ )
1020
+ ```
1021
+
1022
+ Change Subject (name)
1023
+
1024
+ ```ts
1025
+ await sock.groupUpdateSubject(jid, 'New Subject!')
1026
+ ```
1027
+
1028
+ Change Description
1029
+
1030
+ ```ts
1031
+ await sock.groupUpdateDescription(jid, 'New Description!')
1032
+ ```
1033
+
1034
+ Change Settings
1035
+
1036
+ ```ts
1037
+ // only allow admins to send messages
1038
+ await sock.groupSettingUpdate(jid, 'announcement')
1039
+ // allow everyone to send messages
1040
+ await sock.groupSettingUpdate(jid, 'not_announcement')
1041
+ // allow everyone to modify the group's settings -- like display picture etc.
1042
+ await sock.groupSettingUpdate(jid, 'unlocked')
1043
+ // only allow admins to modify the group's settings
1044
+ await sock.groupSettingUpdate(jid, 'locked')
1045
+ ```
1046
+
1047
+ Leave a Group
1048
+
1049
+ ```ts
1050
+ // will throw error if it fails
1051
+ await sock.groupLeave(jid)
1052
+ ```
1053
+
1054
+ Get Invite Code
1055
+
1056
+ · To create link with code use 'https://chat.whatsapp.com/' + code
1057
+
1058
+ ```ts
1059
+ const code = await sock.groupInviteCode(jid)
1060
+ console.log('group code: ' + code)
1061
+ ```
1062
+
1063
+ Revoke Invite Code
1064
+
1065
+ ```ts
1066
+ const code = await sock.groupRevokeInvite(jid)
1067
+ console.log('New group code: ' + code)
1068
+ ```
1069
+
1070
+ Join Using Invitation Code
1071
+
1072
+ · Code can't have https://chat.whatsapp.com/, only code
1073
+
1074
+ ```ts
1075
+ const response = await sock.groupAcceptInvite(code)
1076
+ console.log('joined to: ' + response)
1077
+ ```
1078
+
1079
+ Get Group Info by Invite Code
1080
+
1081
+ ```ts
1082
+ const response = await sock.groupGetInviteInfo(code)
1083
+ console.log('group information: ' + response)
1084
+ ```
1085
+
1086
+ Query Metadata (participants, name, description...)
1087
+
1088
+ ```ts
1089
+ const metadata = await sock.groupMetadata(jid)
1090
+ console.log(metadata.id + ', title: ' + metadata.subject + ', description: ' + metadata.desc)
1091
+ ```
1092
+
1093
+ Join using groupInviteMessage
1094
+
1095
+ ```ts
1096
+ const response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
1097
+ console.log('joined to: ' + response)
1098
+ ```
1099
+
1100
+ Get Request Join List
1101
+
1102
+ ```ts
1103
+ const response = await sock.groupRequestParticipantsList(jid)
1104
+ console.log(response)
1105
+ ```
1106
+
1107
+ Approve/Reject Request Join
1108
+
1109
+ ```ts
1110
+ const response = await sock.groupRequestParticipantsUpdate(
1111
+ jid, // group id
1112
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1113
+ 'approve' // or 'reject'
1114
+ )
1115
+ console.log(response)
1116
+ ```
1117
+
1118
+ Get All Participating Groups Metadata
1119
+
1120
+ ```ts
1121
+ const response = await sock.groupFetchAllParticipating()
1122
+ console.log(response)
1123
+ ```
1124
+
1125
+ Toggle Ephemeral
1126
+
1127
+ · Ephemeral can be:
1128
+
1129
+ Time Seconds
1130
+ Remove 0
1131
+ 24h 86.400
1132
+ 7d 604.800
1133
+ 90d 7.776.000
1134
+
1135
+ ```ts
1136
+ await sock.groupToggleEphemeral(jid, 86400)
1137
+ ```
1138
+
1139
+ Change Add Mode
1140
+
1141
+ ```ts
1142
+ await sock.groupMemberAddMode(
1143
+ jid,
1144
+ 'all_member_add' // or 'admin_add'
1145
+ )
1146
+ ```
1147
+
1148
+ Privacy
1149
+
1150
+ Block/Unblock User
1151
+
1152
+ ```ts
1153
+ await sock.updateBlockStatus(jid, 'block') // Block user
1154
+ await sock.updateBlockStatus(jid, 'unblock') // Unblock user
1155
+ ```
1156
+
1157
+ Get Privacy Settings
1158
+
1159
+ ```ts
1160
+ const privacySettings = await sock.fetchPrivacySettings(true)
1161
+ console.log('privacy settings: ' + privacySettings)
1162
+ ```
1163
+
1164
+ Get BlockList
1165
+
1166
+ ```ts
1167
+ const response = await sock.fetchBlocklist()
1168
+ console.log(response)
1169
+ ```
1170
+
1171
+ Update LastSeen Privacy
1172
+
1173
+ ```ts
1174
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1175
+ await sock.updateLastSeenPrivacy(value)
1176
+ ```
1177
+
1178
+ Update Online Privacy
1179
+
1180
+ ```ts
1181
+ const value = 'all' // 'match_last_seen'
1182
+ await sock.updateOnlinePrivacy(value)
1183
+ ```
1184
+
1185
+ Update Profile Picture Privacy
1186
+
1187
+ ```ts
1188
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1189
+ await sock.updateProfilePicturePrivacy(value)
1190
+ ```
1191
+
1192
+ Update Status Privacy
1193
+
1194
+ ```ts
1195
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1196
+ await sock.updateStatusPrivacy(value)
1197
+ ```
1198
+
1199
+ Update Read Receipts Privacy
1200
+
1201
+ ```ts
1202
+ const value = 'all' // 'none'
1203
+ await sock.updateReadReceiptsPrivacy(value)
1204
+ ```
1205
+
1206
+ Update Groups Add Privacy
1207
+
1208
+ ```ts
1209
+ const value = 'all' // 'contacts' | 'contact_blacklist'
1210
+ await sock.updateGroupsAddPrivacy(value)
1211
+ ```
1212
+
1213
+ Update Default Disappearing Mode
1214
+
1215
+ · Like this, ephemeral can be:
1216
+
1217
+ Time Seconds
1218
+ Remove 0
1219
+ 24h 86.400
1220
+ 7d 604.800
1221
+ 90d 7.776.000
1222
+
1223
+ ```ts
1224
+ const ephemeral = 86400
1225
+ await sock.updateDefaultDisappearingMode(ephemeral)
1226
+ ```
1227
+
1228
+ Broadcast Lists & Stories
1229
+
1230
+ Send Broadcast & Stories
1231
+
1232
+ · Messages can be sent to broadcasts & stories. You need to add the following message options in sendMessage, like this:
1233
+
1234
+ ```ts
1235
+ await sock.sendMessage(
1236
+ jid,
1237
+ {
1238
+ image: {
1239
+ url: url
1240
+ },
1241
+ caption: caption
1242
+ },
1243
+ {
1244
+ backgroundColor: backgroundColor,
1245
+ font: font,
1246
+ statusJidList: statusJidList,
1247
+ broadcast: true
1248
+ }
1249
+ )
1250
+ ```
1251
+
1252
+ · Message body can be a extendedTextMessage or imageMessage or videoMessage or voiceMessage, see here
1253
+ · You can add backgroundColor and other options in the message options, see here
1254
+ · broadcast: true enables broadcast mode
1255
+ · statusJidList: a list of people that you can get which you need to provide, which are the people who will get this status message.
1256
+ · You can send messages to broadcast lists the same way you send messages to groups & individual chats.
1257
+ · Right now, WA Web does not support creating broadcast lists, but you can still delete them.
1258
+ · Broadcast IDs are in the format 12345678@broadcast
1259
+
1260
+ Query a Broadcast List's Recipients & Name
1261
+
1262
+ ```ts
1263
+ const bList = await sock.getBroadcastListInfo('1234@broadcast')
1264
+ console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
1265
+ ```
1266
+
1267
+ Writing Custom Functionality
1268
+
1269
+ Baileys is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
1270
+
1271
+ Enabling Debug Level in Baileys Logs
1272
+
1273
+ First, enable the logging of unhandled messages from WhatsApp by setting:
1274
+
1275
+ ```ts
1276
+ import P from 'pino'
1277
+
1278
+ const sock = makeWASocket({
1279
+ logger: P({ level: 'debug' }),
1280
+ })
1281
+ ```
1282
+
1283
+ This will enable you to see all sorts of messages WhatsApp sends in the console.
1284
+
1285
+ How Whatsapp Communicate With Us
1286
+
1287
+ [!TIP]
1288
+ If you want to learn whatsapp protocol, we recommend to study about Libsignal Protocol and Noise Protocol
1289
+
1290
+ · Example: Functionality to track the battery percentage of your phone. You enable logging and you'll see a message about your battery pop up in the console:
1291
+ ```
1292
+ {
1293
+ "level": 10,
1294
+ "fromMe": false,
1295
+ "frame": {
1296
+ "tag": "ib",
1297
+ "attrs": {
1298
+ "from": "@s.whatsapp.net"
1299
+ },
1300
+ "content": [
1301
+ {
1302
+ "tag": "edge_routing",
1303
+ "attrs": {},
1304
+ "content": [
1305
+ {
1306
+ "tag": "routing_info",
1307
+ "attrs": {},
1308
+ "content": {
1309
+ "type": "Buffer",
1310
+ "data": [8,2,8,5]
1311
+ }
1312
+ }
1313
+ ]
1314
+ }
1315
+ ]
1316
+ },
1317
+ "msg":"communication"
1318
+ }
1319
+ ```
1320
+
1321
+ The 'frame' is what the message received is, it has three components:
1322
+
1323
+ · tag -- what this frame is about (eg. message will have 'message')
1324
+ · attrs -- a string key-value pair with some metadata (contains ID of the message usually)
1325
+ · content -- the actual data (eg. a message node will have the actual message content in it)
1326
+ · read more about this format here
1327
+
1328
+ Register a Callback for Websocket Events
1329
+
1330
+ [!TIP]
1331
+ Recommended to see onMessageReceived function in socket.ts file to understand how websockets events are fired
1332
+
1333
+ ```ts
1334
+ // for any message with tag 'edge_routing'
1335
+ sock.ws.on('CB:edge_routing', (node: BinaryNode) => { })
1336
+
1337
+ // for any message with tag 'edge_routing' and id attribute = abcd
1338
+ sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => { })
1339
+
1340
+ // for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
1341
+ sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => { })
1342
+ ```
1343
+
1344
+ [!NOTE]
1345
+ Also, this repo is now licenced under GPL 3 since it uses libsignal-node
1346
+
1347
+ ---
1348
+
1349
+ Support Channels
1350
+
1351
+ · WhatsApp Channel: Join Here
1352
+ · Telegram: t.me/Skyzopedia (Skyzopedia)
1353
+
1354
+ For any issues, questions, or discussions about Baileys, feel free to join our support channels above. Our community and developers are active and ready to help!