@elrayyxml/baileys 1.0.3 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +2517 -0
  2. package/lib/Defaults/baileys-version.json +1 -1
  3. package/lib/Defaults/index.d.ts +51 -0
  4. package/lib/Defaults/index.js +9 -1
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  7. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  8. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  9. package/lib/Signal/Group/index.d.ts +11 -0
  10. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  11. package/lib/Signal/Group/queue-job.d.ts +1 -0
  12. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  13. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  14. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  15. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  16. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  17. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  18. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  19. package/lib/Signal/libsignal.d.ts +3 -0
  20. package/lib/Socket/Client/index.d.ts +2 -0
  21. package/lib/Socket/Client/types.d.ts +16 -0
  22. package/lib/Socket/Client/websocket.d.ts +13 -0
  23. package/lib/Socket/business.d.ts +172 -0
  24. package/lib/Socket/chats.d.ts +82 -0
  25. package/lib/Socket/groups.d.ts +124 -0
  26. package/lib/Socket/index.d.ts +172 -0
  27. package/lib/Socket/messages-recv.d.ts +161 -0
  28. package/lib/Socket/messages-send.d.ts +151 -0
  29. package/lib/Socket/messages-send.js +236 -59
  30. package/lib/Socket/newsletter.d.ts +136 -0
  31. package/lib/Socket/newsletter.js +5 -1
  32. package/lib/Socket/socket.d.ts +43 -0
  33. package/lib/Socket/usync.d.ts +36 -0
  34. package/lib/Store/index.d.ts +2 -0
  35. package/lib/Store/make-in-memory-store.d.ts +118 -0
  36. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  37. package/lib/Store/object-repository.d.ts +10 -0
  38. package/lib/Types/Auth.d.ts +103 -0
  39. package/lib/Types/Call.d.ts +13 -0
  40. package/lib/Types/Chat.d.ts +109 -0
  41. package/lib/Types/Contact.d.ts +23 -0
  42. package/lib/Types/Events.d.ts +199 -0
  43. package/lib/Types/GroupMetadata.d.ts +64 -0
  44. package/lib/Types/Label.d.ts +35 -0
  45. package/lib/Types/LabelAssociation.d.ts +29 -0
  46. package/lib/Types/Message.d.ts +400 -0
  47. package/lib/Types/Newsletter.d.ts +79 -0
  48. package/lib/Types/Product.d.ts +78 -0
  49. package/lib/Types/Signal.d.ts +57 -0
  50. package/lib/Types/Socket.d.ts +119 -0
  51. package/lib/Types/State.d.ts +27 -0
  52. package/lib/Types/USync.d.ts +25 -0
  53. package/lib/Types/index.d.ts +64 -0
  54. package/lib/Utils/auth-utils.d.ts +18 -0
  55. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  56. package/lib/Utils/business.d.ts +22 -0
  57. package/lib/Utils/chat-utils.d.ts +70 -0
  58. package/lib/Utils/crypto.d.ts +40 -0
  59. package/lib/Utils/decode-wa-message.d.ts +35 -0
  60. package/lib/Utils/event-buffer.d.ts +35 -0
  61. package/lib/Utils/generics.d.ts +89 -0
  62. package/lib/Utils/generics.js +31 -4
  63. package/lib/Utils/history.d.ts +19 -0
  64. package/lib/Utils/index.d.ts +17 -0
  65. package/lib/Utils/link-preview.d.ts +21 -0
  66. package/lib/Utils/logger.d.ts +11 -0
  67. package/lib/Utils/lt-hash.d.ts +12 -0
  68. package/lib/Utils/make-mutex.d.ts +7 -0
  69. package/lib/Utils/messages-media.d.ts +120 -0
  70. package/lib/Utils/messages.d.ts +75 -0
  71. package/lib/Utils/messages.js +400 -38
  72. package/lib/Utils/noise-handler.d.ts +19 -0
  73. package/lib/Utils/process-message.d.ts +42 -0
  74. package/lib/Utils/signal.d.ts +33 -0
  75. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  76. package/lib/Utils/validate-connection.d.ts +10 -0
  77. package/lib/WABinary/constants.d.ts +27 -0
  78. package/lib/WABinary/decode.d.ts +6 -0
  79. package/lib/WABinary/encode.d.ts +2 -0
  80. package/lib/WABinary/generic-utils.d.ts +14 -0
  81. package/lib/WABinary/generic-utils.js +11 -8
  82. package/lib/WABinary/index.d.ts +5 -0
  83. package/lib/WABinary/jid-utils.d.ts +36 -0
  84. package/lib/WABinary/types.d.ts +18 -0
  85. package/lib/WAM/BinaryInfo.d.ts +8 -0
  86. package/lib/WAM/constants.d.ts +38 -0
  87. package/lib/WAM/encode.d.ts +2 -0
  88. package/lib/WAM/index.d.ts +3 -0
  89. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  90. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  91. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  92. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  93. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  94. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
  95. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  96. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  97. package/lib/WAUSync/USyncUser.d.ts +12 -0
  98. package/lib/WAUSync/index.d.ts +3 -0
  99. package/lib/index.d.ts +13 -0
  100. package/lib/index.js +4 -1
  101. package/package.json +17 -14
  102. package/README.MD +0 -78
  103. package/lib/Socket/type.js +0 -405
