@d0v3riz/baileys 6.7.8 → 6.7.12

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