@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.
- package/README.md +309 -1831
- package/WAProto/fix-imports.js +22 -18
- package/WAProto/index.js +22 -18
- package/lib/Defaults/index.d.ts +2 -0
- package/lib/Defaults/index.d.ts.map +1 -1
- package/lib/Defaults/index.js +3 -1
- package/lib/Defaults/index.js.map +1 -1
- package/lib/Socket/business.d.ts +80 -3
- package/lib/Socket/business.d.ts.map +1 -1
- package/lib/Socket/chats.d.ts +9 -0
- package/lib/Socket/chats.d.ts.map +1 -1
- package/lib/Socket/chats.js +216 -58
- package/lib/Socket/chats.js.map +1 -1
- package/lib/Socket/communities.d.ts +80 -3
- package/lib/Socket/communities.d.ts.map +1 -1
- package/lib/Socket/groups.d.ts +6 -0
- package/lib/Socket/groups.d.ts.map +1 -1
- package/lib/Socket/groups.js +6 -0
- package/lib/Socket/groups.js.map +1 -1
- package/lib/Socket/index.d.ts +80 -3
- package/lib/Socket/index.d.ts.map +1 -1
- package/lib/Socket/messages-recv.d.ts +80 -3
- package/lib/Socket/messages-recv.d.ts.map +1 -1
- package/lib/Socket/messages-recv.js +315 -60
- package/lib/Socket/messages-recv.js.map +1 -1
- package/lib/Socket/messages-send.d.ts +109 -3
- package/lib/Socket/messages-send.d.ts.map +1 -1
- package/lib/Socket/messages-send.js +170 -4
- package/lib/Socket/messages-send.js.map +1 -1
- package/lib/Socket/newsletter.d.ts +6 -0
- package/lib/Socket/newsletter.d.ts.map +1 -1
- package/lib/Socket/newsletter.js +2 -2
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/socket.d.ts.map +1 -1
- package/lib/Socket/socket.js +3 -3
- package/lib/Socket/socket.js.map +1 -1
- package/lib/Types/Auth.d.ts +1 -0
- package/lib/Types/Auth.d.ts.map +1 -1
- package/lib/Types/Call.d.ts +1 -1
- package/lib/Types/Call.d.ts.map +1 -1
- package/lib/Types/Contact.d.ts +2 -0
- package/lib/Types/Contact.d.ts.map +1 -1
- package/lib/Types/Events.d.ts +18 -1
- package/lib/Types/Events.d.ts.map +1 -1
- package/lib/Types/GroupMetadata.d.ts +4 -0
- package/lib/Types/GroupMetadata.d.ts.map +1 -1
- package/lib/Types/Message.d.ts +360 -9
- package/lib/Types/Message.d.ts.map +1 -1
- package/lib/Types/Message.js.map +1 -1
- package/lib/Types/Newsletter.d.ts +37 -42
- package/lib/Types/Newsletter.d.ts.map +1 -1
- package/lib/Types/Newsletter.js +18 -23
- package/lib/Types/Newsletter.js.map +1 -1
- package/lib/Types/State.d.ts +54 -0
- package/lib/Types/State.d.ts.map +1 -1
- package/lib/Types/State.js +42 -0
- package/lib/Types/State.js.map +1 -1
- package/lib/Utils/chat-utils.d.ts +30 -0
- package/lib/Utils/chat-utils.d.ts.map +1 -1
- package/lib/Utils/chat-utils.js +34 -8
- package/lib/Utils/chat-utils.js.map +1 -1
- package/lib/Utils/decode-wa-message.d.ts +12 -0
- package/lib/Utils/decode-wa-message.d.ts.map +1 -1
- package/lib/Utils/decode-wa-message.js +16 -0
- package/lib/Utils/decode-wa-message.js.map +1 -1
- package/lib/Utils/event-buffer.js +2 -0
- package/lib/Utils/event-buffer.js.map +1 -1
- package/lib/Utils/generics.d.ts.map +1 -1
- package/lib/Utils/generics.js +9 -0
- package/lib/Utils/generics.js.map +1 -1
- package/lib/Utils/history.d.ts.map +1 -1
- package/lib/Utils/history.js +12 -10
- package/lib/Utils/history.js.map +1 -1
- package/lib/Utils/identity-change-handler.d.ts +7 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -1
- package/lib/Utils/identity-change-handler.js +1 -0
- package/lib/Utils/identity-change-handler.js.map +1 -1
- package/lib/Utils/index.d.ts +3 -0
- package/lib/Utils/index.d.ts.map +1 -1
- package/lib/Utils/index.js +3 -0
- package/lib/Utils/index.js.map +1 -1
- package/lib/Utils/interactive-message.js.map +1 -1
- package/lib/Utils/message-composer.d.ts +5 -0
- package/lib/Utils/message-composer.d.ts.map +1 -0
- package/lib/Utils/message-composer.js +5 -0
- package/lib/Utils/message-composer.js.map +1 -0
- package/lib/Utils/message-retry-manager.js.map +1 -1
- package/lib/Utils/messages-media.d.ts +1 -1
- package/lib/Utils/messages-media.d.ts.map +1 -1
- package/lib/Utils/messages-media.js +2 -2
- package/lib/Utils/messages-media.js.map +1 -1
- package/lib/Utils/messages.d.ts.map +1 -1
- package/lib/Utils/messages.js +14 -5
- package/lib/Utils/messages.js.map +1 -1
- package/lib/Utils/noise-handler.js.map +1 -1
- package/lib/Utils/process-message.d.ts.map +1 -1
- package/lib/Utils/process-message.js +58 -2
- package/lib/Utils/process-message.js.map +1 -1
- package/lib/Utils/sync-action-utils.d.ts.map +1 -1
- package/lib/Utils/sync-action-utils.js +1 -0
- package/lib/Utils/sync-action-utils.js.map +1 -1
- package/lib/Utils/tc-token-utils.d.ts +26 -1
- package/lib/Utils/tc-token-utils.d.ts.map +1 -1
- package/lib/Utils/tc-token-utils.js +149 -4
- package/lib/Utils/tc-token-utils.js.map +1 -1
- package/lib/WABinary/jid-utils.js.map +1 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +26 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/index.d.ts +1 -0
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -1
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/Protocols/index.js.map +1 -1
- package/lib/WAUSync/USyncQuery.d.ts +1 -0
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -1
- package/lib/WAUSync/USyncQuery.js +5 -1
- package/lib/WAUSync/USyncQuery.js.map +1 -1
- package/lib/WAUSync/USyncUser.d.ts +4 -0
- package/lib/WAUSync/USyncUser.d.ts.map +1 -1
- package/lib/WAUSync/USyncUser.js +8 -0
- package/lib/WAUSync/USyncUser.js.map +1 -1
- package/lib/addons/auto-reply.js.map +1 -1
- package/lib/addons/browser-presets.d.ts +16 -0
- package/lib/addons/browser-presets.d.ts.map +1 -0
- package/lib/addons/browser-presets.js +24 -0
- package/lib/addons/browser-presets.js.map +1 -0
- package/lib/addons/button-sender.d.ts +0 -2
- package/lib/addons/button-sender.d.ts.map +1 -1
- package/lib/addons/button-sender.js +21 -23
- package/lib/addons/button-sender.js.map +1 -1
- package/lib/addons/call-handler.d.ts.map +1 -1
- package/lib/addons/call-handler.js.map +1 -1
- package/lib/addons/from-messages-recv.d.ts.map +1 -1
- package/lib/addons/from-messages-recv.js.map +1 -1
- package/lib/addons/from-messages.js.map +1 -1
- package/lib/addons/index.d.ts +22 -5
- package/lib/addons/index.d.ts.map +1 -1
- package/lib/addons/index.js +29 -17
- package/lib/addons/index.js.map +1 -1
- package/lib/addons/interactive-message.js.map +1 -1
- package/lib/addons/jid-plot.d.ts +49 -0
- package/lib/addons/jid-plot.d.ts.map +1 -0
- package/lib/addons/jid-plot.js +84 -0
- package/lib/addons/jid-plot.js.map +1 -0
- package/lib/addons/lid-support.d.ts +41 -0
- package/lib/addons/lid-support.d.ts.map +1 -0
- package/lib/addons/lid-support.js +42 -0
- package/lib/addons/lid-support.js.map +1 -0
- package/lib/addons/message-composer.d.ts +142 -0
- package/lib/addons/message-composer.d.ts.map +1 -0
- package/lib/addons/message-composer.js +377 -0
- package/lib/addons/message-composer.js.map +1 -0
- package/lib/addons/message-scheduler.d.ts +77 -0
- package/lib/addons/message-scheduler.d.ts.map +1 -0
- package/lib/addons/message-scheduler.js +108 -0
- package/lib/addons/message-scheduler.js.map +1 -0
- package/lib/addons/message-utils.d.ts.map +1 -1
- package/lib/addons/message-utils.js.map +1 -1
- package/lib/addons/outgoing-calls.d.ts +64 -0
- package/lib/addons/outgoing-calls.d.ts.map +1 -0
- package/lib/addons/outgoing-calls.js +139 -0
- package/lib/addons/outgoing-calls.js.map +1 -0
- package/lib/addons/pairing-fix.d.ts +31 -0
- package/lib/addons/pairing-fix.d.ts.map +1 -0
- package/lib/addons/pairing-fix.js +74 -0
- package/lib/addons/pairing-fix.js.map +1 -0
- package/lib/addons/past-participants.d.ts +42 -0
- package/lib/addons/past-participants.d.ts.map +1 -0
- package/lib/addons/past-participants.js +41 -0
- package/lib/addons/past-participants.js.map +1 -0
- package/lib/addons/rich-response.d.ts +111 -0
- package/lib/addons/rich-response.d.ts.map +1 -0
- package/lib/addons/rich-response.js +152 -0
- package/lib/addons/rich-response.js.map +1 -0
- package/lib/addons/status-posting.d.ts.map +1 -1
- package/lib/addons/status-posting.js +1 -3
- package/lib/addons/status-posting.js.map +1 -1
- package/lib/addons/stickerpack.d.ts +37 -0
- package/lib/addons/stickerpack.d.ts.map +1 -0
- package/lib/addons/stickerpack.js +39 -0
- package/lib/addons/stickerpack.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,2006 +1,484 @@
|
|
|
1
|
-
<h1 align='center'
|
|
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'>
|
|
5
|
+
<div align='center'>
|
|
4
6
|
|
|
5
|
-
|
|
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
|
-
|
|
9
|
+
Maintained for [@queenanya/baileys](https://github.com/QueenAnya/ANYA-MD) | Last updated: **April 2026**
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
[](#) [](#)
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
</div>
|
|
17
14
|
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
+
---
|
|
1283
48
|
|
|
1284
|
-
|
|
1285
|
-
| ------ | --------- |
|
|
1286
|
-
| Remove | 0 |
|
|
1287
|
-
| 24h | 86.400 |
|
|
1288
|
-
| 7d | 604.800 |
|
|
1289
|
-
| 90d | 7.776.000 |
|
|
49
|
+
## Installation
|
|
1290
50
|
|
|
1291
|
-
```
|
|
1292
|
-
|
|
1293
|
-
|
|
51
|
+
```bash
|
|
52
|
+
npm install anya-bail
|
|
53
|
+
# or
|
|
54
|
+
yarn add anya-bail
|
|
1294
55
|
```
|
|
1295
56
|
|
|
1296
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
1321
|
-
-
|
|
1322
|
-
-
|
|
1323
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
90
|
+
## Connecting
|
|
1330
91
|
|
|
1331
92
|
```ts
|
|
1332
|
-
|
|
1333
|
-
|
|
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
|
-
|
|
96
|
+
const { state, saveCreds } = await useMultiFileAuthState('./auth_info')
|
|
1343
97
|
|
|
1344
|
-
```ts
|
|
1345
98
|
const sock = makeWASocket({
|
|
1346
|
-
|
|
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
|
-
|
|
1422
|
-
const sock = makeWASocket({
|
|
1423
|
-
browser: Browsers.iOS('Chrome')
|
|
1424
|
-
})
|
|
103
|
+
sock.ev.on('creds.update', saveCreds)
|
|
1425
104
|
|
|
1426
|
-
|
|
1427
|
-
const
|
|
1428
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
+
## Sending Messages
|
|
1474
124
|
|
|
1475
|
-
|
|
125
|
+
### Text Message
|
|
1476
126
|
|
|
1477
127
|
```ts
|
|
1478
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
1556
|
-
|
|
137
|
+
// Video
|
|
138
|
+
await sock.sendMessage(jid, { video: { url: './video.mp4' }, caption: 'caption' })
|
|
1557
139
|
|
|
1558
|
-
//
|
|
1559
|
-
|
|
140
|
+
// Audio (PTT)
|
|
141
|
+
await sock.sendMessage(jid, { audio: { url: './audio.mp3' }, mimetype: 'audio/mp4', ptt: true })
|
|
1560
142
|
|
|
1561
|
-
//
|
|
1562
|
-
|
|
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
|
-
|
|
155
|
+
text: 'Pick an option:',
|
|
156
|
+
footer: 'Powered by anya-bail'
|
|
1584
157
|
})
|
|
1585
158
|
```
|
|
1586
159
|
|
|
1587
|
-
|
|
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
|
-
{
|
|
1596
|
-
{
|
|
1597
|
-
{
|
|
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
|
-
|
|
169
|
+
text: 'Template body',
|
|
170
|
+
footer: 'footer'
|
|
1600
171
|
})
|
|
1601
172
|
```
|
|
1602
173
|
|
|
1603
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: '
|
|
1637
|
-
{ title: '
|
|
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
|
-
|
|
1646
|
-
|
|
1647
|
-
footer: 'footer
|
|
198
|
+
title: 'List Title',
|
|
199
|
+
text: 'List body',
|
|
200
|
+
footer: 'footer',
|
|
201
|
+
buttonText: 'Open List'
|
|
1648
202
|
})
|
|
1649
203
|
```
|
|
1650
204
|
|
|
1651
|
-
|
|
205
|
+
### Album Message
|
|
1652
206
|
|
|
1653
207
|
```ts
|
|
1654
208
|
await sock.sendMessage(jid, {
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
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
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
footer: 'Browse products'
|
|
216
|
+
image: { url: './photo1.jpg' },
|
|
217
|
+
caption: 'First',
|
|
218
|
+
albumParentKey: albumMsg.key
|
|
1678
219
|
})
|
|
1679
220
|
```
|
|
1680
221
|
|
|
1681
|
-
|
|
222
|
+
### Sticker Pack Message
|
|
1682
223
|
|
|
1683
224
|
```ts
|
|
1684
225
|
await sock.sendMessage(jid, {
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
1743
|
-
await sock.
|
|
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
|
-
|
|
261
|
+
#### sendTable
|
|
1759
262
|
|
|
1760
263
|
```ts
|
|
1761
|
-
sock.
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
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
|
-
|
|
277
|
+
#### sendList
|
|
1771
278
|
|
|
1772
279
|
```ts
|
|
1773
|
-
|
|
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
|
-
|
|
283
|
+
#### sendCodeBlock
|
|
1782
284
|
|
|
1783
285
|
```ts
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
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
|
-
|
|
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
|
-
|
|
302
|
+
#### sendLatexImage
|
|
1808
303
|
|
|
1809
|
-
|
|
1810
|
-
sock.
|
|
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
|
-
|
|
316
|
+
Same as `sendLatexImage` but each expression renders as its own inline image block.
|
|
1816
317
|
|
|
1817
|
-
|
|
318
|
+
#### sendRichMessage
|
|
1818
319
|
|
|
1819
320
|
```ts
|
|
1820
|
-
import {
|
|
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
|
-
|
|
1834
|
-
await sock.sendMessage(
|
|
323
|
+
await sock.sendRichMessage(
|
|
1835
324
|
jid,
|
|
1836
|
-
|
|
1837
|
-
{
|
|
1838
|
-
{
|
|
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
|
-
|
|
1843
|
-
await sock.sendMessage(jid, createContactCard(quickContact('Jane Smith', '+9876543210', { organization: 'ACME' })))
|
|
339
|
+
#### captureUnifiedResponse / sendUnifiedResponse
|
|
1844
340
|
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
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
|
-
|
|
354
|
+
## Calls
|
|
1856
355
|
|
|
1857
356
|
```ts
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
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
|
-
//
|
|
1869
|
-
const
|
|
1870
|
-
|
|
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
|
-
|
|
1880
|
-
|
|
1881
|
-
Search through a collection of messages:
|
|
372
|
+
## Auth State
|
|
1882
373
|
|
|
1883
374
|
```ts
|
|
1884
|
-
|
|
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
|
-
//
|
|
1905
|
-
|
|
378
|
+
// Single-file
|
|
379
|
+
import { useSingleFileAuthState } from 'anya-bail'
|
|
380
|
+
const { state, saveState } = useSingleFileAuthState('./auth.json')
|
|
1906
381
|
|
|
1907
|
-
//
|
|
1908
|
-
|
|
382
|
+
// MongoDB
|
|
383
|
+
import { useMongoFileAuthState } from 'anya-bail'
|
|
384
|
+
const { state, saveCreds } = await useMongoFileAuthState(mongoCollection)
|
|
1909
385
|
```
|
|
1910
386
|
|
|
1911
387
|
---
|
|
1912
388
|
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
Create reusable message templates with variable substitution:
|
|
389
|
+
## MEX Notifications
|
|
1916
390
|
|
|
1917
391
|
```ts
|
|
1918
|
-
|
|
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
|
-
//
|
|
1921
|
-
|
|
396
|
+
// Linked profiles (LID ↔ PN mapping)
|
|
397
|
+
sock.ev.on('lid-mapping.update', ({ lid, pn }) => {})
|
|
1922
398
|
|
|
1923
|
-
//
|
|
1924
|
-
|
|
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
|
-
//
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
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
|
-
//
|
|
1935
|
-
|
|
1936
|
-
|
|
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
|
-
|
|
1947
|
-
|
|
1948
|
-
## Typing Indicator
|
|
417
|
+
## Addons
|
|
1949
418
|
|
|
1950
419
|
```ts
|
|
1951
|
-
import {
|
|
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
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
484
|
+
> Based on [WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys) and [InnovatorsSOFT/Baileys](https://github.com/InnovatorsSOFT/Baileys). Not affiliated with WhatsApp or Meta.
|