@blckrose/baileys 2.0.3 → 2.0.4
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 +457 -539
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,647 +1,565 @@
|
|
|
1
|
-
<
|
|
2
|
-
<img src="https://files.catbox.moe/f8tj1b.png" alt="Rimuru Bot" width="150"/>
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<h1 align="center">💧 Rimuru Baileys</h1>
|
|
6
|
-
<p align="center">
|
|
7
|
-
<strong>TypeScript-based WhatsApp Multi-Device Library</strong><br/>
|
|
8
|
-
With intelligent @lid/@jid mapping and advanced message handling
|
|
9
|
-
</p>
|
|
10
|
-
|
|
11
|
-
<p align="center">
|
|
12
|
-
<a href="https://github.com/ryuhandev/rimuru-baileys/stargazers"><img src="https://img.shields.io/github/stars/ryuhandev/rimuru-baileys?style=flat-square&logo=github" alt="GitHub Stars"/></a>
|
|
13
|
-
<a href="https://github.com/ryuhandev/rimuru-baileys/issues"><img src="https://img.shields.io/github/issues/ryuhandev/rimuru-baileys?style=flat-square&logo=github" alt="GitHub Issues"/></a>
|
|
14
|
-
<a href="https://www.npmjs.com/package/@ryuhan/baileys"><img src="https://img.shields.io/npm/v/@ryuhan/baileys?style=flat-square&logo=npm" alt="npm Version"/></a>
|
|
15
|
-
<a href="https://www.npmjs.com/package/@ryuhan/baileys"><img src="https://img.shields.io/npm/dt/@ryuhan/baileys?style=flat-square&logo=npm" alt="npm Downloads"/></a>
|
|
16
|
-
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square" alt="License"/>
|
|
17
|
-
</p>
|
|
1
|
+
<h1 align='center'><img alt="Baileys logo" src="https://raw.githubusercontent.com/WhiskeySockets/Baileys/refs/heads/master/Media/logo.png" height="75"/></h1>
|
|
18
2
|
|
|
19
|
-
|
|
3
|
+
<div align='center'>Baileys is a WebSockets-based TypeScript library for interacting with WhatsApp Web.</div>
|
|
20
4
|
|
|
21
|
-
## 🌟 Features
|
|
22
|
-
|
|
23
|
-
### Core Features
|
|
24
|
-
- **💧 Intelligent `@lid` and `@jid` Mapping** - Automatic resolution of LID to phone JID
|
|
25
|
-
- **💧 Multi-Device Support** - Full support for WhatsApp multi-device protocol
|
|
26
|
-
- **💧 End-to-End Encryption** - Complete E2EE support for secure messaging
|
|
27
|
-
- **💧 All Message Types** - Support for text, media, polls, reactions, and more
|
|
28
|
-
- **💧 TypeScript Based** - Type-safe with modern TypeScript
|
|
29
|
-
- **💧 High Performance** - Optimized for speed and efficiency
|
|
30
|
-
|
|
31
|
-
### Advanced Features
|
|
32
|
-
- **💧 Media Handling** - Send/receive images, videos, audio, stickers, documents
|
|
33
|
-
- **💧 Pairing Code Login** - Easy authentication with custom pairing code "MURUSAMA"
|
|
34
|
-
- **💧 Newsletter/Channel Support** - Full support for WhatsApp channels
|
|
35
|
-
- **💧 Group Management** - Complete group controls and administration
|
|
36
|
-
- **💧 Story/Broadcast** - Send and manage stories and broadcast lists
|
|
37
|
-
- **💧 Business API** - Support for WhatsApp Business features
|
|
38
|
-
- **💧 Poll Messages** - Create and manage poll messages with vote tracking
|
|
39
|
-
- **💧 Reaction Messages** - Send and receive emoji reactions
|
|
40
|
-
- **💧 Pin Messages** - Pin important messages in chats
|
|
41
|
-
- **💧 Disappearing Messages** - Configure ephemeral messages
|
|
42
|
-
- **💧 Contact Messages** - Send vCard contacts
|
|
43
|
-
- **💧 Location Messages** - Share live and static locations
|
|
44
|
-
- **💧 Button Messages** - Interactive button messages (where supported)
|
|
45
|
-
- **💧 List Messages** - Interactive list messages
|
|
46
|
-
- **💧 Template Messages** - Pre-defined message templates
|
|
47
|
-
|
|
48
|
-
### Developer Friendly
|
|
49
|
-
- **💧 Clean API** - Simple and intuitive API design
|
|
50
|
-
- **💧 Event-Driven** - Comprehensive event system for all actions
|
|
51
|
-
- **💧 Auth Storage** - Multi-file and single-file auth state options
|
|
52
|
-
- **💧 In-Memory Store** - Built-in store for chats, contacts, messages
|
|
53
|
-
- **💧 Customizable** - Easy to extend and customize
|
|
54
|
-
- **💧 Well Documented** - Comprehensive documentation and examples
|
|
55
5
|
|
|
56
|
-
|
|
6
|
+
> [!CAUTION]
|
|
7
|
+
> NOTICE OF BREAKING CHANGE.
|
|
8
|
+
>
|
|
9
|
+
> As of 1.0.0, multiple breaking changes were introduced into the library.
|
|
10
|
+
>
|
|
11
|
+
> Please check out https://whiskey.so/migrate-latest for more information.
|
|
57
12
|
|
|
58
|
-
|
|
13
|
+
# Important Note
|
|
14
|
+
This is a temporary README.md, the new guide is in development and will this file will be replaced with .github/README.md (already a default on GitHub).
|
|
59
15
|
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npm install @ryuhan/baileys
|
|
63
|
-
```
|
|
16
|
+
New guide link: https://baileys.wiki
|
|
64
17
|
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
yarn add @ryuhan/baileys
|
|
68
|
-
```
|
|
18
|
+
# Get Support
|
|
69
19
|
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
pnpm add @ryuhan/baileys
|
|
73
|
-
```
|
|
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.
|
|
74
21
|
|
|
75
|
-
|
|
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.
|
|
76
23
|
|
|
77
|
-
|
|
24
|
+
# Sponsor
|
|
25
|
+
If you'd like to financially support this project, you can do so by supporting the current maintainer [here](https://purpshell.dev/sponsor).
|
|
78
26
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
import { Boom } from '@hapi/boom'
|
|
27
|
+
# Disclaimer
|
|
28
|
+
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.
|
|
29
|
+
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.
|
|
83
30
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const sock = makeWASocket({
|
|
88
|
-
auth: state,
|
|
89
|
-
printQRInTerminal: true
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
sock.ev.on('connection.update', (update) => {
|
|
93
|
-
const { connection, lastDisconnect } = update
|
|
94
|
-
if (connection === 'close') {
|
|
95
|
-
const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
|
|
96
|
-
if (shouldReconnect) {
|
|
97
|
-
connectToWhatsApp()
|
|
98
|
-
}
|
|
99
|
-
} else if (connection === 'open') {
|
|
100
|
-
console.log('✅ Connected to WhatsApp!')
|
|
101
|
-
}
|
|
102
|
-
})
|
|
31
|
+
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.
|
|
32
|
+
Use at your own discretion. Do not spam people with this. We discourage any stalkerware, bulk or automated messaging usage.
|
|
103
33
|
|
|
104
|
-
|
|
105
|
-
for (const m of messages) {
|
|
106
|
-
if (!m.message) continue
|
|
107
|
-
console.log('📱 New message:', m.key.remoteJid)
|
|
108
|
-
|
|
109
|
-
// Reply to message
|
|
110
|
-
await sock.sendMessage(m.key.remoteJid!, {
|
|
111
|
-
text: 'Hello! I am Rimuru Bot 💧'
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
})
|
|
34
|
+
##
|
|
115
35
|
|
|
116
|
-
|
|
117
|
-
|
|
36
|
+
- Baileys does not require Selenium or any other browser to be interface with WhatsApp Web, it does so directly using a **WebSocket**.
|
|
37
|
+
- Not running Selenium or Chromium saves you like **half a gig** of ram :/
|
|
38
|
+
- Baileys supports interacting with the multi-device & web versions of WhatsApp.
|
|
39
|
+
- 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.
|
|
118
40
|
|
|
119
|
-
|
|
120
|
-
|
|
41
|
+
> [!IMPORTANT]
|
|
42
|
+
> The original repository had to be removed by the original author - we now continue development in this repository here.
|
|
43
|
+
This is the only official repository and is maintained by the community.
|
|
44
|
+
> **Join the Discord [here](https://discord.gg/WeJM5FP9GG)**
|
|
121
45
|
|
|
122
|
-
|
|
46
|
+
## Example
|
|
123
47
|
|
|
124
|
-
|
|
48
|
+
Do check out & run [example.ts](Example/example.ts) to see an example usage of the library.
|
|
49
|
+
The script covers most common use cases.
|
|
50
|
+
To run the example script, download or clone the repo and then type the following in a terminal:
|
|
51
|
+
1. ``` cd path/to/Baileys ```
|
|
52
|
+
2. ``` yarn ```
|
|
53
|
+
3. ``` yarn example ```
|
|
125
54
|
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
import makeWASocket from '@ryuhan/baileys'
|
|
55
|
+
## Install
|
|
129
56
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
57
|
+
Install dari file `.tgz` lokal (versi modified blckrose):
|
|
58
|
+
```
|
|
59
|
+
npm install ./blckrose-baileys-1.2.9.tgz
|
|
60
|
+
```
|
|
133
61
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
62
|
+
Atau tambahkan ke `package.json`:
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@blckrose/baileys": "file:./blckrose-baileys-1.2.9.tgz"
|
|
67
|
+
}
|
|
139
68
|
}
|
|
140
69
|
```
|
|
141
70
|
|
|
142
|
-
|
|
143
|
-
```
|
|
144
|
-
|
|
71
|
+
Kemudian jalankan:
|
|
72
|
+
```
|
|
73
|
+
npm install
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**ESM:**
|
|
77
|
+
```ts
|
|
78
|
+
import makeWASocket from '@blckrose/baileys'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**CJS (destructure langsung, tanpa top-level await):**
|
|
82
|
+
```js
|
|
83
|
+
const { makeWASocket, useMultiFileAuthState, Browsers, DisconnectReason } = require('@blckrose/baileys')
|
|
84
|
+
// global apocalypse otomatis tersedia setelah baris di atas
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
# Links
|
|
88
|
+
|
|
89
|
+
- [Discord](https://discord.gg/WeJM5FP9GG)
|
|
90
|
+
- [Docs](https://guide.whiskeysockets.io/)
|
|
91
|
+
|
|
92
|
+
# Index
|
|
93
|
+
|
|
94
|
+
- [Connecting Account](#connecting-account)
|
|
95
|
+
- [Connect with QR-CODE](#starting-socket-with-qr-code)
|
|
96
|
+
- [Connect with Pairing Code](#starting-socket-with-pairing-code)
|
|
97
|
+
- [Receive Full History](#receive-full-history)
|
|
98
|
+
- [Important Notes About Socket Config](#important-notes-about-socket-config)
|
|
99
|
+
- [Caching Group Metadata (Recommended)](#caching-group-metadata-recommended)
|
|
100
|
+
- [Improve Retry System & Decrypt Poll Votes](#improve-retry-system--decrypt-poll-votes)
|
|
101
|
+
- [Receive Notifications in Whatsapp App](#receive-notifications-in-whatsapp-app)
|
|
102
|
+
|
|
103
|
+
- [Save Auth Info](#saving--restoring-sessions)
|
|
104
|
+
- [Handling Events](#handling-events)
|
|
105
|
+
- [Example to Start](#example-to-start)
|
|
106
|
+
- [Decrypt Poll Votes](#decrypt-poll-votes)
|
|
107
|
+
- [Summary of Events on First Connection](#summary-of-events-on-first-connection)
|
|
108
|
+
- [Implementing a Data Store](#implementing-a-data-store)
|
|
109
|
+
- [Whatsapp IDs Explain](#whatsapp-ids-explain)
|
|
110
|
+
- [Utility Functions](#utility-functions)
|
|
111
|
+
- [Newsletter / Channel](#newsletter--channel)
|
|
112
|
+
- [Kirim Media ke Channel](#kirim-media-ke-channel)
|
|
113
|
+
- [Button di Channel](#button-di-channel)
|
|
114
|
+
- [Edit & Hapus Pesan Channel](#edit--hapus-pesan-channel)
|
|
115
|
+
- [Resolve JID (LID → Phone)](#resolve-jid)
|
|
116
|
+
- [Sending Messages](#sending-messages)
|
|
117
|
+
- [Non-Media Messages](#non-media-messages)
|
|
118
|
+
- [Text Message](#text-message)
|
|
119
|
+
- [Quote Message](#quote-message-works-with-all-types)
|
|
120
|
+
- [Mention User](#mention-user-works-with-most-types)
|
|
121
|
+
- [Forward Messages](#forward-messages)
|
|
122
|
+
- [Location Message](#location-message)
|
|
123
|
+
- [Live Location Message](#live-location-message)
|
|
124
|
+
- [Contact Message](#contact-message)
|
|
125
|
+
- [Reaction Message](#reaction-message)
|
|
126
|
+
- [Pin Message](#pin-message)
|
|
127
|
+
- [Keep Message](#keep-message)
|
|
128
|
+
- [Poll Message](#poll-message)
|
|
129
|
+
- [Poll Result Message](#poll-result-message)
|
|
130
|
+
- [Call Message](#call-message)
|
|
131
|
+
- [Event Message](#event-message)
|
|
132
|
+
- [Order Message](#order-message)
|
|
133
|
+
- [Product Message](#product-message)
|
|
134
|
+
- [Payment Message](#payment-message)
|
|
135
|
+
- [Payment Invite Message](#payment-invite-message)
|
|
136
|
+
- [Admin Invite Message](#admin-invite-message)
|
|
137
|
+
- [Group Invite Message](#group-invite-message)
|
|
138
|
+
- [Sticker Pack Message](#sticker-pack-message)
|
|
139
|
+
- [Share Phone Number Message](#share-phone-number-message)
|
|
140
|
+
- [Request Phone Number Message](#request-phone-number-message)
|
|
141
|
+
- [Buttons Reply Message](#buttons-reply-message)
|
|
142
|
+
- [Buttons Message](#buttons-message)
|
|
143
|
+
- [Buttons List Message](#buttons-list-message)
|
|
144
|
+
- [Buttons Product List Message](#buttons-product-list-message)
|
|
145
|
+
- [Buttons Cards Message](#buttons-cards-message)
|
|
146
|
+
- [Buttons Template Message](#buttons-template-message)
|
|
147
|
+
- [Buttons Interactive Message](#buttons-interactive-message)
|
|
148
|
+
- [Buttons Interactive Message PIX](#buttons-interactive-message-pix)
|
|
149
|
+
- [Buttons Interactive Message PAY](#buttons-interactive-message-pay)
|
|
150
|
+
- [Status Mentions Message](#status-mentions-message)
|
|
151
|
+
- [Shop Message](#shop-message)
|
|
152
|
+
- [Collection Message](#collection-message)
|
|
153
|
+
- [AI Icon Feature](#ai-icon-feature)
|
|
154
|
+
- [Sending with Link Preview](#sending-messages-with-link-previews)
|
|
155
|
+
- [Media Messages](#media-messages)
|
|
156
|
+
- [Gif Message](#gif-message)
|
|
157
|
+
- [Video Message](#video-message)
|
|
158
|
+
- [Audio Message](#audio-message)
|
|
159
|
+
- [Image Message](#image-message)
|
|
160
|
+
- [Album Message](#album-message)
|
|
161
|
+
- [Ptv Video Message](#ptv-video-message)
|
|
162
|
+
- [View Once Message](#view-once-message)
|
|
163
|
+
- [Modify Messages](#modify-messages)
|
|
164
|
+
- [Delete Messages (for everyone)](#deleting-messages-for-everyone)
|
|
165
|
+
- [Edit Messages](#editing-messages)
|
|
166
|
+
- [Manipulating Media Messages](#manipulating-media-messages)
|
|
167
|
+
- [Thumbnail in Media Messages](#thumbnail-in-media-messages)
|
|
168
|
+
- [Downloading Media Messages](#downloading-media-messages)
|
|
169
|
+
- [Re-upload Media Message to Whatsapp](#re-upload-media-message-to-whatsapp)
|
|
170
|
+
- [Reject Call](#reject-call)
|
|
171
|
+
- [Send States in Chat](#send-states-in-chat)
|
|
172
|
+
- [Reading Messages](#reading-messages)
|
|
173
|
+
- [Update Presence](#update-presence)
|
|
174
|
+
- [Modifying Chats](#modifying-chats)
|
|
175
|
+
- [Archive a Chat](#archive-a-chat)
|
|
176
|
+
- [Mute/Unmute a Chat](#muteunmute-a-chat)
|
|
177
|
+
- [Mark a Chat Read/Unread](#mark-a-chat-readunread)
|
|
178
|
+
- [Delete a Message for Me](#delete-a-message-for-me)
|
|
179
|
+
- [Delete a Chat](#delete-a-chat)
|
|
180
|
+
- [Star/Unstar a Message](#starunstar-a-message)
|
|
181
|
+
- [Disappearing Messages](#disappearing-messages)
|
|
182
|
+
- [Clear Messages](#clear-messages)
|
|
183
|
+
- [User Querys](#user-querys)
|
|
184
|
+
- [Check If ID Exists in Whatsapp](#check-if-id-exists-in-whatsapp)
|
|
185
|
+
- [Query Chat History (groups too)](#query-chat-history-groups-too)
|
|
186
|
+
- [Fetch Status](#fetch-status)
|
|
187
|
+
- [Fetch Profile Picture (groups too)](#fetch-profile-picture-groups-too)
|
|
188
|
+
- [Fetch Bussines Profile (such as description or category)](#fetch-bussines-profile-such-as-description-or-category)
|
|
189
|
+
- [Fetch Someone's Presence (if they're typing or online)](#fetch-someones-presence-if-theyre-typing-or-online)
|
|
190
|
+
- [Change Profile](#change-profile)
|
|
191
|
+
- [Change Profile Status](#change-profile-status)
|
|
192
|
+
- [Change Profile Name](#change-profile-name)
|
|
193
|
+
- [Change Display Picture (groups too)](#change-display-picture-groups-too)
|
|
194
|
+
- [Remove display picture (groups too)](#remove-display-picture-groups-too)
|
|
195
|
+
- [Groups](#groups)
|
|
196
|
+
- [Create a Group](#create-a-group)
|
|
197
|
+
- [Add/Remove or Demote/Promote](#addremove-or-demotepromote)
|
|
198
|
+
- [Change Subject (name)](#change-subject-name)
|
|
199
|
+
- [Change Description](#change-description)
|
|
200
|
+
- [Change Settings](#change-settings)
|
|
201
|
+
- [Leave a Group](#leave-a-group)
|
|
202
|
+
- [Get Invite Code](#get-invite-code)
|
|
203
|
+
- [Revoke Invite Code](#revoke-invite-code)
|
|
204
|
+
- [Join Using Invitation Code](#join-using-invitation-code)
|
|
205
|
+
- [Get Group Info by Invite Code](#get-group-info-by-invite-code)
|
|
206
|
+
- [Query Metadata (participants, name, description...)](#query-metadata-participants-name-description)
|
|
207
|
+
- [Join using groupInviteMessage](#join-using-groupinvitemessage)
|
|
208
|
+
- [Get Request Join List](#get-request-join-list)
|
|
209
|
+
- [Approve/Reject Request Join](#approvereject-request-join)
|
|
210
|
+
- [Get All Participating Groups Metadata](#get-all-participating-groups-metadata)
|
|
211
|
+
- [Toggle Ephemeral](#toggle-ephemeral)
|
|
212
|
+
- [Change Add Mode](#change-add-mode)
|
|
213
|
+
- [Privacy](#privacy)
|
|
214
|
+
- [Block/Unblock User](#blockunblock-user)
|
|
215
|
+
- [Get Privacy Settings](#get-privacy-settings)
|
|
216
|
+
- [Get BlockList](#get-blocklist)
|
|
217
|
+
- [Update LastSeen Privacy](#update-lastseen-privacy)
|
|
218
|
+
- [Update Online Privacy](#update-online-privacy)
|
|
219
|
+
- [Update Profile Picture Privacy](#update-profile-picture-privacy)
|
|
220
|
+
- [Update Status Privacy](#update-status-privacy)
|
|
221
|
+
- [Update Read Receipts Privacy](#update-read-receipts-privacy)
|
|
222
|
+
- [Update Groups Add Privacy](#update-groups-add-privacy)
|
|
223
|
+
- [Update Default Disappearing Mode](#update-default-disappearing-mode)
|
|
224
|
+
- [Broadcast Lists & Stories](#broadcast-lists--stories)
|
|
225
|
+
- [Send Broadcast & Stories](#send-broadcast--stories)
|
|
226
|
+
- [Query a Broadcast List's Recipients & Name](#query-a-broadcast-lists-recipients--name)
|
|
227
|
+
- [Writing Custom Functionality](#writing-custom-functionality)
|
|
228
|
+
- [Enabling Debug Level in Baileys Logs](#enabling-debug-level-in-baileys-logs)
|
|
229
|
+
- [How Whatsapp Communicate With Us](#how-whatsapp-communicate-with-us)
|
|
230
|
+
- [Register a Callback for Websocket Events](#register-a-callback-for-websocket-events)
|
|
231
|
+
|
|
232
|
+
## Connecting Account
|
|
233
|
+
|
|
234
|
+
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.
|
|
235
|
+
|
|
236
|
+
> [!NOTE]
|
|
237
|
+
> **[Here](#example-to-start) is a simple example of event handling**
|
|
238
|
+
|
|
239
|
+
> [!TIP]
|
|
240
|
+
> **You can see all supported socket configs [here](https://baileys.whiskeysockets.io/types/SocketConfig.html) (Recommended)**
|
|
241
|
+
|
|
242
|
+
### Starting socket with **QR-CODE**
|
|
243
|
+
|
|
244
|
+
> [!TIP]
|
|
245
|
+
> 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)**
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
import makeWASocket from '@blckrose/baileys'
|
|
145
249
|
|
|
146
250
|
const sock = makeWASocket({
|
|
147
|
-
|
|
251
|
+
// can provide additional config here
|
|
252
|
+
browser: Browsers.ubuntu('My App'),
|
|
148
253
|
printQRInTerminal: true
|
|
149
254
|
})
|
|
150
255
|
```
|
|
151
256
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
## 📚 Common Use Cases
|
|
155
|
-
|
|
156
|
-
### Send Text Message
|
|
157
|
-
```typescript
|
|
158
|
-
await sock.sendMessage(jid, { text: 'Hello World! 💧' })
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Send Image
|
|
162
|
-
```typescript
|
|
163
|
-
await sock.sendMessage(jid, {
|
|
164
|
-
image: { url: './image.jpg' },
|
|
165
|
-
caption: 'Check this out!'
|
|
166
|
-
})
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Send Video
|
|
170
|
-
```typescript
|
|
171
|
-
await sock.sendMessage(jid, {
|
|
172
|
-
video: { url: './video.mp4' },
|
|
173
|
-
caption: 'Amazing video!',
|
|
174
|
-
mimetype: 'video/mp4'
|
|
175
|
-
})
|
|
176
|
-
```
|
|
257
|
+
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!
|
|
177
258
|
|
|
178
|
-
###
|
|
179
|
-
```typescript
|
|
180
|
-
await sock.sendMessage(jid, {
|
|
181
|
-
audio: { url: './audio.mp3' },
|
|
182
|
-
mimetype: 'audio/mp4'
|
|
183
|
-
})
|
|
184
|
-
```
|
|
259
|
+
### Starting socket with **Pairing Code**
|
|
185
260
|
|
|
186
|
-
### Send Sticker
|
|
187
|
-
```typescript
|
|
188
|
-
await sock.sendMessage(jid, {
|
|
189
|
-
sticker: { url: './sticker.webp' }
|
|
190
|
-
})
|
|
191
|
-
```
|
|
192
261
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
await sock.sendMessage(jid, {
|
|
196
|
-
document: { url: './document.pdf' },
|
|
197
|
-
mimetype: 'application/pdf',
|
|
198
|
-
fileName: 'document.pdf'
|
|
199
|
-
})
|
|
200
|
-
```
|
|
262
|
+
> [!IMPORTANT]
|
|
263
|
+
> 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)
|
|
201
264
|
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
await sock.sendMessage(jid, {
|
|
205
|
-
location: {
|
|
206
|
-
degreesLatitude: -6.2088,
|
|
207
|
-
degreesLongitude: 106.8456
|
|
208
|
-
}
|
|
209
|
-
})
|
|
210
|
-
```
|
|
265
|
+
The phone number can't have `+` or `()` or `-`, only numbers, you must provide country code
|
|
211
266
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const vcard = `BEGIN:VCARD
|
|
215
|
-
VERSION:3.0
|
|
216
|
-
FN:John Doe
|
|
217
|
-
TEL;type=CELL;type=VOICE;waid=6281234567890:+62 812-3456-7890
|
|
218
|
-
END:VCARD`
|
|
219
|
-
|
|
220
|
-
await sock.sendMessage(jid, {
|
|
221
|
-
contacts: {
|
|
222
|
-
displayName: 'John Doe',
|
|
223
|
-
contacts: [{ vcard }]
|
|
224
|
-
}
|
|
225
|
-
})
|
|
226
|
-
```
|
|
267
|
+
```ts
|
|
268
|
+
import makeWASocket from '@blckrose/baileys'
|
|
227
269
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
poll: {
|
|
232
|
-
name: 'Favorite Color?',
|
|
233
|
-
values: ['Red', 'Blue', 'Green'],
|
|
234
|
-
selectableCount: 1
|
|
235
|
-
}
|
|
270
|
+
const sock = makeWASocket({
|
|
271
|
+
// can provide additional config here
|
|
272
|
+
printQRInTerminal: false //need to be false
|
|
236
273
|
})
|
|
237
|
-
```
|
|
238
274
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
await sock.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
key: message.key
|
|
245
|
-
}
|
|
246
|
-
})
|
|
275
|
+
if (!sock.authState.creds.registered) {
|
|
276
|
+
const number = 'XXXXXXXXXXX'
|
|
277
|
+
const code = await sock.requestPairingCode(number)
|
|
278
|
+
console.log(code)
|
|
279
|
+
}
|
|
247
280
|
```
|
|
248
281
|
|
|
249
|
-
###
|
|
250
|
-
```typescript
|
|
251
|
-
await sock.sendMessage(jid, {
|
|
252
|
-
text: 'This is a reply'
|
|
253
|
-
}, {
|
|
254
|
-
quoted: message
|
|
255
|
-
})
|
|
256
|
-
```
|
|
282
|
+
### Receive Full History
|
|
257
283
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
text: 'Hello @6281234567890!',
|
|
262
|
-
mentions: ['6281234567890@s.whatsapp.net']
|
|
263
|
-
})
|
|
264
|
-
```
|
|
284
|
+
1. Set `syncFullHistory` as `true`
|
|
285
|
+
2. Baileys, by default, use chrome browser config
|
|
286
|
+
- If you'd like to emulate a desktop connection (and receive more message history), this browser setting to your Socket config:
|
|
265
287
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
288
|
+
```ts
|
|
289
|
+
const sock = makeWASocket({
|
|
290
|
+
...otherOpts,
|
|
291
|
+
// can use Windows, Ubuntu here too
|
|
292
|
+
browser: Browsers.macOS('Desktop'),
|
|
293
|
+
syncFullHistory: true
|
|
270
294
|
})
|
|
271
295
|
```
|
|
272
296
|
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
const msg = await sock.sendMessage(jid, { text: 'test' })
|
|
276
|
-
await sock.sendMessage(jid, { delete: msg.key })
|
|
277
|
-
```
|
|
297
|
+
## Important Notes About Socket Config
|
|
278
298
|
|
|
279
|
-
###
|
|
280
|
-
|
|
281
|
-
await sock.sendMessage(jid, {
|
|
282
|
-
text: 'Updated text',
|
|
283
|
-
edit: message.key
|
|
284
|
-
})
|
|
285
|
-
```
|
|
299
|
+
### Caching Group Metadata (Recommended)
|
|
300
|
+
- If you use baileys for groups, we recommend you to set `cachedGroupMetadata` in socket config, you need to implement a cache like this:
|
|
286
301
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
await sock.sendMessage(jid, {
|
|
290
|
-
pin: {
|
|
291
|
-
type: 1, // 1=24h, 2=7d, 3=30d
|
|
292
|
-
time: 86400,
|
|
293
|
-
key: message.key
|
|
294
|
-
}
|
|
295
|
-
})
|
|
296
|
-
```
|
|
302
|
+
```ts
|
|
303
|
+
const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
|
|
297
304
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
image: { url: './image.jpg' },
|
|
302
|
-
viewOnce: true
|
|
303
|
-
})
|
|
304
|
-
```
|
|
305
|
+
const sock = makeWASocket({
|
|
306
|
+
cachedGroupMetadata: async (jid) => groupCache.get(jid)
|
|
307
|
+
})
|
|
305
308
|
|
|
306
|
-
|
|
309
|
+
sock.ev.on('groups.update', async ([event]) => {
|
|
310
|
+
const metadata = await sock.groupMetadata(event.id)
|
|
311
|
+
groupCache.set(event.id, metadata)
|
|
312
|
+
})
|
|
307
313
|
|
|
308
|
-
|
|
314
|
+
sock.ev.on('group-participants.update', async (event) => {
|
|
315
|
+
const metadata = await sock.groupMetadata(event.id)
|
|
316
|
+
groupCache.set(event.id, metadata)
|
|
317
|
+
})
|
|
318
|
+
```
|
|
309
319
|
|
|
310
|
-
###
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
320
|
+
### Improve Retry System & Decrypt Poll Votes
|
|
321
|
+
- 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:
|
|
322
|
+
```ts
|
|
323
|
+
const sock = makeWASocket({
|
|
324
|
+
getMessage: async (key) => await getMessageFromStore(key)
|
|
325
|
+
})
|
|
326
|
+
```
|
|
315
327
|
|
|
316
|
-
###
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
### Receive Notifications in Whatsapp App
|
|
329
|
+
- If you want to receive notifications in whatsapp app, set `markOnlineOnConnect` to `false`
|
|
330
|
+
```ts
|
|
331
|
+
const sock = makeWASocket({
|
|
332
|
+
markOnlineOnConnect: false
|
|
333
|
+
})
|
|
334
|
+
```
|
|
335
|
+
## Saving & Restoring Sessions
|
|
320
336
|
|
|
321
|
-
|
|
322
|
-
```typescript
|
|
323
|
-
await sock.groupParticipantsUpdate(groupId, ['6281234567890@s.whatsapp.net'], 'remove')
|
|
324
|
-
```
|
|
337
|
+
You obviously don't want to keep scanning the QR code every time you want to connect.
|
|
325
338
|
|
|
326
|
-
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
```
|
|
339
|
+
So, you can load the credentials to log back in:
|
|
340
|
+
```ts
|
|
341
|
+
import makeWASocket, { useMultiFileAuthState } from '@blckrose/baileys'
|
|
330
342
|
|
|
331
|
-
|
|
332
|
-
```typescript
|
|
333
|
-
await sock.groupParticipantsUpdate(groupId, ['6281234567890@s.whatsapp.net'], 'demote')
|
|
334
|
-
```
|
|
343
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
|
|
335
344
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
```
|
|
345
|
+
// will use the given state to connect
|
|
346
|
+
// so if valid credentials are available -- it'll connect without QR
|
|
347
|
+
const sock = makeWASocket({ auth: state })
|
|
340
348
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
await sock.groupUpdateDescription(groupId, 'New Description')
|
|
349
|
+
// this will be called as soon as the credentials are updated
|
|
350
|
+
sock.ev.on('creds.update', saveCreds)
|
|
344
351
|
```
|
|
345
352
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
const code = await sock.groupInviteCode(groupId)
|
|
349
|
-
const inviteLink = 'https://chat.whatsapp.com/' + code
|
|
350
|
-
```
|
|
353
|
+
> [!IMPORTANT]
|
|
354
|
+
> `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.
|
|
351
355
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
await sock.groupAcceptInvite('inviteCode')
|
|
355
|
-
```
|
|
356
|
+
> [!NOTE]
|
|
357
|
+
> 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.
|
|
356
358
|
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
await sock.groupLeave(groupId)
|
|
360
|
-
```
|
|
359
|
+
## Handling Events
|
|
361
360
|
|
|
362
|
-
|
|
361
|
+
- Baileys uses the EventEmitter syntax for events.
|
|
362
|
+
They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
> [!IMPORTANT]
|
|
365
|
+
> **The events are [these](https://baileys.whiskeysockets.io/types/BaileysEventMap.html)**, it's important you see all events
|
|
365
366
|
|
|
366
|
-
|
|
367
|
-
```
|
|
368
|
-
sock
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
367
|
+
You can listen to these events like this:
|
|
368
|
+
```ts
|
|
369
|
+
const sock = makeWASocket()
|
|
370
|
+
sock.ev.on('messages.upsert', ({ messages }) => {
|
|
371
|
+
console.log('got messages', messages)
|
|
372
372
|
})
|
|
373
373
|
```
|
|
374
374
|
|
|
375
|
-
|
|
375
|
+
### Example to Start
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
> [!NOTE]
|
|
378
|
+
> This example includes basic auth storage too
|
|
378
379
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const [result] = await sock.onWhatsApp('6281234567890')
|
|
382
|
-
if (result?.exists) {
|
|
383
|
-
console.log('Number exists:', result.jid)
|
|
384
|
-
}
|
|
385
|
-
```
|
|
380
|
+
> [!NOTE]
|
|
381
|
+
> For reliable serialization of the authentication state, especially when storing as JSON, always use the BufferJSON utility.
|
|
386
382
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const ppUrl = await sock.profilePictureUrl(jid)
|
|
383
|
+
```ts
|
|
384
|
+
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@blckrose/baileys'
|
|
385
|
+
import { Boom } from '@hapi/boom'
|
|
391
386
|
|
|
392
|
-
|
|
393
|
-
const
|
|
394
|
-
|
|
387
|
+
async function connectToWhatsApp () {
|
|
388
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
|
|
389
|
+
const sock = makeWASocket({
|
|
390
|
+
// can provide additional config here
|
|
391
|
+
auth: state,
|
|
392
|
+
printQRInTerminal: true
|
|
393
|
+
})
|
|
394
|
+
sock.ev.on('connection.update', (update) => {
|
|
395
|
+
const { connection, lastDisconnect } = update
|
|
396
|
+
if(connection === 'close') {
|
|
397
|
+
const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
|
|
398
|
+
console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
|
|
399
|
+
// reconnect if not logged out
|
|
400
|
+
if(shouldReconnect) {
|
|
401
|
+
connectToWhatsApp()
|
|
402
|
+
}
|
|
403
|
+
} else if(connection === 'open') {
|
|
404
|
+
console.log('opened connection')
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
sock.ev.on('messages.upsert', event => {
|
|
408
|
+
for (const m of event.messages) {
|
|
409
|
+
console.log(JSON.stringify(m, undefined, 2))
|
|
395
410
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
```
|
|
411
|
+
console.log('replying to', m.key.remoteJid)
|
|
412
|
+
await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
|
|
413
|
+
}
|
|
414
|
+
})
|
|
401
415
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
416
|
+
// to storage creds (session info) when it updates
|
|
417
|
+
sock.ev.on('creds.update', saveCreds)
|
|
418
|
+
}
|
|
419
|
+
// run in main file
|
|
420
|
+
connectToWhatsApp()
|
|
406
421
|
```
|
|
407
422
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
423
|
+
### For example if you use useSingleFileAuthState and useMongoFileAuthState
|
|
424
|
+
```ts
|
|
425
|
+
import makeWASocket, { useSingleFileAuthState, useMongoFileAuthState } from '@blckrose/baileys'
|
|
411
426
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
427
|
+
// Single Auth
|
|
428
|
+
const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json')
|
|
429
|
+
const sock = makeWASocket({
|
|
430
|
+
auth: state,
|
|
431
|
+
printQRInTerminal: true
|
|
432
|
+
})
|
|
417
433
|
|
|
418
|
-
|
|
419
|
-
```typescript
|
|
420
|
-
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid) // 8 hours
|
|
421
|
-
```
|
|
434
|
+
sock.ev.on('creds.update', saveState)
|
|
422
435
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
await sock.chatModify({ mute: null }, jid)
|
|
426
|
-
```
|
|
436
|
+
// Mongo Auth
|
|
437
|
+
import { MongoClient } from "mongodb"
|
|
427
438
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
439
|
+
const connectAuth = async() => {
|
|
440
|
+
global.client = new MongoClient('mongoURL')
|
|
441
|
+
global.client.connect(err => {
|
|
442
|
+
if (err) {
|
|
443
|
+
console.warn("Warning: MongoDB link is invalid or cannot be connected.")
|
|
444
|
+
} else {
|
|
445
|
+
console.log('Successfully Connected To MongoDB Server')
|
|
446
|
+
}
|
|
447
|
+
})
|
|
448
|
+
await client.connect()
|
|
449
|
+
const collection = client.db("@blckrose").collection("sessions")
|
|
450
|
+
return collection
|
|
451
|
+
}
|
|
432
452
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
453
|
+
const Authentication = await connectAuth()
|
|
454
|
+
const { state, saveCreds } = await useMongoFileAuthState(Authentication)
|
|
455
|
+
const sock = makeWASocket({
|
|
456
|
+
auth: state,
|
|
457
|
+
printQRInTerminal: true
|
|
458
|
+
})
|
|
437
459
|
|
|
438
|
-
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
460
|
+
sock.ev.on('creds.update', saveCreds)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
> [!IMPORTANT]
|
|
464
|
+
> In `messages.upsert` it's recommended to use a loop like `for (const message of event.messages)` to handle all messages in array
|
|
465
|
+
|
|
466
|
+
### Decrypt Poll Votes
|
|
467
|
+
|
|
468
|
+
- By default poll votes are encrypted and handled in `messages.update`
|
|
469
|
+
- That's a simple example
|
|
470
|
+
```ts
|
|
471
|
+
sock.ev.on('messages.update', event => {
|
|
472
|
+
for(const { key, update } of event) {
|
|
473
|
+
if(update.pollUpdates) {
|
|
474
|
+
const pollCreation = await getMessage(key)
|
|
475
|
+
if(pollCreation) {
|
|
476
|
+
console.log(
|
|
477
|
+
'got poll update, aggregation: ',
|
|
478
|
+
getAggregateVotesInPollMessage({
|
|
479
|
+
message: pollCreation,
|
|
480
|
+
pollUpdates: update.pollUpdates,
|
|
481
|
+
})
|
|
482
|
+
)
|
|
483
|
+
}
|
|
484
|
+
}
|
|
444
485
|
}
|
|
445
|
-
}, jid)
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### Disappearing Messages
|
|
449
|
-
```typescript
|
|
450
|
-
// Enable
|
|
451
|
-
await sock.sendMessage(jid, {
|
|
452
|
-
disappearingMessagesInChat: 7 * 24 * 60 * 60 // 7 days
|
|
453
486
|
})
|
|
454
|
-
|
|
455
|
-
// Disable
|
|
456
|
-
await sock.sendMessage(jid, {
|
|
457
|
-
disappearingMessagesInChat: false
|
|
458
|
-
})
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
---
|
|
462
|
-
|
|
463
|
-
## 🎨 Profile Management
|
|
464
|
-
|
|
465
|
-
### Update Profile Name
|
|
466
|
-
```typescript
|
|
467
|
-
await sock.updateProfileName('New Name')
|
|
468
487
|
```
|
|
469
488
|
|
|
470
|
-
|
|
471
|
-
```typescript
|
|
472
|
-
await sock.updateProfileStatus('New Status 💧')
|
|
473
|
-
```
|
|
489
|
+
- `getMessage` is a [store](#implementing-a-data-store) implementation (in your end)
|
|
474
490
|
|
|
475
|
-
###
|
|
476
|
-
```typescript
|
|
477
|
-
await sock.updateProfilePicture(jid, { url: './new-pp.jpg' })
|
|
478
|
-
```
|
|
491
|
+
### Summary of Events on First Connection
|
|
479
492
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
await sock.removeProfilePicture(jid)
|
|
483
|
-
```
|
|
493
|
+
1. When you connect first time, `connection.update` will be fired requesting you to restart sock
|
|
494
|
+
2. Then, history messages will be received in `messaging.history-set`
|
|
484
495
|
|
|
485
|
-
|
|
496
|
+
## Implementing a Data Store
|
|
486
497
|
|
|
487
|
-
|
|
498
|
+
- 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.
|
|
488
499
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
sock.ev.on('connection.update', (update) => {
|
|
492
|
-
console.log('Connection:', update)
|
|
493
|
-
})
|
|
494
|
-
```
|
|
500
|
+
> [!IMPORTANT]
|
|
501
|
+
> I highly recommend building your own data store, as storing someone's entire chat history in memory is a terrible waste of RAM.
|
|
495
502
|
|
|
496
|
-
|
|
497
|
-
```typescript
|
|
498
|
-
sock.ev.on('messages.upsert', ({ messages }) => {
|
|
499
|
-
console.log('Messages:', messages)
|
|
500
|
-
})
|
|
501
|
-
|
|
502
|
-
sock.ev.on('messages.update', (updates) => {
|
|
503
|
-
console.log('Message updates:', updates)
|
|
504
|
-
})
|
|
503
|
+
It can be used as follows:
|
|
505
504
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
```typescript
|
|
513
|
-
sock.ev.on('chats.upsert', (chats) => {
|
|
514
|
-
console.log('New chats:', chats)
|
|
515
|
-
})
|
|
516
|
-
|
|
517
|
-
sock.ev.on('chats.update', (updates) => {
|
|
518
|
-
console.log('Chat updates:', updates)
|
|
519
|
-
})
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
### Contact Events
|
|
523
|
-
```typescript
|
|
524
|
-
sock.ev.on('contacts.upsert', (contacts) => {
|
|
525
|
-
console.log('New contacts:', contacts)
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
sock.ev.on('contacts.update', (updates) => {
|
|
529
|
-
console.log('Contact updates:', updates)
|
|
530
|
-
})
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
### Group Events
|
|
534
|
-
```typescript
|
|
535
|
-
sock.ev.on('groups.upsert', (groups) => {
|
|
536
|
-
console.log('New groups:', groups)
|
|
537
|
-
})
|
|
538
|
-
|
|
539
|
-
sock.ev.on('groups.update', (updates) => {
|
|
540
|
-
console.log('Group updates:', updates)
|
|
541
|
-
})
|
|
542
|
-
|
|
543
|
-
sock.ev.on('group-participants.update', (update) => {
|
|
544
|
-
console.log('Participants update:', update)
|
|
545
|
-
})
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
### Presence Events
|
|
549
|
-
```typescript
|
|
550
|
-
sock.ev.on('presence.update', (presence) => {
|
|
551
|
-
console.log('Presence:', presence)
|
|
552
|
-
})
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
---
|
|
556
|
-
|
|
557
|
-
## 🗄️ Data Store
|
|
558
|
-
|
|
559
|
-
### In-Memory Store
|
|
560
|
-
```typescript
|
|
561
|
-
import makeWASocket, { makeInMemoryStore } from '@ryuhan/baileys'
|
|
562
|
-
|
|
563
|
-
const store = makeInMemoryStore()
|
|
505
|
+
```ts
|
|
506
|
+
import makeWASocket, { makeInMemoryStore } from '@blckrose/baileys'
|
|
507
|
+
// the store maintains the data of the WA connection in memory
|
|
508
|
+
// can be written out to a file & read from it
|
|
509
|
+
const store = makeInMemoryStore({ })
|
|
510
|
+
// can be read from a file
|
|
564
511
|
store.readFromFile('./baileys_store.json')
|
|
565
|
-
|
|
512
|
+
// saves the state to a file every 10s
|
|
566
513
|
setInterval(() => {
|
|
567
514
|
store.writeToFile('./baileys_store.json')
|
|
568
|
-
},
|
|
515
|
+
}, 10_000)
|
|
569
516
|
|
|
570
|
-
const sock = makeWASocket()
|
|
517
|
+
const sock = makeWASocket({ })
|
|
518
|
+
// will listen from this socket
|
|
519
|
+
// the store can listen from a new socket once the current socket outlives its lifetime
|
|
571
520
|
store.bind(sock.ev)
|
|
572
521
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
console.log('
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
---
|
|
580
|
-
|
|
581
|
-
## 🔧 Utilities
|
|
582
|
-
|
|
583
|
-
### JID Helpers
|
|
584
|
-
```typescript
|
|
585
|
-
import { jidEncode, jidDecode, isJidGroup, isJidBroadcast } from '@ryuhan/baileys'
|
|
586
|
-
|
|
587
|
-
// Encode JID
|
|
588
|
-
const jid = jidEncode('6281234567890', 's.whatsapp.net')
|
|
589
|
-
|
|
590
|
-
// Decode JID
|
|
591
|
-
const decoded = jidDecode(jid)
|
|
592
|
-
|
|
593
|
-
// Check JID type
|
|
594
|
-
const isGroup = isJidGroup(jid)
|
|
595
|
-
const isBroadcast = isJidBroadcast(jid)
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
### Message Helpers
|
|
599
|
-
```typescript
|
|
600
|
-
import { getContentType, getDevice, downloadMediaMessage } from '@ryuhan/baileys'
|
|
601
|
-
|
|
602
|
-
// Get content type
|
|
603
|
-
const type = getContentType(message)
|
|
522
|
+
sock.ev.on('chats.upsert', () => {
|
|
523
|
+
// can use 'store.chats' however you want, even after the socket dies out
|
|
524
|
+
// 'chats' => a KeyedDB instance
|
|
525
|
+
console.log('got chats', store.chats.all())
|
|
526
|
+
})
|
|
604
527
|
|
|
605
|
-
|
|
606
|
-
|
|
528
|
+
sock.ev.on('contacts.upsert', () => {
|
|
529
|
+
console.log('got contacts', Object.values(store.contacts))
|
|
530
|
+
})
|
|
607
531
|
|
|
608
|
-
// Download media
|
|
609
|
-
const buffer = await downloadMediaMessage(message, 'buffer')
|
|
610
532
|
```
|
|
611
533
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
## 💝 Credits & Inspiration
|
|
615
|
-
|
|
616
|
-
This project is built upon the amazing work of:
|
|
617
|
-
|
|
618
|
-
- **[@blck-baileys](https://github.com/blckrose)** - Original modified Baileys fork with advanced features
|
|
619
|
-
- **[@WhiskeySockets](https://github.com/WhiskeySockets/Baileys)** - Base Baileys library
|
|
620
|
-
- **[@itsukichan](https://github.com/itsukichan/baileys)** - Additional features and improvements
|
|
621
|
-
|
|
622
|
-
Special thanks to all contributors and the WhatsApp community!
|
|
534
|
+
The store also provides some simple functions such as `loadMessages` that utilize the store to speed up data retrieval.
|
|
623
535
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
## ⚠️ Disclaimer
|
|
627
|
-
|
|
628
|
-
This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries. The official WhatsApp website can be found at [whatsapp.com](https://whatsapp.com).
|
|
536
|
+
## Whatsapp IDs Explain
|
|
629
537
|
|
|
630
|
-
|
|
538
|
+
- `id` is the WhatsApp ID, called `jid` too, of the person or group you're sending the message to.
|
|
539
|
+
- It must be in the format ```[country code][phone number]@s.whatsapp.net```
|
|
540
|
+
- Example for people: ```+19999999999@s.whatsapp.net```.
|
|
541
|
+
- For groups, it must be in the format ``` 123456789-123345@g.us ```.
|
|
542
|
+
- For broadcast lists, it's `[timestamp of creation]@broadcast`.
|
|
543
|
+
- For stories, the ID is `status@broadcast`.
|
|
631
544
|
|
|
632
|
-
|
|
545
|
+
## Utility Functions
|
|
633
546
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
547
|
+
### Resize Image
|
|
548
|
+
```ts
|
|
549
|
+
// Resize an image (Buffer, URL, or stream) to given dimensions
|
|
550
|
+
const resized = await sock.resize('https://example.com/image.jpg', 320, 320)
|
|
551
|
+
// or
|
|
552
|
+
const resized = await sock.resize(buffer, 320, 320)
|
|
553
|
+
```
|
|
637
554
|
|
|
638
|
-
|
|
555
|
+
- `getContentType`, returns the content type for any message
|
|
556
|
+
- `getDevice`, returns the device from message
|
|
557
|
+
- `makeCacheableSignalKeyStore`, make auth store more fast
|
|
558
|
+
- `downloadContentFromMessage`, download content from any message
|
|
559
|
+
- `makeNewsletterUtils`, helper lengkap untuk kirim ke newsletter/channel
|
|
560
|
+
- `resolveJid`, resolve LID / participant ID ke JID @s.whatsapp.net
|
|
561
|
+
- `resolveJids`, resolve banyak JID sekaligus
|
|
639
562
|
|
|
640
563
|
---
|
|
641
564
|
|
|
642
|
-
<p align="center">Made with
|
|
643
|
-
<p align="center">
|
|
644
|
-
<a href="https://github.com/ryuhandev/rimuru-baileys">GitHub</a> •
|
|
645
|
-
<a href="https://www.npmjs.com/package/@ryuhan/baileys">npm</a> •
|
|
646
|
-
<a href="https://github.com/ryuhandev/rimuru-baileys/issues">Issues</a>
|
|
647
|
-
</p>
|
|
565
|
+
<p align="center">Made with ⬡ by <a href="https://github.com/blckrose">@blckrose</a></p>
|