package/README.md ADDED
@@ -0,0 +1,2517 @@
1
+ [![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#table-of-contents)
2
+
3
+ <div align="center">
4
+
5
+ ## @elrayyxml/baileys
6
+
7
+ </div>
8
+
9
+ [![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/colored.png)](#table-of-contents)
10
+
11
+ <div align="center">
12
+
13
+ <p><em>Baileys Modified</em></p>
14
+
15
+ <img src="https://files.catbox.moe/ehdrm3.jpg" width="300" alt="Cover Banner" />
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ <div align="center">
22
+
23
+ [![npm version](https://img.shields.io/npm/v/@elrayyxml/baileys.svg)](https://www.npmjs.com/package/@elrayyxml/baileys)
24
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
25
+ [![WhatsApp](https://img.shields.io/badge/WhatsApp-API-green.svg?logo=whatsapp)](https://whatsapp.com)
26
+ [![Node.js](https://img.shields.io/badge/Node.js-20%2B-green.svg)](https://nodejs.org)
27
+ [![npm downloads](https://img.shields.io/npm/dt/@elrayyxml/baileys.svg?color=blueviolet&label=downloads&logo=npm)](https://www.npmjs.com/package/@elrayyxml/baileys)
28
+ [![REST API](https://img.shields.io/badge/REST_API-green.svg)](https://api.nexray.web.id)
29
+
30
+ </div>
31
+
32
+ ## Contact
33
+
34
+ <div align="center">
35
+
36
+ [![Instagram](https://img.shields.io/badge/Instagram-E4405F?style=for-the-badge&logo=instagram&logoColor=white)](https://instagram.com/elrayyxml)
37
+ [![TikTok](https://img.shields.io/badge/TikTok-000000?style=for-the-badge&logo=tiktok&logoColor=white)](https://tik-tok.com/@elrayyxml)
38
+ [![Email](https://img.shields.io/badge/Email-elrayy68@gmail.com-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:elrayy68@gmail.com)
39
+ [![WhatsApp](https://img.shields.io/badge/WhatsApp-6289526377530-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/6289526377530)
40
+
41
+ </div>
42
+
43
+ ## Official Channel
44
+
45
+ <div align="center">
46
+ <a href="https://whatsapp.com/channel/0029Vb69z8n1dAvztHQTDu3r">
47
+ <img src="https://img.shields.io/badge/Join-WhatsApp%20Channel-25D366?logo=whatsapp&logoColor=white" alt="WhatsApp Channel" />
48
+ </a>
49
+
50
+ </div>
51
+
52
+
53
+
54
+ ## Installation
55
+
56
+ Use the stable version:
57
+ ```bash
58
+ npm install @elrayyxml/baileys
59
+ # or
60
+ yarn add @elrayyxml/baileys
61
+ ```
62
+
63
+ ### `package.json` Fork Baileys
64
+
65
+ ```json
66
+ "dependencies": {
67
+ "baileys": "npm:@elrayyxml/baileys"
68
+ }
69
+ ```
70
+
71
+ Then import your code using:
72
+ ```ts
73
+ import makeWASocket from '@elrayyxml/baileys'
74
+ ```
75
+
76
+ ```ts
77
+ import makeWASocket from '@elrayyxml/baileys'
78
+
79
+ const sock = makeWASocket({
80
+ // can provide additional config here
81
+ browser: Browsers.ubuntu('My App'),
82
+ printQRInTerminal: true
83
+ })
84
+ ```
85
+
86
+ 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!
87
+
88
+ ### Starting socket with **Pairing Code**
89
+
90
+
91
+ > [!IMPORTANT]
92
+ > 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)
93
+
94
+ The phone number can't have `+` or `()` or `-`, only numbers, you must provide country code
95
+
96
+ ```ts
97
+ import makeWASocket from '@elrayyxml/baileys'
98
+
99
+ const sock = makeWASocket({
100
+ // can provide additional config here
101
+ printQRInTerminal: false //need to be false
102
+ })
103
+
104
+ if (!sock.authState.creds.registered) {
105
+ const number = 'XXXXXXXXXXX'
106
+ const code = await sock.requestPairingCode(number) // or await sock.requestPairingCode(number, 'CODEOTPS') custom your pairing code
107
+ console.log(code)
108
+ }
109
+ ```
110
+
111
+ ### Receive Full History
112
+
113
+ 1. Set `syncFullHistory` as `true`
114
+ 2. Baileys, by default, use chrome browser config
115
+ - If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config:
116
+
117
+ ```ts
118
+ const sock = makeWASocket({
119
+ ...otherOpts,
120
+ // can use Windows, Ubuntu here too
121
+ browser: Browsers.macOS('Desktop'),
122
+ syncFullHistory: true
123
+ })
124
+ ```
125
+
126
+ ## Important Notes About Socket Config
127
+
128
+ ### Caching Group Metadata (Recommended)
129
+ - If you use baileys for groups, we recommend you to set `cachedGroupMetadata` in socket config, you need to implement a cache like this:
130
+
131
+ ```ts
132
+ const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
133
+
134
+ const sock = makeWASocket({
135
+ cachedGroupMetadata: async (jid) => groupCache.get(jid)
136
+ })
137
+
138
+ sock.ev.on('groups.update', async ([event]) => {
139
+ const metadata = await sock.groupMetadata(event.id)
140
+ groupCache.set(event.id, metadata)
141
+ })
142
+
143
+ sock.ev.on('group-participants.update', async (event) => {
144
+ const metadata = await sock.groupMetadata(event.id)
145
+ groupCache.set(event.id, metadata)
146
+ })
147
+ ```
148
+
149
+ ### Improve Retry System & Decrypt Poll Votes
150
+ - 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:
151
+ ```ts
152
+ const sock = makeWASocket({
153
+ getMessage: async (key) => await getMessageFromStore(key)
154
+ })
155
+ ```
156
+
157
+ ### Receive Notifications in Whatsapp App
158
+ - If you want to receive notifications in whatsapp app, set `markOnlineOnConnect` to `false`
159
+ ```ts
160
+ const sock = makeWASocket({
161
+ markOnlineOnConnect: false
162
+ })
163
+ ```
164
+ ## Saving & Restoring Sessions
165
+
166
+ You obviously don't want to keep scanning the QR code every time you want to connect.
167
+
168
+ So, you can load the credentials to log back in:
169
+ ```ts
170
+ import makeWASocket, { useMultiFileAuthState } from '@elrayyxml/baileys'
171
+
172
+ const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
173
+
174
+ // will use the given state to connect
175
+ // so if valid credentials are available -- it'll connect without QR
176
+ const sock = makeWASocket({ auth: state })
177
+
178
+ // this will be called as soon as the credentials are updated
179
+ sock.ev.on('creds.update', saveCreds)
180
+ ```
181
+
182
+ > [!IMPORTANT]
183
+ > `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.
184
+
185
+ > [!NOTE]
186
+ > 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.
187
+
188
+ ## Handling Events
189
+
190
+ - Baileys uses the EventEmitter syntax for events.
191
+ They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
192
+
193
+ > [!IMPORTANT]
194
+ > **The events are [these](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**, it's important you see all events
195
+
196
+ You can listen to these events like this:
197
+ ```ts
198
+ const sock = makeWASocket()
199
+ sock.ev.on('messages.upsert', ({ messages }) => {
200
+ console.log('got messages', messages)
201
+ })
202
+ ```
203
+
204
+ ### Example to Start
205
+
206
+ > [!NOTE]
207
+ > This example includes basic auth storage too
208
+
209
+ ```ts
210
+ import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@elrayyxml/baileys'
211
+ import { Boom } from '@hapi/boom'
212
+
213
+ async function connectToWhatsApp () {
214
+ const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
215
+ const sock = makeWASocket({
216
+ // can provide additional config here
217
+ auth: state,
218
+ printQRInTerminal: true
219
+ })
220
+ sock.ev.on('connection.update', (update) => {
221
+ const { connection, lastDisconnect } = update
222
+ if(connection === 'close') {
223
+ const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
224
+ console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
225
+ // reconnect if not logged out
226
+ if(shouldReconnect) {
227
+ connectToWhatsApp()
228
+ }
229
+ } else if(connection === 'open') {
230
+ console.log('opened connection')
231
+ }
232
+ })
233
+ sock.ev.on('messages.upsert', event => {
234
+ for (const m of event.messages) {
235
+ console.log(JSON.stringify(m, undefined, 2))
236
+
237
+ console.log('replying to', m.key.remoteJid)
238
+ await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
239
+ }
240
+ })
241
+
242
+ // to storage creds (session info) when it updates
243
+ sock.ev.on('creds.update', saveCreds)
244
+ }
245
+ // run in main file
246
+ connectToWhatsApp()
247
+ ```
248
+
249
+ ### For example if you use useSingleFileAuthState and useMongoFileAuthState
250
+ ```ts
251
+ import makeWASocket, { useSingleFileAuthState, useMongoFileAuthState } from '@elrayyxml/baileys'
252
+
253
+ // Single Auth
254
+ const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json')
255
+ const sock = makeWASocket({
256
+ auth: state,
257
+ printQRInTerminal: true
258
+ })
259
+
260
+ sock.ev.on('creds.update', saveState)
261
+
262
+ // Mongo Auth
263
+ import { MongoClient } from "mongodb"
264
+
265
+ const connectAuth = async() => {
266
+ global.client = new MongoClient('mongoURL')
267
+ global.client.connect(err => {
268
+ if (err) {
269
+ console.warn("Warning: MongoDB link is invalid or cannot be connected.")
270
+ } else {
271
+ console.log('Successfully Connected To MongoDB Server')
272
+ }
273
+ })
274
+ }
275
+ await client.connect()
276
+ const collection = client.db("@itsockchann").collection("sessions")
277
+ return collection
278
+ }
279
+
280
+ const Authentication = await connectAuth()
281
+ const { state, saveCreds } = await useMongoFileAuthState(Authentication)
282
+ const sock = makeWASocket({
283
+ auth: state,
284
+ printQRInTerminal: true
285
+ })
286
+
287
+ sock.ev.on('creds.update', saveCreds)
288
+ ```
289
+
290
+ > [!IMPORTANT]
291
+ > In `messages.upsert` it's recommended to use a loop like `for (const message of event.messages)` to handle all messages in array
292
+
293
+ ### Decrypt Poll Votes
294
+
295
+ - By default poll votes are encrypted and handled in `messages.update`
296
+ ```ts
297
+ import pino from "pino"
298
+ import { makeInMemoryStore, getAggregateVotesInPollMessage } from '@elrayyxml/baileys'
299
+
300
+ const logger = pino({ timestamp: () => `,"time":"${new Date().toJSON()}"` }).child({ class: "@Itsockchann" })
301
+ logger.level = "fatal"
302
+ const store = makeInMemoryStore({ logger })
303
+
304
+ async function getMessage(key){
305
+ if (store) {
306
+ const msg = await store.loadMessage(key.remoteJid, key.id)
307
+ return msg?.message
308
+ }
309
+ return {
310
+ conversation: "Itsocki Kawaiii"
311
+ }
312
+ }
313
+
314
+ sock.ev.on("messages.update", async (chatUpdate) => {
315
+ for(const { key, update } of chatUpdate) {
316
+ if(update.pollUpdates && key.fromMe) {
317
+ const pollCreation = await getMessage(key)
318
+ if(pollCreation) {
319
+ const pollUpdate = await getAggregateVotesInPollMessage({
320
+ message: pollCreation,
321
+ pollUpdates: update.pollUpdates,
322
+ })
323
+ const toCmd = pollUpdate.filter(v => v.voters.length !== 0)[0]?.name
324
+ if (toCmd == undefined) return
325
+ console.log(toCmd)
326
+ }
327
+ }
328
+ }
329
+ })
330
+ ```
331
+
332
+ ### Decrypt Event Response
333
+
334
+ - By default event response are encrypted and handled in `messages.update`
335
+ ```ts
336
+ import { jidNormalizedUser, getAggregateResponsesInEventMessage } from '@elrayyxml/baileys'
337
+
338
+ sock.ev.on("messages.update", async ([chatUpdate]) => {
339
+ const eventResponses = chatUpdate.update?.eventResponses
340
+ const agregate = getAggregateResponsesInEventMessage({ eventResponses }, jidNormalizedUser(sock.user.lid))
341
+ console.log(agregate)
342
+ })
343
+ ```
344
+
345
+ ### Summary of Events on First Connection
346
+
347
+ 1. When you connect first time, `connection.update` will be fired requesting you to restart sock
348
+ 2. Then, history messages will be received in `messaging.history-set`
349
+
350
+ ## Implementing a Data Store
351
+
352
+ - 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.
353
+
354
+ > [!IMPORTANT]
355
+ > I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM.
356
+
357
+ It can be used as follows:
358
+
359
+ ```ts
360
+ import makeWASocket, { makeInMemoryStore } from '@elrayyxml/baileys'
361
+ // the store maintains the data of the WA connection in memory
362
+ // can be written out to a file & read from it
363
+ const store = makeInMemoryStore({ })
364
+ // can be read from a file
365
+ store.readFromFile('./baileys_store.json')
366
+ // saves the state to a file every 10s
367
+ setInterval(() => {
368
+ store.writeToFile('./baileys_store.json')
369
+ }, 10_000)
370
+
371
+ const sock = makeWASocket({ })
372
+ // will listen from this socket
373
+ // the store can listen from a new socket once the current socket outlives its lifetime
374
+ store.bind(sock.ev)
375
+
376
+ sock.ev.on('chats.upsert', () => {
377
+ // can use 'store.chats' however you want, even after the socket dies out
378
+ // 'chats' => a KeyedDB instance
379
+ console.log('got chats', store.chats.all())
380
+ })
381
+
382
+ sock.ev.on('contacts.upsert', () => {
383
+ console.log('got contacts', Object.values(store.contacts))
384
+ })
385
+
386
+ ```
387
+
388
+ The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval.
389
+
390
+ ## Whatsapp IDs Explain
391
+
392
+ - `id` is the WhatsApp ID, called `jid` too, of the person or group you're sending the message to.
393
+ - It must be in the format ```[country code][phone number]@s.whatsapp.net```
394
+ - Example for people: ```+19999999999@s.whatsapp.net```.
395
+ - For groups, it must be in the format ``` 123456789-123345@g.us ```.
396
+ - For broadcast lists, it's `[timestamp of creation]@broadcast`.
397
+ - For stories, the ID is `status@broadcast`.
398
+
399
+ ## Utility Functions
400
+
401
+ - `getContentType`, returns the content type for any message
402
+ - `getDevice`, returns the device from message
403
+ - `makeCacheableSignalKeyStore`, make auth store more fast
404
+ - `downloadContentFromMessage`, download content from any message
405
+
406
+ ## Sending Messages
407
+
408
+ - Send all types of messages with a single function
409
+ - **[Here](https://baileys.whiskeysockets.io/types/AnyMessageContent.html) you can see all message contents supported, like text message**
410
+ - **[Here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html) you can see all options supported, like quote message**
411
+
412
+ ```ts
413
+ const jid: string
414
+ const content: AnyMessageContent
415
+ const options: MiscMessageGenerationOptions
416
+
417
+ sock.sendMessage(jid, content, options)
418
+ ```
419
+
420
+ ### Non-Media Messages
421
+
422
+ #### Text Message
423
+ ```ts
424
+ await sock.sendMessage(jid, { text: 'hello word' })
425
+ ```
426
+
427
+ #### Quote Message (works with all types)
428
+ ```ts
429
+ await sock.sendMessage(jid, { text: 'hello word' }, { quoted: message })
430
+ ```
431
+
432
+ #### Mention User (works with most types)
433
+ - @number is to mention in text, it's optional
434
+ ```ts
435
+ await sock.sendMessage(
436
+ jid,
437
+ {
438
+ text: '@12345678901',
439
+ mentions: ['12345678901@s.whatsapp.net']
440
+ }
441
+ )
442
+ ```
443
+
444
+ #### Forward Messages
445
+ - 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
446
+ ```ts
447
+ const msg = getMessageFromStore() // implement this on your end
448
+ await sock.sendMessage(jid, { forward: msg, force: true or number }) // WA forward the message!
449
+ ```
450
+
451
+ #### Location Message
452
+ ```ts
453
+ await sock.sendMessage(
454
+ jid,
455
+ {
456
+ location: {
457
+ degreesLatitude: 24.121231,
458
+ degreesLongitude: 55.1121221
459
+ }
460
+ }
461
+ )
462
+ ```
463
+
464
+ #### Live Location Message
465
+ ```ts
466
+ await sock.sendMessage(
467
+ jid,
468
+ {
469
+ location: {
470
+ degreesLatitude: 24.121231,
471
+ degreesLongitude: 55.1121221
472
+ },
473
+ live: true
474
+ }
475
+ )
476
+ ```
477
+ #### Contact Message
478
+ ```ts
479
+ const vcard = 'BEGIN:VCARD\n' // metadata of the contact card
480
+ + 'VERSION:3.0\n'
481
+ + 'FN:Jeff Singh\n' // full name
482
+ + 'ORG:Ashoka Uni\n' // the organization of the contact
483
+ + 'TELtype=CELLtype=VOICEwaid=911234567890:+91 12345 67890\n' // WhatsApp ID + phone number
484
+ + 'END:VCARD'
485
+
486
+ await sock.sendMessage(
487
+ jid,
488
+ {
489
+ contacts: {
490
+ displayName: 'ElrayyXml',
491
+ contacts: [{ vcard }]
492
+ }
493
+ }
494
+ )
495
+ ```
496
+
497
+ #### Reaction Message
498
+ - 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
499
+ ```ts
500
+ await sock.sendMessage(
501
+ jid,
502
+ {
503
+ react: {
504
+ text: '💖', // use an empty string to remove the reaction
505
+ key: message.key
506
+ }
507
+ }
508
+ )
509
+ ```
510
+
511
+ #### Pin Message
512
+ - 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
513
+
514
+ - Time can be:
515
+
516
+ | Time | Seconds |
517
+ |-------|----------------|
518
+ | 24h | 86.400 |
519
+ | 7d | 604.800 |
520
+ | 30d | 2.592.000 |
521
+
522
+ ```ts
523
+ await sock.sendMessage(
524
+ jid,
525
+ {
526
+ pin: {
527
+ type: 1, // 2 to remove
528
+ time: 86400,
529
+ key: Key
530
+ }
531
+ }
532
+ )
533
+ ```
534
+
535
+ ### Keep Message
536
+ ```ts
537
+ await sock.sendMessage(
538
+ jid,
539
+ {
540
+ keep: {
541
+ key: Key,
542
+ type: 1 // or 2
543
+ }
544
+ }
545
+ )
546
+ ```
547
+
548
+ #### Poll Message
549
+ ```ts
550
+ await sock.sendMessage(
551
+ jid,
552
+ {
553
+ poll: {
554
+ name: 'My Poll',
555
+ values: ['Option 1', 'Option 2', ...],
556
+ selectableCount: 1,
557
+ toAnnouncementGroup: false // or true
558
+ }
559
+ }
560
+ )
561
+ ```
562
+
563
+ #### Poll Result Message
564
+ ```ts
565
+ await sock.sendMessage(
566
+ jid,
567
+ {
568
+ pollResult: {
569
+ name: 'Hi',
570
+ values: [
571
+ [
572
+ 'Option 1',
573
+ 1000
574
+ ],
575
+ [
576
+ 'Option 2',
577
+ 2000
578
+ ]
579
+ ]
580
+ }
581
+ }
582
+ )
583
+ ```
584
+
585
+ ### Call Message
586
+ ```ts
587
+ await sock.sendMessage(
588
+ jid,
589
+ {
590
+ call: {
591
+ name: 'Hay',
592
+ type: 1 // 2 for video
593
+ }
594
+ }
595
+ )
596
+ ```
597
+
598
+ ### Event Message
599
+ ```ts
600
+ await sock.sendMessage(
601
+ jid,
602
+ {
603
+ event: {
604
+ isCanceled: false, // or true
605
+ name: 'holiday together!',
606
+ description: 'who wants to come along?',
607
+ location: {
608
+ degreesLatitude: 24.121231,
609
+ degreesLongitude: 55.1121221,
610
+ name: 'name'
611
+ },
612
+ call: 'audio', // or 'video'
613
+ startTime: number,
614
+ endTime: number,
615
+ extraGuestsAllowed: true // or false
616
+ }
617
+ }
618
+ )
619
+ ```
620
+
621
+ ### Order Message
622
+ ```ts
623
+ await sock.sendMessage(
624
+ jid,
625
+ {
626
+ order: {
627
+ orderId: '574xxx',
628
+ thumbnail: 'your_thumbnail',
629
+ itemCount: 'your_count',
630
+ status: 'your_status', // INQUIRY || ACCEPTED || DECLINED
631
+ surface: 'CATALOG',
632
+ message: 'your_caption',
633
+ orderTitle: "your_title",
634
+ sellerJid: 'your_jid'',
635
+ token: 'your_token',
636
+ totalAmount1000: 'your_amount',
637
+ totalCurrencyCode: 'IDR'
638
+ }
639
+ }
640
+ )
641
+ ```
642
+
643
+ ### Product Message
644
+ ```ts
645
+ await sock.sendMessage(
646
+ jid,
647
+ {
648
+ product: {
649
+ productImage: { // for using buffer >> productImage: your_buffer
650
+ url: your_url
651
+ },
652
+ productId: 'your_id',
653
+ title: 'your_title',
654
+ description: 'your_description',
655
+ currencyCode: 'IDR',
656
+ priceAmount1000: 'your_amount',
657
+ retailerId: 'your_reid', // optional use if needed
658
+ url: 'your_url', // optional use if needed
659
+ productImageCount: 'your_imageCount',
660
+ firstImageId: 'your_image', // optional use if needed
661
+ salePriceAmount1000: 'your_priceSale',
662
+ signedUrl: 'your_url' // optional use if needed
663
+ },
664
+ businessOwnerJid: 'your_jid'
665
+ }
666
+ )
667
+ ```
668
+
669
+ ### Payment Message
670
+ ```ts
671
+ await sock.sendMessage(
672
+ jid,
673
+ {
674
+ payment: {
675
+ note: 'Hi!',
676
+ currency: 'IDR', // optional
677
+ offset: 0, // optional
678
+ amount: '10000', // optional
679
+ expiry: 0, // optional
680
+ from: '628xxxx@s.whatsapp.net', // optional
681
+ image: { // optional
682
+ placeholderArgb: "your_background", // optional
683
+ textArgb: "your_text", // optional
684
+ subtextArgb: "your_subtext" // optional
685
+ }
686
+ }
687
+ }
688
+ )
689
+ ```
690
+
691
+ #### Payment Invite Message
692
+ ```ts
693
+ await sock.sendMessage(
694
+ id,
695
+ {
696
+ paymentInvite: {
697
+ type: number, // 1 || 2 || 3
698
+ expiry: 0
699
+ }
700
+ }
701
+ )
702
+ ```
703
+
704
+ ### Admin Invite Message
705
+ ```ts
706
+ await sock.sendMessage(
707
+ jid,
708
+ {
709
+ adminInvite: {
710
+ jid: '123xxx@newsletter',
711
+ name: 'newsletter_name',
712
+ caption: 'Please be my channel admin',
713
+ expiration: 86400,
714
+ jpegThumbnail: Buffer // optional
715
+ }
716
+ }
717
+ )
718
+ ```
719
+
720
+ ### Group Invite Message
721
+ ```ts
722
+ await sock.sendMessage(
723
+ jid,
724
+ {
725
+ groupInvite: {
726
+ jid: '123xxx@g.us',
727
+ name: 'group_name',
728
+ caption: 'Please Join My Whatsapp Group',
729
+ code: 'code_invite',
730
+ expiration: 86400,
731
+ jpegThumbnail: Buffer, // optional
732
+ }
733
+ }
734
+ )
735
+ ```
736
+
737
+ ### Sticker Pack Message
738
+ ```ts
739
+ // I don't know why the sticker doesn't appear
740
+ await sock.sendMessage(
741
+ jid,
742
+ {
743
+ stickerPack: {
744
+ name: 'Hiii',
745
+ publisher: 'By Itsockchann',
746
+ description: 'Hello',
747
+ cover: { url: 'https://example.com/cover.webp' }, // Buffer
748
+ stickers: [{
749
+ sticker: { url: 'https://example.com/1234kjd.webp' },
750
+ emojis: ['❤'], // optional
751
+ accessibilityLabel: '', // optional
752
+ isLottie: Boolean, // optional
753
+ isAnimated: Boolean // optional
754
+ },
755
+ {
756
+ sticker: Buffer,
757
+ emojis: ['❤'], // optional
758
+ accessibilityLabel: '', // optional
759
+ isLottie: Boolean, // optional
760
+ isAnimated: Boolean // optional
761
+ }]
762
+ }
763
+ }
764
+ )
765
+ ```
766
+
767
+ ### Share Phone Number Message
768
+ ```ts
769
+ await sock.sendMessage(
770
+ jid,
771
+ {
772
+ sharePhoneNumber: {
773
+ }
774
+ }
775
+ )
776
+ ```
777
+
778
+ ### Request Phone Number Message
779
+ ```ts
780
+ await sock.sendMessage(
781
+ jid,
782
+ {
783
+ requestPhoneNumber: {
784
+ }
785
+ }
786
+ )
787
+ ```
788
+
789
+ ### Buttons Reply Message
790
+ ```ts
791
+ // List
792
+ await sock.sendMessage(
793
+ jid,
794
+ {
795
+ buttonReply: {
796
+ name: 'Hii',
797
+ description: 'description',
798
+ rowId: 'ID'
799
+ },
800
+ type: 'list'
801
+ }
802
+ )
803
+ // Plain
804
+ await sock.sendMessage(
805
+ jid,
806
+ {
807
+ buttonReply: {
808
+ displayText: 'Hii',
809
+ id: 'ID'
810
+ },
811
+ type: 'plain'
812
+ }
813
+ )
814
+
815
+ // Template
816
+ await sock.sendMessage(
817
+ jid,
818
+ {
819
+ buttonReply: {
820
+ displayText: 'Hii',
821
+ id: 'ID',
822
+ index: 'number'
823
+ },
824
+ type: 'template'
825
+ }
826
+ )
827
+
828
+ // Interactive
829
+ await sock.sendMessage(
830
+ jid,
831
+ {
832
+ buttonReply: {
833
+ body: 'Hii',
834
+ nativeFlows: {
835
+ name: 'menu_options',
836
+ paramsJson: JSON.stringify({ id: 'ID', description: 'description' })
837
+ version: 1 // 2 | 3
838
+ }
839
+ },
840
+ type: 'interactive'
841
+ }
842
+ )
843
+ ```
844
+
845
+ ### Buttons Message
846
+ ```ts
847
+ await sock.sendMessage(
848
+ jid,
849
+ {
850
+ text: 'This is a button message!', // image: buffer or // image: { url: url } If you want to use images
851
+ caption: 'caption', // Use this if you are using an image or video
852
+ footer: 'Hello World!',
853
+ buttons: [{
854
+ buttonId: 'Id1',
855
+ buttonText: {
856
+ displayText: 'Button 1'
857
+ }
858
+ },
859
+ {
860
+ buttonId: 'Id2',
861
+ buttonText: {
862
+ displayText: 'Button 2'
863
+ }
864
+ },
865
+ {
866
+ buttonId: 'Id3',
867
+ buttonText: {
868
+ displayText: 'Button 3'
869
+ }
870
+ }]
871
+ }
872
+ )
873
+ ```
874
+
875
+ ### Buttons List Message
876
+ ```ts
877
+ // Just working in a private chat
878
+ await sock.sendMessage(
879
+ jid,
880
+ {
881
+ text: 'This is a list!',
882
+ footer: 'Hello World!',
883
+ title: 'Amazing boldfaced list title',
884
+ buttonText: 'Required, text on the button to view the list',
885
+ sections: [
886
+ {
887
+ title: 'Section 1',
888
+ rows: [{
889
+ title: 'Option 1',
890
+ rowId: 'option1'
891
+ },
892
+ {
893
+ title: 'Option 2',
894
+ rowId: 'option2',
895
+ description: 'This is a description'
896
+ }]
897
+ },
898
+ {
899
+ title: 'Section 2',
900
+ rows: [{
901
+ title: 'Option 3',
902
+ rowId: 'option3'
903
+ },
904
+ {
905
+ title: 'Option 4',
906
+ rowId: 'option4',
907
+ description: 'This is a description V2'
908
+ }]
909
+ }]
910
+ }
911
+ )
912
+ ```
913
+
914
+ ### Buttons Product List Message
915
+ ```ts
916
+ // Just working in a private chat
917
+ await sock.sendMessage(
918
+ jid,
919
+ {
920
+ text: 'This is a list!',
921
+ footer: 'Hello World!',
922
+ title: 'Amazing boldfaced list title',
923
+ buttonText: 'Required, text on the button to view the list',
924
+ productList: [{
925
+ title: 'This is a title',
926
+ products: [
927
+ {
928
+ productId: '1234'
929
+ },
930
+ {
931
+ productId: '5678'
932
+ }
933
+ ]
934
+ }],
935
+ businessOwnerJid: '628xxx@s.whatsapp.net',
936
+ thumbnail: 'https://example.com/jdbenkksjs.jpg' // or buffer
937
+ }
938
+ )
939
+ ```
940
+
941
+ ### Buttons Cards Message
942
+ ```ts
943
+ await sock.sendMessage(
944
+ jid,
945
+ {
946
+ text: 'Body Message',
947
+ title: 'Title Message',
948
+ subtile: 'Subtitle Message',
949
+ footer: 'Footer Message',
950
+ cards: [
951
+ {
952
+ image: { url: 'https://example.com/jdbenkksjs.jpg' }, // or buffer
953
+ title: 'Title Cards',
954
+ body: 'Body Cards',
955
+ footer: 'Footer Cards',
956
+ buttons: [
957
+ {
958
+ name: 'quick_reply',
959
+ buttonParamsJson: JSON.stringify({
960
+ display_text: 'Display Button',
961
+ id: 'ID'
962
+ })
963
+ },
964
+ {
965
+ name: 'cta_url',
966
+ buttonParamsJson: JSON.stringify({
967
+ display_text: 'Display Button',
968
+ url: 'https://www.example.com'
969
+ })
970
+ }
971
+ ]
972
+ },
973
+ {
974
+ video: { url: 'https://example.com/jdbenkksjs.mp4' }, // or buffer
975
+ title: 'Title Cards',
976
+ body: 'Body Cards',
977
+ footer: 'Footer Cards',
978
+ buttons: [
979
+ {
980
+ name: 'quick_reply',
981
+ buttonParamsJson: JSON.stringify({
982
+ display_text: 'Display Button',
983
+ id: 'ID'
984
+ })
985
+ },
986
+ {
987
+ name: 'cta_url',
988
+ buttonParamsJson: JSON.stringify({
989
+ display_text: 'Display Button',
990
+ url: 'https://www.example.com'
991
+ })
992
+ }
993
+ ]
994
+ }
995
+ ]
996
+ }
997
+ )
998
+ ```
999
+
1000
+ ### Buttons Template Message
1001
+ ```ts
1002
+ // This no longer works
1003
+ await sock.sendMessage(
1004
+ jid,
1005
+ {
1006
+ text: 'This is a template message!',
1007
+ footer: 'Hello World!',
1008
+ templateButtons: [{
1009
+ index: 1,
1010
+ urlButton: {
1011
+ displayText: 'Follow Me',
1012
+ url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
1013
+ },
1014
+ },
1015
+ {
1016
+ index: 2,
1017
+ callButton: {
1018
+ displayText: 'Call Me!',
1019
+ phoneNumber: '628xxx'
1020
+ },
1021
+ },
1022
+ {
1023
+ index: 3,
1024
+ quickReplyButton: {
1025
+ displayText: 'This is a reply, just like normal buttons!',
1026
+ id: 'id-like-buttons-message'
1027
+ },
1028
+ }]
1029
+ }
1030
+ )
1031
+ ```
1032
+
1033
+ ### Buttons Interactive Message
1034
+ ```ts
1035
+ await sock.sendMessage(
1036
+ jid,
1037
+ {
1038
+ text: 'This is an Interactive message!',
1039
+ title: 'Hiii',
1040
+ subtitle: 'There is a subtitle',
1041
+ footer: 'Hello World!',
1042
+ interactiveButtons: [
1043
+ {
1044
+ name: 'quick_reply',
1045
+ buttonParamsJson: JSON.stringify({
1046
+ display_text: 'Click Me!',
1047
+ id: 'your_id'
1048
+ })
1049
+ },
1050
+ {
1051
+ name: 'cta_url',
1052
+ buttonParamsJson: JSON.stringify({
1053
+ display_text: 'Follow Me',
1054
+ url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y',
1055
+ merchant_url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
1056
+ })
1057
+ },
1058
+ {
1059
+ name: 'cta_copy',
1060
+ buttonParamsJson: JSON.stringify({
1061
+ display_text: 'Click Me!',
1062
+ copy_code: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
1063
+ })
1064
+ },
1065
+ {
1066
+ name: 'cta_call',
1067
+ buttonParamsJson: JSON.stringify({
1068
+ display_text: 'Call Me!',
1069
+ phone_number: '628xxx'
1070
+ })
1071
+ },
1072
+ {
1073
+ name: 'cta_catalog',
1074
+ buttonParamsJson: JSON.stringify({
1075
+ business_phone_number: '628xxx'
1076
+ })
1077
+ },
1078
+ {
1079
+ name: 'cta_reminder',
1080
+ buttonParamsJson: JSON.stringify({
1081
+ display_text: '...'
1082
+ })
1083
+ },
1084
+ {
1085
+ name: 'cta_cancel_reminder',
1086
+ buttonParamsJson: JSON.stringify({
1087
+ display_text: '...'
1088
+ })
1089
+ },
1090
+ {
1091
+ name: 'address_message',
1092
+ buttonParamsJson: JSON.stringify({
1093
+ display_text: '...'
1094
+ })
1095
+ },
1096
+ {
1097
+ name: 'send_location',
1098
+ buttonParamsJson: JSON.stringify({
1099
+ display_text: '...'
1100
+ })
1101
+ },
1102
+ {
1103
+ name: 'open_webview',
1104
+ buttonParamsJson: JSON.stringify({
1105
+ title: 'Follow Me!',
1106
+ link: {
1107
+ in_app_webview: true, // or false
1108
+ url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
1109
+ }
1110
+ })
1111
+ },
1112
+ {
1113
+ name: 'mpm',
1114
+ buttonParamsJson: JSON.stringify({
1115
+ product_id: '8816262248471474'
1116
+ })
1117
+ },
1118
+ {
1119
+ name: 'wa_payment_transaction_details',
1120
+ buttonParamsJson: JSON.stringify({
1121
+ transaction_id: '12345848'
1122
+ })
1123
+ },
1124
+ {
1125
+ name: 'automated_greeting_message_view_catalog',
1126
+ buttonParamsJson: JSON.stringify({
1127
+ business_phone_number: '628xxx',
1128
+ catalog_product_id: '12345'
1129
+ })
1130
+ },
1131
+ {
1132
+ name: 'galaxy_message',
1133
+ buttonParamsJson: JSON.stringify({
1134
+ mode: 'published',
1135
+ flow_message_version: '3',
1136
+ flow_token: '1:1307913409923914:293680f87029f5a13d1ec5e35e718af3',
1137
+ flow_id: '1307913409923914',
1138
+ flow_cta: 'Itsockchann kawaii >\\<',
1139
+ flow_action: 'navigate',
1140
+ flow_action_payload: {
1141
+ screen: 'QUESTION_ONE',
1142
+ params: {
1143
+ user_id: '123456789',
1144
+ referral: 'campaign_xyz'
1145
+ }
1146
+ },
1147
+ flow_metadata: {
1148
+ flow_json_version: '201',
1149
+ data_api_protocol: 'v2',
1150
+ flow_name: 'Lead Qualification [en]',
1151
+ data_api_version: 'v2',
1152
+ categories: ['Lead Generation', 'Sales']
1153
+ }
1154
+ })
1155
+ },
1156
+ {
1157
+ name: 'single_select',
1158
+ buttonParamsJson: JSON.stringify({
1159
+ title: 'Click Me!',
1160
+ sections: [
1161
+ {
1162
+ title: 'Title 1',
1163
+ highlight_label: 'Highlight label 1',
1164
+ rows: [
1165
+ {
1166
+ header: 'Header 1',
1167
+ title: 'Title 1',
1168
+ description: 'Description 1',
1169
+ id: 'Id 1'
1170
+ },
1171
+ {
1172
+ header: 'Header 2',
1173
+ title: 'Title 2',
1174
+ description: 'Description 2',
1175
+ id: 'Id 2'
1176
+ }
1177
+ ]
1178
+ }
1179
+ ]
1180
+ })
1181
+ }
1182
+ ]
1183
+ }
1184
+ )
1185
+
1186
+ // If you want to use an image
1187
+ await sock.sendMessage(
1188
+ jid,
1189
+ {
1190
+ image: {
1191
+ url: 'https://example.com/jdbenkksjs.jpg'
1192
+ },
1193
+ caption: 'Body',
1194
+ title: 'Title',
1195
+ subtitle: 'Subtitle',
1196
+ footer: 'Footer',
1197
+ interactiveButtons: [
1198
+ {
1199
+ name: 'quick_reply',
1200
+ buttonParamsJson: JSON.stringify({
1201
+ display_text: 'DisplayText',
1202
+ id: 'ID1'
1203
+ })
1204
+ }
1205
+ ],
1206
+ hasMediaAttachment: false // or true
1207
+ }
1208
+ )
1209
+
1210
+ // If you want to use an video
1211
+ await sock.sendMessage(
1212
+ jid,
1213
+ {
1214
+ video: {
1215
+ url: 'https://example.com/jdbenkksjs.mp4'
1216
+ },
1217
+ caption: 'Body',
1218
+ title: 'Title',
1219
+ subtitle: 'Subtitle',
1220
+ footer: 'Footer',
1221
+ interactiveButtons: [
1222
+ {
1223
+ name: 'quick_reply',
1224
+ buttonParamsJson: JSON.stringify({
1225
+ display_text: 'DisplayText',
1226
+ id: 'ID1'
1227
+ })
1228
+ }
1229
+ ],
1230
+ hasMediaAttachment: false // or true
1231
+ }
1232
+ )
1233
+
1234
+ // If you want to use an document
1235
+ await sock.sendMessage(
1236
+ jid,
1237
+ {
1238
+ document: {
1239
+ url: 'https://example.com/jdbenkksjs.jpg'
1240
+ },
1241
+ mimetype: 'image/jpeg',
1242
+ jpegThumbnail: await sock.resize('https://example.com/jdbenkksjs.jpg', 320, 320),
1243
+ caption: 'Body',
1244
+ title: 'Title',
1245
+ subtitle: 'Subtitle',
1246
+ footer: 'Footer',
1247
+ interactiveButtons: [
1248
+ {
1249
+ name: 'quick_reply',
1250
+ buttonParamsJson: JSON.stringify({
1251
+ display_text: 'DisplayText',
1252
+ id: 'ID1'
1253
+ })
1254
+ }
1255
+ ],
1256
+ hasMediaAttachment: false // or true
1257
+ }
1258
+ )
1259
+
1260
+ // If you want to use an location
1261
+ await sock.sendMessage(
1262
+ jid,
1263
+ {
1264
+ location: {
1265
+ degressLatitude: -0,
1266
+ degressLongitude: 0,
1267
+ name: 'Hi'
1268
+ },
1269
+ caption: 'Body',
1270
+ title: 'Title',
1271
+ subtitle: 'Subtitle',
1272
+ footer: 'Footer',
1273
+ interactiveButtons: [
1274
+ {
1275
+ name: 'quick_reply',
1276
+ buttonParamsJson: JSON.stringify({
1277
+ display_text: 'DisplayText',
1278
+ id: 'ID1'
1279
+ })
1280
+ }
1281
+ ],
1282
+ hasMediaAttachment: false // or true
1283
+ }
1284
+ )
1285
+
1286
+ // if you want to use an product
1287
+ await sock.sendMessage(
1288
+ jid,
1289
+ {
1290
+ product: {
1291
+ productImage: {
1292
+ url: 'https://example.com/jdbenkksjs.jpg'
1293
+ },
1294
+ productId: '836xxx',
1295
+ title: 'Title',
1296
+ description: 'Description',
1297
+ currencyCode: 'IDR',
1298
+ priceAmount1000: '283xxx',
1299
+ retailerId: 'Itsockchann',
1300
+ url: 'https://example.com',
1301
+ productImageCount: 1
1302
+ },
1303
+ businessOwnerJid: '628xxx@s.whatsapp.net',
1304
+ caption: 'Body',
1305
+ title: 'Title',
1306
+ subtitle: 'Subtitle',
1307
+ footer: 'Footer',
1308
+ interactiveButtons: [
1309
+ {
1310
+ name: 'quick_reply',
1311
+ buttonParamsJson: JSON.stringify({
1312
+ display_text: 'DisplayText',
1313
+ id: 'ID1'
1314
+ })
1315
+ }
1316
+ ],
1317
+ hasMediaAttachment: false // or true
1318
+ }
1319
+ )
1320
+ ```
1321
+
1322
+ ### Buttons Interactive Message PIX
1323
+ ```ts
1324
+ await sock.sendMessage(
1325
+ jid,
1326
+ {
1327
+ text: '', // This string is required. Even it's empty.
1328
+ interactiveButtons: [
1329
+ {
1330
+ name: 'payment_info',
1331
+ buttonParamsJson: JSON.stringify({
1332
+ payment_settings: [{
1333
+ type: "pix_static_code",
1334
+ pix_static_code: {
1335
+ merchant_name: 'itsockchann kawaii >\\\\\\<',
1336
+ key: 'example@itsockchan.com',
1337
+ key_type: 'EMAIL' // PHONE || EMAIL || CPF || EVP
1338
+ }
1339
+ }]
1340
+ })
1341
+ }
1342
+ ],
1343
+ }
1344
+ )
1345
+ ```
1346
+
1347
+ ### Buttons Interactive Message PAY
1348
+ ```ts
1349
+ await sock.sendMessage(
1350
+ jid,
1351
+ {
1352
+ text: '', // This string is required. Even it's empty.
1353
+ interactiveButtons: [
1354
+ {
1355
+ name: 'review_and_pay',
1356
+ buttonParamsJson: JSON.stringify({
1357
+ currency: 'IDR',
1358
+ payment_configuration: '',
1359
+ payment_type: '',
1360
+ total_amount: {
1361
+ value: '999999999',
1362
+ offset: '100'
1363
+ },
1364
+ reference_id: '45XXXXX',
1365
+ type: 'physical-goods',
1366
+ payment_method: 'confirm',
1367
+ payment_status: 'captured',
1368
+ payment_timestamp: Math.floor(Date.now() / 1000),
1369
+ order: {
1370
+ status: 'completed',
1371
+ description: '',
1372
+ subtotal: {
1373
+ value: '0',
1374
+ offset: '100'
1375
+ },
1376
+ order_type: 'PAYMENT_REQUEST',
1377
+ items: [{
1378
+ retailer_id: 'your_retailer_id',
1379
+ name: 'Itsockchann Kawaii >\\\<',
1380
+ amount: {
1381
+ value: '999999999',
1382
+ offset: '100'
1383
+ },
1384
+ quantity: '1',
1385
+ }]
1386
+ },
1387
+ additional_note: 'Itsockchann Kawaii >\\\<',
1388
+ native_payment_methods: [],
1389
+ share_payment_status: false
1390
+ })
1391
+ }
1392
+ ],
1393
+ }
1394
+ )
1395
+ ```
1396
+
1397
+ ### Group Status Message
1398
+ ```ts
1399
+ // Text
1400
+ await sock.groupStatusMessage(jid,
1401
+ {
1402
+ text: 'Hello Everyone :3',
1403
+ font: 2, // optional
1404
+ textColor: 'FF0000', // optional
1405
+ backgroundColor: '#000000' // optional
1406
+ }
1407
+ )
1408
+
1409
+ // Image
1410
+ await sock.groupStatusMessage(jid,
1411
+ {
1412
+ Image: { url: 'https://example.com/ruriooe.jpg' }, or image buffer
1413
+ caption: 'Hello Everyone :3' // optional
1414
+ }
1415
+ )
1416
+
1417
+ // Video
1418
+ await sock.groupStatusMessage(jid,
1419
+ {
1420
+ video: { url: 'https://example.com/ruriooe.mp4' }, or video buffer
1421
+ caption: 'Hello Everyone :3' // optional
1422
+ }
1423
+ )
1424
+
1425
+ // Audio
1426
+ await sock.groupStatusMessage(jid,
1427
+ {
1428
+ audio: { url: 'https://example.com/ruriooe.mp3' }, or audio buffer
1429
+ backgroundColor: '#000000', // optional
1430
+ mimetype: 'audio/mp4',
1431
+ ppt: true
1432
+ },
1433
+ )
1434
+ ```
1435
+
1436
+ ### Status Mentions Message
1437
+ ```ts
1438
+ const jidat = [
1439
+ '123451679@g.us',
1440
+ '124848899@g.us',
1441
+ '111384848@g.us',
1442
+ '62689xxxx@s.whatsapp.net',
1443
+ '62xxxxxxx@s.whatsapp.net'
1444
+ ]
1445
+ // Text
1446
+ await sock.sendStatusMentions(
1447
+ {
1448
+ text: 'Hello Everyone :3',
1449
+ font: 2, // optional
1450
+ textColor: 'FF0000', // optional
1451
+ backgroundColor: '#000000' // optional
1452
+ },
1453
+ jids // Limit to 5 mentions per status
1454
+ )
1455
+
1456
+ // Image
1457
+ await sock.sendStatusMentions(
1458
+ {
1459
+ Image: { url: 'https://example.com/ruriooe.jpg' }, or image buffer
1460
+ caption: 'Hello Everyone :3' // optional
1461
+ },
1462
+ jids // Limit to 5 mentions per status
1463
+ )
1464
+
1465
+ // Video
1466
+ await sock.sendStatusMentions(
1467
+ {
1468
+ video: { url: 'https://example.com/ruriooe.mp4' }, or video buffer
1469
+ caption: 'Hello Everyone :3' // optional
1470
+ },
1471
+ jids // Limit to 5 mentions per status
1472
+ )
1473
+
1474
+ // Audio
1475
+ await sock.sendStatusMentions(
1476
+ {
1477
+ audio: { url: 'https://example.com/ruriooe.mp3' }, or audio buffer
1478
+ backgroundColor: '#000000', // optional
1479
+ mimetype: 'audio/mp4',
1480
+ ppt: true
1481
+ },
1482
+ jids // Limit to 5 mentions per status
1483
+ )
1484
+ ```
1485
+
1486
+ ### Shop Message
1487
+ ```ts
1488
+ await sock.sendMessage(
1489
+ jid,
1490
+ {
1491
+ text: 'Body',
1492
+ title: 'Title',
1493
+ subtitle: 'Subtitle',
1494
+ footer: 'Footer',
1495
+ shop: {
1496
+ surface: 1, // 2 | 3 | 4
1497
+ id: 'https://example.com'
1498
+ },
1499
+ viewOnce: true
1500
+ }
1501
+ )
1502
+
1503
+ // Image
1504
+ await sock.sendMessage(
1505
+ jid,
1506
+ {
1507
+ image: {
1508
+ url: 'https://example.com/jdbenkksjs.jpg'
1509
+ },
1510
+ caption: 'Body',
1511
+ title: 'Title',
1512
+ subtitle: 'Subtitle',
1513
+ footer: 'Footer',
1514
+ shop: {
1515
+ surface: 1, // 2 | 3 | 4
1516
+ id: 'https://example.com'
1517
+ },
1518
+ hasMediaAttachment: false, // or true
1519
+ viewOnce: true
1520
+ }
1521
+ )
1522
+
1523
+ // Video
1524
+ await sock.sendMessage(
1525
+ jid,
1526
+ {
1527
+ video: {
1528
+ url: 'https://example.com/jdbenkksjs.jpg'
1529
+ },
1530
+ caption: 'Body',
1531
+ title: 'Title',
1532
+ subtitle: 'Subtitle',
1533
+ footer: 'Footer',
1534
+ shop: {
1535
+ surface: 1, // 2 | 3 | 4
1536
+ id: 'https://example.com'
1537
+ },
1538
+ hasMediaAttachment: false, // or true
1539
+ viewOnce: true
1540
+ }
1541
+ )
1542
+
1543
+ // Document
1544
+ await sock.sendMessage(
1545
+ jid,
1546
+ {
1547
+ document: {
1548
+ url: 'https://example.com/jdbenkksjs.jpg'
1549
+ },
1550
+ mimetype: 'image/jpeg',
1551
+ jpegThumbnail: await sock.resize('https://example.com/jdbenkksjs.jpg', 320, 320),
1552
+ caption: 'Body',
1553
+ title: 'Title',
1554
+ subtitle: 'Subtitle',
1555
+ footer: 'Footer',
1556
+ shop: {
1557
+ surface: 1, // 2 | 3 | 4
1558
+ id: 'https://example.com'
1559
+ },
1560
+ hasMediaAttachment: false, // or true,
1561
+ viewOnce: true
1562
+ }
1563
+ )
1564
+
1565
+ // Location
1566
+ await sock.sendMessage(
1567
+ jid,
1568
+ {
1569
+ location: {
1570
+ degressLatitude: -0,
1571
+ degressLongitude: 0,
1572
+ name: 'Hi'
1573
+ },
1574
+ caption: 'Body',
1575
+ title: 'Title',
1576
+ subtitle: 'Subtitle',
1577
+ footer: 'Footer',
1578
+ shop: {
1579
+ surface: 1, // 2 | 3 | 4
1580
+ id: 'https://example.com'
1581
+ },
1582
+ hasMediaAttachment: false, // or true
1583
+ viewOnce: true
1584
+ }
1585
+ )
1586
+
1587
+ // Product
1588
+ await sock.sendMessage(
1589
+ jid,
1590
+ {
1591
+ product: {
1592
+ productImage: {
1593
+ url: 'https://example.com/jdbenkksjs.jpg'
1594
+ },
1595
+ productId: '836xxx',
1596
+ title: 'Title',
1597
+ description: 'Description',
1598
+ currencyCode: 'IDR',
1599
+ priceAmount1000: '283xxx',
1600
+ retailerId: 'Itsockchann',
1601
+ url: 'https://example.com',
1602
+ productImageCount: 1
1603
+ },
1604
+ businessOwnerJid: '628xxx@s.whatsapp.net',
1605
+ caption: 'Body',
1606
+ title: 'Title',
1607
+ subtitle: 'Subtitle',
1608
+ footer: 'Footer',
1609
+ shop: {
1610
+ surface: 1, // 2 | 3 | 4
1611
+ id: 'https://example.com'
1612
+ },
1613
+ hasMediaAttachment: false, // or true
1614
+ viewOnce: true
1615
+ }
1616
+ )
1617
+ ```
1618
+ ### Collection Message
1619
+ ```ts
1620
+ await sock.sendMessage(
1621
+ jid,
1622
+ {
1623
+ text: 'Body',
1624
+ title: 'Title',
1625
+ subtitle: 'Subtitle',
1626
+ footer: 'Footer',
1627
+ collection: {
1628
+ bizJid: 'jid',
1629
+ id: 'https://example.com',
1630
+ version: 1
1631
+ },
1632
+ viewOnce: true
1633
+ }
1634
+ )
1635
+
1636
+ // Image
1637
+ await sock.sendMessage(
1638
+ jid,
1639
+ {
1640
+ image: {
1641
+ url: 'https://example.com/jdbenkksjs.jpg'
1642
+ },
1643
+ caption: 'Body',
1644
+ title: 'Title',
1645
+ subtitle: 'Subtitle',
1646
+ footer: 'Footer',
1647
+ collection: {
1648
+ bizJid: 'jid',
1649
+ id: 'https://example.com',
1650
+ version: 1
1651
+ },
1652
+ hasMediaAttachment: false, // or true
1653
+ viewOnce: true
1654
+ }
1655
+ )
1656
+
1657
+ // Video
1658
+ await sock.sendMessage(
1659
+ jid,
1660
+ {
1661
+ video: {
1662
+ url: 'https://example.com/jdbenkksjs.jpg'
1663
+ },
1664
+ caption: 'Body',
1665
+ title: 'Title',
1666
+ subtitle: 'Subtitle',
1667
+ footer: 'Footer',
1668
+ collection: {
1669
+ bizJid: 'jid',
1670
+ id: 'https://example.com',
1671
+ version: 1
1672
+ },
1673
+ hasMediaAttachment: false, // or true
1674
+ viewOnce: true
1675
+ }
1676
+ )
1677
+
1678
+ // Document
1679
+ await sock.sendMessage(
1680
+ jid,
1681
+ {
1682
+ document: {
1683
+ url: 'https://example.com/jdbenkksjs.jpg'
1684
+ },
1685
+ mimetype: 'image/jpeg',
1686
+ jpegThumbnail: await sock.resize('https://example.com/jdbenkksjs.jpg', 320, 320),
1687
+ caption: 'Body',
1688
+ title: 'Title',
1689
+ subtitle: 'Subtitle',
1690
+ footer: 'Footer',
1691
+ collection: {
1692
+ bizJid: 'jid',
1693
+ id: 'https://example.com',
1694
+ version: 1
1695
+ },
1696
+ hasMediaAttachment: false, // or true,
1697
+ viewOnce: true
1698
+ }
1699
+ )
1700
+
1701
+ // Location
1702
+ await sock.sendMessage(
1703
+ jid,
1704
+ {
1705
+ location: {
1706
+ degressLatitude: -0,
1707
+ degressLongitude: 0,
1708
+ name: 'Hi'
1709
+ },
1710
+ caption: 'Body',
1711
+ title: 'Title',
1712
+ subtitle: 'Subtitle',
1713
+ footer: 'Footer',
1714
+ collection: {
1715
+ bizJid: 'jid',
1716
+ id: 'https://example.com',
1717
+ version: 1
1718
+ },
1719
+ hasMediaAttachment: false, // or true
1720
+ viewOnce: true
1721
+ }
1722
+ )
1723
+
1724
+ // Product
1725
+ await sock.sendMessage(
1726
+ jid,
1727
+ {
1728
+ product: {
1729
+ productImage: {
1730
+ url: 'https://example.com/jdbenkksjs.jpg'
1731
+ },
1732
+ productId: '836xxx',
1733
+ title: 'Title',
1734
+ description: 'Description',
1735
+ currencyCode: 'IDR',
1736
+ priceAmount1000: '283xxx',
1737
+ retailerId: 'Itsockchann',
1738
+ url: 'https://example.com',
1739
+ productImageCount: 1
1740
+ },
1741
+ businessOwnerJid: '628xxx@s.whatsapp.net',
1742
+ caption: 'Body',
1743
+ title: 'Title',
1744
+ subtitle: 'Subtitle',
1745
+ footer: 'Footer',
1746
+ collection: {
1747
+ bizJid: 'jid',
1748
+ id: 'https://example.com',
1749
+ version: 1
1750
+ },
1751
+ hasMediaAttachment: false, // or true
1752
+ viewOnce: true
1753
+ }
1754
+ )
1755
+ ```
1756
+
1757
+ ### AI Icon Feature
1758
+ ```ts
1759
+ await sock.sendMessage(
1760
+ jid,
1761
+ {
1762
+ text: 'Hi'
1763
+ }, {
1764
+ ai: true // Add ai usage and change it to true
1765
+ }
1766
+ )
1767
+
1768
+ // If using relay
1769
+ await sock.relayMessage(
1770
+ jid,
1771
+ {
1772
+ extendedTextMessage: {
1773
+ text: 'Hi'
1774
+ }
1775
+ }, {
1776
+ AI: true // Use capital letters
1777
+ }
1778
+ )
1779
+ ```
1780
+
1781
+ ### Sending Messages with Link Previews
1782
+
1783
+ 1. By default, wa does not have link generation when sent from the web
1784
+ 2. Baileys has a function to generate the content for these link previews
1785
+ 3. To enable this function's usage, add `link-preview-js` as a dependency to your project with `yarn add link-preview-js`
1786
+ 4. Send a link:
1787
+ ```ts
1788
+ await sock.sendMessage(
1789
+ jid,
1790
+ {
1791
+ text: 'Hi, this was sent using https://github.com/whiskeysockets/baileys'
1792
+ }
1793
+ )
1794
+ ```
1795
+
1796
+ ### Media Messages
1797
+
1798
+ Sending media (video, stickers, images) is easier & more efficient than ever.
1799
+
1800
+ > [!NOTE]
1801
+ > 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)
1802
+
1803
+ - When specifying a media url, Baileys never loads the entire buffer into memory it even encrypts the media as a readable stream.
1804
+
1805
+ > [!TIP]
1806
+ > It's recommended to use Stream or Url to save memory
1807
+
1808
+ #### Gif Message
1809
+ - Whatsapp doesn't support `.gif` files, that's why we send gifs as common `.mp4` video with `gifPlayback` flag
1810
+ ```ts
1811
+ await sock.sendMessage(
1812
+ jid,
1813
+ {
1814
+ video: fs.readFileSync('Media/ma_gif.mp4'),
1815
+ caption: 'hello word',
1816
+ gifPlayback: true
1817
+ }
1818
+ )
1819
+ ```
1820
+
1821
+ #### Video Message
1822
+ ```ts
1823
+ await sock.sendMessage(
1824
+ id,
1825
+ {
1826
+ video: {
1827
+ url: './Media/ma_gif.mp4'
1828
+ },
1829
+ caption: 'hello word',
1830
+ }
1831
+ )
1832
+ ```
1833
+
1834
+ #### Video Ptv Message
1835
+ ```ts
1836
+ await sock.sendMessage(
1837
+ id,
1838
+ {
1839
+ video: {
1840
+ url: './Media/ma_gif.mp4'
1841
+ },
1842
+ ptv: true
1843
+ }
1844
+ )
1845
+ ```
1846
+
1847
+ #### Audio Message
1848
+ - To audio message work in all devices you need to convert with some tool like `ffmpeg` with this flags:
1849
+ ```bash
1850
+ codec: libopus //ogg file
1851
+ ac: 1 //one channel
1852
+ avoid_negative_ts
1853
+ make_zero
1854
+ ```
1855
+ - Example:
1856
+ ```bash
1857
+ ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
1858
+ ```
1859
+ ```ts
1860
+ await sock.sendMessage(
1861
+ jid,
1862
+ {
1863
+ audio: {
1864
+ url: './Media/audio.mp3'
1865
+ },
1866
+ mimetype: 'audio/mp4'
1867
+ }
1868
+ )
1869
+ ```
1870
+
1871
+ #### Image Message
1872
+ ```ts
1873
+ await sock.sendMessage(
1874
+ id,
1875
+ {
1876
+ image: {
1877
+ url: './Media/ma_img.png'
1878
+ },
1879
+ caption: 'hello word'
1880
+ }
1881
+ )
1882
+ ```
1883
+
1884
+ ### Album Message
1885
+ ```ts
1886
+ await sock.sendMessage(
1887
+ id,
1888
+ {
1889
+ album: [{
1890
+ image: {
1891
+ url: 'https://example.com/itsockchan.jpg'
1892
+ },
1893
+ caption: 'Hay'
1894
+ }, {
1895
+ image: Buffer,
1896
+ caption: 'Hay'
1897
+ }, {
1898
+ video: {
1899
+ url: 'https://example.com/itsockchan.mp4'
1900
+ },
1901
+ caption: 'Hay'
1902
+ }, {
1903
+ video: Buffer,
1904
+ caption: 'Hay'
1905
+ }
1906
+ }
1907
+ )
1908
+ ```
1909
+
1910
+ #### View Once Message
1911
+
1912
+ - You can send all messages above as `viewOnce`, you only need to pass `viewOnce: true` in content object
1913
+
1914
+ ```ts
1915
+ await sock.sendMessage(
1916
+ id,
1917
+ {
1918
+ image: {
1919
+ url: './Media/ma_img.png'
1920
+ },
1921
+ viewOnce: true, //works with video, audio too
1922
+ caption: 'hello word'
1923
+ }
1924
+ )
1925
+ ```
1926
+
1927
+ ## Modify Messages
1928
+
1929
+ ### Deleting Messages (for everyone)
1930
+
1931
+ ```ts
1932
+ const msg = await sock.sendMessage(jid, { text: 'hello word' })
1933
+ await sock.sendMessage(jid, { delete: msg.key })
1934
+ ```
1935
+
1936
+ **Note:** deleting for oneself is supported via `chatModify`, see in [this section](#modifying-chats)
1937
+
1938
+ ### Editing Messages
1939
+
1940
+ - You can pass all editable contents here
1941
+ ```ts
1942
+ await sock.sendMessage(jid, {
1943
+ text: 'updated text goes here',
1944
+ edit: response.key,
1945
+ })
1946
+ ```
1947
+
1948
+ ## Manipulating Media Messages
1949
+
1950
+ ### Thumbnail in Media Messages
1951
+ - 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`.
1952
+ - Thumbnails for videos can also be generated automatically, though, you need to have `ffmpeg` installed on your system.
1953
+
1954
+ ### Downloading Media Messages
1955
+
1956
+ If you want to save the media you received
1957
+ ```ts
1958
+ import { createWriteStream } from 'fs'
1959
+ import { downloadMediaMessage, getContentType } from '@elrayyxml/baileys'
1960
+
1961
+ sock.ev.on('messages.upsert', async ({ [m] }) => {
1962
+ if (!m.message) return // if there is no text or media message
1963
+ const messageType = getContentType(m) // get what type of message it is (text, image, video...)
1964
+
1965
+ // if the message is an image
1966
+ if (messageType === 'imageMessage') {
1967
+ // download the message
1968
+ const stream = await downloadMediaMessage(
1969
+ m,
1970
+ 'stream', // can be 'buffer' too
1971
+ { },
1972
+ {
1973
+ logger,
1974
+ // pass this so that baileys can request a reupload of media
1975
+ // that has been deleted
1976
+ reuploadRequest: sock.updateMediaMessage
1977
+ }
1978
+ )
1979
+ // save to file
1980
+ const writeStream = createWriteStream('./my-download.jpeg')
1981
+ stream.pipe(writeStream)
1982
+ }
1983
+ }
1984
+ ```
1985
+
1986
+ ### Re-upload Media Message to Whatsapp
1987
+
1988
+ - 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:
1989
+ ```ts
1990
+ await sock.updateMediaMessage(msg)
1991
+ ```
1992
+
1993
+ ## Reject Call
1994
+
1995
+ - You can obtain `callId` and `callFrom` from `call` event
1996
+
1997
+ ```ts
1998
+ await sock.rejectCall(callId, callFrom)
1999
+ ```
2000
+
2001
+ ## Send States in Chat
2002
+
2003
+ ### Reading Messages
2004
+ - A set of message [keys](https://baileys.whiskeysockets.io/types/WAMessageKey.html) must be explicitly marked read now.
2005
+ - You cannot mark an entire 'chat' read as it were with Baileys Web.
2006
+ This means you have to keep track of unread messages.
2007
+
2008
+ ```ts
2009
+ const key: WAMessageKey
2010
+ // can pass multiple keys to read multiple messages as well
2011
+ await sock.readMessages([key])
2012
+ ```
2013
+
2014
+ The message ID is the unique identifier of the message that you are marking as read.
2015
+ On a `WAMessage`, the `messageID` can be accessed using ```messageID = message.key.id```.
2016
+
2017
+ ### Update Presence
2018
+
2019
+ - ``` presence ``` can be one of [these](https://baileys.whiskeysockets.io/types/WAPresence.html)
2020
+ - The presence expires after about 10 seconds.
2021
+ - This lets the person/group with `jid` know whether you're online, offline, typing etc.
2022
+
2023
+ ```ts
2024
+ await sock.sendPresenceUpdate('available', jid)
2025
+ ```
2026
+
2027
+ > [!NOTE]
2028
+ > 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')`
2029
+
2030
+ ## Modifying Chats
2031
+
2032
+ WA uses an encrypted form of communication to send chat/app updates. This has been implemented mostly and you can send the following updates:
2033
+
2034
+ > [!IMPORTANT]
2035
+ > 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.
2036
+
2037
+ ### Archive a Chat
2038
+ ```ts
2039
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
2040
+ await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
2041
+ ```
2042
+ ### Mute/Unmute a Chat
2043
+
2044
+ - Supported times:
2045
+
2046
+ | Time | Miliseconds |
2047
+ |-------|-----------------|
2048
+ | Remove | null |
2049
+ | 8h | 86.400.000 |
2050
+ | 7d | 604.800.000 |
2051
+
2052
+ ```ts
2053
+ // mute for 8 hours
2054
+ await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
2055
+ // unmute
2056
+ await sock.chatModify({ mute: null }, jid)
2057
+ ```
2058
+ ### Mark a Chat Read/Unread
2059
+ ```ts
2060
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
2061
+ // mark it unread
2062
+ await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
2063
+ ```
2064
+
2065
+ ### Delete a Message for Me
2066
+ ```ts
2067
+ await sock.chatModify(
2068
+ {
2069
+ clear: {
2070
+ messages: [
2071
+ {
2072
+ id: 'ATWYHDNNWU81732J',
2073
+ fromMe: true,
2074
+ timestamp: '1654823909'
2075
+ }
2076
+ ]
2077
+ }
2078
+ },
2079
+ jid
2080
+ )
2081
+
2082
+ ```
2083
+ ### Delete a Chat
2084
+ ```ts
2085
+ const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
2086
+ await sock.chatModify({
2087
+ delete: true,
2088
+ lastMessages: [
2089
+ {
2090
+ key: lastMsgInChat.key,
2091
+ messageTimestamp: lastMsgInChat.messageTimestamp
2092
+ }
2093
+ ]
2094
+ },
2095
+ jid
2096
+ )
2097
+ ```
2098
+ ### Pin/Unpin a Chat
2099
+ ```ts
2100
+ await sock.chatModify({
2101
+ pin: true // or `false` to unpin
2102
+ },
2103
+ jid
2104
+ )
2105
+ ```
2106
+ ### Star/Unstar a Message
2107
+ ```ts
2108
+ await sock.chatModify({
2109
+ star: {
2110
+ messages: [
2111
+ {
2112
+ id: 'messageID',
2113
+ fromMe: true // or `false`
2114
+ }
2115
+ ],
2116
+ star: true // - true: Star Message false: Unstar Message
2117
+ }
2118
+ },
2119
+ jid
2120
+ )
2121
+ ```
2122
+
2123
+ ### Disappearing Messages
2124
+
2125
+ - Ephemeral can be:
2126
+
2127
+ | Time | Seconds |
2128
+ |-------|----------------|
2129
+ | Remove | 0 |
2130
+ | 24h | 86.400 |
2131
+ | 7d | 604.800 |
2132
+ | 90d | 7.776.000 |
2133
+
2134
+ - You need to pass in **Seconds**, default is 7 days
2135
+
2136
+ ```ts
2137
+ // turn on disappearing messages
2138
+ await sock.sendMessage(
2139
+ jid,
2140
+ // this is 1 week in seconds -- how long you want messages to appear for
2141
+ { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
2142
+ )
2143
+
2144
+ // will send as a disappearing message
2145
+ await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
2146
+
2147
+ // turn off disappearing messages
2148
+ await sock.sendMessage(
2149
+ jid,
2150
+ { disappearingMessagesInChat: false }
2151
+ )
2152
+ ```
2153
+
2154
+ ### Clear Messages
2155
+ ```ts
2156
+ await sock.clearMessage(jid, key, timestamps)
2157
+ ```
2158
+
2159
+ ## User Querys
2160
+
2161
+ ### Check If ID Exists in Whatsapp
2162
+ ```ts
2163
+ const [result] = await sock.onWhatsApp(jid)
2164
+ if (result.exists) console.log (`${jid} exists on WhatsApp, as jid: ${result.jid}`)
2165
+ ```
2166
+
2167
+ ### Query Chat History (groups too)
2168
+
2169
+ - You need to have oldest message in chat
2170
+ ```ts
2171
+ const msg = await getOldestMessageInChat(jid)
2172
+ await sock.fetchMessageHistory(
2173
+ 50, //quantity (max: 50 per query)
2174
+ msg.key,
2175
+ msg.messageTimestamp
2176
+ )
2177
+ ```
2178
+ - Messages will be received in `messaging.history-set` event
2179
+
2180
+ ### Fetch Status
2181
+ ```ts
2182
+ const status = await sock.fetchStatus(jid)
2183
+ console.log('status: ' + status)
2184
+ ```
2185
+
2186
+ ### Fetch Profile Picture
2187
+ - To get the display picture of some person, group and channel
2188
+ ```ts
2189
+ // for low res picture
2190
+ const ppUrl = await sock.profilePictureUrl(jid)
2191
+ console.log(ppUrl)
2192
+ ```
2193
+
2194
+ ### Fetch Bussines Profile (such as description or category)
2195
+ ```ts
2196
+ const profile = await sock.getBusinessProfile(jid)
2197
+ console.log('business description: ' + profile.description + ', category: ' + profile.category)
2198
+ ```
2199
+
2200
+ ### Fetch Someone's Presence (if they're typing or online)
2201
+ ```ts
2202
+ // the presence update is fetched and called here
2203
+ sock.ev.on('presence.update', console.log)
2204
+
2205
+ // request updates for a chat
2206
+ await sock.presenceSubscribe(jid)
2207
+ ```
2208
+
2209
+ ## Change Profile
2210
+
2211
+ ### Change Profile Status
2212
+ ```ts
2213
+ await sock.updateProfileStatus('Hello World!')
2214
+ ```
2215
+ ### Change Profile Name
2216
+ ```ts
2217
+ await sock.updateProfileName('My name')
2218
+ ```
2219
+ ### Change Display Picture (groups too)
2220
+ - To change your display picture or a group's
2221
+
2222
+ > [!NOTE]
2223
+ > 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)
2224
+
2225
+ ```ts
2226
+ await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
2227
+ ```
2228
+ ### Remove display picture (groups too)
2229
+ ```ts
2230
+ await sock.removeProfilePicture(jid)
2231
+ ```
2232
+
2233
+ ## Groups
2234
+
2235
+ - To change group properties you need to be admin
2236
+
2237
+ ### Create a Group
2238
+ ```ts
2239
+ // title & participants
2240
+ const group = await sock.groupCreate('My Fab Group', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
2241
+ console.log('created group with id: ' + group.gid)
2242
+ await sock.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
2243
+ ```
2244
+ ### Add/Remove or Demote/Promote
2245
+ ```ts
2246
+ // id & people to add to the group (will throw error if it fails)
2247
+ await sock.groupParticipantsUpdate(
2248
+ jid,
2249
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
2250
+ 'add' // replace this parameter with 'remove' or 'demote' or 'promote'
2251
+ )
2252
+ ```
2253
+ ### Change Subject (name)
2254
+ ```ts
2255
+ await sock.groupUpdateSubject(jid, 'New Subject!')
2256
+ ```
2257
+ ### Change Description
2258
+ ```ts
2259
+ await sock.groupUpdateDescription(jid, 'New Description!')
2260
+ ```
2261
+ ### Change Settings
2262
+ ```ts
2263
+ // only allow admins to send messages
2264
+ await sock.groupSettingUpdate(jid, 'announcement')
2265
+ // allow everyone to send messages
2266
+ await sock.groupSettingUpdate(jid, 'not_announcement')
2267
+ // allow everyone to modify the group's settings -- like display picture etc.
2268
+ await sock.groupSettingUpdate(jid, 'unlocked')
2269
+ // only allow admins to modify the group's settings
2270
+ await sock.groupSettingUpdate(jid, 'locked')
2271
+ ```
2272
+ ### Leave a Group
2273
+ ```ts
2274
+ // will throw error if it fails
2275
+ await sock.groupLeave(jid)
2276
+ ```
2277
+ ### Get Invite Code
2278
+ - To create link with code use `'https://chat.whatsapp.com/' + code`
2279
+ ```ts
2280
+ const code = await sock.groupInviteCode(jid)
2281
+ console.log('group code: ' + code)
2282
+ ```
2283
+ ### Revoke Invite Code
2284
+ ```ts
2285
+ const code = await sock.groupRevokeInvite(jid)
2286
+ console.log('New group code: ' + code)
2287
+ ```
2288
+ ### Join Using Invitation Code
2289
+ - Code can't have `https://chat.whatsapp.com/`, only code
2290
+ ```ts
2291
+ const response = await sock.groupAcceptInvite(code)
2292
+ console.log('joined to: ' + response)
2293
+ ```
2294
+ ### Get Group Info by Invite Code
2295
+ ```ts
2296
+ const response = await sock.groupGetInviteInfo(code)
2297
+ console.log('group information: ' + response)
2298
+ ```
2299
+ ### Query Metadata (participants, name, description...)
2300
+ ```ts
2301
+ const metadata = await sock.groupMetadata(jid)
2302
+ console.log(metadata.id + ', title: ' + metadata.subject + ', description: ' + metadata.desc)
2303
+ ```
2304
+ ### Join using `groupInviteMessage`
2305
+ ```ts
2306
+ const response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
2307
+ console.log('joined to: ' + response)
2308
+ ```
2309
+ ### Get Request Join List
2310
+ ```ts
2311
+ const response = await sock.groupRequestParticipantsList(jid)
2312
+ console.log(response)
2313
+ ```
2314
+ ### Approve/Reject Request Join
2315
+ ```ts
2316
+ const response = await sock.groupRequestParticipantsUpdate(
2317
+ jid, // group id
2318
+ ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
2319
+ 'approve' // or 'reject'
2320
+ )
2321
+ console.log(response)
2322
+ ```
2323
+ ### Get All Participating Groups Metadata
2324
+ ```ts
2325
+ const response = await sock.groupFetchAllParticipating()
2326
+ console.log(response)
2327
+ ```
2328
+ ### Toggle Ephemeral
2329
+
2330
+ - Ephemeral can be:
2331
+
2332
+ | Time | Seconds |
2333
+ |-------|----------------|
2334
+ | Remove | 0 |
2335
+ | 24h | 86.400 |
2336
+ | 7d | 604.800 |
2337
+ | 90d | 7.776.000 |
2338
+
2339
+ ```ts
2340
+ await sock.groupToggleEphemeral(jid, 86400)
2341
+ ```
2342
+
2343
+ ### Change Add Mode
2344
+ ```ts
2345
+ await sock.groupMemberAddMode(
2346
+ jid,
2347
+ 'all_member_add' // or 'admin_add'
2348
+ )
2349
+ ```
2350
+
2351
+ ## Privacy
2352
+
2353
+ ### Block/Unblock User
2354
+ ```ts
2355
+ await sock.updateBlockStatus(jid, 'block') // Block user
2356
+ await sock.updateBlockStatus(jid, 'unblock') // Unblock user
2357
+ ```
2358
+ ### Get Privacy Settings
2359
+ ```ts
2360
+ const privacySettings = await sock.fetchPrivacySettings(true)
2361
+ console.log('privacy settings: ' + privacySettings)
2362
+ ```
2363
+ ### Get BlockList
2364
+ ```ts
2365
+ const response = await sock.fetchBlocklist()
2366
+ console.log(response)
2367
+ ```
2368
+ ### Update LastSeen Privacy
2369
+ ```ts
2370
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
2371
+ await sock.updateLastSeenPrivacy(value)
2372
+ ```
2373
+ ### Update Online Privacy
2374
+ ```ts
2375
+ const value = 'all' // 'match_last_seen'
2376
+ await sock.updateOnlinePrivacy(value)
2377
+ ```
2378
+ ### Update Profile Picture Privacy
2379
+ ```ts
2380
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
2381
+ await sock.updateProfilePicturePrivacy(value)
2382
+ ```
2383
+ ### Update Status Privacy
2384
+ ```ts
2385
+ const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
2386
+ await sock.updateStatusPrivacy(value)
2387
+ ```
2388
+ ### Update Read Receipts Privacy
2389
+ ```ts
2390
+ const value = 'all' // 'none'
2391
+ await sock.updateReadReceiptsPrivacy(value)
2392
+ ```
2393
+ ### Update Groups Add Privacy
2394
+ ```ts
2395
+ const value = 'all' // 'contacts' | 'contact_blacklist'
2396
+ await sock.updateGroupsAddPrivacy(value)
2397
+ ```
2398
+ ### Update Default Disappearing Mode
2399
+
2400
+ - Like [this](#disappearing-messages), ephemeral can be:
2401
+
2402
+ | Time | Seconds |
2403
+ |-------|----------------|
2404
+ | Remove | 0 |
2405
+ | 24h | 86.400 |
2406
+ | 7d | 604.800 |
2407
+ | 90d | 7.776.000 |
2408
+
2409
+ ```ts
2410
+ const ephemeral = 86400
2411
+ await sock.updateDefaultDisappearingMode(ephemeral)
2412
+ ```
2413
+
2414
+ ## Broadcast Lists & Stories
2415
+
2416
+ ### Send Broadcast & Stories
2417
+ - Messages can be sent to broadcasts & stories. You need to add the following message options in sendMessage, like this:
2418
+ ```ts
2419
+ await sock.sendMessage(
2420
+ jid,
2421
+ {
2422
+ image: {
2423
+ url: url
2424
+ },
2425
+ caption: caption
2426
+ },
2427
+ {
2428
+ backgroundColor: backgroundColor,
2429
+ font: font,
2430
+ statusJidList: statusJidList,
2431
+ broadcast: true
2432
+ }
2433
+ )
2434
+ ```
2435
+ - Message body can be a `extendedTextMessage` or `imageMessage` or `videoMessage` or `voiceMessage`, see [here](https://baileys.whiskeysockets.io/types/AnyRegularMessageContent.html)
2436
+ - You can add `backgroundColor` and other options in the message options, see [here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html)
2437
+ - `broadcast: true` enables broadcast mode
2438
+ - `statusJidList`: a list of people that you can get which you need to provide, which are the people who will get this status message.
2439
+
2440
+ - You can send messages to broadcast lists the same way you send messages to groups & individual chats.
2441
+ - Right now, WA Web does not support creating broadcast lists, but you can still delete them.
2442
+ - Broadcast IDs are in the format `12345678@broadcast`
2443
+ ### Query a Broadcast List's Recipients & Name
2444
+ ```ts
2445
+ const bList = await sock.getBroadcastListInfo('1234@broadcast')
2446
+ console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)
2447
+ ```
2448
+
2449
+ ## Writing Custom Functionality
2450
+ Baileys is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
2451
+
2452
+ ### Enabling Debug Level in Baileys Logs
2453
+ First, enable the logging of unhandled messages from WhatsApp by setting:
2454
+ ```ts
2455
+ const sock = makeWASocket({
2456
+ logger: P({ level: 'debug' }),
2457
+ })
2458
+ ```
2459
+ This will enable you to see all sorts of messages WhatsApp sends in the console.
2460
+
2461
+ ### How Whatsapp Communicate With Us
2462
+
2463
+ > [!TIP]
2464
+ > If you want to learn whatsapp protocol, we recommend to study about Libsignal Protocol and Noise Protocol
2465
+
2466
+ - **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:
2467
+ ```
2468
+ {
2469
+ "level": 10,
2470
+ "fromMe": false,
2471
+ "frame": {
2472
+ "tag": "ib",
2473
+ "attrs": {
2474
+ "from": "@s.whatsapp.net"
2475
+ },
2476
+ "content": [
2477
+ {
2478
+ "tag": "edge_routing",
2479
+ "attrs": {},
2480
+ "content": [
2481
+ {
2482
+ "tag": "routing_info",
2483
+ "attrs": {},
2484
+ "content": {
2485
+ "type": "Buffer",
2486
+ "data": [8,2,8,5]
2487
+ }
2488
+ }
2489
+ ]
2490
+ }
2491
+ ]
2492
+ },
2493
+ "msg":"communication"
2494
+ }
2495
+ ```
2496
+
2497
+ The `'frame'` is what the message received is, it has three components:
2498
+ - `tag` -- what this frame is about (eg. message will have 'message')
2499
+ - `attrs` -- a string key-value pair with some metadata (contains ID of the message usually)
2500
+ - `content` -- the actual data (eg. a message node will have the actual message content in it)
2501
+ - read more about this format [here](/src/WABinary/readme.md)
2502
+
2503
+ ### Register a Callback for Websocket Events
2504
+
2505
+ > [!TIP]
2506
+ > Recommended to see `onMessageReceived` function in `socket.ts` file to understand how websockets events are fired
2507
+
2508
+ ```ts
2509
+ // for any message with tag 'edge_routing'
2510
+ sock.ws.on('CB:edge_routing', (node: BinaryNode) => { })
2511
+
2512
+ // for any message with tag 'edge_routing' and id attribute = abcd
2513
+ sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => { })
2514
+
2515
+ // for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
2516
+ sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => { })
2517
+ ```