zaileys 1.1.25 β 1.1.27
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 +138 -219
- package/dist/index.js +1 -5276
- package/dist/index.mjs +1 -5246
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,59 +1,64 @@
|
|
|
1
|
-
<div align=
|
|
2
|
-
<img alt="Zaileys -
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img alt="Zaileys - Simplified WhatsApp Node.js API" src="https://socialify.git.ci/zeative/zaileys/image?description=1&descriptionEditable=Zaileys%20is%20a%20simplified%20version%20of%20the%20Baileys%20package%20%0Awhich%20is%20easier%20and%20faster.&font=KoHo&forks=1&issues=1&language=1&name=1&owner=1&pattern=Circuit%20Board&pulls=1&stargazers=1&theme=Auto">
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
|
-
<h1 align="center">Zaileys -
|
|
6
|
-
|
|
7
|
-
<div align=
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
<h1 align="center">Zaileys - Simplified WhatsApp Node.js API</h1>
|
|
6
|
+
|
|
7
|
+
<div align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/zaileys">
|
|
9
|
+
<img src="https://img.shields.io/npm/v/zaileys.svg" alt="NPM Version">
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/zaileys">
|
|
12
|
+
<img src="https://img.shields.io/npm/dw/zaileys?label=npm&color=%23CB3837" alt="NPM Downloads">
|
|
13
|
+
</a>
|
|
14
|
+
<a href="https://github.com/zeative/zaileys">
|
|
15
|
+
<img src="https://img.shields.io/github/languages/code-size/zeative/zaileys" alt="GitHub Code Size">
|
|
16
|
+
</a>
|
|
17
|
+
<a href="https://github.com/zeative/zaileys">
|
|
18
|
+
<img src="https://img.shields.io/github/license/zeative/zaileys" alt="GitHub License">
|
|
19
|
+
</a>
|
|
20
|
+
<a href="https://github.com/zeative/zaileys">
|
|
21
|
+
<img src="https://img.shields.io/github/stars/zeative/zaileys" alt="GitHub Stars">
|
|
22
|
+
</a>
|
|
23
|
+
<a href="https://github.com/zeative/zaileys">
|
|
24
|
+
<img src="https://img.shields.io/github/forks/zeative/zaileys" alt="GitHub Forks">
|
|
25
|
+
</a>
|
|
16
26
|
</div>
|
|
17
27
|
|
|
18
28
|
> [!NOTE]
|
|
19
|
-
> Join
|
|
29
|
+
> Join our [WhatsApp Channel](https://whatsapp.com/channel/0029VazENbmInlqHIWzgn33h) for updates and support.
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
**Zaileys** is a lightweight, high-performance wrapper around the Baileys library for building WhatsApp bots and integrations using TypeScript or ESM JavaScript. Designed for simplicity, speed, and scalability.
|
|
32
|
+
|
|
33
|
+
> [!WARNING]
|
|
34
|
+
> Pairing code authentication is currently experiencing issues and is not supported. Use QR code authentication instead.
|
|
22
35
|
|
|
23
36
|
## π Table of Contents
|
|
24
37
|
|
|
25
|
-
1. [π Features](
|
|
26
|
-
2. [π» Installation](
|
|
27
|
-
3. [β‘ Quick Start](
|
|
38
|
+
1. [π Features](#features)
|
|
39
|
+
2. [π» Installation](#installation)
|
|
40
|
+
3. [β‘ Quick Start](#quick-start)
|
|
28
41
|
- [Simplify Version](#simplify-version)
|
|
29
|
-
4. [π Core Concepts](
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- [Sending Media](#sending-media)
|
|
37
|
-
- [Presence Update](#presence-update)
|
|
38
|
-
- [Get Profile](#get-profile)
|
|
39
|
-
- [Reject Call](#reject-call)
|
|
40
|
-
8. [π Issues & Feedback](#π-issues--feedback)
|
|
41
|
-
9. [β€οΈ Funding & Support](#β€οΈ-funding--support)
|
|
42
|
-
10. [π License](#π-license)
|
|
43
|
-
11. [π Acknowledgements](#π-acknowledgements)
|
|
42
|
+
4. [π Core Concepts](#core-concepts)
|
|
43
|
+
5. [π’ Event Handling](#event-handling)
|
|
44
|
+
6. [πΎ Worker Actions](#worker-actions)
|
|
45
|
+
7. [π Issues & Feedback](#issues--feedback)
|
|
46
|
+
8. [β€οΈ Support](#support)
|
|
47
|
+
9. [π License](#license)
|
|
48
|
+
10. [π Acknowledgements](#acknowledgements)
|
|
44
49
|
|
|
45
50
|
## π Features
|
|
46
51
|
|
|
47
|
-
- π― **Simplified API**: Minimal
|
|
52
|
+
- π― **Simplified API**: Minimal setup for rapid development.
|
|
48
53
|
- π **Secure Multi-Device**: Full multi-device support via Baileys.
|
|
49
|
-
- βοΈ **Modular
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
54
|
+
- βοΈ **Modular Design**: Extensible with middleware and storage layers.
|
|
55
|
+
- π **QR Code Authentication**: Seamless QR-based login in terminal.
|
|
56
|
+
- π οΈ **TypeScript/ESM Only**: Full type definitions and ESM support.
|
|
57
|
+
- πΎ **Database-Driven**: SQLite, PostgreSQL, or MySQL for session storage.
|
|
53
58
|
|
|
54
59
|
## π» Installation
|
|
55
60
|
|
|
56
|
-
Install
|
|
61
|
+
Install via your preferred package manager:
|
|
57
62
|
|
|
58
63
|
```bash
|
|
59
64
|
npm install zaileys
|
|
@@ -61,293 +66,207 @@ npm install zaileys
|
|
|
61
66
|
yarn add zaileys
|
|
62
67
|
# or
|
|
63
68
|
pnpm add zaileys
|
|
64
|
-
|
|
65
|
-
# just install, don't run with these runtime
|
|
66
|
-
bun add zaileys
|
|
67
|
-
deno add npm:zaileys
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
>
|
|
71
|
+
> [!IMPORTANT]
|
|
71
72
|
>
|
|
72
|
-
> -
|
|
73
|
-
> -
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
> - Requires **Node.js >= 18**.
|
|
74
|
+
> - Only supports **ESM** and **TypeScript** (no CommonJS).
|
|
75
|
+
> - QR code authentication only (pairing code not supported).
|
|
76
|
+
> - Deno and Bun are not supported at runtime due to `better-sqlite3` incompatibility.
|
|
76
77
|
|
|
77
78
|
## β‘ Quick Start
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
For a complete example, see [`/test/example.ts`](https://github.com/zeative/zaileys/blob/main/test/example.ts).
|
|
80
81
|
|
|
81
82
|
```ts
|
|
82
|
-
// cjs
|
|
83
|
-
// const { Client } = require("zaileys");
|
|
84
|
-
|
|
85
|
-
// esm
|
|
86
83
|
import { Client } from "zaileys";
|
|
87
84
|
|
|
88
|
-
// the configuration below is the default
|
|
89
85
|
const wa = new Client({
|
|
90
|
-
prefix: "/", //
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
autoOnline: true, // automatically set status to online
|
|
97
|
-
autoRead: true, // automatically mark messages as read
|
|
98
|
-
autoPresence: true, // manage presence updates 'typing' or 'recording'
|
|
99
|
-
autoRejectCall: true, // automatically reject incoming calls
|
|
86
|
+
prefix: "/", // Command prefix
|
|
87
|
+
ignoreMe: true, // Ignore bot's own messages
|
|
88
|
+
autoRead: true, // Auto-mark messages as read
|
|
89
|
+
autoOnline: true, // Auto-set status to online
|
|
90
|
+
autoPresence: true, // Auto-manage presence (typing/recording)
|
|
91
|
+
autoRejectCall: true, // Auto-reject incoming calls
|
|
100
92
|
database: {
|
|
101
|
-
type: "sqlite",
|
|
93
|
+
type: "sqlite",
|
|
102
94
|
connection: { url: "./session/zaileys.db" },
|
|
103
95
|
},
|
|
104
|
-
citation: {
|
|
105
|
-
// your own keys; will generate ctx.citation.is<Key> booleans
|
|
106
|
-
author: async () => {
|
|
107
|
-
// const res = await fetch(...)
|
|
108
|
-
return [628123456789];
|
|
109
|
-
},
|
|
110
|
-
myGroup: () => [120099],
|
|
111
|
-
vipUsers: () => [628123456789],
|
|
112
|
-
},
|
|
113
96
|
});
|
|
114
97
|
|
|
115
|
-
// Connection updates
|
|
116
|
-
wa.on("connection", (ctx) => {
|
|
117
|
-
//
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// Message events
|
|
121
98
|
wa.on("messages", async (ctx) => {
|
|
122
|
-
// Example: checking generated flags
|
|
123
|
-
if (!ctx.citation?.isAuthor) return;
|
|
124
|
-
if (ctx.citation.isVipUsers) {
|
|
125
|
-
// VIP handling
|
|
126
|
-
}
|
|
127
|
-
|
|
128
99
|
if (ctx.text === "test") {
|
|
129
|
-
wa.text("
|
|
100
|
+
await wa.text("Hello!", { roomId: ctx.roomId });
|
|
130
101
|
}
|
|
131
102
|
});
|
|
132
103
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
//
|
|
104
|
+
wa.on("connection", (ctx) => {
|
|
105
|
+
console.log("Connection status:", ctx.status);
|
|
136
106
|
});
|
|
137
107
|
```
|
|
138
108
|
|
|
139
109
|
### Simplify Version
|
|
140
110
|
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
const wa = new Client({
|
|
144
|
-
phoneNumber: 628123456789,
|
|
145
|
-
authType: "pairing",
|
|
146
|
-
});
|
|
111
|
+
```ts
|
|
112
|
+
import { Client } from "zaileys";
|
|
147
113
|
|
|
148
|
-
// auth with qr
|
|
149
114
|
const wa = new Client({
|
|
150
115
|
authType: "qr",
|
|
151
116
|
});
|
|
152
117
|
|
|
153
118
|
wa.on("messages", (ctx) => {
|
|
154
|
-
wa.
|
|
119
|
+
wa.text("Hello", { roomId: ctx.roomId });
|
|
155
120
|
});
|
|
156
121
|
```
|
|
157
122
|
|
|
158
|
-
## π Examples
|
|
159
|
-
|
|
160
|
-
Refer to [`test/example.ts`](https://github.com/zeative/zaileys/blob/main/test/example.ts) for complete example usage.
|
|
161
|
-
|
|
162
123
|
## π Core Concepts
|
|
163
124
|
|
|
164
125
|
### Sessions & Authentication
|
|
165
126
|
|
|
166
|
-
Zaileys
|
|
167
|
-
|
|
168
|
-
- **Unified Storage**: Store session data and authentication credentials in a single, structured database, enabling easy backup, migration, and scalability.
|
|
169
|
-
- **Flexible Data Management**: Query and manage session data directly via SQL, allowing custom integrations and advanced use cases.
|
|
127
|
+
Zaileys uses QR code authentication and stores session data in a database (SQLite, PostgreSQL, or MySQL) for seamless reconnections without repeated QR scans.
|
|
170
128
|
|
|
171
|
-
|
|
129
|
+
```ts
|
|
130
|
+
import { Client } from "zaileys";
|
|
172
131
|
|
|
173
|
-
```js
|
|
174
132
|
const wa = new Client({
|
|
175
133
|
database: {
|
|
176
|
-
type: "sqlite",
|
|
177
|
-
connection: { url: "./session/zaileys.db" },
|
|
134
|
+
type: "sqlite",
|
|
135
|
+
connection: { url: "./session/zaileys.db" },
|
|
178
136
|
},
|
|
179
137
|
});
|
|
180
138
|
```
|
|
181
139
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
Zaileys provides a flexible **citation** mechanism. Define any metadata provider functions under the `citation` option. Each key will automatically generate a boolean on `ctx.citation`, prefixed with `is` and formatted in camelCase.
|
|
140
|
+
### Citation Mechanism
|
|
185
141
|
|
|
186
|
-
|
|
142
|
+
Define custom metadata providers in the `citation` option. Each key generates a boolean on `ctx.citation` (e.g., `isKeyName`).
|
|
187
143
|
|
|
188
144
|
```ts
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
Results in:
|
|
198
|
-
|
|
199
|
-
- `ctx.citation.isAuthorAsync`
|
|
200
|
-
- `ctx.citation.isVipList`
|
|
201
|
-
|
|
202
|
-
Use them in handlers:
|
|
145
|
+
const wa = new Client({
|
|
146
|
+
citation: {
|
|
147
|
+
admins: async () => [628123456789],
|
|
148
|
+
vips: () => [628123456789],
|
|
149
|
+
},
|
|
150
|
+
});
|
|
203
151
|
|
|
204
|
-
```ts
|
|
205
152
|
wa.on("messages", (ctx) => {
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
// VIP logic
|
|
153
|
+
if (ctx.citation?.isAdmins) {
|
|
154
|
+
wa.text("Admin access granted", { roomId: ctx.roomId });
|
|
209
155
|
}
|
|
210
156
|
});
|
|
211
157
|
```
|
|
212
158
|
|
|
213
159
|
## π’ Event Handling
|
|
214
160
|
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
|
|
161
|
+
```ts
|
|
162
|
+
wa.on("connection", (ctx) => {
|
|
163
|
+
console.log("Connection:", ctx.status);
|
|
164
|
+
});
|
|
218
165
|
|
|
219
|
-
|
|
220
|
-
|
|
166
|
+
wa.on("messages", (ctx) => {
|
|
167
|
+
console.log("Message:", ctx.text);
|
|
168
|
+
});
|
|
221
169
|
|
|
222
|
-
|
|
223
|
-
wa.
|
|
170
|
+
wa.on("calls", (ctx) => {
|
|
171
|
+
wa.rejectCall(ctx);
|
|
172
|
+
});
|
|
224
173
|
```
|
|
225
174
|
|
|
226
175
|
## πΎ Worker Actions
|
|
227
176
|
|
|
228
177
|
### Sending Messages
|
|
229
178
|
|
|
230
|
-
```
|
|
179
|
+
```ts
|
|
231
180
|
const roomId = ctx.roomId;
|
|
232
181
|
const message = ctx.message;
|
|
233
182
|
|
|
234
|
-
|
|
235
|
-
wa.text("
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
wa.text("
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
wa.text("
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
wa.
|
|
245
|
-
|
|
246
|
-
// also combine verified number and forwarded
|
|
247
|
-
wa.text("Test verified reply", { roomId, quoted: message, verifiedReply: "meta", asForwarded: true });
|
|
248
|
-
|
|
249
|
-
// sending view once message
|
|
250
|
-
// support: image, video, audio
|
|
251
|
-
wa.text({ image: "https://github.com/zaadevofc.png", text: "Test view once" }, { roomId, asViewOnce: true });
|
|
252
|
-
|
|
253
|
-
// sending reaction message
|
|
254
|
-
// empty string for removing reaction
|
|
255
|
-
wa.reaction("π", { message });
|
|
256
|
-
|
|
257
|
-
// editing message
|
|
258
|
-
const msg1 = await wa.text("Test edit", { roomId });
|
|
259
|
-
wa.edit("Editing success", { message: msg1?.message });
|
|
260
|
-
|
|
261
|
-
// deleting message
|
|
262
|
-
const msg2 = await wa.text("Test delete", { roomId });
|
|
263
|
-
wa.delete("Deleting success", { message: msg2?.message });
|
|
264
|
-
|
|
265
|
-
// sending location message
|
|
266
|
-
wa.location({ latitude: 24.121231, longitude: 55.1121221, ...other }, { roomId });
|
|
267
|
-
|
|
268
|
-
// sending contact message
|
|
269
|
-
wa.contact({ fullname: "Kejaa", whatsAppNumber: 628123456789, ...other }, { roomId });
|
|
270
|
-
|
|
271
|
-
// sending polling message
|
|
272
|
-
wa.poll({ name: "Are you love me?", answers: ["yes", "maybe", "no"] }, { roomId });
|
|
183
|
+
wa.text("Hello", { roomId });
|
|
184
|
+
wa.text("Reply", { roomId, quoted: message });
|
|
185
|
+
wa.text("Forwarded", { roomId, asForwarded: true });
|
|
186
|
+
wa.text("Verified reply", { roomId, quoted: message, verifiedReply: "whatsapp" });
|
|
187
|
+
wa.text({ image: "https://example.com/image.png", text: "View once" }, { roomId, asViewOnce: true });
|
|
188
|
+
wa.reaction("π", { message });
|
|
189
|
+
wa.edit("Edited", { message: await wa.text("Original", { roomId })?.message });
|
|
190
|
+
wa.delete("Deleted", { message: await wa.text("To delete", { roomId })?.message });
|
|
191
|
+
wa.location({ latitude: 24.121231, longitude: 55.1121221 }, { roomId });
|
|
192
|
+
wa.contact({ fullname: "Kejaa", whatsAppNumber: 628123456789 }, { roomId });
|
|
193
|
+
wa.poll({ name: "Do you love me?", answers: ["Yes", "Maybe", "No"] }, { roomId });
|
|
273
194
|
```
|
|
274
195
|
|
|
275
196
|
### Sending Media
|
|
276
197
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
198
|
+
Supports URLs and local files (via Buffer).
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import fs from "fs";
|
|
202
|
+
|
|
203
|
+
// Image (URL or file)
|
|
204
|
+
wa.text({ image: "https://example.com/image.png", text: "Image" }, { roomId });
|
|
205
|
+
wa.text({ image: fs.readFileSync("example/image.png"), text: "Image" }, { roomId });
|
|
282
206
|
|
|
283
|
-
//
|
|
284
|
-
wa.text({ sticker: "https://
|
|
207
|
+
// Sticker
|
|
208
|
+
wa.text({ sticker: "https://example.com/sticker.png" }, { roomId });
|
|
209
|
+
wa.text({ sticker: fs.readFileSync("example/sticker.png") }, { roomId });
|
|
285
210
|
|
|
286
|
-
//
|
|
287
|
-
wa.text({ gif: "https://
|
|
211
|
+
// GIF
|
|
212
|
+
wa.text({ gif: "https://example.com/video.mp4" }, { roomId });
|
|
213
|
+
wa.text({ gif: fs.readFileSync("example/video.mp4") }, { roomId });
|
|
288
214
|
|
|
289
|
-
//
|
|
290
|
-
wa.text({ video: "https://
|
|
215
|
+
// Video
|
|
216
|
+
wa.text({ video: "https://example.com/video.mp4", text: "Video" }, { roomId });
|
|
217
|
+
wa.text({ video: fs.readFileSync("example/video.mp4"), text: "Video" }, { roomId });
|
|
291
218
|
|
|
292
|
-
//
|
|
293
|
-
wa.text({ videoNote: "https://
|
|
219
|
+
// Video Note
|
|
220
|
+
wa.text({ videoNote: "https://example.com/video.mp4" }, { roomId });
|
|
221
|
+
wa.text({ videoNote: fs.readFileSync("example/video.mp4") }, { roomId });
|
|
294
222
|
|
|
295
|
-
//
|
|
296
|
-
|
|
297
|
-
wa.text({ audio: "
|
|
223
|
+
// Audio (use .ogg for better compatibility)
|
|
224
|
+
wa.text({ audio: "https://example.com/audio.ogg" }, { roomId });
|
|
225
|
+
wa.text({ audio: fs.readFileSync("example/audio.ogg") }, { roomId });
|
|
298
226
|
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
wa.text({ audioNote: "
|
|
227
|
+
// Voice Note (use .ogg for better compatibility)
|
|
228
|
+
wa.text({ audioNote: "https://example.com/audio.ogg" }, { roomId });
|
|
229
|
+
wa.text({ audioNote: fs.readFileSync("example/audio.ogg") }, { roomId });
|
|
302
230
|
```
|
|
303
231
|
|
|
304
232
|
### Presence Update
|
|
305
233
|
|
|
306
|
-
```
|
|
307
|
-
//
|
|
308
|
-
// typing | recording | online | offline | paused
|
|
309
|
-
wa.presence("typing", { roomId });
|
|
234
|
+
```ts
|
|
235
|
+
wa.presence("typing", { roomId }); // Options: typing, recording, online, offline, paused
|
|
310
236
|
```
|
|
311
237
|
|
|
312
238
|
### Get Profile
|
|
313
239
|
|
|
314
|
-
```
|
|
315
|
-
//
|
|
316
|
-
wa.profile("
|
|
317
|
-
|
|
318
|
-
// get group profile
|
|
319
|
-
wa.profile("1209999@g.us");
|
|
240
|
+
```ts
|
|
241
|
+
wa.profile("628123456789@s.whatsapp.net"); // User profile
|
|
242
|
+
wa.profile("1209999@g.us"); // Group profile
|
|
320
243
|
```
|
|
321
244
|
|
|
322
245
|
### Reject Call
|
|
323
246
|
|
|
324
|
-
```
|
|
247
|
+
```ts
|
|
325
248
|
wa.on("calls", (ctx) => {
|
|
326
249
|
wa.rejectCall({ callId: ctx.callId, callerId: ctx.callerId });
|
|
327
|
-
|
|
328
|
-
// for simplify
|
|
329
|
-
wa.rejectCall(ctx);
|
|
330
250
|
});
|
|
331
251
|
```
|
|
332
252
|
|
|
333
253
|
## π Issues & Feedback
|
|
334
254
|
|
|
335
|
-
|
|
336
|
-
[https://github.com/zeative/zaileys/issues](https://github.com/zeative/zaileys/issues)
|
|
255
|
+
Report issues or request features at [GitHub Issues](https://github.com/zeative/zaileys/issues).
|
|
337
256
|
|
|
338
|
-
## β€οΈ
|
|
257
|
+
## β€οΈ Support
|
|
339
258
|
|
|
340
|
-
|
|
259
|
+
Support the project:
|
|
341
260
|
|
|
342
261
|
- [Buy me a coffee β](https://saweria.co/zaadevofc)
|
|
343
|
-
- β Star the repo on GitHub
|
|
262
|
+
- β Star the repo on [GitHub](https://github.com/zeative/zaileys).
|
|
344
263
|
|
|
345
264
|
## π License
|
|
346
265
|
|
|
347
|
-
|
|
266
|
+
[MIT License](https://github.com/zeative/zaileys/blob/main/LICENSE).
|
|
348
267
|
|
|
349
268
|
## π Acknowledgements
|
|
350
269
|
|
|
351
|
-
|
|
270
|
+
Built on [Baileys](https://github.com/WhiskeySockets/Baileys) by Whiskey Sockets.
|
|
352
271
|
|
|
353
272
|
> Happy coding! π
|