@queenanya/baileys 9.5.4 → 9.5.5-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +309 -1831
  2. package/WAProto/fix-imports.js +22 -18
  3. package/WAProto/index.js +22 -18
  4. package/lib/Defaults/index.d.ts +2 -0
  5. package/lib/Defaults/index.d.ts.map +1 -1
  6. package/lib/Defaults/index.js +3 -1
  7. package/lib/Defaults/index.js.map +1 -1
  8. package/lib/Socket/business.d.ts +80 -3
  9. package/lib/Socket/business.d.ts.map +1 -1
  10. package/lib/Socket/chats.d.ts +9 -0
  11. package/lib/Socket/chats.d.ts.map +1 -1
  12. package/lib/Socket/chats.js +216 -58
  13. package/lib/Socket/chats.js.map +1 -1
  14. package/lib/Socket/communities.d.ts +80 -3
  15. package/lib/Socket/communities.d.ts.map +1 -1
  16. package/lib/Socket/groups.d.ts +6 -0
  17. package/lib/Socket/groups.d.ts.map +1 -1
  18. package/lib/Socket/groups.js +6 -0
  19. package/lib/Socket/groups.js.map +1 -1
  20. package/lib/Socket/index.d.ts +80 -3
  21. package/lib/Socket/index.d.ts.map +1 -1
  22. package/lib/Socket/messages-recv.d.ts +80 -3
  23. package/lib/Socket/messages-recv.d.ts.map +1 -1
  24. package/lib/Socket/messages-recv.js +315 -60
  25. package/lib/Socket/messages-recv.js.map +1 -1
  26. package/lib/Socket/messages-send.d.ts +109 -3
  27. package/lib/Socket/messages-send.d.ts.map +1 -1
  28. package/lib/Socket/messages-send.js +170 -4
  29. package/lib/Socket/messages-send.js.map +1 -1
  30. package/lib/Socket/newsletter.d.ts +6 -0
  31. package/lib/Socket/newsletter.d.ts.map +1 -1
  32. package/lib/Socket/newsletter.js +2 -2
  33. package/lib/Socket/newsletter.js.map +1 -1
  34. package/lib/Socket/socket.d.ts.map +1 -1
  35. package/lib/Socket/socket.js +3 -3
  36. package/lib/Socket/socket.js.map +1 -1
  37. package/lib/Types/Auth.d.ts +1 -0
  38. package/lib/Types/Auth.d.ts.map +1 -1
  39. package/lib/Types/Call.d.ts +1 -1
  40. package/lib/Types/Call.d.ts.map +1 -1
  41. package/lib/Types/Contact.d.ts +2 -0
  42. package/lib/Types/Contact.d.ts.map +1 -1
  43. package/lib/Types/Events.d.ts +18 -1
  44. package/lib/Types/Events.d.ts.map +1 -1
  45. package/lib/Types/GroupMetadata.d.ts +4 -0
  46. package/lib/Types/GroupMetadata.d.ts.map +1 -1
  47. package/lib/Types/Message.d.ts +360 -9
  48. package/lib/Types/Message.d.ts.map +1 -1
  49. package/lib/Types/Message.js.map +1 -1
  50. package/lib/Types/Newsletter.d.ts +37 -42
  51. package/lib/Types/Newsletter.d.ts.map +1 -1
  52. package/lib/Types/Newsletter.js +18 -23
  53. package/lib/Types/Newsletter.js.map +1 -1
  54. package/lib/Types/State.d.ts +54 -0
  55. package/lib/Types/State.d.ts.map +1 -1
  56. package/lib/Types/State.js +42 -0
  57. package/lib/Types/State.js.map +1 -1
  58. package/lib/Utils/chat-utils.d.ts +30 -0
  59. package/lib/Utils/chat-utils.d.ts.map +1 -1
  60. package/lib/Utils/chat-utils.js +34 -8
  61. package/lib/Utils/chat-utils.js.map +1 -1
  62. package/lib/Utils/decode-wa-message.d.ts +12 -0
  63. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  64. package/lib/Utils/decode-wa-message.js +16 -0
  65. package/lib/Utils/decode-wa-message.js.map +1 -1
  66. package/lib/Utils/event-buffer.js +2 -0
  67. package/lib/Utils/event-buffer.js.map +1 -1
  68. package/lib/Utils/generics.d.ts.map +1 -1
  69. package/lib/Utils/generics.js +9 -0
  70. package/lib/Utils/generics.js.map +1 -1
  71. package/lib/Utils/history.d.ts.map +1 -1
  72. package/lib/Utils/history.js +12 -10
  73. package/lib/Utils/history.js.map +1 -1
  74. package/lib/Utils/identity-change-handler.d.ts +7 -0
  75. package/lib/Utils/identity-change-handler.d.ts.map +1 -1
  76. package/lib/Utils/identity-change-handler.js +1 -0
  77. package/lib/Utils/identity-change-handler.js.map +1 -1
  78. package/lib/Utils/index.d.ts +3 -0
  79. package/lib/Utils/index.d.ts.map +1 -1
  80. package/lib/Utils/index.js +3 -0
  81. package/lib/Utils/index.js.map +1 -1
  82. package/lib/Utils/interactive-message.js.map +1 -1
  83. package/lib/Utils/message-composer.d.ts +5 -0
  84. package/lib/Utils/message-composer.d.ts.map +1 -0
  85. package/lib/Utils/message-composer.js +5 -0
  86. package/lib/Utils/message-composer.js.map +1 -0
  87. package/lib/Utils/message-retry-manager.js.map +1 -1
  88. package/lib/Utils/messages-media.d.ts +1 -1
  89. package/lib/Utils/messages-media.d.ts.map +1 -1
  90. package/lib/Utils/messages-media.js +2 -2
  91. package/lib/Utils/messages-media.js.map +1 -1
  92. package/lib/Utils/messages.d.ts.map +1 -1
  93. package/lib/Utils/messages.js +14 -5
  94. package/lib/Utils/messages.js.map +1 -1
  95. package/lib/Utils/noise-handler.js.map +1 -1
  96. package/lib/Utils/process-message.d.ts.map +1 -1
  97. package/lib/Utils/process-message.js +58 -2
  98. package/lib/Utils/process-message.js.map +1 -1
  99. package/lib/Utils/sync-action-utils.d.ts.map +1 -1
  100. package/lib/Utils/sync-action-utils.js +1 -0
  101. package/lib/Utils/sync-action-utils.js.map +1 -1
  102. package/lib/Utils/tc-token-utils.d.ts +26 -1
  103. package/lib/Utils/tc-token-utils.d.ts.map +1 -1
  104. package/lib/Utils/tc-token-utils.js +149 -4
  105. package/lib/Utils/tc-token-utils.js.map +1 -1
  106. package/lib/WABinary/jid-utils.js.map +1 -1
  107. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
  108. package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
  109. package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
  110. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  111. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
  112. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  113. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
  114. package/lib/WAUSync/Protocols/index.d.ts +1 -0
  115. package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
  116. package/lib/WAUSync/Protocols/index.js +1 -0
  117. package/lib/WAUSync/Protocols/index.js.map +1 -1
  118. package/lib/WAUSync/USyncQuery.d.ts +1 -0
  119. package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
  120. package/lib/WAUSync/USyncQuery.js +5 -1
  121. package/lib/WAUSync/USyncQuery.js.map +1 -1
  122. package/lib/WAUSync/USyncUser.d.ts +4 -0
  123. package/lib/WAUSync/USyncUser.d.ts.map +1 -1
  124. package/lib/WAUSync/USyncUser.js +8 -0
  125. package/lib/WAUSync/USyncUser.js.map +1 -1
  126. package/lib/addons/auto-reply.js.map +1 -1
  127. package/lib/addons/browser-presets.d.ts +16 -0
  128. package/lib/addons/browser-presets.d.ts.map +1 -0
  129. package/lib/addons/browser-presets.js +24 -0
  130. package/lib/addons/browser-presets.js.map +1 -0
  131. package/lib/addons/button-sender.d.ts +0 -2
  132. package/lib/addons/button-sender.d.ts.map +1 -1
  133. package/lib/addons/button-sender.js +21 -23
  134. package/lib/addons/button-sender.js.map +1 -1
  135. package/lib/addons/call-handler.d.ts.map +1 -1
  136. package/lib/addons/call-handler.js.map +1 -1
  137. package/lib/addons/from-messages-recv.d.ts.map +1 -1
  138. package/lib/addons/from-messages-recv.js.map +1 -1
  139. package/lib/addons/from-messages.js.map +1 -1
  140. package/lib/addons/index.d.ts +22 -5
  141. package/lib/addons/index.d.ts.map +1 -1
  142. package/lib/addons/index.js +29 -17
  143. package/lib/addons/index.js.map +1 -1
  144. package/lib/addons/interactive-message.js.map +1 -1
  145. package/lib/addons/jid-plot.d.ts +49 -0
  146. package/lib/addons/jid-plot.d.ts.map +1 -0
  147. package/lib/addons/jid-plot.js +84 -0
  148. package/lib/addons/jid-plot.js.map +1 -0
  149. package/lib/addons/lid-support.d.ts +41 -0
  150. package/lib/addons/lid-support.d.ts.map +1 -0
  151. package/lib/addons/lid-support.js +42 -0
  152. package/lib/addons/lid-support.js.map +1 -0
  153. package/lib/addons/message-composer.d.ts +142 -0
  154. package/lib/addons/message-composer.d.ts.map +1 -0
  155. package/lib/addons/message-composer.js +377 -0
  156. package/lib/addons/message-composer.js.map +1 -0
  157. package/lib/addons/message-scheduler.d.ts +77 -0
  158. package/lib/addons/message-scheduler.d.ts.map +1 -0
  159. package/lib/addons/message-scheduler.js +108 -0
  160. package/lib/addons/message-scheduler.js.map +1 -0
  161. package/lib/addons/message-utils.d.ts.map +1 -1
  162. package/lib/addons/message-utils.js.map +1 -1
  163. package/lib/addons/outgoing-calls.d.ts +64 -0
  164. package/lib/addons/outgoing-calls.d.ts.map +1 -0
  165. package/lib/addons/outgoing-calls.js +139 -0
  166. package/lib/addons/outgoing-calls.js.map +1 -0
  167. package/lib/addons/pairing-fix.d.ts +31 -0
  168. package/lib/addons/pairing-fix.d.ts.map +1 -0
  169. package/lib/addons/pairing-fix.js +74 -0
  170. package/lib/addons/pairing-fix.js.map +1 -0
  171. package/lib/addons/past-participants.d.ts +42 -0
  172. package/lib/addons/past-participants.d.ts.map +1 -0
  173. package/lib/addons/past-participants.js +41 -0
  174. package/lib/addons/past-participants.js.map +1 -0
  175. package/lib/addons/rich-response.d.ts +111 -0
  176. package/lib/addons/rich-response.d.ts.map +1 -0
  177. package/lib/addons/rich-response.js +152 -0
  178. package/lib/addons/rich-response.js.map +1 -0
  179. package/lib/addons/status-posting.d.ts.map +1 -1
  180. package/lib/addons/status-posting.js +1 -3
  181. package/lib/addons/status-posting.js.map +1 -1
  182. package/lib/addons/stickerpack.d.ts +37 -0
  183. package/lib/addons/stickerpack.d.ts.map +1 -0
  184. package/lib/addons/stickerpack.js +39 -0
  185. package/lib/addons/stickerpack.js.map +1 -0
  186. package/package.json +3 -3
package/README.md CHANGED
@@ -1,2006 +1,484 @@
1
- <h1 align='center'><img alt="Baileys logo" src="https://raw.githubusercontent.com/WhiskeySockets/Baileys/refs/heads/master/Media/logo.png" height="75"/></h1>
1
+ <h1 align='center'>
2
+ <img alt="anya-bail logo" src="https://raw.githubusercontent.com/WhiskeySockets/Baileys/refs/heads/master/Media/logo.png" height="75"/>
3
+ </h1>
2
4
 
3
- <div align='center'>Baileys is a WebSockets-based TypeScript library for interacting with the WhatsApp Web API.</div>
5
+ <div align='center'>
4
6
 
