@jkt48connect-corp/baileys 7.3.1 → 7.3.3

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,58 +1,632 @@
1
- # @jkt48connect-corp/baileys - Typescript/Javascript WhatsApp Web API
1
+ # <div align='center'>WhatsApp Web API</div>
2
2
 
3
- ### INFORMATION !!
4
- This Baileys has been modified by @jkt48connect-corp. Don't use it for illegal activities or to harm other people.
3
+ <div align='center'>
5
4
 
6
- ### Important Note
5
+ ![WhatsApp API](https://raw.githubusercontent.com/Bell575/Upload/main/uploads/1742387351904.png)
7
6
 
8
- This library was originally a project of *@adiwajshing/baileys* and is in no way affiliated with or endorsed by WhatsApp. Use at your own discretion. Don't spam others with this. We do not encourage the use of stalking, mass or automated messaging.
7
+ </div>
9
8
 
10
- #### Liability and License Notice
11
- Indraazy and its managers are not responsible for misuse of this application, as stated in the MIT license. Indraazy management in no way condones the use of this application in practices that violate the WhatsApp Terms of Service. The manager of this application holds its users personally responsible for using this application in a fair manner, as it is intended to be used.
12
- ##
9
+ Baileys is a WebSockets-based TypeScript library for interacting with the WhatsApp Web API.
13
10
 
14
- BaileysPro doesn't require Selenium or any other browser to interact with WhatsApp Web, it does it directly using WebSocket. Not running Selenium or Chromimum saves half a gig of ram :/ BaileysPro supports interaction with multi-device & web versions of WhatsApp.
15
-
16
- ## Please Read
11
+ # Disclaimer
12
+ This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates.
13
+ The official WhatsApp website can be found at whatsapp.com. "WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners.
17
14
 
18
- The original repository had to be removed by the original author - we are now continuing development of this repository here. This is one of the modification repositories and is maintained by Indraazy.
19
- ___
15
+ The maintainers of Baileys do not in any way condone the use of this application in practices that violate the Terms of Service of WhatsApp. The maintainers of this application call upon the personal responsibility of its users to use this application in a fair way, as it is intended to be used.
16
+ Use at your own discretion. Do not spam people with this. We discourage any stalkerware, bulk or automated messaging usage.
20
17
 
21
- ## Shop Message:
18
+ ## Example
19
+
20
+ Here is an example you can use: [example.ts](Example/example.ts) or here is a tutorial for running the Baileys WhatsApp API code
21
+ 1. ``` cd path/to/Baileys ```
22
+ 2. ``` npm install```
23
+ 3. ``` node example.js```
24
+
25
+ ## Install
26
+
27
+ Use the stable version:
28
+ ```bash
29
+ npm install @fizzxydev/baileys-pro
22
30
  ```
23
- client.sendMessage(
24
- jid,
25
- {
26
- text: "YOUR TEXT",
27
- title: "YOUR TITLE",
28
- subtitle: "YOUR SUBTITLE",
29
- footer: "FOOTER",
30
- viewOnce: true,
31
- shop: 3,
32
- id: "199872865193",
31
+
32
+ Use the edge version (no guarantee of stability, but latest fixes + features)
33
+ ```bash
34
+ yarn add @fizzxydev/baileys-pro@latest
35
+ ```
36
+
37
+ Then import your code using:
38
+ ```javascript
39
+ const { default: makeWASocket } = require("@fizzxydev/baileys-pro")
40
+ ```
41
+
42
+ # Index
43
+
44
+ - [Connecting Account](#connecting-account)
45
+ - [Connect with QR-CODE](#starting-socket-with-qr-code)
46
+ - [Connect with Pairing Code](#starting-socket-with-pairing-code)
47
+ - [Receive Full History](#receive-full-history)
48
+ - [Important Notes About Socket Config](#important-notes-about-socket-config)
49
+ - [Caching Group Metadata (Recommended)](#caching-group-metadata-recommended)
50
+ - [Improve Retry System & Decrypt Poll Votes](#improve-retry-system--decrypt-poll-votes)
51
+ - [Receive Notifications in Whatsapp App](#receive-notifications-in-whatsapp-app)
52
+
53
+ - [Save Auth Info](#saving--restoring-sessions)
54
+ - [Handling Events](#handling-events)
55
+ - [Example to Start](#example-to-start)
56
+ - [Decrypt Poll Votes](#decrypt-poll-votes)
57
+ - [Summary of Events on First Connection](#summary-of-events-on-first-connection)
58
+ - [Implementing a Data Store](#implementing-a-data-store)
59
+ - [Whatsapp IDs Explain](#whatsapp-ids-explain)
60
+ - [Utility Functions](#utility-functions)
61
+ - [Sending Messages](#sending-messages)
62
+ - [Non-Media Messages](#non-media-messages)
63
+ - [Buttons Message](#buttons-message)
64
+ - [Buttons Flow](#buttons-flow)
65
+ - [Interactive Message](#interactive-message)
66
+ - [Text Message](#text-message)
67
+ - [Quote Message](#quote-message-works-with-all-types)
68
+ - [Mention User](#mention-user-works-with-most-types)
69
+ - [Mention Status](#mention-status)
70
+ - [Result Poll From Newsletter](#result-poll-from-newsletter)
71
+ - [SendAlbumMessage](#send-album-message)
72
+ - [Interactive Response](#interactive-response)
73
+ - [Request Payment](#request-payment)
74
+ - [Event Message](#event-message)
75
+ - [Interactive](#interactive)
76
+ - [Forward Messages](#forward-messages)
77
+ - [Location Message](#location-message)
78
+ - [Contact Message](#contact-message)
79
+ - [Reaction Message](#reaction-message)
80
+ - [Pin Message](#pin-message)
81
+ - [Poll Message](#poll-message)
82
+ - [Sending with Link Preview](#sending-messages-with-link-previews)
83
+ - [Media Messages](#media-messages)
84
+ - [Gif Message](#gif-message)
85
+ - [Video Message](#video-message)
86
+ - [Audio Message](#audio-message)
87
+ - [Image Message](#image-message)
88
+ - [ViewOnce Message](#view-once-message)
89
+ - [Modify Messages](#modify-messages)
90
+ - [Delete Messages (for everyone)](#deleting-messages-for-everyone)
91
+ - [Edit Messages](#editing-messages)
92
+ - [Manipulating Media Messages](#manipulating-media-messages)
93
+ - [Thumbnail in Media Messages](#thumbnail-in-media-messages)
94
+ - [Downloading Media Messages](#downloading-media-messages)
95
+ - [Re-upload Media Message to Whatsapp](#re-upload-media-message-to-whatsapp)
96
+ - [Reject Call](#reject-call)
97
+ - [Send States in Chat](#send-states-in-chat)
98
+ - [Reading Messages](#reading-messages)
99
+ - [Update Presence](#update-presence)
100
+ - [Modifying Chats](#modifying-chats)
101
+ - [Archive a Chat](#archive-a-chat)
102
+ - [Mute/Unmute a Chat](#muteunmute-a-chat)
103
+ - [Mark a Chat Read/Unread](#mark-a-chat-readunread)
104
+ - [Delete a Message for Me](#delete-a-message-for-me)
105
+ - [Delete a Chat](#delete-a-chat)
106
+ - [Star/Unstar a Message](#starunstar-a-message)
107
+ - [Disappearing Messages](#disappearing-messages)
108
+ - [User Querys](#user-querys)
109
+ - [Check If ID Exists in Whatsapp](#check-if-id-exists-in-whatsapp)
110
+ - [Query Chat History (groups too)](#query-chat-history-groups-too)
111
+ - [Fetch Status](#fetch-status)
112
+ - [Fetch Profile Picture (groups too)](#fetch-profile-picture-groups-too)
113
+ - [Fetch Bussines Profile (such as description or category)](#fetch-bussines-profile-such-as-description-or-category)
114
+ - [Fetch Someone's Presence (if they're typing or online)](#fetch-someones-presence-if-theyre-typing-or-online)
115
+ - [Change Profile](#change-profile)
116
+ - [Change Profile Status](#change-profile-status)
117
+ - [Change Profile Name](#change-profile-name)
118
+ - [Change Display Picture (groups too)](#change-display-picture-groups-too)
119
+ - [Remove display picture (groups too)](#remove-display-picture-groups-too)
120
+ - [Groups](#groups)
121
+ - [Create a Group](#create-a-group)
122
+ - [Add/Remove or Demote/Promote](#addremove-or-demotepromote)
123
+ - [Change Subject (name)](#change-subject-name)
124
+ - [Change Description](#change-description)
125
+ - [Change Settings](#change-settings)
126
+ - [Leave a Group](#leave-a-group)
127
+ - [Get Invite Code](#get-invite-code)
128
+ - [Revoke Invite Code](#revoke-invite-code)
129
+ - [Join Using Invitation Code](#join-using-invitation-code)
130
+ - [Get Group Info by Invite Code](#get-group-info-by-invite-code)
131
+ - [Query Metadata (participants, name, description...)](#query-metadata-participants-name-description)
132
+ - [Join using groupInviteMessage](#join-using-groupinvitemessage)
133
+ - [Get Request Join List](#get-request-join-list)
134
+ - [Approve/Reject Request Join](#approvereject-request-join)
135
+ - [Get All Participating Groups Metadata](#get-all-participating-groups-metadata)
136
+ - [Toggle Ephemeral](#toggle-ephemeral)
137
+ - [Change Add Mode](#change-add-mode)
138
+ - [Privacy](#privacy)
139
+ - [Block/Unblock User](#blockunblock-user)
140
+ - [Get Privacy Settings](#get-privacy-settings)
141
+ - [Get BlockList](#get-blocklist)
142
+ - [Update LastSeen Privacy](#update-lastseen-privacy)
143
+ - [Update Online Privacy](#update-online-privacy)
144
+ - [Update Profile Picture Privacy](#update-profile-picture-privacy)
145
+ - [Update Status Privacy](#update-status-privacy)
146
+ - [Update Read Receipts Privacy](#update-read-receipts-privacy)
147
+ - [Update Groups Add Privacy](#update-groups-add-privacy)
148
+ - [Update Default Disappearing Mode](#update-default-disappearing-mode)
149
+ - [Broadcast Lists & Stories](#broadcast-lists--stories)
150
+ - [Send Broadcast & Stories](#send-broadcast--stories)
151
+ - [Query a Broadcast List's Recipients & Name](#query-a-broadcast-lists-recipients--name)
152
+ - [Writing Custom Functionality](#writing-custom-functionality)
153
+ - [Enabling Debug Level in Baileys Logs](#enabling-debug-level-in-baileys-logs)
154
+ - [How Whatsapp Communicate With Us](#how-whatsapp-communicate-with-us)
155
+ - [Register a Callback for Websocket Events](#register-a-callback-for-websocket-events)
156
+
157
+ ## Connecting Account
158
+
159
+ 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.
160
+
161
+ ### Starting socket with **QR-CODE**
162
+
163
+ > [!TIP]
164
+ > You can customize browser name if you connect with **QR-CODE**, with `Browser` constant, we have some browsers config, **see [here](https://baileys.whiskeysockets.io/types/BrowsersMap.html)**
165
+
166
+ ```javascript
167
+ const { default: makeWASocket } = require("@fizzxydev/baileys-pro")
168
+
169
+
170
+ const sock = makeWASocket({
171
+ // can provide additional config here
172
+ browser: Browsers.ubuntu('My App'),
173
+ printQRInTerminal: true
174
+ })
175
+ ```
176
+
177
+ 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!
178
+
179
+ ### Starting socket with **Pairing Code**
180
+
181
+
182
+ > [!IMPORTANT]
183
+ > 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](https://faq.whatsapp.com/1324084875126592/?cms_platform=web)
184
+
185
+ The phone number can't have `+` or `()` or `-`, only numbers, you must provide country code
186
+
187
+ ```javascript
188
+ const { default: makeWASocket } = require("@fizzxydev/baileys-pro")
189
+
190
+ const sock = makeWASocket({
191
+ // can provide additional config here
192
+ printQRInTerminal: false //need to be false
193
+ })
194
+
195
+ - Normal Pairing
196
+ if (!sock.authState.creds.registered) {
197
+ const number = 'XXXXXXXXXXX'
198
+ const code = await sock.requestPairingCode(number)
199
+ console.log(code)
200
+ }
201
+
202
+ - Costum Pairing
203
+ if (!sock.authState.creds.registered) {
204
+ const pair = "12345678" // only 8 digit numbers or letters (no more or less)
205
+ const number = 'XXXXXXXXXXX'
206
+ const code = await sock.requestPairingCode(number, pair)
207
+ console.log(code)
208
+ }
209
+ ```
210
+
211
+ ### Receive Full History
212
+
213
+ 1. Set `syncFullHistory` as `true`
214
+ 2. Baileys, by default, use chrome browser config
215
+ - If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config:
216
+
217
+ ```javascript
218
+ const sock = makeWASocket({
219
+ ...otherOpts,
220
+ // can use Windows, Ubuntu here too
221
+ browser: Browsers.macOS('Desktop'),
222
+ syncFullHistory: true
223
+ })
224
+ ```
225
+
226
+ ## Important Notes About Socket Config
227
+
228
+ ### Caching Group Metadata (Recommended)
229
+ - If you use baileys for groups, we recommend you to set `cachedGroupMetadata` in socket config, you need to implement a cache like this:
230
+
231
+ ```javascript
232
+ const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
233
+
234
+ const sock = makeWASocket({
235
+ cachedGroupMetadata: async (jid) => groupCache.get(jid)
236
+ })
237
+
238
+ sock.ev.on('groups.update', async ([event]) => {
239
+ const metadata = await sock.groupMetadata(event.id)
240
+ groupCache.set(event.id, metadata)
241
+ })
242
+
243
+ sock.ev.on('group-participants.update', async (event) => {
244
+ const metadata = await sock.groupMetadata(event.id)
245
+ groupCache.set(event.id, metadata)
246
+ })
247
+ ```
248
+
249
+ ### Improve Retry System & Decrypt Poll Votes
250
+ - 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:
251
+ ```javascript
252
+ const sock = makeWASocket({
253
+ getMessage: async (key) => await getMessageFromStore(key)
254
+ })
255
+ ```
256
+
257
+ ### Receive Notifications in Whatsapp App
258
+ - If you want to receive notifications in whatsapp app, set `markOnlineOnConnect` to `false`
259
+ ```javascript
260
+ const sock = makeWASocket({
261
+ markOnlineOnConnect: false
262
+ })
263
+ ```
264
+ ## Saving & Restoring Sessions
265
+
266
+ You obviously don't want to keep scanning the QR code every time you want to connect.
267
+
268
+ So, you can load the credentials to log back in:
269
+ ```javascript
270
+ const makeWASocket = require("@fizzxydev/baileys-pro").default;
271
+ const { useMultiFileAuthState } = require("@fizzxydev/baileys-pro");
272
+
273
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
274
+
275
+ // will use the given state to connect
276
+ // so if valid credentials are available -- it'll connect without QR
277
+ const sock = makeWASocket({ auth: state })
278
+
279
+ // this will be called as soon as the credentials are updated
280
+ sock.ev.on('creds.update', saveCreds)
281
+ ```
282
+
283
+ > [!IMPORTANT]
284
+ > `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.
285
+
286
+ > [!NOTE]
287
+ > 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.
288
+
289
+ ## Handling Events
290
+
291
+ - Baileys uses the EventEmitter syntax for events.
292
+ They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
293
+
294
+ > [!IMPORTANT]
295
+ > **The events are [these](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**, it's important you see all events
296
+
297
+ You can listen to these events like this:
298
+ ```javascript
299
+ const sock = makeWASocket()
300
+ sock.ev.on('messages.upsert', ({ messages }) => {
301
+ console.log('got messages', messages)
302
+ })
303
+ ```
304
+
305
+ ### Example to Start
306
+
307
+ > [!NOTE]
308
+ > This example includes basic auth storage too
309
+
310
+ ```javascript
311
+ const makeWASocket = require("@fizzxydev/baileys-pro").default;
312
+ const { DisconnectReason, useMultiFileAuthState } = require("@fizzxydev/baileys-pro");
313
+ const Boom = require('@hapi/boom');
314
+
315
+ async function connectToWhatsApp () {
316
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
317
+ const sock = makeWASocket({
318
+ // can provide additional config here
319
+ auth: state,
320
+ printQRInTerminal: true
321
+ })
322
+ sock.ev.on('connection.update', (update) => {
323
+ const { connection, lastDisconnect } = update
324
+ if(connection === 'close') {
325
+ const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
326
+ console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
327
+ // reconnect if not logged out
328
+ if(shouldReconnect) {
329
+ connectToWhatsApp()
330
+ }
331
+ } else if(connection === 'open') {
332
+ console.log('opened connection')
333
+ }
334
+ })
335
+ sock.ev.on('messages.upsert', event => {
336
+ for (const m of event.messages) {
337
+ console.log(JSON.stringify(m, undefined, 2))
338
+
339
+ console.log('replying to', m.key.remoteJid)
340
+ await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
341
+ }
342
+ })
343
+
344
+ // to storage creds (session info) when it updates
345
+ sock.ev.on('creds.update', saveCreds)
346
+ }
347
+ // run in main file
348
+ connectToWhatsApp()
349
+ ```
350
+
351
+ > [!IMPORTANT]
352
+ > In `messages.upsert` it's recommended to use a loop like `for (const message of event.messages)` to handle all messages in array
353
+
354
+ ### Decrypt Poll Votes
355
+
356
+ - By default poll votes are encrypted and handled in `messages.update`
357
+ - That's a simple example
358
+ ```javascript
359
+ sock.ev.on('messages.update', event => {
360
+ for(const { key, update } of event) {
361
+ if(update.pollUpdates) {
362
+ const pollCreation = await getMessage(key)
363
+ if(pollCreation) {
364
+ console.log(
365
+ 'got poll update, aggregation: ',
366
+ getAggregateVotesInPollMessage({
367
+ message: pollCreation,
368
+ pollUpdates: update.pollUpdates,
369
+ })
370
+ )
371
+ }
372
+ }
373
+ }
374
+ })
375
+ ```
376
+
377
+ - `getMessage` is a [store](#implementing-a-data-store) implementation (in your end)
378
+
379
+ ### Summary of Events on First Connection
380
+
381
+ 1. When you connect first time, `connection.update` will be fired requesting you to restart sock
382
+ 2. Then, history messages will be received in `messaging.history-set`
383
+
384
+ ## Implementing a Data Store
385
+
386
+ - 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.
387
+
388
+ > [!IMPORTANT]
389
+ > I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM.
390
+
391
+ It can be used as follows:
392
+
393
+ ```javascript
394
+ const makeWASocket = require("@fizzxydev/baileys-pro").default;
395
+ const { makeInMemoryStore } = require("@fizzxydev/baileys-pro");
396
+ // the store maintains the data of the WA connection in memory
397
+ // can be written out to a file & read from it
398
+ const store = makeInMemoryStore({ })
399
+ // can be read from a file
400
+ store.readFromFile('./baileys_store.json')
401
+ // saves the state to a file every 10s
402
+ setInterval(() => {
403
+ store.writeToFile('./baileys_store.json')
404
+ }, 10_000)
405
+
406
+ const sock = makeWASocket({ })
407
+ // will listen from this socket
408
+ // the store can listen from a new socket once the current socket outlives its lifetime
409
+ store.bind(sock.ev)
410
+
411
+ sock.ev.on('chats.upsert', () => {
412
+ // can use 'store.chats' however you want, even after the socket dies out
413
+ // 'chats' => a KeyedDB instance
414
+ console.log('got chats', store.chats.all())
415
+ })
416
+
417
+ sock.ev.on('contacts.upsert', () => {
418
+ console.log('got contacts', Object.values(store.contacts))
419
+ })
420
+
421
+ ```
422
+
423
+ The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval.
424
+
425
+ ## Whatsapp IDs Explain
426
+
427
+ - `id` is the WhatsApp ID, called `jid` too, of the person or group you're sending the message to.
428
+ - It must be in the format ```[country code][phone number]@s.whatsapp.net```
429
+ - Example for people: ```+19999999999@s.whatsapp.net```.
430
+ - For groups, it must be in the format ``` 123456789-123345@g.us ```.
431
+ - For broadcast lists, it's `[timestamp of creation]@broadcast`.
432
+ - For stories, the ID is `status@broadcast`.
433
+
434
+ ## Utility Functions
435
+
436
+ - `getContentType`, returns the content type for any message
437
+ - `getDevice`, returns the device from message
438
+ - `makeCacheableSignalKeyStore`, make auth store more fast
439
+ - `downloadContentFromMessage`, download content from any message
440
+
441
+ ## Sending Messages
442
+
443
+ - Send all types of messages with a single function
444
+ - **[Here](https://baileys.whiskeysockets.io/types/AnyMessageContent.html) you can see all message contents supported, like text message**
445
+ - **[Here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html) you can see all options supported, like quote message**
446
+
447
+ ```javascript
448
+ const jid: string
449
+ const content: AnyMessageContent
450
+ const options: MiscMessageGenerationOptions
451
+
452
+ sock.sendMessage(jid, content, options)
453
+ ```
454
+
455
+ ### Non-Media Messages
456
+
457
+ #### Buttons Message
458
+ ```javascript
459
+ // send a buttons message!
460
+ sock.sendMessage(jid, {
461
+ text: "Hello World !",
462
+ footer: "Fizzxy - 2025",
463
+ buttons: [
464
+ {
465
+ buttonId: `🚀`,
466
+ buttonText: {
467
+ displayText: '🗿'
468
+ },
469
+ type: 1
470
+ }
471
+ ],
472
+ headerType: 1,
473
+ viewOnce: true
474
+ },{ quoted: null })
475
+ ```
476
+
477
+ #### Buttons Flow
478
+ ```javascript
479
+ sock.sendMessage(jid, {
480
+ text: "Hello Wolrd !;",
481
+ footer: "© Fizzxy Dev",
482
+ buttons: [
483
+ {
484
+ buttonId: '.tes',
485
+ buttonText: {
486
+ displayText: 'TESTING BOT'
33
487
  },
488
+ type: 1,
489
+ },
34
490
  {
35
- quoted : m
36
- }
37
- )
491
+ buttonId: ' ',
492
+ buttonText: {
493
+ displayText: 'PRIVATE SCRIPT'
494
+ },
495
+ type: 1,
496
+ },
497
+ {
498
+ buttonId: 'action',
499
+ buttonText: {
500
+ displayText: 'ini pesan interactiveMeta'
501
+ },
502
+ type: 4,
503
+ nativeFlowInfo: {
504
+ name: 'single_select',
505
+ paramsJson: JSON.stringify({
506
+ title: 'message',
507
+ sections: [
508
+ {
509
+ title: 'FizzxyDev - 2025',
510
+ highlight_label: '😜',
511
+ rows: [
512
+ {
513
+ header: 'HEADER',
514
+ title: 'TITLE',
515
+ description: 'DESCRIPTION',
516
+ id: 'YOUR ID',
517
+ },
518
+ {
519
+ header: 'HEADER',
520
+ title: 'TITLE',
521
+ description: 'DESCRIPTION',
522
+ id: 'YOUR ID',
523
+ },
524
+ ],
525
+ },
526
+ ],
527
+ }),
528
+ },
529
+ },
530
+ ],
531
+ headerType: 1,
532
+ viewOnce: true
533
+ }, { quoted: m });
38
534
  ```
39
535
 
40
- #### Poll Result From Newsletter Message
41
- ```ts
42
- await client.sendMessage(
536
+ #### Interactive Message
537
+ ```javascript
538
+ let msg = generateWAMessageFromContent(m.chat, {
539
+ viewOnceMessage: {
540
+ message: {
541
+ "messageContextInfo": {
542
+ "deviceListMetadata": {},
543
+ "deviceListMetadataVersion": 2
544
+ },
545
+ interactiveMessage: proto.Message.InteractiveMessage.create({
546
+ body: proto.Message.InteractiveMessage.Body.create({
547
+ text: "Fizzxy Dev"
548
+ }),
549
+ footer: proto.Message.InteractiveMessage.Footer.create({
550
+ text: "Bot"
551
+ }),
552
+ header: proto.Message.InteractiveMessage.Header.create({
553
+ title: "Igna",
554
+ subtitle: "test",
555
+ hasMediaAttachment: false
556
+ }),
557
+ nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({
558
+ buttons: [
559
+ {
560
+ "name": "single_select",
561
+ "buttonParamsJson": "{\"title\":\"title\",\"sections\":[{\".menu\":\".play dj webito\",\"highlight_label\":\"label\",\"rows\":[{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"},{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"}]}]}"
562
+ },
563
+ {
564
+ "name": "cta_reply",
565
+ "buttonParamsJson": "{\"display_text\":\"quick_reply\",\"id\":\"message\"}"
566
+ },
567
+ {
568
+ "name": "cta_url",
569
+ "buttonParamsJson": "{\"display_text\":\"url\",\"url\":\"https://www.google.com\",\"merchant_url\":\"https://www.google.com\"}"
570
+ },
571
+ {
572
+ "name": "cta_call",
573
+ "buttonParamsJson": "{\"display_text\":\"call\",\"id\":\"message\"}"
574
+ },
575
+ {
576
+ "name": "cta_copy",
577
+ "buttonParamsJson": "{\"display_text\":\"copy\",\"id\":\"123456789\",\"copy_code\":\"message\"}"
578
+ },
579
+ {
580
+ "name": "cta_reminder",
581
+ "buttonParamsJson": "{\"display_text\":\"Recordatorio\",\"id\":\"message\"}"
582
+ },
583
+ {
584
+ "name": "cta_cancel_reminder",
585
+ "buttonParamsJson": "{\"display_text\":\"cta_cancel_reminder\",\"id\":\"message\"}"
586
+ },
587
+ {
588
+ "name": "address_message",
589
+ "buttonParamsJson": "{\"display_text\":\"address_message\",\"id\":\"message\"}"
590
+ },
591
+ {
592
+ "name": "send_location",
593
+ "buttonParamsJson": ""
594
+ }
595
+ ],
596
+ })
597
+ })
598
+ }
599
+ }
600
+ }, {})
601
+
602
+ return sock.relayMessage(msg.key.remoteJid, msg.message, { messageId: msg.key.id })
603
+ ```
604
+
605
+ #### Text Message
606
+ ```javascript
607
+ await sock.sendMessage(jid, { text: 'hello word' })
608
+ ```
609
+
610
+ #### Quote Message (works with all types)
611
+ ```javascript
612
+ await sock.sendMessage(jid, { text: 'hello word' }, { quoted: message })
613
+ ```
614
+
615
+ #### Mention User (works with most types)
616
+ - @number is to mention in text, it's optional
617
+ ```javascript
618
+ await sock.sendMessage(
43
619
  jid,
44
620
  {
45
- pollResult: {
46
- name: "Text poll",
47
- votes: [["Options 1", 10], ["Options 2", 10]], // 10 For Fake Polling Count Results
48
- }
49
- }, { quoted : message }
621
+ text: '@12345678901',
622
+ mentions: ['12345678901@s.whatsapp.net']
623
+ }
50
624
  )
51
625
  ```
52
626
 
53
-
54
- #### Status Mentions
55
- ```ts
627
+ #### Mention Status
628
+ - [ jid ] If the Jid Group and Jid Private Chat are included in the JID list, try to make the JID group first starting from the Jid Private Chat or Jid Private Chat in the middle between the group Jid
629
+ ```javascript
56
630
  await sock.StatusMentions(
57
631
  {
58
632
  text: "Hello", // or image / video / audio ( url or buffer )
@@ -61,73 +635,27 @@ await sock.StatusMentions(
61
635
  "123456789123456789@g.us",
62
636
  "123456789@s.whatsapp.net",
63
637
  // Enter jid chat here
64
- ] // If the Jid Group and Jid Private Chat are included in the JID list, try to make the JID group first starting from the Jid Private Chat or Jid Private Chat in the middle between the group Jid
638
+ ]
65
639
  )
66
640
  ```
67
641
 
68
-
69
- ##### Cards Message
70
- ```ts
642
+ #### Result Poll From Newsletter
643
+ ```javascript
71
644
  await client.sendMessage(
72
645
  jid,
73
646
  {
74
- text: "Hello",
75
- footer: "Footer Message",
76
- cards: [
77
- {
78
- image: { url: 'https://example.jpg' }, // or buffer,
79
- title: 'Title Cards',
80
- caption: 'Caption Cards',
81
- footer: 'Footer Cards',
82
- buttons: [
83
- {
84
- name: "quick_reply",
85
- buttonParamsJson: JSON.stringify({
86
- display_text: "Display Button",
87
- id: "ID"
88
- })
89
- },
90
- {
91
- name: "cta_url",
92
- buttonParamsJson: JSON.stringify({
93
- display_text: "Display Button",
94
- url: "https://www.example.com"
95
- })
96
- }
97
- ]
98
- },
99
- {
100
- video: { url: 'https://example.mp4' }, // or buffer,
101
- title: 'Title Cards',
102
- caption: 'Caption Cards',
103
- footer: 'Footer Cards',
104
- buttons: [
105
- {
106
- name: "quick_reply",
107
- buttonParamsJson: JSON.stringify({
108
- display_text: "Display Button",
109
- id: "ID"
110
- })
111
- },
112
- {
113
- name: "cta_url",
114
- buttonParamsJson: JSON.stringify({
115
- display_text: "Display Button",
116
- url: "https://www.example.com"
117
- })
118
- }
119
- ]
120
- }
121
- ]
122
- },
123
- { quoted : message }
647
+ pollResult: {
648
+ name: "Text poll",
649
+ votes: [["Options 1", 10], ["Options 2", 10]], // 10 For Fake Polling Count Results
650
+ }
651
+ }, { quoted : message }
124
652
  )
125
653
  ```
126
654
 
127
-
128
- #### Album Message
129
- ```ts
130
- await sock.AlbumMessage(
655
+ #### Send Album Message
656
+ - url or buffer ( image or video )
657
+ ```javascript
658
+ await sock.sendAlbumMessage(
131
659
  jid,
132
660
  [
133
661
  {
@@ -144,11 +672,11 @@ await sock.AlbumMessage(
144
672
  delay : 2000 // number in seconds
145
673
  }
146
674
  )
147
- ```
148
675
 
676
+ ```
149
677
 
150
- #### Interactive Response Message
151
- ```ts
678
+ #### Interactive Response
679
+ ```javascript
152
680
  await client.sendMessage(
153
681
  jid,
154
682
  {
@@ -162,119 +690,12 @@ await client.sendMessage(
162
690
  ephemeral: true,
163
691
  }
164
692
  )
165
- ```
166
-
167
693
 
168
- #### Keep Message
169
- - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object
170
-
171
- - Time can be:
172
-
173
- | Time | Seconds |
174
- |-------|----------------|
175
- | 24h | 86.400 |
176
- | 7d | 604.800 |
177
- | 30d | 2.592.000 |
178
-
179
- ```ts
180
- await client.sendMessage(
181
- jid,
182
- {
183
- keep: message.key,
184
- type: 1, // 2 to unpin
185
- time: 86400
186
- }
187
- )
188
694
  ```
189
695
 
190
-
191
- #### Pin Message
192
- - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object
193
-
194
- - Time can be:
195
-
196
- | Time | Seconds |
197
- |-------|----------------|
198
- | 24h | 86.400 |
199
- | 7d | 604.800 |
200
- | 30d | 2.592.000 |
201
-
202
- ```ts
203
- await client.sendMessage(
204
- jid,
205
- {
206
- pin: message.key
207
- type: 1, // 2 to unpin
208
- time: 86400
209
- }
210
- )
211
- ```
212
-
213
-
214
- #### Group Invite Message With Thumbnail According to Jid
215
- ```ts
216
- await client.sendMessage(
217
- jid,
218
- {
219
- groupInvite: {
220
- subject: "Your Group Name", // Group name
221
- jid: "1234@g.us", // Group ID
222
- text: "WhatsApp Group Invitation", // Additional information
223
- inviteCode: "CODE INVITATION", // Group invitation code
224
- inviteExpiration: 86400 * 3, // Expiration time in seconds (example: 86400 for 24 hours)
225
- }
226
- },
227
- {
228
- quoted: message,
229
- getProfilePicUrl: sock.profilePictureUrl
230
- }
231
- )
232
- ```
233
-
234
-
235
- #### Group Invite Message With Thumbnail Custom
236
- ```ts
237
- const thumbnail = "https://example.jpg" // or buffer
238
- // The image is used under 300 so that the thumbnail can be displayed
239
- let Jimp = require("jimp");
240
- // import Jimp from "jimp"; => for type esm
241
- let img = await Jimp.read(thumbnail);
242
- let newWidth = img.bitmap.width;
243
- let newHeight = img.bitmap.height;
244
- if (newWidth > 300 || newHeight > 300) {
245
- const aspectRatio = newWidth / newHeight;
246
- if (aspectRatio > 1) {
247
- newWidth = 300;
248
- newHeight = Math.round(newWidth / aspectRatio);
249
- } else {
250
- newHeight = 300;
251
- newWidth = Math.round(newHeight * aspectRatio);
252
- }
253
- }
254
- let buff = await img
255
- .resize(newWidth, newHeight)
256
- .getBufferAsync(Jimp.MIME_JPEG);
257
-
258
- await client.sendMessage(
259
- jid,
260
- {
261
- groupInvite: {
262
- subject: "Your Group Name", // Group name
263
- jid: "1234@g.us", // Group ID
264
- text: "WhatsApp Group Invitation", // Additional information
265
- inviteCode: "CODE INVITATION", // Group invitation code
266
- inviteExpiration: number, // Expiration time in seconds (example: 86400 for 24 hours),
267
- thumbnail: buff || null // if result not found or error
268
- }
269
- },
270
- { quoted: message }
271
- )
272
- ```
273
-
274
-
275
- #### Request Payment Message Available To Quote Message
276
- ```ts
277
- // Example non media sticker
696
+ #### Request Payment
697
+ ```javascript
698
+ - Example non media sticker
278
699
  await client.sendMessage(
279
700
  jid,
280
701
  {
@@ -289,8 +710,7 @@ await client.sendMessage(
289
710
  { quoted : message }
290
711
  )
291
712
 
292
-
293
- // with media sticker buffer
713
+ - with media sticker buffer
294
714
  await client.sendMessage(
295
715
  jid,
296
716
  {
@@ -305,8 +725,7 @@ await client.sendMessage(
305
725
  { quoted : message }
306
726
  )
307
727
 
308
-
309
- // with media sticker url
728
+ - with media sticker url
310
729
  await client.sendMessage(
311
730
  jid,
312
731
  {
@@ -322,9 +741,8 @@ await client.sendMessage(
322
741
  )
323
742
  ```
324
743
 
325
-
326
744
  #### Event Message
327
- ```ts
745
+ ```javascript
328
746
  await client.sendMessage(
329
747
  jid,
330
748
  {
@@ -338,35 +756,17 @@ await client.sendMessage(
338
756
  },
339
757
  link: Call Link,
340
758
  startTime: m.messageTimestamp.low,
341
- endTime: m.messageTimestamp.low + 86400, // 86400 is day in seconds
342
- extraGuestsAllowed: true // or false
343
- }
344
- },
345
- { quoted : message }
346
- )
347
- ```
348
-
349
-
350
- #### Poll Message
351
- ```ts
352
- await client.sendMessage(
353
- jid,
354
- {
355
- poll: {
356
- name: 'My Poll',
357
- values: ['Option 1', 'Option 2', ...],
358
- selectableCount: 1,
359
- toAnnouncementGroup: false // or true
360
- }
361
- },
362
- { quoted : message }
759
+ endTime: m.messageTimestamp.low + 86400, // 86400 is day in seconds
760
+ extraGuestsAllowed: true // or false
761
+ }
762
+ },
763
+ { quoted : message }
363
764
  )
364
765
  ```
365
766
 
366
-
367
- #### Interactive Message
368
- ```ts
369
- // Example non header media
767
+ #### Interactive
768
+ ```javascript
769
+ - Example non header media
370
770
  await client.sendMessage(
371
771
  jid,
372
772
  {
@@ -396,7 +796,7 @@ await client.sendMessage(
396
796
  }
397
797
  )
398
798
 
399
- // Example with media
799
+ - Example with media
400
800
  await client.sendMessage(
401
801
  jid,
402
802
  {
@@ -428,7 +828,7 @@ await client.sendMessage(
428
828
  }
429
829
  )
430
830
 
431
- // Example with header product
831
+ - Example with header product
432
832
  await client.sendMessage(
433
833
  jid,
434
834
  {
@@ -470,1167 +870,795 @@ await client.sendMessage(
470
870
  )
471
871
  ```
472
872
 
473
- ## Buttons Message:
474
- ```
475
- // send old a buttons
476
- client.sendMessage(m.chat, {
477
- text: "Hello World !",
478
- footer: "Indraazy - 2025",
479
- buttons: [
480
- { buttonId: `🚀`,
481
- buttonText: {
482
- displayText: '🗿'
483
- }, type: 1 }
484
- ],
485
- headerType: 1,
486
- viewOnce: true
487
- },{ quoted: null })
488
- ```
489
-
490
- ## send location buttons:
491
- ```
492
- client.sendMessage(m.chat, {
493
- location: {
494
- degreesLatitude: -6.2088, // Ganti dengan latitude lokasi
495
- degreesLongitude: 106.8456, // Ganti dengan longitude lokasi
496
- },
497
- caption: "Ini adalah lokasi yang dikirim.",
498
- footer: "© dcodeindraa",
499
- buttons: [
500
- { buttonId: `🚀`,
501
- buttonText: {
502
- displayText: '🗿'
503
- },
504
- type: 1 }
505
- ], // isi buttons nya
506
- headerType: 6,
507
- viewOnce: true
508
- }, { quoted: m });
873
+ #### Forward Messages
874
+ - You need to have message object, can be retrieved from [store](#implementing-a-data-store) or use a [message](https://baileys.whiskeysockets.io/types/WAMessage.html) object
875
+ ```javascript
876
+ const msg = getMessageFromStore() // implement this on your end
877
+ await sock.sendMessage(jid, { forward: msg }) // WA forward the message!
509
878
  ```
510
879
 
511
-
512
- ## send image buttons:
513
- ```
514
- client.sendMessage(m.chat, {
515
- image: { url: "LINK YOUR IMAGE" },
516
- caption: "Ini pesan gambar Buttons",
517
- footer: "© Indraazy Dev",
518
- buttons: [
519
- {
520
- buttonId: '.owner',
521
- buttonText: {
522
- displayText: 'Dev bot'
523
- },
524
- type: 1
525
- },
526
- ],
527
- headerType: 1,
528
- viewOnce: true
529
- }, { quoted: m })
530
- ```
531
-
532
- ## send document buttons:
533
- ```
534
- let buttonMessage = {
535
- document: { url: "https://www.youtube.com/" },
536
- mimetype: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
537
- fileName: "「 dcodeindraa 」",
538
- fileLength: 999,
539
- pageCount: 999,
540
- contextInfo: {
541
- forwardingScore: 555,
542
- isForwarded: true,
543
- externalAdReply: {
544
- mediaUrl: "https://www.youtube.com/",
545
- mediaType: 2,
546
- previewType: "pdf",
547
- title: "kamu mana punya",
548
- body: "ini",
549
- thumbnail: fs.readFileSync("./path/to/image"),
550
- sourceUrl: "https://www.youtube.com/",
551
- },
552
- },
553
- caption: "tes",
554
- footer: "2020",
555
- buttons: [
880
+ #### Location Message
881
+ ```javascript
882
+ await sock.sendMessage(
883
+ jid,
556
884
  {
557
- buttonId: "ID MU",
558
- buttonText: {
559
- displayText: 'Display text'
560
- }
561
- }, {
562
- buttonId: "ID MU",
563
- buttonText: {
564
- displayText: "DISPLAY TEXT"
885
+ location: {
886
+ degreesLatitude: 24.121231,
887
+ degreesLongitude: 55.1121221
888
+ }
565
889
  }
566
- }
567
- ],
568
- viewOnce: true,
569
- headerType: 6,
570
- };
571
-
572
- return await client.sendMessage(m.chat, buttonMessage, { quoted: null });
890
+ )
573
891
  ```
892
+ #### Contact Message
893
+ ```javascript
894
+ const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
895
+ + 'VERSION:3.0\n'
896
+ + 'FN:Jeff Singh\n' // full name
897
+ + 'ORG:Ashoka Uni;\n' // the organization of the contact
898
+ + 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number
899
+ + 'END:VCARD'
574
900
 
575
- ## send all buttons interactive:
576
- ```
577
- const { generateWAMessageFromContent, proto } = require("@indraazy/baileys")
578
- let msg = generateWAMessageFromContent(m.chat, {
579
- viewOnceMessage: {
580
- message: {
581
- "messageContextInfo": {
582
- "deviceListMetadata": {},
583
- "deviceListMetadataVersion": 2
584
- },
585
- interactiveMessage: proto.Message.InteractiveMessage.create({
586
- body: proto.Message.InteractiveMessage.Body.create({
587
- text: "Indraazy Dev"
588
- }),
589
- footer: proto.Message.InteractiveMessage.Footer.create({
590
- text: "Bot"
591
- }),
592
- header: proto.Message.InteractiveMessage.Header.create({
593
- title: "Igna",
594
- subtitle: "test",
595
- hasMediaAttachment: false
596
- }),
597
- nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({
598
- buttons: [
599
- {
600
- "name": "single_select",
601
- "buttonParamsJson": "{\"title\":\"title\",\"sections\":[{\".menu\":\".play dj webito\",\"highlight_label\":\"label\",\"rows\":[{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"},{\"header\":\"header\",\"title\":\"title\",\"description\":\"description\",\"id\":\"id\"}]}]}"
602
- },
603
- {
604
- "name": "cta_reply",
605
- "buttonParamsJson": "{\"display_text\":\"quick_reply\",\"id\":\"message\"}"
606
- },
607
- {
608
- "name": "cta_url",
609
- "buttonParamsJson": "{\"display_text\":\"url\",\"url\":\"https://www.google.com\",\"merchant_url\":\"https://www.google.com\"}"
610
- },
611
- {
612
- "name": "cta_call",
613
- "buttonParamsJson": "{\"display_text\":\"call\",\"id\":\"message\"}"
614
- },
615
- {
616
- "name": "cta_copy",
617
- "buttonParamsJson": "{\"display_text\":\"copy\",\"id\":\"123456789\",\"copy_code\":\"message\"}"
618
- },
619
- {
620
- "name": "cta_reminder",
621
- "buttonParamsJson": "{\"display_text\":\"Recordatorio\",\"id\":\"message\"}"
622
- },
623
- {
624
- "name": "cta_cancel_reminder",
625
- "buttonParamsJson": "{\"display_text\":\"cta_cancel_reminder\",\"id\":\"message\"}"
626
- },
627
- {
628
- "name": "address_message",
629
- "buttonParamsJson": "{\"display_text\":\"address_message\",\"id\":\"message\"}"
630
- },
631
- {
632
- "name": "send_location",
633
- "buttonParamsJson": ""
634
- }
635
- ],
636
- })
637
- })
901
+ await sock.sendMessage(
902
+ id,
903
+ {
904
+ contacts: {
905
+ displayName: 'Jeff',
906
+ contacts: [{ vcard }]
907
+ }
638
908
  }
639
- }
640
- }, {})
641
-
642
- return client.relayMessage(msg.key.remoteJid, msg.message, { messageId: msg.key.id })
643
- ```
644
-
645
- ## buttons double:
646
- ```
647
- client.sendMessage(m.key.remoteJid, {
648
- text: "Hello Wolrd !;",
649
- footer: "© Indraazy Dev",
650
- buttons: [
651
- {
652
- buttonId: '.tes',
653
- buttonText: {
654
- displayText: 'TESTING BOT'
655
- },
656
- type: 1,
657
- },
658
- {
659
- buttonId: ' ',
660
- buttonText: {
661
- displayText: 'PRIVATE SCRIPT'
662
- },
663
- type: 1,
664
- },
665
- {
666
- buttonId: 'action',
667
- buttonText: {
668
- displayText: 'ini pesan interactiveMeta'
669
- },
670
- type: 4,
671
- nativeFlowInfo: {
672
- name: 'single_select',
673
- paramsJson: JSON.stringify({
674
- title: 'message',
675
- sections: [
676
- {
677
- title: 'IndraazyDev - 2025',
678
- highlight_label: '😜',
679
- rows: [
680
- {
681
- header: 'HEADER',
682
- title: 'TITLE',
683
- description: 'DESCRIPTION',
684
- id: 'YOUR ID',
685
- },
686
- {
687
- header: 'HEADER',
688
- title: 'TITLE',
689
- description: 'DESCRIPTION',
690
- id: 'YOUR ID',
691
- },
692
- ],
693
- },
694
- ],
695
- }),
696
- },
697
- },
698
- ],
699
- headerType: 1,
700
- viewOnce: true
701
- }, { quoted: m });
702
- ```
703
- ## Example
704
-
705
- Do check out & run [example.ts](Example/example.ts) to see an example usage of the library.
706
- The script covers most common use cases.
707
- To run the example script, download or clone the repo and then type the following in a terminal:
708
- 1. ``` cd path/to/BaileysPro ```
709
- 2. ``` yarn ```
710
- 3. ``` yarn example ```
711
-
712
- ## Install
713
-
714
- Use the stable version:
715
- ```
716
- yarn add @indraazy/baileys
717
- ```
718
-
719
- Use the edge version (no guarantee of stability, but latest fixes + features)
720
- ```
721
- yarn add github:IndraazyDev/BaileysV2
722
- ```
723
-
724
- Then import your code using:
725
- ``` ts
726
- import makeWASocket from '@indraazy/baileys'
909
+ )
727
910
  ```
728
911
 
729
- ## Unit Tests
730
-
731
- TODO
732
-
733
- ## Connecting multi device (recommended)
734
-
735
- WhatsApp provides a multi-device API that allows BaileysPro to be authenticated as a second WhatsApp client by scanning a QR code with WhatsApp on your phone.
736
-
737
- ``` ts
738
- import makeWASocket, { DisconnectReason } from '@indraazy/baileys'
739
- import { Boom } from '@hapi/boom'
740
-
741
- async function connectToWhatsApp () {
742
- const sock = makeWASocket({
743
- // can provide additional config here
744
- printQRInTerminal: true
745
- })
746
- sock.ev.on('connection.update', (update) => {
747
- const { connection, lastDisconnect } = update
748
- if(connection === 'close') {
749
- const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
750
- console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
751
- // reconnect if not logged out
752
- if(shouldReconnect) {
753
- connectToWhatsApp()
754
- }
755
- } else if(connection === 'open') {
756
- console.log('opened connection')
912
+ #### Reaction Message
913
+ - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object
914
+ ```javascript
915
+ await sock.sendMessage(
916
+ jid,
917
+ {
918
+ react: {
919
+ text: '💖', // use an empty string to remove the reaction
920
+ key: message.key
757
921
  }
758
- })
759
- sock.ev.on('messages.upsert', m => {
760
- console.log(JSON.stringify(m, undefined, 2))
761
-
762
- console.log('replying to', m.messages[0].key.remoteJid)
763
- await client.sendMessage(m.messages[0].key.remoteJid!, { text: 'Hello there!' })
764
- })
765
- }
766
- // run in main file
767
- connectToWhatsApp()
768
- ```
769
-
770
- 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!
771
-
772
- **Note:** install `qrcode-terminal` using `yarn add qrcode-terminal` to auto-print the QR to the terminal.
773
-
774
- **Note:** the code to support the legacy version of WA Web (pre multi-device) has been removed in v5. Only the standard multi-device connection is now supported. This is done as WA seems to have completely dropped support for the legacy version.
775
-
776
- ## Connecting native mobile api
777
-
778
- BaileysPro also supports the native mobile API, which allows users to authenticate as a standalone WhatsApp client using their phone number.
779
-
780
- Run the [example](Example/example.ts) file with ``--mobile`` cli flag to use the native mobile API.
781
-
782
- ## Configuring the Connection
783
-
784
- You can configure the connection by passing a `SocketConfig` object.
785
-
786
- The entire `SocketConfig` structure is mentioned here with default values:
787
- ``` ts
788
- type SocketConfig = {
789
- /** the WS url to connect to WA */
790
- waWebSocketUrl: string | URL
791
- /** Fails the connection if the socket times out in this interval */
792
- connectTimeoutMs: number
793
- /** Default timeout for queries, undefined for no timeout */
794
- defaultQueryTimeoutMs: number | undefined
795
- /** ping-pong interval for WS connection */
796
- keepAliveIntervalMs: number
797
- /** proxy agent */
798
- agent?: Agent
799
- /** pino logger */
800
- logger: Logger
801
- /** version to connect with */
802
- version: WAVersion
803
- /** override browser config */
804
- browser: WABrowserDescription
805
- /** agent used for fetch requests -- uploading/downloading media */
806
- fetchAgent?: Agent
807
- /** should the QR be printed in the terminal */
808
- printQRInTerminal: boolean
809
- /** should events be emitted for actions done by this socket connection */
810
- emitOwnEvents: boolean
811
- /** provide a cache to store media, so does not have to be re-uploaded */
812
- mediaCache?: NodeCache
813
- /** custom upload hosts to upload media to */
814
- customUploadHosts: MediaConnInfo['hosts']
815
- /** time to wait between sending new retry requests */
816
- retryRequestDelayMs: number
817
- /** max msg retry count */
818
- maxMsgRetryCount: number
819
- /** time to wait for the generation of the next QR in ms */
820
- qrTimeout?: number;
821
- /** provide an auth state object to maintain the auth state */
822
- auth: AuthenticationState
823
- /** manage history processing with this control; by default will sync up everything */
824
- shouldSyncHistoryMessage: (msg: proto.Message.IHistorySyncNotification) => boolean
825
- /** transaction capability options for SignalKeyStore */
826
- transactionOpts: TransactionCapabilityOptions
827
- /** provide a cache to store a user's device list */
828
- userDevicesCache?: NodeCache
829
- /** marks the client as online whenever the socket successfully connects */
830
- markOnlineOnConnect: boolean
831
- /**
832
- * map to store the retry counts for failed messages;
833
- * used to determine whether to retry a message or not */
834
- msgRetryCounterMap?: MessageRetryMap
835
- /** width for link preview images */
836
- linkPreviewImageThumbnailWidth: number
837
- /** Should BaileysPro ask the phone for full history, will be received async */
838
- syncFullHistory: boolean
839
- /** Should BaileysPro fire init queries automatically, default true */
840
- fireInitQueries: boolean
841
- /**
842
- * generate a high quality link preview,
843
- * entails uploading the jpegThumbnail to WA
844
- * */
845
- generateHighQualityLinkPreview: boolean
846
-
847
- /** options for axios */
848
- options: AxiosRequestConfig<any>
849
- /**
850
- * fetch a message from your store
851
- * implement this so that messages failed to send (solves the "this message can take a while" issue) can be retried
852
- * */
853
- getMessage: (key: proto.IMessageKey) => Promise<proto.IMessage | undefined>
854
- }
855
- ```
856
-
857
- ### Emulating the Desktop app instead of the web
858
-
859
- 1. BaileysPro, by default, emulates a chrome web session
860
- 2. If you'd like to emulate a desktop connection (and receive more message history), add this to your Socket config:
861
- ``` ts
862
- const conn = makeWASocket({
863
- ...otherOpts,
864
- // can use Windows, Ubuntu here too
865
- browser: Browsers.macOS('Desktop'),
866
- syncFullHistory: true
867
- })
868
- ```
869
-
870
- ## Saving & Restoring Sessions
871
-
872
- You obviously don't want to keep scanning the QR code every time you want to connect.
873
-
874
- So, you can load the credentials to log back in:
875
- ``` ts
876
- import makeWASocket, { BufferJSON, useMultiFileAuthState } from '@indraazy/baileys'
877
- import * as fs from 'fs'
878
-
879
- // utility function to help save the auth state in a single folder
880
- // 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
881
- const { state, saveCreds } = await useMultiFileAuthState('auth_info_BaileysPro')
882
- // will use the given state to connect
883
- // so if valid credentials are available -- it'll connect without QR
884
- const conn = makeWASocket({ auth: state })
885
- // this will be called as soon as the credentials are updated
886
- conn.ev.on ('creds.update', saveCreds)
887
- ```
888
-
889
- **Note:** 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.
890
-
891
- ## Listening to Connection Updates
892
-
893
- BaileysPro now fires the `connection.update` event to let you know something has updated in the connection. This data has the following structure:
894
- ``` ts
895
- type ConnectionState = {
896
- /** connection is now open, connecting or closed */
897
- connection: WAConnectionState
898
- /** the error that caused the connection to close */
899
- lastDisconnect?: {
900
- error: Error
901
- date: Date
902
- }
903
- /** is this a new login */
904
- isNewLogin?: boolean
905
- /** the current QR code */
906
- qr?: string
907
- /** has the device received all pending notifications while it was offline */
908
- receivedPendingNotifications?: boolean
909
- }
910
- ```
911
-
912
- **Note:** this also offers any updates to the QR
913
-
914
- ## Handling Events
915
-
916
- BaileysPro uses the EventEmitter syntax for events.
917
- They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
918
-
919
- The events are typed as mentioned here:
920
-
921
- ``` ts
922
-
923
- export type BaileysProEventMap = {
924
- /** connection state has been updated -- WS closed, opened, connecting etc. */
925
- 'connection.update': Partial<ConnectionState>
926
- /** credentials updated -- some metadata, keys or something */
927
- 'creds.update': Partial<AuthenticationCreds>
928
- /** history sync, everything is reverse chronologically sorted */
929
- 'messaging-history.set': {
930
- chats: Chat[]
931
- contacts: Contact[]
932
- messages: WAMessage[]
933
- isLatest: boolean
934
922
  }
935
- /** upsert chats */
936
- 'chats.upsert': Chat[]
937
- /** update the given chats */
938
- 'chats.update': Partial<Chat>[]
939
- /** delete chats with given ID */
940
- 'chats.delete': string[]
941
- 'labels.association': LabelAssociation
942
- 'labels.edit': Label
943
- /** presence of contact in a chat updated */
944
- 'presence.update': { id: string, presences: { [participant: string]: PresenceData } }
945
-
946
- 'contacts.upsert': Contact[]
947
- 'contacts.update': Partial<Contact>[]
948
-
949
- 'messages.delete': { keys: WAMessageKey[] } | { jid: string, all: true }
950
- 'messages.update': WAMessageUpdate[]
951
- 'messages.media-update': { key: WAMessageKey, media?: { ciphertext: Uint8Array, iv: Uint8Array }, error?: Boom }[]
952
- /**
953
- * add/update the given messages. If they were received while the connection was online,
954
- * the update will have type: "notify"
955
- * */
956
- 'messages.upsert': { messages: WAMessage[], type: MessageUpsertType }
957
- /** message was reacted to. If reaction was removed -- then "reaction.text" will be falsey */
958
- 'messages.reaction': { key: WAMessageKey, reaction: proto.IReaction }[]
959
-
960
- 'message-receipt.update': MessageUserReceiptUpdate[]
961
-
962
- 'groups.upsert': GroupMetadata[]
963
- 'groups.update': Partial<GroupMetadata>[]
964
- /** apply an action to participants in a group */
965
- 'group-participants.update': { id: string, participants: string[], action: ParticipantAction }
966
-
967
- 'blocklist.set': { blocklist: string[] }
968
- 'blocklist.update': { blocklist: string[], type: 'add' | 'remove' }
969
- /** Receive an update on a call, including when the call was received, rejected, accepted */
970
- 'call': WACallEvent[]
971
- }
972
- ```
973
-
974
- You can listen to these events like this:
975
- ``` ts
976
-
977
- const sock = makeWASocket()
978
- sock.ev.on('messages.upsert', ({ messages }) => {
979
- console.log('got messages', messages)
980
- })
981
-
923
+ )
982
924
  ```
983
925
 
984
- ## Implementing a Data Store
985
-
986
- BaileysPro 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.
987
-
988
- It can be used as follows:
989
-
990
- ``` ts
991
- import makeWASocket, { makeInMemoryStore } from '@indraazy/baileys'
992
- // the store maintains the data of the WA connection in memory
993
- // can be written out to a file & read from it
994
- const store = makeInMemoryStore({ })
995
- // can be read from a file
996
- store.readFromFile('./BaileysPro_store.json')
997
- // saves the state to a file every 10s
998
- setInterval(() => {
999
- store.writeToFile('./BaileysPro_store.json')
1000
- }, 10_000)
1001
-
1002
- const sock = makeWASocket({ })
1003
- // will listen from this socket
1004
- // the store can listen from a new socket once the current socket outlives its lifetime
1005
- store.bind(sock.ev)
926
+ #### Pin Message
927
+ - You need to pass the key of message, you can retrieve from [store](#implementing-a-data-store) or use a [key](https://baileys.whiskeysockets.io/types/WAMessageKey.html) object
1006
928
 
1007
- sock.ev.on('chats.set', () => {
1008
- // can use "store.chats" however you want, even after the socket dies out
1009
- // "chats" => a KeyedDB instance
1010
- console.log('got chats', store.chats.all())
1011
- })
929
+ - Time can be:
1012
930
 
1013
- sock.ev.on('contacts.set', () => {
1014
- console.log('got contacts', Object.values(store.contacts))
1015
- })
931
+ | Time | Seconds |
932
+ |-------|----------------|
933
+ | 24h | 86.400 |
934
+ | 7d | 604.800 |
935
+ | 30d | 2.592.000 |
1016
936
 
937
+ ```javascript
938
+ await sock.sendMessage(
939
+ jid,
940
+ {
941
+ pin: {
942
+ type: 1, // 0 to remove
943
+ time: 86400
944
+ key: message.key
945
+ }
946
+ }
947
+ )
1017
948
  ```
1018
949
 
1019
- The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval.
1020
-
1021
- **Note:** I highly recommend building your own data store especially for MD connections, as storing someone's entire chat history in memory is a terrible waste of RAM.
1022
-
1023
- ## Sending Messages
1024
-
1025
- **Send all types of messages with a single function:**
1026
-
1027
- ### Non-Media Messages
1028
-
1029
- ``` ts
1030
- import { MessageType, MessageOptions, Mimetype } from '@indraazy/baileys'
1031
-
1032
- const id = 'abcd@s.whatsapp.net' // the WhatsApp ID
1033
- // send a simple text!
1034
- const sentMsg = await client.sendMessage(id, { text: 'oh hello there' })
1035
- // send a reply messagge
1036
- const sentMsg = await client.sendMessage(id, { text: 'oh hello there' }, { quoted: message })
1037
- // send a mentions message
1038
- const sentMsg = await client.sendMessage(id, { text: '@12345678901', mentions: ['12345678901@s.whatsapp.net'] })
1039
- // send a location!
1040
- const sentMsg = await client.sendMessage(
1041
- id,
1042
- { location: { degreesLatitude: 24.121231, degreesLongitude: 55.1121221 } }
1043
- )
1044
- // send a contact!
1045
- const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
1046
- + 'VERSION:3.0\n'
1047
- + 'FN:Jeff Singh\n' // full name
1048
- + 'ORG:Ashoka Uni;\n' // the organization of the contact
1049
- + 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number
1050
- + 'END:VCARD'
1051
- const sentMsg = await client.sendMessage(
1052
- id,
1053
- {
1054
- contacts: {
1055
- displayName: 'Jeff',
1056
- contacts: [{ vcard }]
950
+ #### Poll Message
951
+ ```javascript
952
+ await sock.sendMessage(
953
+ jid,
954
+ {
955
+ poll: {
956
+ name: 'My Poll',
957
+ values: ['Option 1', 'Option 2', ...],
958
+ selectableCount: 1,
959
+ toAnnouncementGroup: false // or true
1057
960
  }
1058
961
  }
1059
962
  )
1060
-
1061
- const reactionMessage = {
1062
- react: {
1063
- text: "💖", // use an empty string to remove the reaction
1064
- key: message.key
1065
- }
1066
- }
1067
-
1068
- const sendMsg = await client.sendMessage(id, reactionMessage)
1069
963
  ```
1070
964
 
1071
- ### Sending messages with link previews
965
+ ### Sending Messages with Link Previews
1072
966
 
1073
- 1. By default, WA MD does not have link generation when sent from the web
1074
- 2. BaileysPro has a function to generate the content for these link previews
967
+ 1. By default, wa does not have link generation when sent from the web
968
+ 2. Baileys has a function to generate the content for these link previews
1075
969
  3. To enable this function's usage, add `link-preview-js` as a dependency to your project with `yarn add link-preview-js`
1076
970
  4. Send a link:
1077
- ``` ts
1078
- // send a link
1079
- const sentMsg = await client.sendMessage(id, { text: 'Hi, this was sent using https://github.com/adiwajshing/BaileysPro' })
971
+ ```javascript
972
+ await sock.sendMessage(
973
+ jid,
974
+ {
975
+ text: 'Hi, this was sent using https://github.com/whiskeysockets/baileys'
976
+ }
977
+ )
1080
978
  ```
1081
979
 
1082
980
  ### Media Messages
1083
981
 
1084
- Sending media (video, stickers, images) is easier & more efficient than ever.
1085
- - You can specify a buffer, a local url or even a remote url.
1086
- - When specifying a media url, BaileysPro never loads the entire buffer into memory; it even encrypts the media as a readable stream.
982
+ Sending media (video, stickers, images) is easier & more efficient than ever.
1087
983
 
1088
- ``` ts
1089
- import { MessageType, MessageOptions, Mimetype } from '@indraazy/baileys'
1090
- // Sending gifs
1091
- await client.sendMessage(
1092
- id,
1093
- {
1094
- video: fs.readFileSync("Media/ma_gif.mp4"),
1095
- caption: "hello!",
984
+ > [!NOTE]
985
+ > In media messages, you can pass `{ stream: Stream }` or `{ url: Url }` or `Buffer` directly, you can see more [here](https://baileys.whiskeysockets.io/types/WAMediaUpload.html)
986
+
987
+ - When specifying a media url, Baileys never loads the entire buffer into memory; it even encrypts the media as a readable stream.
988
+
989
+ > [!TIP]
990
+ > It's recommended to use Stream or Url to save memory
991
+
992
+ #### Gif Message
993
+ - Whatsapp doesn't support `.gif` files, that's why we send gifs as common `.mp4` video with `gifPlayback` flag
994
+ ```javascript
995
+ await sock.sendMessage(
996
+ jid,
997
+ {
998
+ video: fs.readFileSync('Media/ma_gif.mp4'),
999
+ caption: 'hello word',
1096
1000
  gifPlayback: true
1097
1001
  }
1098
1002
  )
1003
+ ```
1099
1004
 
1100
- await client.sendMessage(
1101
- id,
1102
- {
1103
- video: "./Media/ma_gif.mp4",
1104
- caption: "hello!",
1105
- gifPlayback: true
1005
+ #### Video Message
1006
+ ```javascript
1007
+ await sock.sendMessage(
1008
+ id,
1009
+ {
1010
+ video: {
1011
+ url: './Media/ma_gif.mp4'
1012
+ },
1013
+ caption: 'hello word',
1014
+ ptv: false // if set to true, will send as a `video note`
1106
1015
  }
1107
1016
  )
1017
+ ```
1108
1018
 
1109
- // send an audio file
1110
- await client.sendMessage(
1111
- id,
1112
- { audio: { url: "./Media/audio.mp3" }, mimetype: 'audio/mp4' }
1113
- { url: "Media/audio.mp3" }, // can send mp3, mp4, & ogg
1019
+ #### Audio Message
1020
+ - To audio message work in all devices you need to convert with some tool like `ffmpeg` with this flags:
1021
+ ```bash
1022
+ codec: libopus //ogg file
1023
+ ac: 1 //one channel
1024
+ avoid_negative_ts
1025
+ make_zero
1026
+ ```
1027
+ - Example:
1028
+ ```bash
1029
+ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1030
+ ```
1031
+ ```javascript
1032
+ await sock.sendMessage(
1033
+ jid,
1034
+ {
1035
+ audio: {
1036
+ url: './Media/audio.mp3'
1037
+ },
1038
+ mimetype: 'audio/mp4'
1039
+ }
1114
1040
  )
1115
1041
  ```
1116
1042
 
1117
- ### Notes
1118
-
1119
- - `id` is the WhatsApp ID of the person or group you're sending the message to.
1120
- - It must be in the format ```[country code][phone number]@s.whatsapp.net```
1121
- - Example for people: ```+19999999999@s.whatsapp.net```.
1122
- - For groups, it must be in the format ``` 123456789-123345@g.us ```.
1123
- - For broadcast lists, it's `[timestamp of creation]@broadcast`.
1124
- - For stories, the ID is `status@broadcast`.
1125
- - 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`. Thumbnails for videos can also be generated automatically, though, you need to have `ffmpeg` installed on your system.
1126
- - **MiscGenerationOptions**: some extra info about the message. It can have the following __optional__ values:
1127
- ``` ts
1128
- const info: MessageOptions = {
1129
- quoted: quotedMessage, // the message you want to quote
1130
- contextInfo: { forwardingScore: 2, isForwarded: true }, // some random context info (can show a forwarded message with this too)
1131
- timestamp: Date(), // optional, if you want to manually set the timestamp of the message
1132
- caption: "hello there!", // (for media messages) the caption to send with the media (cannot be sent with stickers though)
1133
- jpegThumbnail: "23GD#4/==", /* (for location & media messages) has to be a base 64 encoded JPEG if you want to send a custom thumb,
1134
- or set to null if you don't want to send a thumbnail.
1135
- Do not enter this field if you want to automatically generate a thumb
1136
- */
1137
- mimetype: Mimetype.pdf, /* (for media messages) specify the type of media (optional for all media types except documents),
1138
- import {Mimetype} from '@indraazy/baileys'
1139
- */
1140
- fileName: 'somefile.pdf', // (for media messages) file name for the media
1141
- /* will send audio messages as voice notes, if set to true */
1142
- ptt: true,
1143
- /** Should it send as a disappearing messages.
1144
- * By default 'chat' -- which follows the setting of the chat */
1145
- ephemeralExpiration: WA_DEFAULT_EPHEMERAL
1043
+ #### Image Message
1044
+ ```javascript
1045
+ await sock.sendMessage(
1046
+ id,
1047
+ {
1048
+ image: {
1049
+ url: './Media/ma_img.png'
1050
+ },
1051
+ caption: 'hello word'
1146
1052
  }
1147
- ```
1148
- ## Forwarding Messages
1149
-
1150
- ``` ts
1151
- const msg = getMessageFromStore('455@s.whatsapp.net', 'HSJHJWH7323HSJSJ') // implement this on your end
1152
- await client.sendMessage('1234@s.whatsapp.net', { forward: msg }) // WA forward the message!
1053
+ )
1153
1054
  ```
1154
1055
 
1155
- ## Reading Messages
1056
+ #### View Once Message
1156
1057
 
1157
- A set of message keys must be explicitly marked read now.
1158
- In multi-device, you cannot mark an entire "chat" read as it were with BaileysPro Web.
1159
- This means you have to keep track of unread messages.
1058
+ - You can send all messages above as `viewOnce`, you only need to pass `viewOnce: true` in content object
1160
1059
 
1161
- ``` ts
1162
- const key = {
1163
- remoteJid: '1234-123@g.us',
1164
- id: 'AHASHH123123AHGA', // id of the message you want to read
1165
- participant: '912121232@s.whatsapp.net' // the ID of the user that sent the message (undefined for individual chats)
1166
- }
1167
- // pass to readMessages function
1168
- // can pass multiple keys to read multiple messages as well
1169
- await sock.readMessages([key])
1060
+ ```javascript
1061
+ await sock.sendMessage(
1062
+ id,
1063
+ {
1064
+ image: {
1065
+ url: './Media/ma_img.png'
1066
+ },
1067
+ viewOnce: true, //works with video, audio too
1068
+ caption: 'hello word'
1069
+ }
1070
+ )
1170
1071
  ```
1171
1072
 
1172
- The message ID is the unique identifier of the message that you are marking as read.
1173
- On a `WAMessage`, the `messageID` can be accessed using ```messageID = message.key.id```.
1174
-
1175
- ## Update Presence
1073
+ ## Modify Messages
1176
1074
 
1177
- ``` ts
1178
- await sock.sendPresenceUpdate('available', id)
1075
+ ### Deleting Messages (for everyone)
1179
1076
 
1077
+ ```javascript
1078
+ const msg = await sock.sendMessage(jid, { text: 'hello word' })
1079
+ await sock.sendMessage(jid, { delete: msg.key })
1180
1080
  ```
1181
- This lets the person/group with ``` id ``` know whether you're online, offline, typing etc.
1182
1081
 
1183
- ``` presence ``` can be one of the following:
1184
- ``` ts
1185
- type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused'
1082
+ **Note:** deleting for oneself is supported via `chatModify`, see in [this section](#modifying-chats)
1083
+
1084
+ ### Editing Messages
1085
+
1086
+ - You can pass all editable contents here
1087
+ ```javascript
1088
+ await sock.sendMessage(jid, {
1089
+ text: 'updated text goes here',
1090
+ edit: response.key,
1091
+ });
1186
1092
  ```
1187
1093
 
1188
- The presence expires after about 10 seconds.
1094
+ ## Manipulating Media Messages
1189
1095
 
1190
- **Note:** In the multi-device version of WhatsApp -- 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 BaileysPro client offline using `sock.sendPresenceUpdate('unavailable')`
1096
+ ### Thumbnail in Media Messages
1097
+ - 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`.
1098
+ - Thumbnails for videos can also be generated automatically, though, you need to have `ffmpeg` installed on your system.
1191
1099
 
1192
- ## Downloading Media Messages
1100
+ ### Downloading Media Messages
1193
1101
 
1194
1102
  If you want to save the media you received
1195
- ``` ts
1196
- import { writeFile } from 'fs/promises'
1197
- import { downloadMediaMessage } from '@indraazy/baileys'
1198
-
1199
- sock.ev.on('messages.upsert', async ({ messages }) => {
1200
- const m = messages[0]
1103
+ ```javascript
1104
+ const { createWriteStream } = require('fs');
1105
+ const { downloadMediaMessage, getContentType } = require("@fizzxydev/baileys-pro");
1201
1106
 
1107
+ sock.ev.on('messages.upsert', async ({ [m] }) => {
1202
1108
  if (!m.message) return // if there is no text or media message
1203
- const messageType = Object.keys (m.message)[0]// get what type of message it is -- text, image, video
1109
+ const messageType = getContentType(m) // get what type of message it is (text, image, video...)
1110
+
1204
1111
  // if the message is an image
1205
1112
  if (messageType === 'imageMessage') {
1206
1113
  // download the message
1207
- const buffer = await downloadMediaMessage(
1114
+ const stream = await downloadMediaMessage(
1208
1115
  m,
1209
- 'buffer',
1116
+ 'stream', // can be 'buffer' too
1210
1117
  { },
1211
- {
1118
+ {
1212
1119
  logger,
1213
- // pass this so that BaileysPro can request a reupload of media
1120
+ // pass this so that baileys can request a reupload of media
1214
1121
  // that has been deleted
1215
1122
  reuploadRequest: sock.updateMediaMessage
1216
1123
  }
1217
1124
  )
1218
1125
  // save to file
1219
- await writeFile('./my-download.jpeg', buffer)
1126
+ const writeStream = createWriteStream('./my-download.jpeg')
1127
+ stream.pipe(writeStream)
1220
1128
  }
1221
1129
  }
1222
1130
  ```
1223
1131
 
1224
- **Note:** 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:
1225
- ``` ts
1226
- const updatedMediaMsg = await sock.updateMediaMessage(msg)
1132
+ ### Re-upload Media Message to Whatsapp
1133
+
1134
+ - 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:
1135
+ ```javascript
1136
+ await sock.updateMediaMessage(msg)
1227
1137
  ```
1228
1138
 
1229
- ## Deleting Messages
1139
+ ## Reject Call
1140
+
1141
+ - You can obtain `callId` and `callFrom` from `call` event
1230
1142
 
1231
- ``` ts
1232
- const jid = '1234@s.whatsapp.net' // can also be a group
1233
- const response = await client.sendMessage(jid, { text: 'hello!' }) // send a message
1234
- // sends a message to delete the given message
1235
- // this deletes the message for everyone
1236
- await client.sendMessage(jid, { delete: response.key })
1143
+ ```javascript
1144
+ await sock.rejectCall(callId, callFrom)
1237
1145
  ```
1238
1146
 
1239
- **Note:** deleting for oneself is supported via `chatModify` (next section)
1147
+ ## Send States in Chat
1240
1148
 
1241
- ## Updating Messages
1149
+ ### Reading Messages
1150
+ - A set of message [keys](https://baileys.whiskeysockets.io/types/WAMessageKey.html) must be explicitly marked read now.
1151
+ - You cannot mark an entire 'chat' read as it were with Baileys Web.
1152
+ This means you have to keep track of unread messages.
1242
1153
 
1243
- ``` ts
1244
- const jid = '1234@s.whatsapp.net'
1154
+ ```javascript
1155
+ const key: WAMessageKey
1156
+ // can pass multiple keys to read multiple messages as well
1157
+ await sock.readMessages([key])
1158
+ ```
1245
1159
 
1246
- await client.sendMessage(jid, {
1247
- text: 'updated text goes here',
1248
- edit: response.key,
1249
- });
1160
+ The message ID is the unique identifier of the message that you are marking as read.
1161
+ On a `WAMessage`, the `messageID` can be accessed using ```messageID = message.key.id```.
1162
+
1163
+ ### Update Presence
1164
+
1165
+ - ``` presence ``` can be one of [these](https://baileys.whiskeysockets.io/types/WAPresence.html)
1166
+ - The presence expires after about 10 seconds.
1167
+ - This lets the person/group with `jid` know whether you're online, offline, typing etc.
1168
+
1169
+ ```javascript
1170
+ await sock.sendPresenceUpdate('available', jid)
1250
1171
  ```
1251
1172
 
1173
+ > [!NOTE]
1174
+ > 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')`
1175
+
1252
1176
  ## Modifying Chats
1253
1177
 
1254
1178
  WA uses an encrypted form of communication to send chat/app updates. This has been implemented mostly and you can send the following updates:
1255
1179
 
1256
- - Archive a chat
1257
- ``` ts
1258
- const lastMsgInChat = await getLastMessageInChat('123456@s.whatsapp.net') // implement this on your end
1259
- await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, '123456@s.whatsapp.net')
1260
- ```
1261
- - Mute/unmute a chat
1262
- ``` ts
1263
- // mute for 8 hours
1264
- await sock.chatModify({ mute: 8*60*60*1000 }, '123456@s.whatsapp.net', [])
1265
- // unmute
1266
- await sock.chatModify({ mute: null }, '123456@s.whatsapp.net', [])
1267
- ```
1268
- - Mark a chat read/unread
1269
- ``` ts
1270
- const lastMsgInChat = await getLastMessageInChat('123456@s.whatsapp.net') // implement this on your end
1271
- // mark it unread
1272
- await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, '123456@s.whatsapp.net')
1273
- ```
1274
-
1275
- - Delete a message for me
1276
- ``` ts
1277
- await sock.chatModify(
1278
- { clear: { messages: [{ id: 'ATWYHDNNWU81732J', fromMe: true, timestamp: "1654823909" }] } },
1279
- '123456@s.whatsapp.net',
1280
- []
1281
- )
1282
-
1283
- ```
1284
-
1285
- - Delete a chat
1286
- ``` ts
1287
- const lastMsgInChat = await getLastMessageInChat('123456@s.whatsapp.net') // implement this on your end
1288
- await sock.chatModify({
1289
- delete: true,
1290
- lastMessages: [{ key: lastMsgInChat.key, messageTimestamp: lastMsgInChat.messageTimestamp }]
1291
- },
1292
- '123456@s.whatsapp.net')
1293
- ```
1180
+ > [!IMPORTANT]
1181
+ > 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.
1294
1182
 
1295
- - Pin/unpin a chat
1296
- ``` ts
1297
- await sock.chatModify({
1298
- pin: true // or `false` to unpin
1299
- },
1300
- '123456@s.whatsapp.net')
1301
- ```
1302
-
1303
- - Star/unstar a message
1304
- ``` ts
1305
- await sock.chatModify({
1306
- star: {
1307
- messages: [{ id: 'messageID', fromMe: true // or `false` }],
1308
- star: true // - true: Star Message; false: Unstar Message
1309
- }},'123456@s.whatsapp.net');
1310
- ```
1311
-
1312
- **Note:** 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.
1313
-
1314
- ## Disappearing Messages
1315
-
1316
- ``` ts
1317
- const jid = '1234@s.whatsapp.net' // can also be a group
1183
+ ### Archive a Chat
1184
+ ```javascript
1185
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
1186
+ await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
1187
+ ```
1188
+ ### Mute/Unmute a Chat
1189
+
1190
+ - Supported times:
1191
+
1192
+ | Time | Miliseconds |
1193
+ |-------|-----------------|
1194
+ | Remove | null |
1195
+ | 8h | 86.400.000 |
1196
+ | 7d | 604.800.000 |
1197
+
1198
+ ```javascript
1199
+ // mute for 8 hours
1200
+ await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
1201
+ // unmute
1202
+ await sock.chatModify({ mute: null }, jid)
1203
+ ```
1204
+ ### Mark a Chat Read/Unread
1205
+ ```javascript
1206
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
1207
+ // mark it unread
1208
+ await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
1209
+ ```
1210
+
1211
+ ### Delete a Message for Me
1212
+ ```javascript
1213
+ await sock.chatModify(
1214
+ {
1215
+ clear: {
1216
+ messages: [
1217
+ {
1218
+ id: 'ATWYHDNNWU81732J',
1219
+ fromMe: true,
1220
+ timestamp: '1654823909'
1221
+ }
1222
+ ]
1223
+ }
1224
+ },
1225
+ jid
1226
+ )
1227
+
1228
+ ```
1229
+ ### Delete a Chat
1230
+ ```javascript
1231
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
1232
+ await sock.chatModify({
1233
+ delete: true,
1234
+ lastMessages: [
1235
+ {
1236
+ key: lastMsgInChat.key,
1237
+ messageTimestamp: lastMsgInChat.messageTimestamp
1238
+ }
1239
+ ]
1240
+ },
1241
+ jid
1242
+ )
1243
+ ```
1244
+ ### Pin/Unpin a Chat
1245
+ ```javascript
1246
+ await sock.chatModify({
1247
+ pin: true // or `false` to unpin
1248
+ },
1249
+ jid
1250
+ )
1251
+ ```
1252
+ ### Star/Unstar a Message
1253
+ ```javascript
1254
+ await sock.chatModify({
1255
+ star: {
1256
+ messages: [
1257
+ {
1258
+ id: 'messageID',
1259
+ fromMe: true // or `false`
1260
+ }
1261
+ ],
1262
+ star: true // - true: Star Message; false: Unstar Message
1263
+ }
1264
+ },
1265
+ jid
1266
+ )
1267
+ ```
1268
+
1269
+ ### Disappearing Messages
1270
+
1271
+ - Ephemeral can be:
1272
+
1273
+ | Time | Seconds |
1274
+ |-------|----------------|
1275
+ | Remove | 0 |
1276
+ | 24h | 86.400 |
1277
+ | 7d | 604.800 |
1278
+ | 90d | 7.776.000 |
1279
+
1280
+ - You need to pass in **Seconds**, default is 7 days
1281
+
1282
+ ```javascript
1318
1283
  // turn on disappearing messages
1319
- await client.sendMessage(
1320
- jid,
1284
+ await sock.sendMessage(
1285
+ jid,
1321
1286
  // this is 1 week in seconds -- how long you want messages to appear for
1322
1287
  { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
1323
1288
  )
1289
+
1324
1290
  // will send as a disappearing message
1325
- await client.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
1291
+ await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
1292
+
1326
1293
  // turn off disappearing messages
1327
- await client.sendMessage(
1328
- jid,
1294
+ await sock.sendMessage(
1295
+ jid,
1329
1296
  { disappearingMessagesInChat: false }
1330
1297
  )
1298
+ ```
1331
1299
 
1300
+ ## User Querys
1301
+
1302
+ ### Check If ID Exists in Whatsapp
1303
+ ```javascript
1304
+ const [result] = await sock.onWhatsApp(jid)
1305
+ if (result.exists) console.log (`${jid} exists on WhatsApp, as jid: ${result.jid}`)
1332
1306
  ```
1333
1307
 
1334
- ## Misc
1308
+ ### Query Chat History (groups too)
1335
1309
 
1336
- - To check if a given ID is on WhatsApp
1337
- ``` ts
1338
- const id = '123456'
1339
- const [result] = await sock.onWhatsApp(id)
1340
- if (result.exists) console.log (`${id} exists on WhatsApp, as jid: ${result.jid}`)
1341
- ```
1342
- - To query chat history on a group or with someone
1343
- TODO, if possible
1344
- - To get the status of some person
1345
- ``` ts
1346
- const status = await sock.fetchStatus("xyz@s.whatsapp.net")
1347
- console.log("status: " + status)
1348
- ```
1349
- - To change your profile status
1350
- ``` ts
1351
- const status = 'Hello World!'
1352
- await sock.updateProfileStatus(status)
1353
- ```
1354
- - To change your profile name
1355
- ``` ts
1356
- const name = 'My name'
1357
- await sock.updateProfileName(name)
1358
- ```
1310
+ - You need to have oldest message in chat
1311
+ ```javascript
1312
+ const msg = await getOldestMessageInChat(jid)
1313
+ await sock.fetchMessageHistory(
1314
+ 50, //quantity (max: 50 per query)
1315
+ msg.key,
1316
+ msg.messageTimestamp
1317
+ )
1318
+ ```
1319
+ - Messages will be received in `messaging.history-set` event
1320
+
1321
+ ### Fetch Status
1322
+ ```javascript
1323
+ const status = await sock.fetchStatus(jid)
1324
+ console.log('status: ' + status)
1325
+ ```
1326
+
1327
+ ### Fetch Profile Picture (groups too)
1359
1328
  - To get the display picture of some person/group
1360
- ``` ts
1361
- // for low res picture
1362
- const ppUrl = await sock.profilePictureUrl("xyz@g.us")
1363
- console.log("download profile picture from: " + ppUrl)
1364
- // for high res picture
1365
- const ppUrl = await sock.profilePictureUrl("xyz@g.us", 'image')
1366
- ```
1329
+ ```javascript
1330
+ // for low res picture
1331
+ const ppUrl = await sock.profilePictureUrl(jid)
1332
+ console.log(ppUrl)
1333
+
1334
+ // for high res picture
1335
+ const ppUrl = await sock.profilePictureUrl(jid, 'image')
1336
+ ```
1337
+
1338
+ ### Fetch Bussines Profile (such as description or category)
1339
+ ```javascript
1340
+ const profile = await sock.getBusinessProfile(jid)
1341
+ console.log('business description: ' + profile.description + ', category: ' + profile.category)
1342
+ ```
1343
+
1344
+ ### Fetch Someone's Presence (if they're typing or online)
1345
+ ```javascript
1346
+ // the presence update is fetched and called here
1347
+ sock.ev.on('presence.update', console.log)
1348
+
1349
+ // request updates for a chat
1350
+ await sock.presenceSubscribe(jid)
1351
+ ```
1352
+
1353
+ ## Change Profile
1354
+
1355
+ ### Change Profile Status
1356
+ ```javascript
1357
+ await sock.updateProfileStatus('Hello World!')
1358
+ ```
1359
+ ### Change Profile Name
1360
+ ```javascript
1361
+ await sock.updateProfileName('My name')
1362
+ ```
1363
+ ### Change Display Picture (groups too)
1367
1364
  - To change your display picture or a group's
1368
- ``` ts
1369
- const jid = '111234567890-1594482450@g.us' // can be your own too
1370
- await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
1371
- ```
1372
- - To remove your display picture or a group's
1373
- ``` ts
1374
- const jid = '111234567890-1594482450@g.us' // can be your own too
1375
- await sock.removeProfilePicture(jid)
1376
- ```
1377
- - To get someone's presence (if they're typing or online)
1378
- ``` ts
1379
- // the presence update is fetched and called here
1380
- sock.ev.on('presence.update', json => console.log(json))
1381
- // request updates for a chat
1382
- await sock.presenceSubscribe("xyz@s.whatsapp.net")
1383
- ```
1384
- - To block or unblock user
1385
- ``` ts
1386
- await sock.updateBlockStatus("xyz@s.whatsapp.net", "block") // Block user
1387
- await sock.updateBlockStatus("xyz@s.whatsapp.net", "unblock") // Unblock user
1388
- ```
1389
- - To get a business profile, such as description or category
1390
- ```ts
1391
- const profile = await sock.getBusinessProfile("xyz@s.whatsapp.net")
1392
- console.log("business description: " + profile.description + ", category: " + profile.category)
1393
- ```
1394
- Of course, replace ``` xyz ``` with an actual ID.
1395
-
1396
- ## Newsletter
1397
- - To get info newsletter
1398
- ``` ts
1399
- const metadata = await sock.newsletterMetadata("invite", "xxxxx")
1400
- // or
1401
- const metadata = await sock.newsletterMetadata("jid", "abcd@newsletter")
1402
- console.log(metadata)
1403
- ```
1404
- - To update the description of a newsletter
1405
- ``` ts
1406
- await sock.newsletterUpdateDescription("abcd@newsletter", "New Description")
1407
- ```
1408
- - To update the name of a newsletter
1409
- ``` ts
1410
- await sock.newsletterUpdateName("abcd@newsletter", "New Name")
1411
- ```
1412
- - To update the profile picture of a newsletter.
1413
- ``` ts
1414
- await sock.newsletterUpdatePicture("abcd@newsletter", buffer)
1415
- ```
1416
- - To remove the profile picture of a newsletter
1417
- ``` ts
1418
- await sock.newsletterRemovePicture("abcd@newsletter")
1419
- ```
1420
- - To mute notifications for a newsletter.
1421
- ``` ts
1422
- await sock.newsletterUnmute("abcd@newsletter")
1423
- ```
1424
- - To mute notifications for a newsletter.
1425
- ``` ts
1426
- await sock.newsletterMute("abcd@newsletter")
1427
- ```
1428
- - To create a newsletter
1429
- ``` ts
1430
- const metadata = await sock.newsletterCreate("Newsletter Name", "Newsletter Description")
1431
- console.log(metadata)
1432
- ```
1433
- - To delete a newsletter.
1434
- ``` ts
1435
- await sock.newsletterDelete("abcd@newsletter")
1436
- ```
1437
- - To follow a newsletter
1438
- ``` ts
1439
- await sock.newsletterFollow("abcd@newsletter")
1440
- ```
1441
- - To unfollow a newsletter
1442
- ``` ts
1443
- await sock.newsletterUnfollow("abcd@newsletter")
1444
- ```
1445
- - To send reaction
1446
- ``` ts
1447
- // jid, id message & emoticon
1448
- // way to get the ID is to copy the message url from channel
1449
- // Example: [ https://whatsapp.com/channel/xxxxx/175 ]
1450
- // The last number of the URL is the ID
1451
- const id = "175"
1452
- await sock.newsletterReactMessage("abcd@newsletter", id, "🥳")
1453
- ```
1365
+
1366
+ > [!NOTE]
1367
+ > Like media messages, you can pass `{ stream: Stream }` or `{ url: Url }` or `Buffer` directly, you can see more [here](https://baileys.whiskeysockets.io/types/WAMediaUpload.html)
1368
+
1369
+ ```javascript
1370
+ await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
1371
+ ```
1372
+ ### Remove display picture (groups too)
1373
+ ```javascript
1374
+ await sock.removeProfilePicture(jid)
1375
+ ```
1376
+
1454
1377
  ## Groups
1455
- - To create a group
1456
- ``` ts
1457
- // title & participants
1458
- const group = await sock.groupCreate("My Fab Group", ["1234@s.whatsapp.net", "4564@s.whatsapp.net"])
1459
- console.log ("created group with id: " + group.gid)
1460
- client.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
1461
- ```
1462
- - To add/remove people to a group or demote/promote people
1463
- ``` ts
1464
- // id & people to add to the group (will throw error if it fails)
1465
- const response = await sock.groupParticipantsUpdate(
1466
- "abcd-xyz@g.us",
1467
- ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"],
1468
- "add" // replace this parameter with "remove", "demote" or "promote"
1469
- )
1470
- ```
1471
- - To change the group's subject
1472
- ``` ts
1473
- await sock.groupUpdateSubject("abcd-xyz@g.us", "New Subject!")
1474
- ```
1475
- - To change the group's description
1476
- ``` ts
1477
- await sock.groupUpdateDescription("abcd-xyz@g.us", "New Description!")
1478
- ```
1479
- - To change group settings
1480
- ``` ts
1481
- // only allow admins to send messages
1482
- await sock.groupSettingUpdate("abcd-xyz@g.us", 'announcement')
1483
- // allow everyone to send messages
1484
- await sock.groupSettingUpdate("abcd-xyz@g.us", 'not_announcement')
1485
- // allow everyone to modify the group's settings -- like display picture etc.
1486
- await sock.groupSettingUpdate("abcd-xyz@g.us", 'unlocked')
1487
- // only allow admins to modify the group's settings
1488
- await sock.groupSettingUpdate("abcd-xyz@g.us", 'locked')
1489
- ```
1490
- - To leave a group
1491
- ``` ts
1492
- await sock.groupLeave("abcd-xyz@g.us") // (will throw error if it fails)
1493
- ```
1494
- - To get the invite code for a group
1495
- ``` ts
1496
- const code = await sock.groupInviteCode("abcd-xyz@g.us")
1497
- console.log("group code: " + code)
1498
- ```
1499
- - To revoke the invite code in a group
1500
- ```ts
1501
- const code = await sock.groupRevokeInvite("abcd-xyz@g.us")
1502
- console.log("New group code: " + code)
1503
- ```
1504
- - To query the metadata of a group
1505
- ``` ts
1506
- const metadata = await sock.groupMetadata("abcd-xyz@g.us")
1507
- console.log(metadata.id + ", title: " + metadata.subject + ", description: " + metadata.desc)
1508
- ```
1509
- - To join the group using the invitation code
1510
- ``` ts
1511
- const response = await sock.groupAcceptInvite("xxx")
1512
- console.log("joined to: " + response)
1513
- ```
1514
- Of course, replace ``` xxx ``` with invitation code.
1515
- - To get group info by invite code
1516
- ```ts
1517
- const response = await sock.groupGetInviteInfo("xxx")
1518
- console.log("group information: " + response)
1519
- ```
1520
- - To join the group using groupInviteMessage
1521
- ``` ts
1522
- const response = await sock.groupAcceptInviteV4("abcd@s.whatsapp.net", groupInviteMessage)
1523
- console.log("joined to: " + response)
1524
- ```
1525
- Of course, replace ``` xxx ``` with invitation code.
1526
1378
 
1527
- - To get list request join
1528
- ``` ts
1529
- const response = await sock.groupRequestParticipantsList("abcd-xyz@g.us")
1530
- console.log(response)
1531
- ```
1532
- - To approve/reject request join
1533
- ``` ts
1534
- const response = await sock.groupRequestParticipantsUpdate(
1535
- "abcd-xyz@g.us", // id group,
1536
- ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"],
1537
- "approve" // replace this parameter with "reject"
1538
- )
1539
- console.log(response)
1540
- ```
1379
+ - To change group properties you need to be admin
1380
+
1381
+ ### Create a Group
1382
+ ```javascript
1383
+ // title & participants
1384
+ const group = await sock.groupCreate('My Fab Group', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
1385
+ console.log('created group with id: ' + group.gid)
1386
+ await sock.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
1387
+ ```
1388
+ ### Add/Remove or Demote/Promote
1389
+ ```javascript
1390
+ // id & people to add to the group (will throw error if it fails)
1391
+ await sock.groupParticipantsUpdate(
1392
+ jid,
1393
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1394
+ 'add' // replace this parameter with 'remove' or 'demote' or 'promote'
1395
+ )
1396
+ ```
1397
+ ### Change Subject (name)
1398
+ ```javascript
1399
+ await sock.groupUpdateSubject(jid, 'New Subject!')
1400
+ ```
1401
+ ### Change Description
1402
+ ```javascript
1403
+ await sock.groupUpdateDescription(jid, 'New Description!')
1404
+ ```
1405
+ ### Change Settings
1406
+ ```javascript
1407
+ // only allow admins to send messages
1408
+ await sock.groupSettingUpdate(jid, 'announcement')
1409
+ // allow everyone to send messages
1410
+ await sock.groupSettingUpdate(jid, 'not_announcement')
1411
+ // allow everyone to modify the group's settings -- like display picture etc.
1412
+ await sock.groupSettingUpdate(jid, 'unlocked')
1413
+ // only allow admins to modify the group's settings
1414
+ await sock.groupSettingUpdate(jid, 'locked')
1415
+ ```
1416
+ ### Leave a Group
1417
+ ```javascript
1418
+ // will throw error if it fails
1419
+ await sock.groupLeave(jid)
1420
+ ```
1421
+ ### Get Invite Code
1422
+ - To create link with code use `'https://chat.whatsapp.com/' + code`
1423
+ ```javascript
1424
+ const code = await sock.groupInviteCode(jid)
1425
+ console.log('group code: ' + code)
1426
+ ```
1427
+ ### Revoke Invite Code
1428
+ ```javascript
1429
+ const code = await sock.groupRevokeInvite(jid)
1430
+ console.log('New group code: ' + code)
1431
+ ```
1432
+ ### Join Using Invitation Code
1433
+ - Code can't have `https://chat.whatsapp.com/`, only code
1434
+ ```javascript
1435
+ const response = await sock.groupAcceptInvite(code)
1436
+ console.log('joined to: ' + response)
1437
+ ```
1438
+ ### Get Group Info by Invite Code
1439
+ ```javascript
1440
+ const response = await sock.groupGetInviteInfo(code)
1441
+ console.log('group information: ' + response)
1442
+ ```
1443
+ ### Query Metadata (participants, name, description...)
1444
+ ```javascript
1445
+ const metadata = await sock.groupMetadata(jid)
1446
+ console.log(metadata.id + ', title: ' + metadata.subject + ', description: ' + metadata.desc)
1447
+ ```
1448
+ ### Join using `groupInviteMessage`
1449
+ ```javascript
1450
+ const response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
1451
+ console.log('joined to: ' + response)
1452
+ ```
1453
+ ### Get Request Join List
1454
+ ```javascript
1455
+ const response = await sock.groupRequestParticipantsList(jid)
1456
+ console.log(response)
1457
+ ```
1458
+ ### Approve/Reject Request Join
1459
+ ```javascript
1460
+ const response = await sock.groupRequestParticipantsUpdate(
1461
+ jid, // group id
1462
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1463
+ 'approve' // or 'reject'
1464
+ )
1465
+ console.log(response)
1466
+ ```
1467
+ ### Get All Participating Groups Metadata
1468
+ ```javascript
1469
+ const response = await sock.groupFetchAllParticipating()
1470
+ console.log(response)
1471
+ ```
1472
+ ### Toggle Ephemeral
1473
+
1474
+ - Ephemeral can be:
1475
+
1476
+ | Time | Seconds |
1477
+ |-------|----------------|
1478
+ | Remove | 0 |
1479
+ | 24h | 86.400 |
1480
+ | 7d | 604.800 |
1481
+ | 90d | 7.776.000 |
1482
+
1483
+ ```javascript
1484
+ await sock.groupToggleEphemeral(jid, 86400)
1485
+ ```
1486
+
1487
+ ### Change Add Mode
1488
+ ```javascript
1489
+ await sock.groupMemberAddMode(
1490
+ jid,
1491
+ 'all_member_add' // or 'admin_add'
1492
+ )
1493
+ ```
1541
1494
 
1542
1495
  ## Privacy
1543
- - To get the privacy settings
1544
- ``` ts
1545
- const privacySettings = await sock.fetchPrivacySettings(true)
1546
- console.log("privacy settings: " + privacySettings)
1547
- ```
1548
- - To update the LastSeen privacy
1549
- ``` ts
1550
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1551
- await sock.updateLastSeenPrivacy(value)
1552
- ```
1553
- - To update the Online privacy
1554
- ``` ts
1555
- const value = 'all' // 'match_last_seen'
1556
- await sock.updateOnlinePrivacy(value)
1557
- ```
1558
- - To update the Profile Picture privacy
1559
- ``` ts
1560
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1561
- await sock.updateProfilePicturePrivacy(value)
1562
- ```
1563
- - To update the Status privacy
1564
- ``` ts
1565
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1566
- await sock.updateStatusPrivacy(value)
1567
- ```
1568
- - To update the Read Receipts privacy
1569
- ``` ts
1570
- const value = 'all' // 'none'
1571
- await sock.updateReadReceiptsPrivacy(value)
1572
- ```
1573
- - To update the Groups Add privacy
1574
- ``` ts
1575
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1576
- await sock.updateGroupsAddPrivacy(value)
1577
- ```
1578
- - To update the Default Disappearing Mode
1579
- ``` ts
1580
- const duration = 86400 // 604800 | 7776000 | 0
1581
- await sock.updateDefaultDisappearingMode(duration)
1582
- ```
1496
+
1497
+ ### Block/Unblock User
1498
+ ```javascript
1499
+ await sock.updateBlockStatus(jid, 'block') // Block user
1500
+ await sock.updateBlockStatus(jid, 'unblock') // Unblock user
1501
+ ```
1502
+ ### Get Privacy Settings
1503
+ ```javascript
1504
+ const privacySettings = await sock.fetchPrivacySettings(true)
1505
+ console.log('privacy settings: ' + privacySettings)
1506
+ ```
1507
+ ### Get BlockList
1508
+ ```javascript
1509
+ const response = await sock.fetchBlocklist()
1510
+ console.log(response)
1511
+ ```
1512
+ ### Update LastSeen Privacy
1513
+ ```javascript
1514
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1515
+ await sock.updateLastSeenPrivacy(value)
1516
+ ```
1517
+ ### Update Online Privacy
1518
+ ```javascript
1519
+ const value = 'all' // 'match_last_seen'
1520
+ await sock.updateOnlinePrivacy(value)
1521
+ ```
1522
+ ### Update Profile Picture Privacy
1523
+ ```javascript
1524
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1525
+ await sock.updateProfilePicturePrivacy(value)
1526
+ ```
1527
+ ### Update Status Privacy
1528
+ ```javascript
1529
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1530
+ await sock.updateStatusPrivacy(value)
1531
+ ```
1532
+ ### Update Read Receipts Privacy
1533
+ ```javascript
1534
+ const value = 'all' // 'none'
1535
+ await sock.updateReadReceiptsPrivacy(value)
1536
+ ```
1537
+ ### Update Groups Add Privacy
1538
+ ```javascript
1539
+ const value = 'all' // 'contacts' | 'contact_blacklist'
1540
+ await sock.updateGroupsAddPrivacy(value)
1541
+ ```
1542
+ ### Update Default Disappearing Mode
1543
+
1544
+ - Like [this](#disappearing-messages), ephemeral can be:
1545
+
1546
+ | Time | Seconds |
1547
+ |-------|----------------|
1548
+ | Remove | 0 |
1549
+ | 24h | 86.400 |
1550
+ | 7d | 604.800 |
1551
+ | 90d | 7.776.000 |
1552
+
1553
+ ```javascript
1554
+ const ephemeral = 86400
1555
+ await sock.updateDefaultDisappearingMode(ephemeral)
1556
+ ```
1557
+
1583
1558
  ## Broadcast Lists & Stories
1584
1559
 
1585
- Messages can be sent to broadcasts & stories.
1586
- you need to add the following message options in sendMessage, like this:
1587
- ```ts
1588
- client.sendMessage(jid, {image: {url: url}, caption: caption}, {backgroundColor : backgroundColor, font : font, statusJidList: statusJidList, broadcast : true})
1560
+ ### Send Broadcast & Stories
1561
+ - Messages can be sent to broadcasts & stories. You need to add the following message options in sendMessage, like this:
1562
+ ```javascript
1563
+ await sock.sendMessage(
1564
+ jid,
1565
+ {
1566
+ image: {
1567
+ url: url
1568
+ },
1569
+ caption: caption
1570
+ },
1571
+ {
1572
+ backgroundColor: backgroundColor,
1573
+ font: font,
1574
+ statusJidList: statusJidList,
1575
+ broadcast: true
1576
+ }
1577
+ )
1589
1578
  ```
1590
- - the message body can be a extendedTextMessage or imageMessage or videoMessage or voiceMessage
1591
- - You can add backgroundColor and other options in the message options
1592
- - broadcast: true enables broadcast mode
1593
- - statusJidList: a list of people that you can get which you need to provide, which are the people who will get this status message.
1579
+ - Message body can be a `extendedTextMessage` or `imageMessage` or `videoMessage` or `voiceMessage`, see [here](https://baileys.whiskeysockets.io/types/AnyRegularMessageContent.html)
1580
+ - You can add `backgroundColor` and other options in the message options, see [here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html)
1581
+ - `broadcast: true` enables broadcast mode
1582
+ - `statusJidList`: a list of people that you can get which you need to provide, which are the people who will get this status message.
1594
1583
 
1595
1584
  - You can send messages to broadcast lists the same way you send messages to groups & individual chats.
1596
1585
  - Right now, WA Web does not support creating broadcast lists, but you can still delete them.
1597
1586
  - Broadcast IDs are in the format `12345678@broadcast`
1598
- - To query a broadcast list's recipients & name:
1599
- ``` ts
1600
- const bList = await sock.getBroadcastListInfo("1234@broadcast")
1601
- console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
1602
- ```
1587
+ ### Query a Broadcast List's Recipients & Name
1588
+ ```javascript
1589
+ const bList = await sock.getBroadcastListInfo('1234@broadcast')
1590
+ console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
1591
+ ```
1603
1592
 
1604
1593
  ## Writing Custom Functionality
1605
- BaileysPro is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
1594
+ Baileys is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
1606
1595
 
1596
+ ### Enabling Debug Level in Baileys Logs
1607
1597
  First, enable the logging of unhandled messages from WhatsApp by setting:
1608
- ``` ts
1598
+ ```javascript
1609
1599
  const sock = makeWASocket({
1610
1600
  logger: P({ level: 'debug' }),
1611
1601
  })
1612
1602
  ```
1613
- This will enable you to see all sorts of messages WhatsApp sends in the console.
1614
-
1615
- Some examples:
1616
-
1617
- 1. Functionality to track the battery percentage of your phone.
1618
- You enable logging and you'll see a message about your battery pop up in the console:
1619
- ```{"level":10,"fromMe":false,"frame":{"tag":"ib","attrs":{"from":"@s.whatsapp.net"},"content":[{"tag":"edge_routing","attrs":{},"content":[{"tag":"routing_info","attrs":{},"content":{"type":"Buffer","data":[8,2,8,5]}}]}]},"msg":"communication"} ```
1620
-
1621
- The "frame" is what the message received is, it has three components:
1622
- - `tag` -- what this frame is about (eg. message will have "message")
1623
- - `attrs` -- a string key-value pair with some metadata (contains ID of the message usually)
1624
- - `content` -- the actual data (eg. a message node will have the actual message content in it)
1625
- - read more about this format [here](/src/WABinary/readme.md)
1626
-
1627
- You can register a callback for an event using the following:
1628
- ``` ts
1629
- // for any message with tag 'edge_routing'
1630
- sock.ws.on(`CB:edge_routing`, (node: BinaryNode) => { })
1631
- // for any message with tag 'edge_routing' and id attribute = abcd
1632
- sock.ws.on(`CB:edge_routing,id:abcd`, (node: BinaryNode) => { })
1633
- // for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
1634
- sock.ws.on(`CB:edge_routing,id:abcd,routing_info`, (node: BinaryNode) => { })
1603
+ This will enable you to see all sorts of messages WhatsApp sends in the console.
1604
+
1605
+ ### How Whatsapp Communicate With Us
1606
+
1607
+ > [!TIP]
1608
+ > If you want to learn whatsapp protocol, we recommend to study about Libsignal Protocol and Noise Protocol
1609
+
1610
+ - **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:
1611
+ ```
1612
+ {
1613
+ "level": 10,
1614
+ "fromMe": false,
1615
+ "frame": {
1616
+ "tag": "ib",
1617
+ "attrs": {
1618
+ "from": "@s.whatsapp.net"
1619
+ },
1620
+ "content": [
1621
+ {
1622
+ "tag": "edge_routing",
1623
+ "attrs": {},
1624
+ "content": [
1625
+ {
1626
+ "tag": "routing_info",
1627
+ "attrs": {},
1628
+ "content": {
1629
+ "type": "Buffer",
1630
+ "data": [8,2,8,5]
1631
+ }
1632
+ }
1633
+ ]
1634
+ }
1635
+ ]
1636
+ },
1637
+ "msg":"communication"
1638
+ }
1635
1639
  ```
1636
- Also, this repo is now licenced under GPL 3 since it uses [libsignal-node](https://git.questbook.io/backend/service-coderunner/-/merge_requests/1)
1640
+
1641
+ The `'frame'` is what the message received is, it has three components:
1642
+ - `tag` -- what this frame is about (eg. message will have 'message')
1643
+ - `attrs` -- a string key-value pair with some metadata (contains ID of the message usually)
1644
+ - `content` -- the actual data (eg. a message node will have the actual message content in it)
1645
+ - read more about this format [here](/src/WABinary/readme.md)
1646
+
1647
+ ### Register a Callback for Websocket Events
1648
+
1649
+ > [!TIP]
1650
+ > Recommended to see `onMessageReceived` function in `socket.ts` file to understand how websockets events are fired
1651
+
1652
+ ```javascript
1653
+ // for any message with tag 'edge_routing'
1654
+ sock.ws.on('CB:edge_routing', (node: BinaryNode) => { })
1655
+
1656
+ // for any message with tag 'edge_routing' and id attribute = abcd
1657
+ sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => { })
1658
+
1659
+ // for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
1660
+ sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => { })
1661
+ ```
1662
+
1663
+ > [!NOTE]
1664
+ > Also, this repo is now licenced under GPL 3 since it uses [libsignal-node](https://git.questbook.io/backend/service-coderunner/-/merge_requests/1)