@jkt48connect-corp/baileys 7.3.0 → 7.3.2

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