5
- > [!CAUTION]
6
- > NOTICE OF BREAKING CHANGE.
7
- >
8
- > As of 7.0.0, multiple breaking changes were introduced into the library.
9
- >
10
- > Please check out https://whiskey.so/migrate-latest for more information.
7
+ **anya-bail** — A heavily extended fork of [WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys), the WhatsApp Web API library.
11
8
 
12
- # Important Note
9
+ Maintained for [@queenanya/baileys](https://github.com/QueenAnya/ANYA-MD) | Last updated: **April 2026**
13
10
 
14
- This is a temporary README.md, the new guide is in development and will this file will be replaced with .github/README.md (already a default on GitHub).
11
+ [![WA Version](https://img.shields.io/badge/WA%20Version-2.3000.1037656372-green)](#) [![Base](https://img.shields.io/badge/Base-WhiskeySockets%2FBaileys-blue)](#)
15
12
 
16
- New guide link: https://baileys.wiki
13
+ </div>
17
14
 
18
- # Get Support
19
-
20
- If you'd like business to enterprise-level support from Rajeh, the current maintainer of Baileys, you can book a video chat. Book a 1 hour time slot by contacting him on Discord or pre-ordering [here](https://purpshell.dev/book). The earlier you pre-order the better, as his time slots usually fill up very quickly. He offers immense value per hour and will answer all your questions before the time runs out.
21
-
22
- If you are a business, we encourage you to contribute back to the high development costs of the project and to feed the maintainers who dump tens of hours a week on this. You can do so by booking meetings or sponsoring below. All support, even in bona fide / contribution hours, is welcome by businesses of all sizes. This is not condoning or endorsing businesses to use the library. See the Disclaimer below.
23
-
24
- # Sponsor
25
-
26
- If you'd like to financially support this project, you can do so by supporting the current maintainer [here](https://purpshell.dev/sponsor).
27
-
28
- # Disclaimer
29
-
30
- This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates.
31
- The official WhatsApp website can be found at whatsapp.com. "WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners.
32
-
33
- 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.
34
- Use at your own discretion. Do not spam people with this. We discourage any stalkerware, bulk or automated messaging usage.
35
-
36
- ##
37
-
38
- - Baileys does not require Selenium or any other browser to be interface with WhatsApp Web, it does so directly using a **WebSocket**.
39
- - Not running Selenium or Chromium saves you like **half a gig** of ram :/
40
- - Baileys supports interacting with the multi-device & web versions of WhatsApp.
41
- - 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.
42
-
43
- > [!IMPORTANT]
44
- > The original repository had to be removed by the original author - we now continue development in this repository here.
45
- > This is the only official repository and is maintained by the community.
46
- > **Join the Discord [here](https://discord.gg/WeJM5FP9GG)**
47
-
48
- ## Example
49
-
50
- Do check out & run [example.ts](Example/example.ts) to see an example usage of the library.
51
- The script covers most common use cases.
52
- To run the example script, download or clone the repo and then type the following in a terminal:
53
-
54
- 1. `cd path/to/Baileys`
55
- 2. `yarn`
56
- 3. `yarn example`
57
-
58
- ## Install
59
-
60
- Use the stable version:
61
-
62
- ```
63
- yarn add @whiskeysockets/baileys
64
- ```
65
-
66
- Use the edge version (no guarantee of stability, but latest fixes + features)
67
-
68
- ```
69
- yarn add github:WhiskeySockets/Baileys
70
- ```
71
-
72
- Then import your code using:
73
-
74
- ```ts
75
- import makeWASocket from '@whiskeysockets/baileys'
76
- ```
77
-
78
- # Links
79
-
80
- - [Discord](https://discord.gg/WeJM5FP9GG)
81
- - [Docs](https://guide.whiskeysockets.io/)
82
-
83
- # Index
84
-
85
- - [Connecting Account](#connecting-account)
86
- - [Connect with QR-CODE](#starting-socket-with-qr-code)
87
- - [Connect with Pairing Code](#starting-socket-with-pairing-code)
88
- - [Receive Full History](#receive-full-history)
89
- - [Important Notes About Socket Config](#important-notes-about-socket-config)
90
- - [Caching Group Metadata (Recommended)](#caching-group-metadata-recommended)
91
- - [Improve Retry System & Decrypt Poll Votes](#improve-retry-system--decrypt-poll-votes)
92
- - [Receive Notifications in Whatsapp App](#receive-notifications-in-whatsapp-app)
93
-
94
- - [Save Auth Info](#saving--restoring-sessions)
95
- - [Handling Events](#handling-events)
96
- - [Example to Start](#example-to-start)
97
- - [Decrypt Poll Votes](#decrypt-poll-votes)
98
- - [Summary of Events on First Connection](#summary-of-events-on-first-connection)
99
- - [Implementing a Data Store](#implementing-a-data-store)
100
- - [Whatsapp IDs Explain](#whatsapp-ids-explain)
101
- - [Utility Functions](#utility-functions)
102
- - [Sending Messages](#sending-messages)
103
- - [Non-Media Messages](#non-media-messages)
104
- - [Text Message](#text-message)
105
- - [Quote Message](#quote-message-works-with-all-types)
106
- - [Mention User](#mention-user-works-with-most-types)
107
- - [Forward Messages](#forward-messages)
108
- - [Location Message](#location-message)
109
- - [Contact Message](#contact-message)
110
- - [Reaction Message](#reaction-message)
111
- - [Pin Message](#pin-message)
112
- - [Poll Message](#poll-message)
113
- - [Sending with Link Preview](#sending-messages-with-link-previews)
114
- - [Media Messages](#media-messages)
115
- - [Gif Message](#gif-message)
116
- - [Video Message](#video-message)
117
- - [Audio Message](#audio-message)
118
- - [Image Message](#image-message)
119
- - [ViewOnce Message](#view-once-message)
120
- - [Modify Messages](#modify-messages)
121
- - [Delete Messages (for everyone)](#deleting-messages-for-everyone)
122
- - [Edit Messages](#editing-messages)
123
- - [Manipulating Media Messages](#manipulating-media-messages)
124
- - [Thumbnail in Media Messages](#thumbnail-in-media-messages)
125
- - [Downloading Media Messages](#downloading-media-messages)
126
- - [Re-upload Media Message to Whatsapp](#re-upload-media-message-to-whatsapp)
127
- - [Reject Call](#reject-call)
128
- - [Send States in Chat](#send-states-in-chat)
129
- - [Reading Messages](#reading-messages)
130
- - [Update Presence](#update-presence)
131
- - [Modifying Chats](#modifying-chats)
132
- - [Archive a Chat](#archive-a-chat)
133
- - [Mute/Unmute a Chat](#muteunmute-a-chat)
134
- - [Mark a Chat Read/Unread](#mark-a-chat-readunread)
135
- - [Delete a Message for Me](#delete-a-message-for-me)
136
- - [Delete a Chat](#delete-a-chat)
137
- - [Star/Unstar a Message](#starunstar-a-message)
138
- - [Disappearing Messages](#disappearing-messages)
139
- - [User Querys](#user-querys)
140
- - [Check If ID Exists in Whatsapp](#check-if-id-exists-in-whatsapp)
141
- - [Query Chat History (groups too)](#query-chat-history-groups-too)
142
- - [Fetch Status](#fetch-status)
143
- - [Fetch Profile Picture (groups too)](#fetch-profile-picture-groups-too)
144
- - [Fetch Bussines Profile (such as description or category)](#fetch-bussines-profile-such-as-description-or-category)
145
- - [Fetch Someone's Presence (if they're typing or online)](#fetch-someones-presence-if-theyre-typing-or-online)
146
- - [Change Profile](#change-profile)
147
- - [Change Profile Status](#change-profile-status)
148
- - [Change Profile Name](#change-profile-name)
149
- - [Change Display Picture (groups too)](#change-display-picture-groups-too)
150
- - [Remove display picture (groups too)](#remove-display-picture-groups-too)
151
- - [Groups](#groups)
152
- - [Create a Group](#create-a-group)
153
- - [Add/Remove or Demote/Promote](#addremove-or-demotepromote)
154
- - [Change Subject (name)](#change-subject-name)
155
- - [Change Description](#change-description)
156
- - [Change Settings](#change-settings)
157
- - [Leave a Group](#leave-a-group)
158
- - [Get Invite Code](#get-invite-code)
159
- - [Revoke Invite Code](#revoke-invite-code)
160
- - [Join Using Invitation Code](#join-using-invitation-code)
161
- - [Get Group Info by Invite Code](#get-group-info-by-invite-code)
162
- - [Query Metadata (participants, name, description...)](#query-metadata-participants-name-description)
163
- - [Join using groupInviteMessage](#join-using-groupinvitemessage)
164
- - [Get Request Join List](#get-request-join-list)
165
- - [Approve/Reject Request Join](#approvereject-request-join)
166
- - [Get All Participating Groups Metadata](#get-all-participating-groups-metadata)
167
- - [Toggle Ephemeral](#toggle-ephemeral)
168
- - [Change Add Mode](#change-add-mode)
169
- - [Privacy](#privacy)
170
- - [Block/Unblock User](#blockunblock-user)
171
- - [Get Privacy Settings](#get-privacy-settings)
172
- - [Get BlockList](#get-blocklist)
173
- - [Update LastSeen Privacy](#update-lastseen-privacy)
174
- - [Update Online Privacy](#update-online-privacy)
175
- - [Update Profile Picture Privacy](#update-profile-picture-privacy)
176
- - [Update Status Privacy](#update-status-privacy)
177
- - [Update Read Receipts Privacy](#update-read-receipts-privacy)
178
- - [Update Groups Add Privacy](#update-groups-add-privacy)
179
- - [Update Default Disappearing Mode](#update-default-disappearing-mode)
180
- - [Broadcast Lists & Stories](#broadcast-lists--stories)
181
- - [Send Broadcast & Stories](#send-broadcast--stories)
182
- - [Query a Broadcast List's Recipients & Name](#query-a-broadcast-lists-recipients--name)
183
- - [iOS & Android Support](#ios--android-support)
184
- - [Anti-Delete System](#anti-delete-system)
185
- - [Auto-Reply System](#auto-reply-system)
186
- - [Message Scheduler](#message-scheduler)
187
- - [Interactive Messages](#interactive-messages)
188
- - [Buttons Message](#buttons-message)
189
- - [Template Buttons Message](#template-buttons-message)
190
- - [Interactive Buttons Message](#interactive-buttons-message)
191
- - [List Message](#list-message)
192
- - [Product List Message](#product-list-message)
193
- - [Shop Message](#shop-message)
194
- - [Collection Message](#collection-message)
195
- - [Cards / Carousel Message](#cards--carousel-message)
196
- - [Album Message](#album-message)
197
- - [Status Mentions](#status-mentions)
198
- - [Call Functions](#call-functions)
199
- - [Reject Call](#reject-call-1)
200
- - [Initiate Call](#initiate-call)
201
- - [Accept / Terminate Call](#accept--terminate-call)
202
- - [Single File Auth State](#single-file-auth-state)
203
- - [Contact Cards (vCard)](#contact-cards-vcard)
204
- - [JID Utilities](#jid-utilities)
205
- - [Message Search](#message-search)
206
- - [Templates](#templates)
207
- - [Chat Control](#chat-control)
208
- - [Writing Custom Functionality](#writing-custom-functionality)
209
- - [Enabling Debug Level in Baileys Logs](#enabling-debug-level-in-baileys-logs)
210
- - [How Whatsapp Communicate With Us](#how-whatsapp-communicate-with-us)
211
- - [Register a Callback for Websocket Events](#register-a-callback-for-websocket-events)
212
-
213
- ## Connecting Account
214
-
215
- 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.
216
-
217
- > [!NOTE]
218
- > **[Here](#example-to-start) is a simple example of event handling**
219
-
220
- > [!TIP]
221
- > **You can see all supported socket configs [here](https://baileys.whiskeysockets.io/types/SocketConfig.html) (Recommended)**
222
-
223
- ### Starting socket with **QR-CODE**
224
-
225
- > [!TIP]
226
- > 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)**
227
-
228
- ```ts
229
- import makeWASocket from '@whiskeysockets/baileys'
230
-
231
- const sock = makeWASocket({
232
- // can provide additional config here
233
- browser: Browsers.ubuntu('My App'),
234
- printQRInTerminal: true
235
- })
236
- ```
237
-
238
- 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!
239
-
240
- ### Starting socket with **Pairing Code**
241
-
242
- > [!IMPORTANT]
243
- > 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)
244
-
245
- The phone number can't have `+` or `()` or `-`, only numbers, you must provide country code
246
-
247
- ```ts
248
- import makeWASocket from '@whiskeysockets/baileys'
249
-
250
- const sock = makeWASocket({
251
- // can provide additional config here
252
- printQRInTerminal: false //need to be false
253
- })
254
-
255
- if (!sock.authState.creds.registered) {
256
- const number = 'XXXXXXXXXXX'
257
- const code = await sock.requestPairingCode(number)
258
- console.log(code)
259
- }
260
- ```
261
-
262
- ### Receive Full History
263
-
264
- 1. Set `syncFullHistory` as `true`
265
- 2. Baileys, by default, use chrome browser config
266
- - If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config:
267
-
268
- ```ts
269
- const sock = makeWASocket({
270
- ...otherOpts,
271
- // can use Windows, Ubuntu here too
272
- browser: Browsers.macOS('Desktop'),
273
- syncFullHistory: true
274
- })
275
- ```
276
-
277
- ## Important Notes About Socket Config
278
-
279
- ### Caching Group Metadata (Recommended)
280
-
281
- - If you use baileys for groups, we recommend you to set `cachedGroupMetadata` in socket config, you need to implement a cache like this:
282
-
283
- ```ts
284
- const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
285
-
286
- const sock = makeWASocket({
287
- cachedGroupMetadata: async jid => groupCache.get(jid)
288
- })
289
-
290
- sock.ev.on('groups.update', async ([event]) => {
291
- const metadata = await sock.groupMetadata(event.id)
292
- groupCache.set(event.id, metadata)
293
- })
294
-
295
- sock.ev.on('group-participants.update', async event => {
296
- const metadata = await sock.groupMetadata(event.id)
297
- groupCache.set(event.id, metadata)
298
- })
299
- ```
300
-
301
- ### Improve Retry System & Decrypt Poll Votes
302
-
303
- - 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:
304
- ```ts
305
- const sock = makeWASocket({
306
- getMessage: async key => await getMessageFromStore(key)
307
- })
308
- ```
309
-
310
- ### Receive Notifications in Whatsapp App
311
-
312
- - If you want to receive notifications in whatsapp app, set `markOnlineOnConnect` to `false`
313
- ```ts
314
- const sock = makeWASocket({
315
- markOnlineOnConnect: false
316
- })
317
- ```
318
-
319
- ## Saving & Restoring Sessions
320
-
321
- You obviously don't want to keep scanning the QR code every time you want to connect.
322
-
323
- So, you can load the credentials to log back in:
324
-
325
- ```ts
326
- import makeWASocket, { useMultiFileAuthState } from '@whiskeysockets/baileys'
327
-
328
- const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
329
-
330
- // will use the given state to connect
331
- // so if valid credentials are available -- it'll connect without QR
332
- const sock = makeWASocket({ auth: state })
333
-
334
- // this will be called as soon as the credentials are updated
335
- sock.ev.on('creds.update', saveCreds)
336
- ```
337
-
338
- > [!IMPORTANT]
339
- > `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.
340
-
341
- > [!NOTE]
342
- > 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.
343
-
344
- ## Handling Events
345
-
346
- - Baileys uses the EventEmitter syntax for events.
347
- They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
348
-
349
- > [!IMPORTANT]
350
- > **The events are [these](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**, it's important you see all events
351
-
352
- You can listen to these events like this:
353
-
354
- ```ts
355
- const sock = makeWASocket()
356
- sock.ev.on('messages.upsert', ({ messages }) => {
357
- console.log('got messages', messages)
358
- })
359
- ```
360
-
361
- ### Example to Start
362
-
363
- > [!NOTE]
364
- > This example includes basic auth storage too
365
-
366
- > [!NOTE]
367
- > For reliable serialization of the authentication state, especially when storing as JSON, always use the BufferJSON utility.
368
-
369
- ```ts
370
- import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@whiskeysockets/baileys'
371
- import { Boom } from '@hapi/boom'
372
-
373
- async function connectToWhatsApp() {
374
- const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
375
- const sock = makeWASocket({
376
- // can provide additional config here
377
- auth: state,
378
- printQRInTerminal: true
379
- })
380
- sock.ev.on('connection.update', update => {
381
- const { connection, lastDisconnect } = update
382
- if (connection === 'close') {
383
- const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
384
- console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
385
- // reconnect if not logged out
386
- if (shouldReconnect) {
387
- connectToWhatsApp()
388
- }
389
- } else if (connection === 'open') {
390
- console.log('opened connection')
391
- }
392
- })
393
- sock.ev.on('messages.upsert', event => {
394
- for (const m of event.messages) {
395
- console.log(JSON.stringify(m, undefined, 2))
396
-
397
- console.log('replying to', m.key.remoteJid)
398
- await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
399
- }
400
- })
401
-
402
- // to storage creds (session info) when it updates
403
- sock.ev.on('creds.update', saveCreds)
404
- }
405
- // run in main file
406
- connectToWhatsApp()
407
- ```
408
-
409
- > [!IMPORTANT]
410
- > In `messages.upsert` it's recommended to use a loop like `for (const message of event.messages)` to handle all messages in array
411
-
412
- ### Decrypt Poll Votes
413
-
414
- - By default poll votes are encrypted and handled in `messages.update`
415
- - That's a simple example
416
-
417
- ```ts
418
- sock.ev.on('messages.update', event => {
419
- for (const { key, update } of event) {
420
- if (update.pollUpdates) {
421
- const pollCreation = await getMessage(key)
422
- if (pollCreation) {
423
- console.log(
424
- 'got poll update, aggregation: ',
425
- getAggregateVotesInPollMessage({
426
- message: pollCreation,
427
- pollUpdates: update.pollUpdates
428
- })
429
- )
430
- }
431
- }
432
- }
433
- })
434
- ```
435
-
436
- - `getMessage` is a [store](#implementing-a-data-store) implementation (in your end)
437
-
438
- ### Summary of Events on First Connection
439
-
440
- 1. When you connect first time, `connection.update` will be fired requesting you to restart sock
441
- 2. Then, history messages will be received in `messaging.history-set`
442
-
443
- ## Implementing a Data Store
444
-
445
- - 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.
446
-
447
- > [!IMPORTANT]
448
- > I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM.
449
-
450
- It can be used as follows:
451
-
452
- ```ts
453
- import makeWASocket, { makeInMemoryStore } from '@whiskeysockets/baileys'
454
- // the store maintains the data of the WA connection in memory
455
- // can be written out to a file & read from it
456
- const store = makeInMemoryStore({})
457
- // can be read from a file
458
- store.readFromFile('./baileys_store.json')
459
- // saves the state to a file every 10s
460
- setInterval(() => {
461
- store.writeToFile('./baileys_store.json')
462
- }, 10_000)
463
-
464
- const sock = makeWASocket({})
465
- // will listen from this socket
466
- // the store can listen from a new socket once the current socket outlives its lifetime
467
- store.bind(sock.ev)
468
-
469
- sock.ev.on('chats.upsert', () => {
470
- // can use 'store.chats' however you want, even after the socket dies out
471
- // 'chats' => a KeyedDB instance
472
- console.log('got chats', store.chats.all())
473
- })
474
-
475
- sock.ev.on('contacts.upsert', () => {
476
- console.log('got contacts', Object.values(store.contacts))
477
- })
478
- ```
479
-
480
- The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval.
481
-
482
- ## Whatsapp IDs Explain
483
-
484
- - `id` is the WhatsApp ID, called `jid` too, of the person or group you're sending the message to.
485
- - It must be in the format `[country code][phone number]@s.whatsapp.net`
486
- - Example for people: `+19999999999@s.whatsapp.net`.
487
- - For groups, it must be in the format `123456789-123345@g.us`.
488
- - For broadcast lists, it's `[timestamp of creation]@broadcast`.
489
- - For stories, the ID is `status@broadcast`.
490
-
491
- ## Utility Functions
492
-
493
- - `getContentType`, returns the content type for any message
494
- - `getDevice`, returns the device from message
495
- - `makeCacheableSignalKeyStore`, make auth store more fast
496
- - `downloadContentFromMessage`, download content from any message
497
-
498
- ## Sending Messages
499
-
500
- - Send all types of messages with a single function
501
- - **[Here](https://baileys.whiskeysockets.io/types/AnyMessageContent.html) you can see all message contents supported, like text message**
502
- - **[Here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html) you can see all options supported, like quote message**
503
-
504
- ```ts
505
- const jid: string
506
- const content: AnyMessageContent
507
- const options: MiscMessageGenerationOptions
508
-
509
- sock.sendMessage(jid, content, options)
510
- ```
511
-
512
- ### Non-Media Messages
513
-
514
- #### Text Message
515
-
516
- ```ts
517
- await sock.sendMessage(jid, { text: 'hello word' })
518
- ```
519
-
520
- #### Quote Message (works with all types)
521
-
522
- ```ts
523
- await sock.sendMessage(jid, { text: 'hello word' }, { quoted: message })
524
- ```
525
-
526
- #### Mention User (works with most types)
527
-
528
- - @number is to mention in text, it's optional
529
-
530
- ```ts
531
- await sock.sendMessage(jid, {
532
- text: '@12345678901',
533
- mentions: ['12345678901@s.whatsapp.net']
534
- })
535
- ```
536
-
537
- #### Forward Messages
538
-
539
- - 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
540
-
541
- ```ts
542
- const msg = getMessageFromStore() // implement this on your end
543
- await sock.sendMessage(jid, { forward: msg }) // WA forward the message!
544
- ```
545
-
546
- #### Location Message
547
-
548
- ```ts
549
- await sock.sendMessage(jid, {
550
- location: {
551
- degreesLatitude: 24.121231,
552
- degreesLongitude: 55.1121221
553
- }
554
- })
555
- ```
556
-
557
- #### Contact Message
558
-
559
- ```ts
560
- const vcard =
561
- 'BEGIN:VCARD\n' + // metadata of the contact card
562
- 'VERSION:3.0\n' +
563
- 'FN:Jeff Singh\n' + // full name
564
- 'ORG:Ashoka Uni;\n' + // the organization of the contact
565
- 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n' + // WhatsApp ID + phone number
566
- 'END:VCARD'
567
-
568
- await sock.sendMessage(id, {
569
- contacts: {
570
- displayName: 'Jeff',
571
- contacts: [{ vcard }]
572
- }
573
- })
574
- ```
575
-
576
- #### Reaction Message
577
-
578
- - 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
579
-
580
- ```ts
581
- await sock.sendMessage(jid, {
582
- react: {
583
- text: '💖', // use an empty string to remove the reaction
584
- key: message.key
585
- }
586
- })
587
- ```
588
-
589
- #### Pin Message
590
-
591
- - 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
592
-
593
- - Time can be:
594
-
595
- | Time | Seconds |
596
- | ---- | --------- |
597
- | 24h | 86.400 |
598
- | 7d | 604.800 |
599
- | 30d | 2.592.000 |
600
-
601
- ```ts
602
- await sock.sendMessage(
603
- jid,
604
- {
605
- pin: {
606
- type: 1, // 0 to remove
607
- time: 86400
608
- key: message.key
609
- }
610
- }
611
- )
612
- ```
613
-
614
- #### Poll Message
615
-
616
- ```ts
617
- await sock.sendMessage(
618
- jid,
619
- {
620
- poll: {
621
- name: 'My Poll',
622
- values: ['Option 1', 'Option 2', ...],
623
- selectableCount: 1,
624
- toAnnouncementGroup: false // or true
625
- }
626
- }
627
- )
628
- ```
629
-
630
- ### Sending Messages with Link Previews
631
-
632
- 1. By default, wa does not have link generation when sent from the web
633
- 2. Baileys has a function to generate the content for these link previews
634
- 3. To enable this function's usage, add `link-preview-js` as a dependency to your project with `yarn add link-preview-js`
635
- 4. Send a link:
636
-
637
- ```ts
638
- await sock.sendMessage(jid, {
639
- text: 'Hi, this was sent using https://github.com/whiskeysockets/baileys'
640
- })
641
- ```
642
-
643
- ### Media Messages
644
-
645
- Sending media (video, stickers, images) is easier & more efficient than ever.
646
-
647
- > [!NOTE]
648
- > 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)
649
-
650
- - When specifying a media url, Baileys never loads the entire buffer into memory; it even encrypts the media as a readable stream.
651
-
652
- > [!TIP]
653
- > It's recommended to use Stream or Url to save memory
654
-
655
- #### Gif Message
656
-
657
- - Whatsapp doesn't support `.gif` files, that's why we send gifs as common `.mp4` video with `gifPlayback` flag
658
-
659
- ```ts
660
- await sock.sendMessage(jid, {
661
- video: fs.readFileSync('Media/ma_gif.mp4'),
662
- caption: 'hello word',
663
- gifPlayback: true
664
- })
665
- ```
666
-
667
- #### Video Message
668
-
669
- ```ts
670
- await sock.sendMessage(id, {
671
- video: {
672
- url: './Media/ma_gif.mp4'
673
- },
674
- caption: 'hello word',
675
- ptv: false // if set to true, will send as a `video note`
676
- })
677
- ```
678
-
679
- #### Audio Message
680
-
681
- - To audio message work in all devices you need to convert with some tool like `ffmpeg` with this flags:
682
-
683
- ```bash
684
- codec: libopus //ogg file
685
- ac: 1 //one channel
686
- avoid_negative_ts
687
- make_zero
688
- ```
689
-
690
- - Example:
691
-
692
- ```bash
693
- ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
694
- ```
695
-
696
- ```ts
697
- await sock.sendMessage(jid, {
698
- audio: {
699
- url: './Media/audio.mp3'
700
- },
701
- mimetype: 'audio/mp4'
702
- })
703
- ```
704
-
705
- #### Image Message
706
-
707
- ```ts
708
- await sock.sendMessage(id, {
709
- image: {
710
- url: './Media/ma_img.png'
711
- },
712
- caption: 'hello word'
713
- })
714
- ```
715
-
716
- #### View Once Message
717
-
718
- - You can send all messages above as `viewOnce`, you only need to pass `viewOnce: true` in content object
719
-
720
- ```ts
721
- await sock.sendMessage(id, {
722
- image: {
723
- url: './Media/ma_img.png'
724
- },
725
- viewOnce: true, //works with video, audio too
726
- caption: 'hello word'
727
- })
728
- ```
729
-
730
- ## Modify Messages
731
-
732
- ### Deleting Messages (for everyone)
733
-
734
- ```ts
735
- const msg = await sock.sendMessage(jid, { text: 'hello word' })
736
- await sock.sendMessage(jid, { delete: msg.key })
737
- ```
738
-
739
- **Note:** deleting for oneself is supported via `chatModify`, see in [this section](#modifying-chats)
740
-
741
- ### Editing Messages
742
-
743
- - You can pass all editable contents here
744
-
745
- ```ts
746
- await sock.sendMessage(jid, {
747
- text: 'updated text goes here',
748
- edit: response.key
749
- })
750
- ```
751
-
752
- ## Manipulating Media Messages
753
-
754
- ### Thumbnail in Media Messages
755
-
756
- - 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`.
757
- - Thumbnails for videos can also be generated automatically, though, you need to have `ffmpeg` installed on your system.
758
-
759
- ### Downloading Media Messages
760
-
761
- If you want to save the media you received
762
-
763
- ```ts
764
- import { createWriteStream } from 'fs'
765
- import { downloadMediaMessage, getContentType } from '@whiskeysockets/baileys'
766
-
767
- sock.ev.on('messages.upsert', async ({ [m] }) => {
768
- if (!m.message) return // if there is no text or media message
769
- const messageType = getContentType(m) // get what type of message it is (text, image, video...)
770
-
771
- // if the message is an image
772
- if (messageType === 'imageMessage') {
773
- // download the message
774
- const stream = await downloadMediaMessage(
775
- m,
776
- 'stream', // can be 'buffer' too
777
- { },
778
- {
779
- logger,
780
- // pass this so that baileys can request a reupload of media
781
- // that has been deleted
782
- reuploadRequest: sock.updateMediaMessage
783
- }
784
- )
785
- // save to file
786
- const writeStream = createWriteStream('./my-download.jpeg')
787
- stream.pipe(writeStream)
788
- }
789
- }
790
- ```
791
-
792
- ### Re-upload Media Message to Whatsapp
793
-
794
- - 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:
795
-
796
- ```ts
797
- await sock.updateMediaMessage(msg)
798
- ```
799
-
800
- ## Reject Call
801
-
802
- - You can obtain `callId` and `callFrom` from `call` event
803
-
804
- ```ts
805
- await sock.rejectCall(callId, callFrom)
806
- ```
807
-
808
- ## Send States in Chat
809
-
810
- ### Reading Messages
811
-
812
- - A set of message [keys](https://baileys.whiskeysockets.io/types/WAMessageKey.html) must be explicitly marked read now.
813
- - You cannot mark an entire 'chat' read as it were with Baileys Web.
814
- This means you have to keep track of unread messages.
815
-
816
- ```ts
817
- const key: WAMessageKey
818
- // can pass multiple keys to read multiple messages as well
819
- await sock.readMessages([key])
820
- ```
821
-
822
- The message ID is the unique identifier of the message that you are marking as read.
823
- On a `WAMessage`, the `messageID` can be accessed using `messageID = message.key.id`.
824
-
825
- ### Update Presence
826
-
827
- - `presence` can be one of [these](https://baileys.whiskeysockets.io/types/WAPresence.html)
828
- - The presence expires after about 10 seconds.
829
- - This lets the person/group with `jid` know whether you're online, offline, typing etc.
830
-
831
- ```ts
832
- await sock.sendPresenceUpdate('available', jid)
833
- ```
834
-
835
- > [!NOTE]
836
- > 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')`
837
-
838
- ## Modifying Chats
839
-
840
- WA uses an encrypted form of communication to send chat/app updates. This has been implemented mostly and you can send the following updates:
841
-
842
- > [!IMPORTANT]
843
- > 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.
844
-
845
- ### Archive a Chat
846
-
847
- ```ts
848
- const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
849
- await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
850
- ```
851
-
852
- ### Mute/Unmute a Chat
853
-
854
- - Supported times:
855
-
856
- | Time | Miliseconds |
857
- | ------ | ----------- |
858
- | Remove | null |
859
- | 8h | 86.400.000 |
860
- | 7d | 604.800.000 |
861
-
862
- ```ts
863
- // mute for 8 hours
864
- await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
865
- // unmute
866
- await sock.chatModify({ mute: null }, jid)
867
- ```
868
-
869
- ### Mark a Chat Read/Unread
870
-
871
- ```ts
872
- const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
873
- // mark it unread
874
- await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
875
- ```
876
-
877
- ### Delete a Message for Me
878
-
879
- ```ts
880
- await sock.chatModify(
881
- {
882
- clear: {
883
- messages: [
884
- {
885
- id: 'ATWYHDNNWU81732J',
886
- fromMe: true,
887
- timestamp: '1654823909'
888
- }
889
- ]
890
- }
891
- },
892
- jid
893
- )
894
- ```
895
-
896
- ### Delete a Chat
897
-
898
- ```ts
899
- const lastMsgInChat = await getLastMessageInChat(jid) // implement this on your end
900
- await sock.chatModify(
901
- {
902
- delete: true,
903
- lastMessages: [
904
- {
905
- key: lastMsgInChat.key,
906
- messageTimestamp: lastMsgInChat.messageTimestamp
907
- }
908
- ]
909
- },
910
- jid
911
- )
912
- ```
913
-
914
- ### Pin/Unpin a Chat
915
-
916
- ```ts
917
- await sock.chatModify(
918
- {
919
- pin: true // or `false` to unpin
920
- },
921
- jid
922
- )
923
- ```
924
-
925
- ### Star/Unstar a Message
926
-
927
- ```ts
928
- await sock.chatModify(
929
- {
930
- star: {
931
- messages: [
932
- {
933
- id: 'messageID',
934
- fromMe: true // or `false`
935
- }
936
- ],
937
- star: true // - true: Star Message; false: Unstar Message
938
- }
939
- },
940
- jid
941
- )
942
- ```
943
-
944
- ### Disappearing Messages
945
-
946
- - Ephemeral can be:
947
-
948
- | Time | Seconds |
949
- | ------ | --------- |
950
- | Remove | 0 |
951
- | 24h | 86.400 |
952
- | 7d | 604.800 |
953
- | 90d | 7.776.000 |
954
-
955
- - You need to pass in **Seconds**, default is 7 days
956
-
957
- ```ts
958
- // turn on disappearing messages
959
- await sock.sendMessage(
960
- jid,
961
- // this is 1 week in seconds -- how long you want messages to appear for
962
- { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL }
963
- )
964
-
965
- // will send as a disappearing message
966
- await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
967
-
968
- // turn off disappearing messages
969
- await sock.sendMessage(jid, { disappearingMessagesInChat: false })
970
- ```
971
-
972
- ## User Querys
973
-
974
- ### Check If ID Exists in Whatsapp
975
-
976
- ```ts
977
- const [result] = await sock.onWhatsApp(jid)
978
- if (result.exists) console.log(`${jid} exists on WhatsApp, as jid: ${result.jid}`)
979
- ```
980
-
981
- ### Query Chat History (groups too)
982
-
983
- - You need to have oldest message in chat
984
-
985
- ```ts
986
- const msg = await getOldestMessageInChat(jid) // implement this on your end
987
- await sock.fetchMessageHistory(
988
- 50, //quantity (max: 50 per query)
989
- msg.key,
990
- msg.messageTimestamp
991
- )
992
- ```
993
-
994
- - Messages will be received in `messaging.history-set` event
995
-
996
- ### Fetch Status
997
-
998
- ```ts
999
- const status = await sock.fetchStatus(jid)
1000
- console.log('status: ' + status)
1001
- ```
1002
-
1003
- ### Fetch Profile Picture (groups too)
1004
-
1005
- - To get the display picture of some person/group
1006
-
1007
- ```ts
1008
- // for low res picture
1009
- const ppUrl = await sock.profilePictureUrl(jid)
1010
- console.log(ppUrl)
1011
-
1012
- // for high res picture
1013
- const ppUrl = await sock.profilePictureUrl(jid, 'image')
1014
- ```
1015
-
1016
- ### Fetch Bussines Profile (such as description or category)
1017
-
1018
- ```ts
1019
- const profile = await sock.getBusinessProfile(jid)
1020
- console.log('business description: ' + profile.description + ', category: ' + profile.category)
1021
- ```
1022
-
1023
- ### Fetch Someone's Presence (if they're typing or online)
1024
-
1025
- ```ts
1026
- // the presence update is fetched and called here
1027
- sock.ev.on('presence.update', console.log)
1028
-
1029
- // request updates for a chat
1030
- await sock.presenceSubscribe(jid)
1031
- ```
1032
-
1033
- ## Change Profile
1034
-
1035
- ### Change Profile Status
1036
-
1037
- ```ts
1038
- await sock.updateProfileStatus('Hello World!')
1039
- ```
1040
-
1041
- ### Change Profile Name
1042
-
1043
- ```ts
1044
- await sock.updateProfileName('My name')
1045
- ```
1046
-
1047
- ### Change Display Picture (groups too)
1048
-
1049
- - To change your display picture or a group's
1050
-
1051
- > [!NOTE]
1052
- > 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)
1053
-
1054
- ```ts
1055
- await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })
1056
- ```
1057
-
1058
- ### Remove display picture (groups too)
1059
-
1060
- ```ts
1061
- await sock.removeProfilePicture(jid)
1062
- ```
1063
-
1064
- ## Groups
1065
-
1066
- - To change group properties you need to be admin
1067
-
1068
- ### Create a Group
1069
-
1070
- ```ts
1071
- // title & participants
1072
- const group = await sock.groupCreate('My Fab Group', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
1073
- console.log('created group with id: ' + group.gid)
1074
- await sock.sendMessage(group.id, { text: 'hello there' }) // say hello to everyone on the group
1075
- ```
1076
-
1077
- ### Add/Remove or Demote/Promote
1078
-
1079
- ```ts
1080
- // id & people to add to the group (will throw error if it fails)
1081
- await sock.groupParticipantsUpdate(
1082
- jid,
1083
- ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1084
- 'add' // replace this parameter with 'remove' or 'demote' or 'promote'
1085
- )
1086
- ```
1087
-
1088
- ### Change Subject (name)
1089
-
1090
- ```ts
1091
- await sock.groupUpdateSubject(jid, 'New Subject!')
1092
- ```
1093
-
1094
- ### Change Description
1095
-
1096
- ```ts
1097
- await sock.groupUpdateDescription(jid, 'New Description!')
1098
- ```
1099
-
1100
- ### Change Settings
1101
-
1102
- ```ts
1103
- // only allow admins to send messages
1104
- await sock.groupSettingUpdate(jid, 'announcement')
1105
- // allow everyone to send messages
1106
- await sock.groupSettingUpdate(jid, 'not_announcement')
1107
- // allow everyone to modify the group's settings -- like display picture etc.
1108
- await sock.groupSettingUpdate(jid, 'unlocked')
1109
- // only allow admins to modify the group's settings
1110
- await sock.groupSettingUpdate(jid, 'locked')
1111
- ```
1112
-
1113
- ### Leave a Group
1114
-
1115
- ```ts
1116
- // will throw error if it fails
1117
- await sock.groupLeave(jid)
1118
- ```
1119
-
1120
- ### Get Invite Code
1121
-
1122
- - To create link with code use `'https://chat.whatsapp.com/' + code`
1123
-
1124
- ```ts
1125
- const code = await sock.groupInviteCode(jid)
1126
- console.log('group code: ' + code)
1127
- ```
1128
-
1129
- ### Revoke Invite Code
1130
-
1131
- ```ts
1132
- const code = await sock.groupRevokeInvite(jid)
1133
- console.log('New group code: ' + code)
1134
- ```
1135
-
1136
- ### Join Using Invitation Code
1137
-
1138
- - Code can't have `https://chat.whatsapp.com/`, only code
1139
-
1140
- ```ts
1141
- const response = await sock.groupAcceptInvite(code)
1142
- console.log('joined to: ' + response)
1143
- ```
1144
-
1145
- ### Get Group Info by Invite Code
1146
-
1147
- ```ts
1148
- const response = await sock.groupGetInviteInfo(code)
1149
- console.log('group information: ' + response)
1150
- ```
1151
-
1152
- ### Query Metadata (participants, name, description...)
1153
-
1154
- ```ts
1155
- const metadata = await sock.groupMetadata(jid)
1156
- console.log(metadata.id + ', title: ' + metadata.subject + ', description: ' + metadata.desc)
1157
- ```
1158
-
1159
- ### Join using `groupInviteMessage`
1160
-
1161
- ```ts
1162
- const response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
1163
- console.log('joined to: ' + response)
1164
- ```
1165
-
1166
- ### Get Request Join List
1167
-
1168
- ```ts
1169
- const response = await sock.groupRequestParticipantsList(jid)
1170
- console.log(response)
1171
- ```
1172
-
1173
- ### Approve/Reject Request Join
1174
-
1175
- ```ts
1176
- const response = await sock.groupRequestParticipantsUpdate(
1177
- jid, // group id
1178
- ['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
1179
- 'approve' // or 'reject'
1180
- )
1181
- console.log(response)
1182
- ```
1183
-
1184
- ### Get All Participating Groups Metadata
1185
-
1186
- ```ts
1187
- const response = await sock.groupFetchAllParticipating()
1188
- console.log(response)
1189
- ```
1190
-
1191
- ### Toggle Ephemeral
1192
-
1193
- - Ephemeral can be:
1194
-
1195
- | Time | Seconds |
1196
- | ------ | --------- |
1197
- | Remove | 0 |
1198
- | 24h | 86.400 |
1199
- | 7d | 604.800 |
1200
- | 90d | 7.776.000 |
1201
-
1202
- ```ts
1203
- await sock.groupToggleEphemeral(jid, 86400)
1204
- ```
1205
-
1206
- ### Change Add Mode
1207
-
1208
- ```ts
1209
- await sock.groupMemberAddMode(
1210
- jid,
1211
- 'all_member_add' // or 'admin_add'
1212
- )
1213
- ```
1214
-
1215
- ## Privacy
1216
-
1217
- ### Block/Unblock User
1218
-
1219
- ```ts
1220
- await sock.updateBlockStatus(jid, 'block') // Block user
1221
- await sock.updateBlockStatus(jid, 'unblock') // Unblock user
1222
- ```
1223
-
1224
- ### Get Privacy Settings
1225
-
1226
- ```ts
1227
- const privacySettings = await sock.fetchPrivacySettings(true)
1228
- console.log('privacy settings: ' + privacySettings)
1229
- ```
1230
-
1231
- ### Get BlockList
1232
-
1233
- ```ts
1234
- const response = await sock.fetchBlocklist()
1235
- console.log(response)
1236
- ```
1237
-
1238
- ### Update LastSeen Privacy
1239
-
1240
- ```ts
1241
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1242
- await sock.updateLastSeenPrivacy(value)
1243
- ```
1244
-
1245
- ### Update Online Privacy
1246
-
1247
- ```ts
1248
- const value = 'all' // 'match_last_seen'
1249
- await sock.updateOnlinePrivacy(value)
1250
- ```
1251
-
1252
- ### Update Profile Picture Privacy
1253
-
1254
- ```ts
1255
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1256
- await sock.updateProfilePicturePrivacy(value)
1257
- ```
1258
-
1259
- ### Update Status Privacy
1260
-
1261
- ```ts
1262
- const value = 'all' // 'contacts' | 'contact_blacklist' | 'none'
1263
- await sock.updateStatusPrivacy(value)
1264
- ```
1265
-
1266
- ### Update Read Receipts Privacy
1267
-
1268
- ```ts
1269
- const value = 'all' // 'none'
1270
- await sock.updateReadReceiptsPrivacy(value)
1271
- ```
1272
-
1273
- ### Update Groups Add Privacy
1274
-
1275
- ```ts
1276
- const value = 'all' // 'contacts' | 'contact_blacklist'
1277
- await sock.updateGroupsAddPrivacy(value)
1278
- ```
15
+ ---
1279
16
 
1280
- ### Update Default Disappearing Mode
17
+ ## What's Different from Upstream
18
+
19
+ | Feature | Upstream Baileys | anya-bail |
20
+ | ------------------------------------- | ---------------- | ----------------------------------------- |
21
+ | Interactive / button messages | ❌ | ✅ Full support |
22
+ | Template messages | ❌ | ✅ |
23
+ | List messages | ❌ | ✅ |
24
+ | Cards / Carousel messages | ❌ | ✅ |
25
+ | Album messages | ❌ | ✅ |
26
+ | Sticker pack messages | ❌ | ✅ |
27
+ | Share / Request phone number | ❌ | ✅ |
28
+ | AI icon on messages | ❌ | ✅ |
29
+ | Rich response / Meta AI messages | ❌ | ✅ |
30
+ | Outgoing call API | ❌ | ✅ |
31
+ | Full MEX notification dispatcher | Partial | ✅ |
32
+ | `messaging-history.status` event | ❌ | ✅ |
33
+ | `message-capping.update` event | ❌ | ✅ |
34
+ | Reachout timelock event | ❌ | ✅ |
35
+ | MongoDB auth state | ❌ | ✅ |
36
+ | Single-file auth state | ❌ | ✅ |
37
+ | iOS / Android / KaiOS browser support | Limited | ✅ Extended |
38
+ | Pairing race-condition fix | ❌ | ✅ |
39
+ | Username in contacts / groups | ❌ | ✅ |
40
+ | `authorUsername` in group events | ❌ | ✅ |
41
+ | `chunkOrder` in history sync | ❌ | ✅ |
42
+ | tctoken prune on reconnect | ❌ | ✅ |
43
+ | App state sync resilience | Partial | ✅ `forceSnapshot` + `blockedCollections` |
44
+ | Message ID prefix | `3EB0` | `4NY4W3B` |
45
+ | Addons layer | ❌ | ✅ 18 addon files |
1281
46
 
1282
- - Like [this](#disappearing-messages), ephemeral can be:
47
+ ---
1283
48
 
1284
- | Time | Seconds |
1285
- | ------ | --------- |
1286
- | Remove | 0 |
1287
- | 24h | 86.400 |
1288
- | 7d | 604.800 |
1289
- | 90d | 7.776.000 |
49
+ ## Installation
1290
50
 
1291
- ```ts
1292
- const ephemeral = 86400
1293
- await sock.updateDefaultDisappearingMode(ephemeral)
51
+ ```bash
52
+ npm install anya-bail
53
+ # or
54
+ yarn add anya-bail
1294
55
  ```
1295
56
 
1296
- ## Broadcast Lists & Stories
1297
-
1298
- ### Send Broadcast & Stories
1299
-
1300
- - Messages can be sent to broadcasts & stories. You need to add the following message options in sendMessage, like this:
57
+ ---
1301
58
 
1302
- ```ts
1303
- await sock.sendMessage(
1304
- jid,
1305
- {
1306
- image: {
1307
- url: url
1308
- },
1309
- caption: caption
1310
- },
1311
- {
1312
- backgroundColor: backgroundColor,
1313
- font: font,
1314
- statusJidList: statusJidList,
1315
- broadcast: true
1316
- }
1317
- )
1318
- ```
59
+ ## Table of Contents
1319
60
 
1320
- - Message body can be a `extendedTextMessage` or `imageMessage` or `videoMessage` or `voiceMessage`, see [here](https://baileys.whiskeysockets.io/types/AnyRegularMessageContent.html)
1321
- - You can add `backgroundColor` and other options in the message options, see [here](https://baileys.whiskeysockets.io/types/MiscMessageGenerationOptions.html)
1322
- - `broadcast: true` enables broadcast mode
1323
- - `statusJidList`: a list of people that you can get which you need to provide, which are the people who will get this status message.
61
+ - [Connecting](#connecting)
62
+ - [Sending Messages](#sending-messages)
63
+ - [Text](#text-message)
64
+ - [Media](#image--video--audio--document)
65
+ - [Buttons](#button-message)
66
+ - [Template](#template-message)
67
+ - [Interactive / List](#interactive--list-message)
68
+ - [Album](#album-message)
69
+ - [Sticker Pack](#sticker-pack-message)
70
+ - [Share Phone Number](#share-phone-number-message)
71
+ - [Request Phone Number](#request-phone-number-message)
72
+ - [AI Icon Feature](#ai-icon-feature)
73
+ - [Rich Response / Meta AI Messages](#rich-response-message)
74
+ - [sendTable](#sendtable)
75
+ - [sendList](#sendlist)
76
+ - [sendCodeBlock](#sendcodeblock)
77
+ - [sendLatex](#sendlatex)
78
+ - [sendLatexImage](#sendlateximage)
79
+ - [sendLatexInlineImage](#sendlatexinlineimage)
80
+ - [sendRichMessage](#sendrichmessage)
81
+ - [captureUnifiedResponse / sendUnifiedResponse](#captureunifiedresponse--sendunifiedresponse)
82
+ - [Calls](#calls)
83
+ - [Auth State](#auth-state)
84
+ - [MEX Notifications](#mex-notifications)
85
+ - [Addons](#addons)
86
+ - [Changelog](#changelog)
1324
87
 
1325
- - You can send messages to broadcast lists the same way you send messages to groups & individual chats.
1326
- - Right now, WA Web does not support creating broadcast lists, but you can still delete them.
1327
- - Broadcast IDs are in the format `12345678@broadcast`
88
+ ---
1328
89
 
1329
- ### Query a Broadcast List's Recipients & Name
90
+ ## Connecting
1330
91
 
1331
92
  ```ts
1332
- const bList = await sock.getBroadcastListInfo('1234@broadcast')
1333
- console.log(`list name: ${bList.name}, recps: ${bList.recipients}`)
1334
- ```
1335
-
1336
- ## Writing Custom Functionality
1337
-
1338
- Baileys is written with custom functionality in mind. Instead of forking the project & re-writing the internals, you can simply write your own extensions.
1339
-
1340
- ### Enabling Debug Level in Baileys Logs
93
+ import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'anya-bail'
94
+ import { Boom } from '@hapi/boom'
1341
95
 
1342
- First, enable the logging of unhandled messages from WhatsApp by setting:
96
+ const { state, saveCreds } = await useMultiFileAuthState('./auth_info')
1343
97
 
1344
- ```ts
1345
98
  const sock = makeWASocket({
1346
- logger: P({ level: 'debug' })
99
+ auth: state,
100
+ printQRInTerminal: true
1347
101
  })
1348
- ```
1349
-
1350
- This will enable you to see all sorts of messages WhatsApp sends in the console.
1351
-
1352
- ### How Whatsapp Communicate With Us
1353
-
1354
- > [!TIP]
1355
- > If you want to learn whatsapp protocol, we recommend to study about Libsignal Protocol and Noise Protocol
1356
-
1357
- - **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:
1358
- ```
1359
- {
1360
- "level": 10,
1361
- "fromMe": false,
1362
- "frame": {
1363
- "tag": "ib",
1364
- "attrs": {
1365
- "from": "@s.whatsapp.net"
1366
- },
1367
- "content": [
1368
- {
1369
- "tag": "edge_routing",
1370
- "attrs": {},
1371
- "content": [
1372
- {
1373
- "tag": "routing_info",
1374
- "attrs": {},
1375
- "content": {
1376
- "type": "Buffer",
1377
- "data": [8,2,8,5]
1378
- }
1379
- }
1380
- ]
1381
- }
1382
- ]
1383
- },
1384
- "msg":"communication"
1385
- }
1386
- ```
1387
-
1388
- The `'frame'` is what the message received is, it has three components:
1389
-
1390
- - `tag` -- what this frame is about (eg. message will have 'message')
1391
- - `attrs` -- a string key-value pair with some metadata (contains ID of the message usually)
1392
- - `content` -- the actual data (eg. a message node will have the actual message content in it)
1393
- - read more about this format [here](/src/WABinary/readme.md)
1394
-
1395
- ### Register a Callback for Websocket Events
1396
-
1397
- > [!TIP]
1398
- > Recommended to see `onMessageReceived` function in `socket.ts` file to understand how websockets events are fired
1399
-
1400
- ```ts
1401
- // for any message with tag 'edge_routing'
1402
- sock.ws.on('CB:edge_routing', (node: BinaryNode) => {})
1403
-
1404
- // for any message with tag 'edge_routing' and id attribute = abcd
1405
- sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => {})
1406
-
1407
- // for any message with tag 'edge_routing', id attribute = abcd & first content node routing_info
1408
- sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => {})
1409
- ```
1410
-
1411
- # iOS & Android Support
1412
-
1413
- By default this patched version uses an iOS browser identity (same as addons). You can switch to Android if needed:
1414
-
1415
- ```ts
1416
- import makeWASocket, { Browsers } from 'baileys'
1417
-
1418
- // iOS (default — no change needed)
1419
- const sock = makeWASocket({})
1420
102
 
1421
- // Explicit iOS
1422
- const sock = makeWASocket({
1423
- browser: Browsers.iOS('Chrome')
1424
- })
103
+ sock.ev.on('creds.update', saveCreds)
1425
104
 
1426
- // Android
1427
- const sock = makeWASocket({
1428
- browser: Browsers.android('Chrome')
105
+ sock.ev.on('connection.update', update => {
106
+ const { connection, lastDisconnect } = update
107
+ if (connection === 'close') {
108
+ const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
109
+ if (shouldReconnect) connectToWhatsApp()
110
+ }
1429
111
  })
1430
112
  ```
1431
113
 
1432
- ---
1433
-
1434
- # Anti-Delete System
1435
-
1436
- Stores incoming messages in memory and recovers them when a sender deletes them.
114
+ **Pairing Code (instead of QR):**
1437
115
 
1438
116
  ```ts
1439
- import { MessageStore, createMessageStoreHandler, createAntiDeleteHandler, isDeleteMessage } from 'baileys'
1440
-
1441
- const store = new MessageStore({
1442
- maxMessagesPerChat: 1000, // max messages per chat (default: 1000)
1443
- ttl: 24 * 60 * 60 * 1000, // keep for 24h (default)
1444
- cleanupInterval: 60 * 60 * 1000 // cleanup every 1h (default)
1445
- })
1446
-
1447
- // Store every incoming message
1448
- sock.ev.on('messages.upsert', createMessageStoreHandler(store))
1449
-
1450
- // Detect and recover deleted messages
1451
- sock.ev.on('messages.update', updates => {
1452
- const deleted = createAntiDeleteHandler(store)(updates)
1453
- for (const info of deleted) {
1454
- console.log('Message was deleted:', info.originalMessage)
1455
- console.log('Deleted by:', info.deletedBy)
1456
- console.log('Deleted at:', new Date(info.deletedAt))
1457
- }
1458
- })
1459
-
1460
- // Manual lookup
1461
- const original = store.getOriginalMessage(key)
1462
-
1463
- // Stats
1464
- console.log(store.getStats())
1465
- // { totalChats: 5, totalMessages: 120, totalDeleted: 3 }
1466
-
1467
- // Stop cleanup timer when done
1468
- store.stopCleanup()
117
+ const code = await sock.requestPairingCode('+91XXXXXXXXXX')
118
+ console.log('Pairing code:', code)
1469
119
  ```
1470
120
 
1471
121
  ---
1472
122
 
1473
- # Auto-Reply System
123
+ ## Sending Messages
1474
124
 
1475
- Rule-based automatic reply system with cooldowns, typing simulation, and JID filtering.
125
+ ### Text Message
1476
126
 
1477
127
  ```ts
1478
- import { createAutoReply } from 'baileys'
1479
-
1480
- const autoReply = createAutoReply(
1481
- (jid, content, options) => sock.sendMessage(jid, content, options),
1482
- (jid, presence) => sock.sendPresenceUpdate(presence as any, jid),
1483
- {
1484
- globalCooldown: 1000, // ms between any reply to same JID
1485
- simulateTyping: true, // show typing indicator before reply
1486
- typingDuration: 1500, // ms to show typing
1487
- multiMatch: false // stop at first matching rule
1488
- }
1489
- )
1490
-
1491
- // Add a keyword rule
1492
- autoReply.addRule({
1493
- keywords: ['hello', 'hi'],
1494
- response: { text: 'Hello! How can I help?' },
1495
- cooldown: 5000, // 5s cooldown per JID
1496
- priority: 10,
1497
- quoted: true // quote the original message
1498
- })
1499
-
1500
- // Add an exact match rule
1501
- autoReply.addRule({
1502
- exactMatch: '!ping',
1503
- response: { text: 'pong 🏓' },
1504
- privateOnly: true // only in private chats
1505
- })
1506
-
1507
- // Add a regex rule
1508
- autoReply.addRule({
1509
- pattern: /order\s*#?(\d+)/i,
1510
- response: async (msg, match) => ({ text: `Looking up order ${match[1]}...` }),
1511
- groupsOnly: true,
1512
- allowedJids: ['1234567890@g.us']
1513
- })
1514
-
1515
- // Process every incoming message
1516
- sock.ev.on('messages.upsert', async ({ messages }) => {
1517
- for (const msg of messages) {
1518
- if (!msg.key.fromMe) await autoReply.processMessage(msg)
1519
- }
1520
- })
1521
-
1522
- // Manage rules
1523
- const rule = autoReply.addRule({ keywords: ['bye'], response: { text: 'Goodbye!' } })
1524
- autoReply.setRuleActive(rule.id, false) // disable
1525
- autoReply.removeRule(rule.id) // remove
1526
- autoReply.clearRules() // remove all
128
+ await sock.sendMessage(jid, { text: 'Hello World!' })
1527
129
  ```
1528
130
 
1529
- ---
1530
-
1531
- # Message Scheduler
1532
-
1533
- Schedule messages to be sent at a future time.
131
+ ### Image / Video / Audio / Document
1534
132
 
1535
133
  ```ts
1536
- import { createMessageScheduler } from 'baileys'
1537
-
1538
- const scheduler = createMessageScheduler((jid, content) => sock.sendMessage(jid, content), {
1539
- maxQueue: 1000,
1540
- checkInterval: 1000, // check every 1s
1541
- onSent: (scheduled, msg) => console.log('Sent:', scheduled.id),
1542
- onFailed: (scheduled, err) => console.error('Failed:', err.message)
1543
- })
1544
-
1545
- // Schedule at a specific time
1546
- const item = scheduler.schedule(
1547
- '1234567890@s.whatsapp.net',
1548
- { text: 'Good morning! ☀️' },
1549
- new Date('2025-06-01T08:00:00')
1550
- )
1551
-
1552
- // Schedule after a delay (ms)
1553
- scheduler.scheduleDelay('1234567890@s.whatsapp.net', { text: 'Reminder after 10 minutes' }, 10 * 60 * 1000)
134
+ // Image
135
+ await sock.sendMessage(jid, { image: { url: './image.jpg' }, caption: 'caption' })
1554
136
 
1555
- // Cancel a scheduled message
1556
- scheduler.cancel(item.id)
137
+ // Video
138
+ await sock.sendMessage(jid, { video: { url: './video.mp4' }, caption: 'caption' })
1557
139
 
1558
- // Cancel all messages to a JID
1559
- scheduler.cancelForJid('1234567890@s.whatsapp.net')
140
+ // Audio (PTT)
141
+ await sock.sendMessage(jid, { audio: { url: './audio.mp3' }, mimetype: 'audio/mp4', ptt: true })
1560
142
 
1561
- // List pending
1562
- const pending = scheduler.getPending()
1563
- console.log(`${pending.length} messages scheduled`)
1564
-
1565
- // Stop the scheduler
1566
- scheduler.stop()
143
+ // Document
144
+ await sock.sendMessage(jid, { document: { url: './file.pdf' }, mimetype: 'application/pdf', fileName: 'file.pdf' })
1567
145
  ```
1568
146
 
1569
- ---
1570
-
1571
- # Interactive Messages
1572
-
1573
- ## Buttons Message
147
+ ### Button Message
1574
148
 
1575
149
  ```ts
1576
150
  await sock.sendMessage(jid, {
1577
- text: 'Choose an option:',
1578
151
  buttons: [
1579
- { buttonId: 'btn1', buttonText: { displayText: 'Option 1' } },
1580
- { buttonId: 'btn2', buttonText: { displayText: 'Option 2' } },
1581
- { buttonId: 'btn3', buttonText: { displayText: 'Option 3' } }
152
+ { buttonId: 'btn1', buttonText: { displayText: 'Option 1' }, type: 1 },
153
+ { buttonId: 'btn2', buttonText: { displayText: 'Option 2' }, type: 1 }
1582
154
  ],
1583
- footer: 'footer text'
155
+ text: 'Pick an option:',
156
+ footer: 'Powered by anya-bail'
1584
157
  })
1585
158
  ```
1586
159
 
1587
- ## Template Buttons Message
160
+ ### Template Message
1588
161
 
1589
162
  ```ts
1590
- import { proto } from 'baileys'
1591
-
1592
163
  await sock.sendMessage(jid, {
1593
- text: 'Template message',
1594
164
  templateButtons: [
1595
- { quickReplyButton: { displayText: 'Quick Reply', id: 'qr1' } },
1596
- { urlButton: { displayText: 'Visit Website', url: 'https://example.com' } },
1597
- { callButton: { displayText: 'Call Us', phoneNumber: '+1234567890' } }
165
+ { index: 1, urlButton: { displayText: 'Visit', url: 'https://example.com' } },
166
+ { index: 2, callButton: { displayText: 'Call', phoneNumber: '+91XXXXXXXXXX' } },
167
+ { index: 3, quickReplyButton: { displayText: 'Reply', id: 'id1' } }
1598
168
  ],
1599
- footer: 'footer text'
169
+ text: 'Template body',
170
+ footer: 'footer'
1600
171
  })
1601
172
  ```
1602
173
 
1603
- ## Interactive Buttons Message
1604
-
1605
- Works on both iOS and Android:
174
+ ### Interactive / List Message
1606
175
 
1607
176
  ```ts
177
+ // Interactive buttons
1608
178
  await sock.sendMessage(jid, {
1609
- text: 'Pick one:',
1610
179
  interactiveButtons: [
1611
180
  { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Yes', id: 'yes' }) },
1612
181
  { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'No', id: 'no' }) }
1613
182
  ],
1614
- footer: 'footer text'
1615
- })
1616
-
1617
- // With image header
1618
- await sock.sendMessage(jid, {
1619
- image: { url: 'https://example.com/image.jpg' },
1620
- caption: 'Check this out',
1621
- interactiveButtons: [
1622
- { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Buy Now', id: 'buy' }) }
1623
- ]
183
+ body: { text: 'Are you sure?' },
184
+ footer: { text: 'anya-bail' }
1624
185
  })
1625
- ```
1626
-
1627
- ## List Message
1628
186
 
1629
- ```ts
187
+ // List message
1630
188
  await sock.sendMessage(jid, {
1631
- text: 'Here are your options',
1632
189
  sections: [
1633
190
  {
1634
191
  title: 'Section 1',
1635
192
  rows: [
1636
- { title: 'Option 1', rowId: 'opt1', description: 'Description 1' },
1637
- { title: 'Option 2', rowId: 'opt2', description: 'Description 2' }
193
+ { title: 'Row 1', rowId: 'r1', description: 'Description 1' },
194
+ { title: 'Row 2', rowId: 'r2', description: 'Description 2' }
1638
195
  ]
1639
- },
1640
- {
1641
- title: 'Section 2',
1642
- rows: [{ title: 'Option 3', rowId: 'opt3' }]
1643
196
  }
1644
197
  ],
1645
- buttonText: 'Tap to choose',
1646
- title: 'Menu',
1647
- footer: 'footer text'
198
+ title: 'List Title',
199
+ text: 'List body',
200
+ footer: 'footer',
201
+ buttonText: 'Open List'
1648
202
  })
1649
203
  ```
1650
204
 
1651
- ## Product List Message
205
+ ### Album Message
1652
206
 
1653
207
  ```ts
1654
208
  await sock.sendMessage(jid, {
1655
- text: 'Our products',
1656
- productList: [
1657
- {
1658
- title: 'Featured',
1659
- products: [{ productId: 'prod_001' }, { productId: 'prod_002' }]
1660
- }
1661
- ],
1662
- title: 'Shop',
1663
- buttonText: 'View',
1664
- footer: 'Tap to browse',
1665
- businessOwnerJid: '1234567890@s.whatsapp.net',
1666
- thumbnail: { url: 'https://example.com/thumb.jpg' }
209
+ album: {
210
+ expectedImageCount: 2,
211
+ expectedVideoCount: 1
212
+ }
1667
213
  })
1668
- ```
1669
-
1670
- ## Shop Message
1671
-
1672
- ```ts
214
+ // Then send each media with albumParentKey
1673
215
  await sock.sendMessage(jid, {
1674
- text: 'Welcome to our store',
1675
- shop: { surface: 1, id: 'store_id' },
1676
- title: 'Our Store',
1677
- footer: 'Browse products'
216
+ image: { url: './photo1.jpg' },
217
+ caption: 'First',
218
+ albumParentKey: albumMsg.key
1678
219
  })
1679
220
  ```
1680
221
 
1681
- ## Collection Message
222
+ ### Sticker Pack Message
1682
223
 
1683
224
  ```ts
1684
225
  await sock.sendMessage(jid, {
1685
- text: 'Check our collection',
1686
- collection: {
1687
- bizJid: '1234567890@s.whatsapp.net',
1688
- id: 'collection_id',
1689
- messageVersion: 1
1690
- },
1691
- title: 'New Collection',
1692
- footer: 'Limited time'
226
+ stickerPack: {
227
+ stickers: [
228
+ {
229
+ fileSha256: Buffer.from('...'),
230
+ fileEncSha256: Buffer.from('...'),
231
+ mediaKey: Buffer.from('...'),
232
+ directPath: '/v/...',
233
+ fileLength: 12345
234
+ }
235
+ ]
236
+ }
1693
237
  })
1694
238
  ```
1695
239
 
1696
- ## Cards / Carousel Message
240
+ ### Share Phone Number Message
1697
241
 
1698
242
  ```ts
1699
- await sock.sendMessage(jid, {
1700
- text: 'Check out our products',
1701
- cards: [
1702
- {
1703
- image: { url: 'https://example.com/product1.jpg' },
1704
- title: 'Product 1',
1705
- body: 'Great product at a great price',
1706
- footer: '$19.99',
1707
- buttons: [{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Buy', id: 'buy_1' }) }]
1708
- },
1709
- {
1710
- video: { url: 'https://example.com/product2.mp4' },
1711
- title: 'Product 2',
1712
- body: 'Watch the demo',
1713
- footer: '$29.99',
1714
- buttons: [{ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Buy', id: 'buy_2' }) }]
1715
- }
1716
- ],
1717
- footer: 'Swipe to see more'
1718
- })
243
+ await sock.sendMessage(jid, { sharePhoneNumber: true })
1719
244
  ```
1720
245
 
1721
- ## Album Message
1722
-
1723
- Sends multiple images/videos as a grouped album:
246
+ ### Request Phone Number Message
1724
247
 
1725
248
  ```ts
1726
- await sock.sendMessage(jid, {
1727
- album: [
1728
- { image: { url: 'https://example.com/img1.jpg' }, caption: 'Photo 1' },
1729
- { image: { url: 'https://example.com/img2.jpg' }, caption: 'Photo 2' },
1730
- { video: { url: 'https://example.com/clip.mp4' }, caption: 'Video clip' }
1731
- ]
1732
- })
249
+ await sock.sendMessage(jid, { requestPhoneNumber: true })
1733
250
  ```
1734
251
 
1735
- ---
1736
-
1737
- # Status Mentions
1738
-
1739
- Send a status and notify specific contacts/groups that they were mentioned:
252
+ ### AI Icon Feature
1740
253
 
1741
254
  ```ts
1742
- // Mention individuals
1743
- await sock.sendStatusMentions({ text: 'Check this out!', backgroundColor: '#25D366' }, [
1744
- '1234567890@s.whatsapp.net',
1745
- '0987654321@s.whatsapp.net'
1746
- ])
1747
-
1748
- // Mention all members of a group
1749
- await sock.sendStatusMentions({ image: { url: 'https://example.com/photo.jpg' }, caption: 'New update!' }, [
1750
- '1234567890@g.us'
1751
- ])
255
+ // Adds Meta AI bot icon to any message
256
+ await sock.sendMessage(jid, { text: 'I am a bot!' }, { ai: true })
1752
257
  ```
1753
258
 
1754
- ---
1755
-
1756
- # Call Functions
259
+ ### Rich Response Message
1757
260
 
1758
- ## Reject Call
261
+ #### sendTable
1759
262
 
1760
263
  ```ts
1761
- sock.ev.on('call', async calls => {
1762
- for (const call of calls) {
1763
- if (call.status === 'offer') {
1764
- await sock.rejectCall(call.id, call.from)
1765
- }
1766
- }
1767
- })
264
+ await sock.sendTable(
265
+ jid,
266
+ 'Results',
267
+ ['Name', 'Score'],
268
+ [
269
+ ['Alice', '98'],
270
+ ['Bob', '87']
271
+ ],
272
+ quotedMsg,
273
+ { headerText: 'Leaderboard:', footer: 'Updated now' }
274
+ )
1768
275
  ```
1769
276
 
1770
- ## Initiate Call
277
+ #### sendList
1771
278
 
1772
279
  ```ts
1773
- // Audio call
1774
- const result = await sock.initiateCall('1234567890@s.whatsapp.net')
1775
- console.log('Call ID:', result.callId)
1776
-
1777
- // Video call
1778
- const result = await sock.initiateCall('1234567890@s.whatsapp.net', { isVideo: true })
280
+ await sock.sendList(jid, 'Todo', ['Buy milk', 'Call mom', 'Push code'], quotedMsg)
1779
281
  ```
1780
282
 
1781
- ## Accept / Terminate Call
283
+ #### sendCodeBlock
1782
284
 
1783
285
  ```ts
1784
- // Accept an incoming call
1785
- await sock.acceptCall(call.id, call.from, call.isVideo)
1786
-
1787
- // Hang up / terminate
1788
- await sock.terminateCall(call.id, call.from)
1789
-
1790
- // Cancel an outgoing call
1791
- await sock.cancelCall(callId, toJid)
1792
-
1793
- // Mute/unmute during a call
1794
- await sock.muteCall(call.id, call.from, toJid, true) // mute
1795
- await sock.muteCall(call.id, call.from, toJid, false) // unmute
286
+ await sock.sendCodeBlock(jid, `const greet = name => \`Hello \${name}\``, quotedMsg, {
287
+ title: 'Example',
288
+ language: 'javascript'
289
+ })
290
+ // Supported: javascript, typescript, python (js, ts, py)
1796
291
  ```
1797
292
 
1798
- ---
1799
-
1800
- # Single File Auth State
1801
-
1802
- Alternative to `useMultiFileAuthState` — stores everything in a single JSON file:
293
+ #### sendLatex
1803
294
 
1804
295
  ```ts
1805
- import { useSingleFileAuthState } from 'baileys'
296
+ await sock.sendLatex(jid, quotedMsg, {
297
+ text: 'Quadratic formula:',
298
+ expressions: [{ latexExpression: 'x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}' }]
299
+ })
300
+ ```
1806
301
 
1807
- const { state, saveCreds } = await useSingleFileAuthState('./auth.json')
302
+ #### sendLatexImage
1808
303
 
1809
- const sock = makeWASocket({ auth: state })
1810
- sock.ev.on('creds.update', saveCreds)
304
+ ```ts
305
+ await sock.sendLatexImage(
306
+ jid,
307
+ quotedMsg,
308
+ { expressions: [{ latexExpression: 'e^{i\\pi}+1=0' }] },
309
+ async latex => renderToPng(latex), // → { buffer, width, height }
310
+ async (buf, type) => uploadToWA(buf, type) // → { url?, directPath? }
311
+ )
1811
312
  ```
1812
313
 
1813
- ---
314
+ #### sendLatexInlineImage
1814
315
 
1815
- # Contact Cards (vCard)
316
+ Same as `sendLatexImage` but each expression renders as its own inline image block.
1816
317
 
1817
- Generate and send vCard contact messages:
318
+ #### sendRichMessage
1818
319
 
1819
320
  ```ts
1820
- import { generateVCard, createContactCard, createContactCards, quickContact } from 'baileys'
1821
-
1822
- // Single contact
1823
- await sock.sendMessage(
1824
- jid,
1825
- createContactCard({
1826
- fullName: 'John Doe',
1827
- phones: [{ number: '+1234567890', type: 'CELL' }],
1828
- emails: [{ email: 'john@example.com', type: 'WORK' }],
1829
- organization: 'Acme Corp'
1830
- })
1831
- )
321
+ import { RichSubMessageType } from 'anya-bail'
1832
322
 
1833
- // Multiple contacts
1834
- await sock.sendMessage(
323
+ await sock.sendRichMessage(
1835
324
  jid,
1836
- createContactCards([
1837
- { fullName: 'Alice', phones: [{ number: '+1111111111' }] },
1838
- { fullName: 'Bob', phones: [{ number: '+2222222222' }] }
1839
- ])
325
+ [
326
+ { messageType: RichSubMessageType.TEXT, messageText: 'Hello from bot!' },
327
+ {
328
+ messageType: RichSubMessageType.TABLE,
329
+ tableMetadata: {
330
+ title: 'Data',
331
+ rows: [{ items: ['Key', 'Value'], isHeading: true }, { items: ['status', 'ok'] }]
332
+ }
333
+ }
334
+ ],
335
+ quotedMsg
1840
336
  )
337
+ ```
1841
338
 
1842
- // Quick shorthand
1843
- await sock.sendMessage(jid, createContactCard(quickContact('Jane Smith', '+9876543210', { organization: 'ACME' })))
339
+ #### captureUnifiedResponse / sendUnifiedResponse
1844
340
 
1845
- // Generate raw vCard string
1846
- const vcard = generateVCard({
1847
- fullName: 'John Doe',
1848
- phones: [{ number: '+1234567890' }]
341
+ ```ts
342
+ sock.ev.on('messages.upsert', async ({ messages }) => {
343
+ for (const msg of messages) {
344
+ const captured = sock.captureUnifiedResponse(msg.message)
345
+ if (captured) {
346
+ await sock.sendUnifiedResponse(otherJid, quotedMsg, captured)
347
+ }
348
+ }
1849
349
  })
1850
- console.log(vcard)
1851
350
  ```
1852
351
 
1853
352
  ---
1854
353
 
1855
- # JID Utilities
354
+ ## Calls
1856
355
 
1857
356
  ```ts
1858
- import { parseJid, plotJid, isSelf, getSenderPn, normalizePhoneToJid } from 'baileys'
1859
-
1860
- // Parse a JID into its components
1861
- const info = parseJid('1234567890@s.whatsapp.net')
1862
- // { user, server, device, isLid, isPn, isGroup, isNewsletter, normalizedUser }
1863
-
1864
- // Check if a JID is the connected account
1865
- const senderInfo = getSenderPn(sock.authState.creds)
1866
- console.log(isSelf('1234567890@s.whatsapp.net', senderInfo)) // true/false
357
+ // Outgoing call
358
+ const { callId } = await sock.initiateCall(jid, { isVideo: false })
359
+ await sock.acceptCall(jid, callId)
360
+ await sock.preacceptCall(jid, callId)
361
+ await sock.muteCall(jid, callId, { isMuted: true })
362
+ await sock.terminateCall(jid, callId)
363
+ await sock.cancelCall(jid, callId)
1867
364
 
1868
- // Convert phone number to JID
1869
- const jid = normalizePhoneToJid('+1234567890')
1870
- // → '1234567890@s.whatsapp.net'
1871
-
1872
- // Plot a JID to its canonical form (resolves LID ↔ PN)
1873
- const plotted = plotJid('1234567890@s.whatsapp.net')
1874
- // { original, primary, info, pn?, lid? }
365
+ // Group call links
366
+ const link = await sock.queryCallLink(callLinkToken)
367
+ await sock.joinCallLink(callLinkToken)
1875
368
  ```
1876
369
 
1877
370
  ---
1878
371
 
1879
- # Message Search
1880
-
1881
- Search through a collection of messages:
372
+ ## Auth State
1882
373
 
1883
374
  ```ts
1884
- import { MessageSearchManager } from 'baileys'
1885
-
1886
- const search = new MessageSearchManager()
1887
-
1888
- // Feed messages into the index
1889
- sock.ev.on('messages.upsert', ({ messages }) => {
1890
- search.addMessages(messages)
1891
- })
1892
-
1893
- // Full-text search
1894
- const results = search.search('hello world', {
1895
- jid: '1234567890@s.whatsapp.net', // optional: limit to one chat
1896
- fromMe: false,
1897
- messageTypes: ['text'],
1898
- limit: 20
1899
- })
1900
-
1901
- // Regex search
1902
- const results = search.searchRegex(/order\s*#\d+/i)
375
+ // Multi-file (default)
376
+ const { state, saveCreds } = await useMultiFileAuthState('./auth_info')
1903
377
 
1904
- // Get all messages in a chat
1905
- const chatMessages = search.getByJid('1234567890@s.whatsapp.net')
378
+ // Single-file
379
+ import { useSingleFileAuthState } from 'anya-bail'
380
+ const { state, saveState } = useSingleFileAuthState('./auth.json')
1906
381
 
1907
- // Get by type
1908
- const images = search.getByType('image')
382
+ // MongoDB
383
+ import { useMongoFileAuthState } from 'anya-bail'
384
+ const { state, saveCreds } = await useMongoFileAuthState(mongoCollection)
1909
385
  ```
1910
386
 
1911
387
  ---
1912
388
 
1913
- # Templates
1914
-
1915
- Create reusable message templates with variable substitution:
389
+ ## MEX Notifications
1916
390
 
1917
391
  ```ts
1918
- import { createTemplateManager, renderTemplate } from 'baileys'
392
+ // Newsletter
393
+ sock.ev.on('newsletter-settings.update', ({ id, update }) => {})
394
+ sock.ev.on('newsletter-participants.update', ({ id, user, new_role }) => {})
1919
395
 
1920
- // Create manager (comes with preset templates)
1921
- const manager = createTemplateManager()
396
+ // Linked profiles (LID PN mapping)
397
+ sock.ev.on('lid-mapping.update', ({ lid, pn }) => {})
1922
398
 
1923
- // Use a preset
1924
- const msg = manager.render('welcome', { name: 'John', companyName: 'Acme' })
1925
- await sock.sendMessage(jid, { text: msg })
399
+ // Message capping quota
400
+ sock.ev.on('message-capping.update', ({ used_quota, total_quota }) => {})
1926
401
 
1927
- // Create a custom template
1928
- const tpl = manager.create({
1929
- name: 'Appointment',
1930
- content: 'Hi {{name}}, your appointment is on {{date}} at {{time:TBD}}.',
1931
- category: 'reminder'
402
+ // WA Business reachout timelock
403
+ sock.ev.on('connection.update', ({ reachoutTimeLock }) => {
404
+ if (reachoutTimeLock?.isActive) {
405
+ console.log('Restricted until:', reachoutTimeLock.timeEnforcementEnds)
406
+ }
1932
407
  })
1933
408
 
1934
- // Render it
1935
- const text = manager.render(tpl.id, { name: 'Alice', date: 'Monday', time: '3 PM' })
1936
- await sock.sendMessage(jid, { text })
1937
-
1938
- // One-off render without manager
1939
- const text2 = renderTemplate('Hello {{name}}!', { name: 'Bob' })
1940
-
1941
- // Available presets: 'welcome', 'order_confirmation', 'reminder', 'support_ticket', 'birthday'
409
+ // History sync completion / stall
410
+ sock.ev.on('messaging-history.status', ({ syncType, status, explicit }) => {
411
+ console.log(`History sync ${status} (${syncType}) explicit=${explicit}`)
412
+ })
1942
413
  ```
1943
414
 
1944
415
  ---
1945
416
 
1946
- # Chat Control
1947
-
1948
- ## Typing Indicator
417
+ ## Addons
1949
418
 
1950
419
  ```ts
1951
- import { createTypingIndicator } from 'baileys'
1952
-
1953
- const typing = createTypingIndicator((jid, presence) => sock.sendPresenceUpdate(presence as any, jid))
1954
-
1955
- await typing.startTyping(jid, { duration: 3000 }) // auto-stop after 3s
1956
- await typing.startRecording(jid) // voice note indicator
1957
- await typing.stopTyping(jid)
1958
- await typing.stopAll()
1959
-
1960
- // Simulate typing then send
1961
- await typing.simulateTyping(jid, 2000, async () => {
1962
- return sock.sendMessage(jid, { text: 'Hello!' })
1963
- })
420
+ import { buildVCard, AutoReplyEngine, createScheduler, ... } from 'anya-bail'
1964
421
  ```
1965
422
 
1966
- ## Read Receipt Control
1967
-
1968
- ```ts
1969
- import { createReadReceiptController } from 'baileys'
1970
-
1971
- const readCtrl = createReadReceiptController(
1972
- (jid, participant, ids) => sock.readMessages([{ remoteJid: jid, id: ids[0]!, participant }]),
1973
- { enabled: true, readDelay: 500, excludeJids: ['1234567890@s.whatsapp.net'] }
1974
- )
1975
-
1976
- readCtrl.disable() // stop auto read receipts
1977
- readCtrl.enable()
1978
- await readCtrl.markRead(jid, participant, [messageId])
1979
- ```
423
+ | Addon | Description |
424
+ | --------------------- | ---------------------------------------------------- |
425
+ | `message-composer` | Rich/bot message builders (table, list, code, latex) |
426
+ | `button-sender` | Interactive / native-flow button helpers |
427
+ | `call-handler` | Inbound call handling |
428
+ | `auto-reply` | Rule-based auto-reply engine |
429
+ | `scheduling` | Message queue + scheduled sending |
430
+ | `anti-delete` | Detect and recover deleted messages |
431
+ | `vcard` | Build vCard contact strings |
432
+ | `message-search` | Search messages by type/text/regex |
433
+ | `status-posting` | Broadcast statuses to multiple JIDs |
434
+ | `jid-plotting` | JID resolution + LID/PN mapping helpers |
435
+ | `templates` | Template message variable helpers |
436
+ | `interactive-message` | Interactive message utilities |
437
+ | `from-messages` | Message processing helpers |
438
+ | `from-messages-recv` | Inbound message helpers |
439
+ | `from-messages-send` | Outbound message helpers |
440
+ | `from-chats` | Chat event helpers |
1980
441
 
1981
442
  ---
1982
443
 
1983
- # License
444
+ ## Changelog
445
+
446
+ ### v8.0.0 — April 2026 (anya-bail)
447
+
448
+ **Based on:** WhiskeySockets/Baileys master (April 2026) + InnovatorsSOFT Baileys additions
449
+
450
+ **Added over upstream:**
451
+
452
+ - Full interactive/button/template/list/cards/carousel message system
453
+ - Album messages with `albumParentKey` support
454
+ - Sticker pack messages
455
+ - Share/Request phone number messages
456
+ - AI icon on any message (`options.ai = true`)
457
+ - Rich response / Meta AI messages — `sendTable`, `sendList`, `sendCodeBlock`, `sendLatex`, `sendLatexImage`, `sendLatexInlineImage`, `sendRichMessage`, `captureUnifiedResponse`, `sendUnifiedResponse`
458
+ - Full outgoing call API (`initiateCall`, `acceptCall`, `preacceptCall`, `muteCall`, `terminateCall`, `cancelCall`, `queryCallLink`, `joinCallLink`)
459
+ - Full MEX notification dispatcher — reachout timelock, message capping, linked profiles, newsletter ops
460
+ - `messaging-history.status` event with pause timeout (120s)
461
+ - `message-capping.update` event
462
+ - `authorUsername` in group participant events
463
+ - `chunkOrder` in history sync
464
+ - MongoDB + single-file auth states
465
+ - Extended browser map: iOS, Android, androidCompanion, Linux, KaiOS, ChromeOS
466
+ - `getPlatformDisplayName()` utility
467
+ - Pairing race-condition fix (`sendPairingIQ` + queue)
468
+ - `buildPairingQRData` from companion-reg-client-utils
469
+ - tctoken issuance + prune system (daily cleanup on reconnect)
470
+ - App state sync resilience: `forceSnapshotCollections`, `blockedCollections`
471
+ - `ensureLTHashStateVersion`, `isMissingKeyError`, `isAppStateSyncIrrecoverable`, `MAX_SYNC_ATTEMPTS`
472
+ - `storeTcTokensFromHistorySync` — saves tctokens from history sync chats
473
+ - `SERVER_ERROR_CODES` (463 MissingTcToken, 479 SmaxInvalid)
474
+ - Username fields in Contact, GroupMetadata, GroupParticipant, WAMessageKey
475
+ - `isJidBot`, `isJidMetaAI`, `PSA_WID` exports
476
+ - `onBeforeSessionRefresh` in identity change handler
477
+ - `QueryIdd`, `MexOperations`, `XWAPathsMexUpdates` in Newsletter types
478
+ - 18-file addons layer
479
+ - Message ID prefix: `4NY4W3B`
480
+ - WA version: `2.3000.1037656372`
1984
481
 
1985
- Copyright (c) 2025 Rajeh Taher/WhiskeySockets
1986
-
1987
- Licensed under the MIT License:
1988
- Permission is hereby granted, free of charge, to any person obtaining a copy
1989
- of this software and associated documentation files (the "Software"), to deal
1990
- in the Software without restriction, including without limitation the rights
1991
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1992
- copies of the Software, and to permit persons to whom the Software is
1993
- furnished to do so, subject to the following conditions:
1994
-
1995
- The above copyright notice and this permission notice shall be included in all
1996
- copies or substantial portions of the Software.
1997
-
1998
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1999
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2000
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2001
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2002
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2004
- SOFTWARE.
482
+ ---
2005
483
 
2006
- Thus, the maintainers of the project can't be held liable for any potential misuse of this project.
484
+ > Based on [WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys) and [InnovatorsSOFT/Baileys](https://github.com/InnovatorsSOFT/Baileys). Not affiliated with WhatsApp or Meta.