miaw-core 0.9.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/CHANGELOG.md +305 -0
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/USAGE.md +1399 -0
- package/babel.config.js +5 -0
- package/dist/client/MiawClient.d.ts +580 -0
- package/dist/client/MiawClient.d.ts.map +1 -0
- package/dist/client/MiawClient.js +2637 -0
- package/dist/client/MiawClient.js.map +1 -0
- package/dist/handlers/AuthHandler.d.ts +21 -0
- package/dist/handlers/AuthHandler.d.ts.map +1 -0
- package/dist/handlers/AuthHandler.js +30 -0
- package/dist/handlers/AuthHandler.js.map +1 -0
- package/dist/handlers/MessageHandler.d.ts +45 -0
- package/dist/handlers/MessageHandler.d.ts.map +1 -0
- package/dist/handlers/MessageHandler.js +185 -0
- package/dist/handlers/MessageHandler.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +632 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +44 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/storage.d.ts +25 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +60 -0
- package/dist/utils/storage.js.map +1 -0
- package/package.json +44 -0
- package/tsconfig.json +24 -0
- package/tsconfig.test.json +13 -0
package/USAGE.md
ADDED
|
@@ -0,0 +1,1399 @@
|
|
|
1
|
+
# Miaw Core - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document covers all current capabilities of Miaw Core. It will be updated as new features are added.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Configuration](#configuration)
|
|
10
|
+
- [Authentication](#authentication)
|
|
11
|
+
- [Sending Messages](#sending-messages)
|
|
12
|
+
- [Advanced Messaging](#advanced-messaging)
|
|
13
|
+
- [Group Management](#group-management)
|
|
14
|
+
- [Profile Management](#profile-management)
|
|
15
|
+
- [Business & Social Features](#business--social-features-v090)
|
|
16
|
+
- [Receiving Messages](#receiving-messages)
|
|
17
|
+
- [Connection Management](#connection-management)
|
|
18
|
+
- [Multiple Instances](#multiple-instances)
|
|
19
|
+
- [Session Management](#session-management)
|
|
20
|
+
- [Event Reference](#event-reference)
|
|
21
|
+
- [Error Handling](#error-handling)
|
|
22
|
+
- [TypeScript Usage](#typescript-usage)
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install miaw-core
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
Here's a minimal example to get started:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { MiawClient } from "miaw-core";
|
|
36
|
+
|
|
37
|
+
// Create client
|
|
38
|
+
const client = new MiawClient({
|
|
39
|
+
instanceId: "my-bot",
|
|
40
|
+
sessionPath: "./sessions",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Handle QR code
|
|
44
|
+
client.on("qr", (qr) => {
|
|
45
|
+
console.log("Scan this QR code:", qr);
|
|
46
|
+
// Display QR code for WhatsApp scanning
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// When ready
|
|
50
|
+
client.on("ready", () => {
|
|
51
|
+
console.log("Bot is ready!");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Receive messages
|
|
55
|
+
client.on("message", async (message) => {
|
|
56
|
+
console.log("Received:", message.text);
|
|
57
|
+
|
|
58
|
+
// Reply
|
|
59
|
+
await client.sendText(message.from, "Hello!");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Start
|
|
63
|
+
await client.connect();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
### MiawClientOptions
|
|
69
|
+
|
|
70
|
+
When creating a client, you can configure these options:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const client = new MiawClient({
|
|
74
|
+
// Required
|
|
75
|
+
instanceId: "unique-bot-id",
|
|
76
|
+
|
|
77
|
+
// Optional
|
|
78
|
+
sessionPath: "./sessions", // Default: './sessions'
|
|
79
|
+
debug: true, // Default: false
|
|
80
|
+
autoReconnect: true, // Default: true
|
|
81
|
+
maxReconnectAttempts: 10, // Default: Infinity
|
|
82
|
+
reconnectDelay: 5000, // Default: 3000 (ms)
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Configuration Options:**
|
|
87
|
+
|
|
88
|
+
| Option | Type | Default | Description |
|
|
89
|
+
| ---------------------- | --------- | -------------- | --------------------------------------------------- |
|
|
90
|
+
| `instanceId` | `string` | _required_ | Unique identifier for this WhatsApp instance |
|
|
91
|
+
| `sessionPath` | `string` | `'./sessions'` | Directory path where session data will be stored |
|
|
92
|
+
| `debug` | `boolean` | `false` | Enable verbose logging |
|
|
93
|
+
| `autoReconnect` | `boolean` | `true` | Auto-reconnect on connection loss |
|
|
94
|
+
| `maxReconnectAttempts` | `number` | `Infinity` | Maximum reconnection attempts |
|
|
95
|
+
| `reconnectDelay` | `number` | `3000` | Delay between reconnection attempts in milliseconds |
|
|
96
|
+
|
|
97
|
+
## Authentication
|
|
98
|
+
|
|
99
|
+
### QR Code Authentication
|
|
100
|
+
|
|
101
|
+
On first connection, WhatsApp requires QR code scanning:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
client.on("qr", (qr) => {
|
|
105
|
+
console.log("QR Code:", qr);
|
|
106
|
+
|
|
107
|
+
// For terminal display, install qrcode-terminal:
|
|
108
|
+
// npm install qrcode-terminal
|
|
109
|
+
// import qrcode from 'qrcode-terminal';
|
|
110
|
+
// qrcode.generate(qr, { small: true });
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Session Persistence
|
|
115
|
+
|
|
116
|
+
After first authentication, the session is automatically saved and reused:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// First run: QR code required
|
|
120
|
+
await client.connect(); // Will emit 'qr' event
|
|
121
|
+
|
|
122
|
+
// Subsequent runs: No QR code needed
|
|
123
|
+
await client.connect(); // Uses saved session
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Sessions are stored in: `{sessionPath}/{instanceId}/`
|
|
127
|
+
|
|
128
|
+
### Logout
|
|
129
|
+
|
|
130
|
+
To logout and clear session:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
await client.disconnect();
|
|
134
|
+
// Then manually delete: ./sessions/{instanceId}/
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Sending Messages
|
|
138
|
+
|
|
139
|
+
### Send Text Message
|
|
140
|
+
|
|
141
|
+
Basic text message sending:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const result = await client.sendText(
|
|
145
|
+
"1234567890@s.whatsapp.net",
|
|
146
|
+
"Hello, World!"
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
if (result.success) {
|
|
150
|
+
console.log("Message sent! ID:", result.messageId);
|
|
151
|
+
} else {
|
|
152
|
+
console.error("Failed to send:", result.error);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Phone Number Formatting
|
|
157
|
+
|
|
158
|
+
You can use phone numbers or WhatsApp JIDs:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// Both formats work:
|
|
162
|
+
await client.sendText("1234567890", "Hello");
|
|
163
|
+
await client.sendText("1234567890@s.whatsapp.net", "Hello");
|
|
164
|
+
|
|
165
|
+
// Group messages:
|
|
166
|
+
await client.sendText("123456789@g.us", "Hello group!");
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Send to Groups
|
|
170
|
+
|
|
171
|
+
Same API for individual and group chats:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// Send to group (use group JID)
|
|
175
|
+
await client.sendText("123456789@g.us", "Hello everyone!");
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Advanced Messaging
|
|
179
|
+
|
|
180
|
+
### Send Reactions
|
|
181
|
+
|
|
182
|
+
React to messages with emojis:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
client.on("message", async (msg) => {
|
|
186
|
+
// React to the message with a heart
|
|
187
|
+
const result = await client.sendReaction(msg, "❤️");
|
|
188
|
+
|
|
189
|
+
if (result.success) {
|
|
190
|
+
console.log("Reaction sent!");
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Other common reactions
|
|
195
|
+
await client.sendReaction(msg, "👍"); // Thumbs up
|
|
196
|
+
await client.sendReaction(msg, "😂"); // Laughing
|
|
197
|
+
await client.sendReaction(msg, "😮"); // Surprised
|
|
198
|
+
await client.sendReaction(msg, "😢"); // Sad
|
|
199
|
+
await client.sendReaction(msg, "🙏"); // Pray/Thanks
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Remove Reactions
|
|
203
|
+
|
|
204
|
+
Remove your reaction from a message:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Remove reaction (sends empty string)
|
|
208
|
+
await client.removeReaction(msg);
|
|
209
|
+
|
|
210
|
+
// Or equivalently:
|
|
211
|
+
await client.sendReaction(msg, "");
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Forward Messages
|
|
215
|
+
|
|
216
|
+
Forward a message to another chat:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
client.on("message", async (msg) => {
|
|
220
|
+
// Forward this message to another contact
|
|
221
|
+
const result = await client.forwardMessage(msg, "0987654321");
|
|
222
|
+
|
|
223
|
+
if (result.success) {
|
|
224
|
+
console.log("Message forwarded!");
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Forward to a group
|
|
229
|
+
await client.forwardMessage(msg, "123456789@g.us");
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Edit Messages
|
|
233
|
+
|
|
234
|
+
Edit your own sent messages (within WhatsApp's 15-minute window):
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// Send a message and keep the reference
|
|
238
|
+
const result = await client.sendText("1234567890", "Hello, Wordl!");
|
|
239
|
+
|
|
240
|
+
// Later, fix the typo by editing
|
|
241
|
+
// Note: You need to store/retrieve the sent message object
|
|
242
|
+
client.on("message", async (msg) => {
|
|
243
|
+
if (msg.fromMe && msg.text === "Hello, Wordl!") {
|
|
244
|
+
await client.editMessage(msg, "Hello, World!");
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Important:** You can only edit your own messages (`fromMe: true`).
|
|
250
|
+
|
|
251
|
+
### Delete Messages
|
|
252
|
+
|
|
253
|
+
Delete messages for everyone:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
client.on("message", async (msg) => {
|
|
257
|
+
// Delete this message for everyone
|
|
258
|
+
const result = await client.deleteMessage(msg);
|
|
259
|
+
|
|
260
|
+
if (result.success) {
|
|
261
|
+
console.log("Message deleted for everyone!");
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Delete messages only for yourself:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Delete message locally (others still see it)
|
|
270
|
+
const success = await client.deleteMessageForMe(msg);
|
|
271
|
+
|
|
272
|
+
// Optionally, also delete associated media files
|
|
273
|
+
await client.deleteMessageForMe(msg, true); // deleteMedia = true (default)
|
|
274
|
+
await client.deleteMessageForMe(msg, false); // keep media files
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Auto-React Bot Example
|
|
278
|
+
|
|
279
|
+
Bot that automatically reacts to messages:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
client.on("message", async (msg) => {
|
|
283
|
+
if (msg.fromMe) return;
|
|
284
|
+
|
|
285
|
+
// React based on keywords
|
|
286
|
+
const text = msg.text?.toLowerCase() || "";
|
|
287
|
+
|
|
288
|
+
if (text.includes("thank")) {
|
|
289
|
+
await client.sendReaction(msg, "🙏");
|
|
290
|
+
} else if (text.includes("love")) {
|
|
291
|
+
await client.sendReaction(msg, "❤️");
|
|
292
|
+
} else if (text.includes("funny") || text.includes("lol")) {
|
|
293
|
+
await client.sendReaction(msg, "😂");
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Group Management
|
|
299
|
+
|
|
300
|
+
Full group administration capabilities for creating and managing WhatsApp groups.
|
|
301
|
+
|
|
302
|
+
### Create Group
|
|
303
|
+
|
|
304
|
+
Create a new WhatsApp group:
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const result = await client.createGroup("My New Group", [
|
|
308
|
+
"1234567890", // Phone number
|
|
309
|
+
"0987654321",
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
if (result.success) {
|
|
313
|
+
console.log("Group created:", result.groupJid);
|
|
314
|
+
console.log("Group name:", result.groupInfo?.name);
|
|
315
|
+
console.log("Participants:", result.groupInfo?.participantCount);
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Add Participants
|
|
320
|
+
|
|
321
|
+
Add members to an existing group (requires admin):
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
const results = await client.addParticipants("123456789@g.us", [
|
|
325
|
+
"1234567890",
|
|
326
|
+
"0987654321",
|
|
327
|
+
]);
|
|
328
|
+
|
|
329
|
+
for (const result of results) {
|
|
330
|
+
if (result.success) {
|
|
331
|
+
console.log(`Added: ${result.jid}`);
|
|
332
|
+
} else {
|
|
333
|
+
console.log(`Failed to add ${result.jid}: ${result.status}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Remove Participants
|
|
339
|
+
|
|
340
|
+
Remove members from a group (requires admin):
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
const results = await client.removeParticipants("123456789@g.us", [
|
|
344
|
+
"1234567890",
|
|
345
|
+
]);
|
|
346
|
+
|
|
347
|
+
results.forEach((r) => console.log(`${r.jid}: ${r.success ? "Removed" : r.status}`));
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Leave Group
|
|
351
|
+
|
|
352
|
+
Leave a group:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
const result = await client.leaveGroup("123456789@g.us");
|
|
356
|
+
if (result.success) {
|
|
357
|
+
console.log("Left the group");
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Promote/Demote Admins
|
|
362
|
+
|
|
363
|
+
Manage group admin roles:
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// Promote member to admin
|
|
367
|
+
const promoteResults = await client.promoteToAdmin("123456789@g.us", [
|
|
368
|
+
"1234567890",
|
|
369
|
+
]);
|
|
370
|
+
|
|
371
|
+
// Demote admin to member
|
|
372
|
+
const demoteResults = await client.demoteFromAdmin("123456789@g.us", [
|
|
373
|
+
"1234567890",
|
|
374
|
+
]);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Update Group Name
|
|
378
|
+
|
|
379
|
+
Change the group name/subject:
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
const result = await client.updateGroupName("123456789@g.us", "New Group Name");
|
|
383
|
+
if (result.success) {
|
|
384
|
+
console.log("Group name updated");
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Update Group Description
|
|
389
|
+
|
|
390
|
+
Set or clear group description:
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Set description
|
|
394
|
+
await client.updateGroupDescription(
|
|
395
|
+
"123456789@g.us",
|
|
396
|
+
"Welcome to our group! Please read the rules."
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
// Clear description (pass undefined)
|
|
400
|
+
await client.updateGroupDescription("123456789@g.us");
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Update Group Picture
|
|
404
|
+
|
|
405
|
+
Change the group profile picture:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
// From file path
|
|
409
|
+
await client.updateGroupPicture("123456789@g.us", "./group-icon.jpg");
|
|
410
|
+
|
|
411
|
+
// From URL
|
|
412
|
+
await client.updateGroupPicture("123456789@g.us", "https://example.com/image.jpg");
|
|
413
|
+
|
|
414
|
+
// From Buffer
|
|
415
|
+
const imageBuffer = fs.readFileSync("./image.png");
|
|
416
|
+
await client.updateGroupPicture("123456789@g.us", imageBuffer);
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Group Invite Links
|
|
420
|
+
|
|
421
|
+
Manage group invite links:
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
// Get invite link
|
|
425
|
+
const link = await client.getGroupInviteLink("123456789@g.us");
|
|
426
|
+
console.log("Invite link:", link);
|
|
427
|
+
// Output: https://chat.whatsapp.com/AbCdEfGhIjK
|
|
428
|
+
|
|
429
|
+
// Revoke current link and get new one
|
|
430
|
+
const newLink = await client.revokeGroupInvite("123456789@g.us");
|
|
431
|
+
console.log("New invite link:", newLink);
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Join Group via Invite
|
|
435
|
+
|
|
436
|
+
Accept a group invitation:
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
// Accept with full URL
|
|
440
|
+
const groupJid = await client.acceptGroupInvite(
|
|
441
|
+
"https://chat.whatsapp.com/AbCdEfGhIjK"
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
// Or just the code
|
|
445
|
+
const groupJid2 = await client.acceptGroupInvite("AbCdEfGhIjK");
|
|
446
|
+
|
|
447
|
+
if (groupJid) {
|
|
448
|
+
console.log("Joined group:", groupJid);
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Preview Group from Invite
|
|
453
|
+
|
|
454
|
+
Get group info before joining:
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
const info = await client.getGroupInviteInfo("AbCdEfGhIjK");
|
|
458
|
+
|
|
459
|
+
if (info) {
|
|
460
|
+
console.log("Group name:", info.name);
|
|
461
|
+
console.log("Description:", info.description);
|
|
462
|
+
console.log("Members:", info.participantCount);
|
|
463
|
+
console.log("Created:", new Date(info.createdAt! * 1000));
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Group Admin Bot Example
|
|
468
|
+
|
|
469
|
+
Bot that manages group membership:
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
client.on("message", async (msg) => {
|
|
473
|
+
if (!msg.isGroup || msg.fromMe) return;
|
|
474
|
+
|
|
475
|
+
const command = msg.text?.toLowerCase();
|
|
476
|
+
const groupJid = msg.from;
|
|
477
|
+
|
|
478
|
+
if (command === "!invite") {
|
|
479
|
+
const link = await client.getGroupInviteLink(groupJid);
|
|
480
|
+
await client.sendText(groupJid, `Join link: ${link}`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (command === "!groupinfo") {
|
|
484
|
+
const info = await client.getGroupInfo(groupJid);
|
|
485
|
+
if (info) {
|
|
486
|
+
await client.sendText(
|
|
487
|
+
groupJid,
|
|
488
|
+
`Group: ${info.name}\nMembers: ${info.participantCount}\nDescription: ${info.description || "None"}`
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Profile Management
|
|
496
|
+
|
|
497
|
+
Customize your bot's WhatsApp profile.
|
|
498
|
+
|
|
499
|
+
### Update Profile Picture
|
|
500
|
+
|
|
501
|
+
Change your profile picture:
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
// From file path
|
|
505
|
+
const result = await client.updateProfilePicture("./my-avatar.jpg");
|
|
506
|
+
|
|
507
|
+
// From URL
|
|
508
|
+
const result2 = await client.updateProfilePicture("https://example.com/avatar.jpg");
|
|
509
|
+
|
|
510
|
+
// From Buffer
|
|
511
|
+
const imageBuffer = fs.readFileSync("./avatar.png");
|
|
512
|
+
const result3 = await client.updateProfilePicture(imageBuffer);
|
|
513
|
+
|
|
514
|
+
if (result.success) {
|
|
515
|
+
console.log("Profile picture updated!");
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Remove Profile Picture
|
|
520
|
+
|
|
521
|
+
Remove your profile picture:
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
const result = await client.removeProfilePicture();
|
|
525
|
+
|
|
526
|
+
if (result.success) {
|
|
527
|
+
console.log("Profile picture removed");
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Update Profile Name
|
|
532
|
+
|
|
533
|
+
Change your display name (push name):
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
const result = await client.updateProfileName("My Bot Name");
|
|
537
|
+
|
|
538
|
+
if (result.success) {
|
|
539
|
+
console.log("Profile name updated!");
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Update Profile Status
|
|
544
|
+
|
|
545
|
+
Change your "About" text:
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
const result = await client.updateProfileStatus("Powered by Miaw Core 🤖");
|
|
549
|
+
|
|
550
|
+
if (result.success) {
|
|
551
|
+
console.log("Profile status updated!");
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// Clear status
|
|
555
|
+
await client.updateProfileStatus("");
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Profile Bot Example
|
|
559
|
+
|
|
560
|
+
Bot that updates its profile based on commands:
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
client.on("message", async (msg) => {
|
|
564
|
+
if (msg.fromMe) return; // Ignore own messages
|
|
565
|
+
|
|
566
|
+
const text = msg.text?.toLowerCase();
|
|
567
|
+
|
|
568
|
+
if (text === "!setstatus online") {
|
|
569
|
+
await client.updateProfileStatus("🟢 Online and ready to help!");
|
|
570
|
+
await client.sendText(msg.from, "Status updated to online!");
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (text === "!setstatus busy") {
|
|
574
|
+
await client.updateProfileStatus("🔴 Busy - response may be delayed");
|
|
575
|
+
await client.sendText(msg.from, "Status updated to busy!");
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
## Business & Social Features (v0.9.0)
|
|
581
|
+
|
|
582
|
+
This section covers WhatsApp Business features (labels, catalog/products) and social features (newsletters/channels, contacts).
|
|
583
|
+
|
|
584
|
+
> **Note:** Label and Catalog/Product features require a **WhatsApp Business account**.
|
|
585
|
+
|
|
586
|
+
### Label Operations (WhatsApp Business Only)
|
|
587
|
+
|
|
588
|
+
Labels help organize chats and messages. WhatsApp Business provides 20 label colors and 5 predefined labels.
|
|
589
|
+
|
|
590
|
+
#### Create/Edit a Label
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
import { LabelColor } from "miaw-core";
|
|
594
|
+
|
|
595
|
+
const result = await client.addLabel({
|
|
596
|
+
id: "vip-customers",
|
|
597
|
+
name: "VIP Customers",
|
|
598
|
+
color: LabelColor.Color5,
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
if (result.success) {
|
|
602
|
+
console.log("Label created:", result.labelId);
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
#### Add Label to Chat
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
const result = await client.addChatLabel("6281234567890", "label-id");
|
|
610
|
+
|
|
611
|
+
if (result.success) {
|
|
612
|
+
console.log("Label added to chat");
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
#### Remove Label from Chat
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
const result = await client.removeChatLabel("6281234567890", "label-id");
|
|
620
|
+
|
|
621
|
+
if (result.success) {
|
|
622
|
+
console.log("Label removed from chat");
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
#### Add/Remove Label from Message
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
// Add label to message
|
|
630
|
+
await client.addMessageLabel("6281234567890", "message-id", "label-id");
|
|
631
|
+
|
|
632
|
+
// Remove label from message
|
|
633
|
+
await client.removeMessageLabel("6281234567890", "message-id", "label-id");
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Catalog/Product Operations (WhatsApp Business Only)
|
|
637
|
+
|
|
638
|
+
Manage your product catalog and inventory.
|
|
639
|
+
|
|
640
|
+
#### Get Product Catalog
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
const catalog = await client.getCatalog();
|
|
644
|
+
|
|
645
|
+
if (catalog.success) {
|
|
646
|
+
console.log("Products:", catalog.products);
|
|
647
|
+
console.log("Next page cursor:", catalog.nextCursor);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Get from another business
|
|
651
|
+
const otherCatalog = await client.getCatalog("6289876543210");
|
|
652
|
+
|
|
653
|
+
// With pagination
|
|
654
|
+
const paginated = await client.getCatalog(undefined, 20, catalog.nextCursor);
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
#### Get Product Collections
|
|
658
|
+
|
|
659
|
+
```typescript
|
|
660
|
+
const collections = await client.getCollections();
|
|
661
|
+
|
|
662
|
+
collections.forEach(col => {
|
|
663
|
+
console.log("Collection:", col.name);
|
|
664
|
+
console.log("Products:", col.products);
|
|
665
|
+
});
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
#### Create a Product
|
|
669
|
+
|
|
670
|
+
```typescript
|
|
671
|
+
const result = await client.createProduct({
|
|
672
|
+
name: "Premium Widget",
|
|
673
|
+
description: "High-quality widget for all your needs",
|
|
674
|
+
price: 1999, // In cents (e.g., $19.99)
|
|
675
|
+
imageUrls: ["https://example.com/product.jpg"],
|
|
676
|
+
isHidden: false,
|
|
677
|
+
retailerId: "SKU-001",
|
|
678
|
+
url: "https://example.com/product",
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
if (result.success) {
|
|
682
|
+
console.log("Product created:", result.productId);
|
|
683
|
+
}
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
#### Update a Product
|
|
687
|
+
|
|
688
|
+
```typescript
|
|
689
|
+
const result = await client.updateProduct("product-id", {
|
|
690
|
+
name: "Premium Widget v2",
|
|
691
|
+
price: 2499, // $24.99
|
|
692
|
+
description: "Updated with new features",
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
if (result.success) {
|
|
696
|
+
console.log("Product updated:", result.productId);
|
|
697
|
+
}
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
#### Delete Products
|
|
701
|
+
|
|
702
|
+
```typescript
|
|
703
|
+
const result = await client.deleteProducts(["product-id-1", "product-id-2"]);
|
|
704
|
+
|
|
705
|
+
if (result.success) {
|
|
706
|
+
console.log("Deleted count:", result.deletedCount);
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
### Newsletter/Channel Features
|
|
711
|
+
|
|
712
|
+
WhatsApp Channels (newsletters) for broadcasting updates.
|
|
713
|
+
|
|
714
|
+
#### Create a Newsletter
|
|
715
|
+
|
|
716
|
+
```typescript
|
|
717
|
+
const result = await client.createNewsletter(
|
|
718
|
+
"My Tech Updates",
|
|
719
|
+
"Latest technology news and updates"
|
|
720
|
+
);
|
|
721
|
+
|
|
722
|
+
if (result.success) {
|
|
723
|
+
console.log("Newsletter created:", result.newsletterId);
|
|
724
|
+
// Newsletter ID format: "1234567890@newsletter"
|
|
725
|
+
}
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
#### Get Newsletter Metadata
|
|
729
|
+
|
|
730
|
+
```typescript
|
|
731
|
+
const meta = await client.getNewsletterMetadata("1234567890@newsletter");
|
|
732
|
+
|
|
733
|
+
if (meta) {
|
|
734
|
+
console.log("Name:", meta.name);
|
|
735
|
+
console.log("Description:", meta.description);
|
|
736
|
+
console.log("Subscribers:", meta.subscribers);
|
|
737
|
+
console.log("Picture:", meta.pictureUrl);
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
#### Follow/Unfollow Newsletter
|
|
742
|
+
|
|
743
|
+
```typescript
|
|
744
|
+
// Follow
|
|
745
|
+
const followed = await client.followNewsletter("1234567890@newsletter");
|
|
746
|
+
|
|
747
|
+
// Unfollow
|
|
748
|
+
const unfollowed = await client.unfollowNewsletter("1234567890@newsletter");
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
#### Mute/Unmute Newsletter
|
|
752
|
+
|
|
753
|
+
```typescript
|
|
754
|
+
await client.muteNewsletter("1234567890@newsletter");
|
|
755
|
+
await client.unmuteNewsletter("1234567890@newsletter");
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### Update Newsletter
|
|
759
|
+
|
|
760
|
+
```typescript
|
|
761
|
+
// Update name
|
|
762
|
+
await client.updateNewsletterName("1234567890@newsletter", "New Name");
|
|
763
|
+
|
|
764
|
+
// Update description
|
|
765
|
+
await client.updateNewsletterDescription("1234567890@newsletter", "New description");
|
|
766
|
+
|
|
767
|
+
// Update picture
|
|
768
|
+
await client.updateNewsletterPicture("1234567890@newsletter", "./cover.jpg");
|
|
769
|
+
|
|
770
|
+
// Remove picture
|
|
771
|
+
await client.removeNewsletterPicture("1234567890@newsletter");
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
#### Fetch Newsletter Messages
|
|
775
|
+
|
|
776
|
+
```typescript
|
|
777
|
+
const messages = await client.fetchNewsletterMessages(
|
|
778
|
+
"1234567890@newsletter",
|
|
779
|
+
50, // count
|
|
780
|
+
Date.now(), // since timestamp
|
|
781
|
+
0 // after cursor (for pagination)
|
|
782
|
+
);
|
|
783
|
+
|
|
784
|
+
if (messages.success) {
|
|
785
|
+
messages.messages?.forEach(msg => {
|
|
786
|
+
console.log("Message:", msg.content);
|
|
787
|
+
console.log("Timestamp:", msg.timestamp);
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
#### React to Newsletter Message
|
|
793
|
+
|
|
794
|
+
```typescript
|
|
795
|
+
// Add reaction
|
|
796
|
+
await client.reactToNewsletterMessage("1234567890@newsletter", "msg-id", "👍");
|
|
797
|
+
|
|
798
|
+
// Remove reaction
|
|
799
|
+
await client.reactToNewsletterMessage("1234567890@newsletter", "msg-id", "");
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
#### Newsletter Subscriber Info
|
|
803
|
+
|
|
804
|
+
```typescript
|
|
805
|
+
// Get subscriber count
|
|
806
|
+
const info = await client.getNewsletterSubscribers("1234567890@newsletter");
|
|
807
|
+
console.log("Subscribers:", info?.subscribers);
|
|
808
|
+
|
|
809
|
+
// Get admin count
|
|
810
|
+
const adminCount = await client.getNewsletterAdminCount("1234567890@newsletter");
|
|
811
|
+
console.log("Admins:", adminCount);
|
|
812
|
+
|
|
813
|
+
// Subscribe to live updates
|
|
814
|
+
await client.subscribeNewsletterUpdates("1234567890@newsletter");
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
#### Newsletter Admin Operations
|
|
818
|
+
|
|
819
|
+
```typescript
|
|
820
|
+
// Change owner
|
|
821
|
+
await client.changeNewsletterOwner("1234567890@newsletter", "new-owner@s.whatsapp.net");
|
|
822
|
+
|
|
823
|
+
// Demote admin
|
|
824
|
+
await client.demoteNewsletterAdmin("1234567890@newsletter", "admin@s.whatsapp.net");
|
|
825
|
+
|
|
826
|
+
// Delete newsletter
|
|
827
|
+
await client.deleteNewsletter("1234567890@newsletter");
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
### Contact Management
|
|
831
|
+
|
|
832
|
+
Manage your WhatsApp contacts.
|
|
833
|
+
|
|
834
|
+
#### Add or Edit Contact
|
|
835
|
+
|
|
836
|
+
```typescript
|
|
837
|
+
const result = await client.addOrEditContact({
|
|
838
|
+
phone: "6281234567890",
|
|
839
|
+
name: "John Doe",
|
|
840
|
+
firstName: "John",
|
|
841
|
+
lastName: "Doe",
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
if (result.success) {
|
|
845
|
+
console.log("Contact saved!");
|
|
846
|
+
}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
#### Remove Contact
|
|
850
|
+
|
|
851
|
+
```typescript
|
|
852
|
+
const result = await client.removeContact("6281234567890");
|
|
853
|
+
|
|
854
|
+
if (result.success) {
|
|
855
|
+
console.log("Contact removed!");
|
|
856
|
+
}
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
### Business Bot Example
|
|
860
|
+
|
|
861
|
+
Bot that manages labels and products:
|
|
862
|
+
|
|
863
|
+
```typescript
|
|
864
|
+
client.on("message", async (msg) => {
|
|
865
|
+
if (msg.fromMe) return;
|
|
866
|
+
|
|
867
|
+
const text = msg.text?.toLowerCase();
|
|
868
|
+
|
|
869
|
+
// Label management
|
|
870
|
+
if (text === "!label vip") {
|
|
871
|
+
const result = await client.addChatLabel(msg.from, "vip-label-id");
|
|
872
|
+
if (result.success) {
|
|
873
|
+
await client.sendText(msg.from, "You've been marked as VIP! ⭐");
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// Catalog query
|
|
878
|
+
if (text === "!products") {
|
|
879
|
+
const catalog = await client.getCatalog();
|
|
880
|
+
if (catalog.success && catalog.products) {
|
|
881
|
+
let response = "Our products:\n\n";
|
|
882
|
+
catalog.products.forEach(p => {
|
|
883
|
+
response += `${p.name}: $${(p.priceAmount1000! / 100).toFixed(2)}\n`;
|
|
884
|
+
});
|
|
885
|
+
await client.sendText(msg.from, response);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// Create product (admin only)
|
|
890
|
+
if (text.startsWith("!addproduct")) {
|
|
891
|
+
const args = text.split(" ");
|
|
892
|
+
// Format: !addproduct <name> <price>
|
|
893
|
+
const name = args.slice(1, -1).join(" ");
|
|
894
|
+
const price = parseInt(args[args.length - 1]) * 100; // Convert to cents
|
|
895
|
+
|
|
896
|
+
const result = await client.createProduct({
|
|
897
|
+
name,
|
|
898
|
+
price,
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
if (result.success) {
|
|
902
|
+
await client.sendText(msg.from, `Product created: ${result.productId}`);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
### Newsletter Bot Example
|
|
909
|
+
|
|
910
|
+
Bot that manages a newsletter:
|
|
911
|
+
|
|
912
|
+
```typescript
|
|
913
|
+
let newsletterId: string | null = null;
|
|
914
|
+
|
|
915
|
+
// Create newsletter on startup
|
|
916
|
+
client.on("ready", async () => {
|
|
917
|
+
const result = await client.createNewsletter(
|
|
918
|
+
"My Daily Updates",
|
|
919
|
+
"Daily news and updates"
|
|
920
|
+
);
|
|
921
|
+
if (result.success) {
|
|
922
|
+
newsletterId = result.newsletterId || null;
|
|
923
|
+
console.log("Newsletter created:", newsletterId);
|
|
924
|
+
}
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
// Post to newsletter from command
|
|
928
|
+
client.on("message", async (msg) => {
|
|
929
|
+
if (msg.fromMe || !newsletterId) return;
|
|
930
|
+
|
|
931
|
+
const text = msg.text?.toLowerCase();
|
|
932
|
+
|
|
933
|
+
if (text.startsWith("!broadcast ")) {
|
|
934
|
+
const broadcastText = msg.text?.slice(11); // Remove "!broadcast "
|
|
935
|
+
await client.sendText(`${newsletterId}`, broadcastText);
|
|
936
|
+
await client.sendText(msg.from, "Broadcast sent to newsletter!");
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (text === "!stats") {
|
|
940
|
+
const info = await client.getNewsletterSubscribers(newsletterId);
|
|
941
|
+
await client.sendText(msg.from, `Subscribers: ${info?.subscribers}`);
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
## Receiving Messages
|
|
947
|
+
|
|
948
|
+
### Message Event
|
|
949
|
+
|
|
950
|
+
Listen for incoming messages:
|
|
951
|
+
|
|
952
|
+
```typescript
|
|
953
|
+
client.on("message", (message) => {
|
|
954
|
+
console.log("From:", message.from);
|
|
955
|
+
console.log("Text:", message.text);
|
|
956
|
+
console.log("Type:", message.type);
|
|
957
|
+
console.log("Is Group:", message.isGroup);
|
|
958
|
+
console.log("Timestamp:", message.timestamp);
|
|
959
|
+
console.log("From Me:", message.fromMe);
|
|
960
|
+
});
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
### Message Structure
|
|
964
|
+
|
|
965
|
+
The `MiawMessage` object contains:
|
|
966
|
+
|
|
967
|
+
```typescript
|
|
968
|
+
interface MiawMessage {
|
|
969
|
+
id: string; // Unique message ID
|
|
970
|
+
from: string; // Sender WhatsApp ID (JID)
|
|
971
|
+
text?: string; // Message text content
|
|
972
|
+
timestamp: number; // Unix timestamp (seconds)
|
|
973
|
+
isGroup: boolean; // Whether from group chat
|
|
974
|
+
participant?: string; // Group participant ID (if isGroup)
|
|
975
|
+
fromMe: boolean; // Whether sent by bot
|
|
976
|
+
type: string; // Message type: 'text' | 'image' | 'video' | etc.
|
|
977
|
+
raw?: any; // Original Baileys message
|
|
978
|
+
}
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
### Filter Messages
|
|
982
|
+
|
|
983
|
+
Common filtering patterns:
|
|
984
|
+
|
|
985
|
+
```typescript
|
|
986
|
+
client.on("message", async (msg) => {
|
|
987
|
+
// Ignore own messages
|
|
988
|
+
if (msg.fromMe) return;
|
|
989
|
+
|
|
990
|
+
// Only text messages
|
|
991
|
+
if (msg.type !== "text" || !msg.text) return;
|
|
992
|
+
|
|
993
|
+
// Only from specific user
|
|
994
|
+
if (msg.from !== "1234567890@s.whatsapp.net") return;
|
|
995
|
+
|
|
996
|
+
// Only from groups
|
|
997
|
+
if (!msg.isGroup) return;
|
|
998
|
+
|
|
999
|
+
// Process message
|
|
1000
|
+
console.log("Valid message:", msg.text);
|
|
1001
|
+
});
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
### Echo Bot Example
|
|
1005
|
+
|
|
1006
|
+
Simple bot that echoes messages:
|
|
1007
|
+
|
|
1008
|
+
```typescript
|
|
1009
|
+
client.on("message", async (msg) => {
|
|
1010
|
+
if (msg.fromMe || !msg.text) return;
|
|
1011
|
+
|
|
1012
|
+
await client.sendText(msg.from, `Echo: ${msg.text}`);
|
|
1013
|
+
});
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
### Command Handler Example
|
|
1017
|
+
|
|
1018
|
+
Bot with command handling:
|
|
1019
|
+
|
|
1020
|
+
```typescript
|
|
1021
|
+
client.on("message", async (msg) => {
|
|
1022
|
+
if (msg.fromMe || !msg.text) return;
|
|
1023
|
+
|
|
1024
|
+
const text = msg.text.toLowerCase();
|
|
1025
|
+
|
|
1026
|
+
if (text === "/help") {
|
|
1027
|
+
await client.sendText(
|
|
1028
|
+
msg.from,
|
|
1029
|
+
"Available commands:\n" +
|
|
1030
|
+
"/help - Show this message\n" +
|
|
1031
|
+
"/ping - Test bot response\n" +
|
|
1032
|
+
"/time - Get current time"
|
|
1033
|
+
);
|
|
1034
|
+
} else if (text === "/ping") {
|
|
1035
|
+
await client.sendText(msg.from, "Pong! 🏓");
|
|
1036
|
+
} else if (text === "/time") {
|
|
1037
|
+
const time = new Date().toLocaleString();
|
|
1038
|
+
await client.sendText(msg.from, `Current time: ${time}`);
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
## Connection Management
|
|
1044
|
+
|
|
1045
|
+
### Connect
|
|
1046
|
+
|
|
1047
|
+
Start the WhatsApp connection:
|
|
1048
|
+
|
|
1049
|
+
```typescript
|
|
1050
|
+
await client.connect();
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
### Disconnect
|
|
1054
|
+
|
|
1055
|
+
Stop the connection and logout:
|
|
1056
|
+
|
|
1057
|
+
```typescript
|
|
1058
|
+
await client.disconnect();
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
### Check Connection State
|
|
1062
|
+
|
|
1063
|
+
```typescript
|
|
1064
|
+
// Get current state
|
|
1065
|
+
const state = client.getConnectionState();
|
|
1066
|
+
// Returns: 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'qr_required'
|
|
1067
|
+
|
|
1068
|
+
// Check if connected
|
|
1069
|
+
if (client.isConnected()) {
|
|
1070
|
+
console.log("Ready to send messages");
|
|
1071
|
+
}
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
### Connection Events
|
|
1075
|
+
|
|
1076
|
+
Monitor connection status:
|
|
1077
|
+
|
|
1078
|
+
```typescript
|
|
1079
|
+
client.on("connection", (state) => {
|
|
1080
|
+
console.log("Connection state:", state);
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
client.on("ready", () => {
|
|
1084
|
+
console.log("Connected and ready!");
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
client.on("disconnected", (reason) => {
|
|
1088
|
+
console.log("Disconnected:", reason);
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
client.on("reconnecting", (attempt) => {
|
|
1092
|
+
console.log(`Reconnecting... Attempt ${attempt}`);
|
|
1093
|
+
});
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
### Auto-Reconnection
|
|
1097
|
+
|
|
1098
|
+
Miaw Core automatically handles reconnection:
|
|
1099
|
+
|
|
1100
|
+
```typescript
|
|
1101
|
+
const client = new MiawClient({
|
|
1102
|
+
instanceId: "bot",
|
|
1103
|
+
autoReconnect: true, // Enable auto-reconnect
|
|
1104
|
+
maxReconnectAttempts: 10, // Try 10 times
|
|
1105
|
+
reconnectDelay: 5000, // Wait 5s between attempts
|
|
1106
|
+
});
|
|
1107
|
+
|
|
1108
|
+
// Connection drops are handled automatically
|
|
1109
|
+
client.on("reconnecting", (attempt) => {
|
|
1110
|
+
console.log(`Reconnection attempt ${attempt}`);
|
|
1111
|
+
});
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
## Multiple Instances
|
|
1115
|
+
|
|
1116
|
+
Run multiple WhatsApp connections in the same process:
|
|
1117
|
+
|
|
1118
|
+
```typescript
|
|
1119
|
+
import { MiawClient } from "miaw-core";
|
|
1120
|
+
|
|
1121
|
+
// Create multiple instances
|
|
1122
|
+
const bot1 = new MiawClient({
|
|
1123
|
+
instanceId: "customer-support",
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1126
|
+
const bot2 = new MiawClient({
|
|
1127
|
+
instanceId: "sales-bot",
|
|
1128
|
+
});
|
|
1129
|
+
|
|
1130
|
+
const bot3 = new MiawClient({
|
|
1131
|
+
instanceId: "notifications",
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
// Each has separate QR code and session
|
|
1135
|
+
bot1.on("qr", (qr) => console.log("Bot 1 QR:", qr));
|
|
1136
|
+
bot2.on("qr", (qr) => console.log("Bot 2 QR:", qr));
|
|
1137
|
+
bot3.on("qr", (qr) => console.log("Bot 3 QR:", qr));
|
|
1138
|
+
|
|
1139
|
+
// Start all instances
|
|
1140
|
+
await Promise.all([bot1.connect(), bot2.connect(), bot3.connect()]);
|
|
1141
|
+
|
|
1142
|
+
// Each operates independently
|
|
1143
|
+
bot1.on("message", (msg) => {
|
|
1144
|
+
console.log("Bot 1 received:", msg.text);
|
|
1145
|
+
});
|
|
1146
|
+
|
|
1147
|
+
bot2.on("message", (msg) => {
|
|
1148
|
+
console.log("Bot 2 received:", msg.text);
|
|
1149
|
+
});
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
## Session Management
|
|
1153
|
+
|
|
1154
|
+
### Session Storage Location
|
|
1155
|
+
|
|
1156
|
+
Sessions are stored in the filesystem:
|
|
1157
|
+
|
|
1158
|
+
```
|
|
1159
|
+
sessions/
|
|
1160
|
+
├── bot-1/
|
|
1161
|
+
│ ├── creds.json
|
|
1162
|
+
│ └── app-state-sync-*.json
|
|
1163
|
+
├── bot-2/
|
|
1164
|
+
│ ├── creds.json
|
|
1165
|
+
│ └── app-state-sync-*.json
|
|
1166
|
+
└── bot-3/
|
|
1167
|
+
├── creds.json
|
|
1168
|
+
└── app-state-sync-*.json
|
|
1169
|
+
```
|
|
1170
|
+
|
|
1171
|
+
### Custom Session Path
|
|
1172
|
+
|
|
1173
|
+
```typescript
|
|
1174
|
+
const client = new MiawClient({
|
|
1175
|
+
instanceId: "my-bot",
|
|
1176
|
+
sessionPath: "/var/lib/whatsapp/sessions",
|
|
1177
|
+
});
|
|
1178
|
+
// Session will be stored in: /var/lib/whatsapp/sessions/my-bot/
|
|
1179
|
+
```
|
|
1180
|
+
|
|
1181
|
+
### Session Persistence
|
|
1182
|
+
|
|
1183
|
+
Sessions persist across restarts:
|
|
1184
|
+
|
|
1185
|
+
```typescript
|
|
1186
|
+
// First run
|
|
1187
|
+
const client = new MiawClient({ instanceId: "bot" });
|
|
1188
|
+
await client.connect(); // QR code required
|
|
1189
|
+
// Session saved automatically
|
|
1190
|
+
|
|
1191
|
+
// Next run (restart app)
|
|
1192
|
+
const client = new MiawClient({ instanceId: "bot" });
|
|
1193
|
+
await client.connect(); // No QR code! Uses saved session
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
### Clear Session (Logout)
|
|
1197
|
+
|
|
1198
|
+
To logout and start fresh:
|
|
1199
|
+
|
|
1200
|
+
```bash
|
|
1201
|
+
# Manual deletion
|
|
1202
|
+
rm -rf ./sessions/my-bot/
|
|
1203
|
+
|
|
1204
|
+
# Or programmatically
|
|
1205
|
+
import { rmSync } from 'fs';
|
|
1206
|
+
rmSync('./sessions/my-bot', { recursive: true, force: true });
|
|
1207
|
+
```
|
|
1208
|
+
|
|
1209
|
+
## Event Reference
|
|
1210
|
+
|
|
1211
|
+
### Available Events
|
|
1212
|
+
|
|
1213
|
+
| Event | Parameters | Description |
|
|
1214
|
+
| --------------- | -------------------------- | --------------------------- |
|
|
1215
|
+
| `qr` | `(qrCode: string)` | QR code needs to be scanned |
|
|
1216
|
+
| `ready` | `()` | Client connected and ready |
|
|
1217
|
+
| `message` | `(message: MiawMessage)` | New message received |
|
|
1218
|
+
| `connection` | `(state: ConnectionState)` | Connection state changed |
|
|
1219
|
+
| `disconnected` | `(reason?: string)` | Client disconnected |
|
|
1220
|
+
| `reconnecting` | `(attempt: number)` | Attempting to reconnect |
|
|
1221
|
+
| `error` | `(error: Error)` | Error occurred |
|
|
1222
|
+
| `session_saved` | `()` | Session credentials saved |
|
|
1223
|
+
|
|
1224
|
+
### Event Examples
|
|
1225
|
+
|
|
1226
|
+
```typescript
|
|
1227
|
+
// QR Code
|
|
1228
|
+
client.on("qr", (qr) => {
|
|
1229
|
+
console.log("Scan this:", qr);
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
// Ready
|
|
1233
|
+
client.on("ready", () => {
|
|
1234
|
+
console.log("Connected!");
|
|
1235
|
+
});
|
|
1236
|
+
|
|
1237
|
+
// Message
|
|
1238
|
+
client.on("message", (msg) => {
|
|
1239
|
+
console.log("New message:", msg.text);
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
// Connection State
|
|
1243
|
+
client.on("connection", (state) => {
|
|
1244
|
+
console.log("State:", state);
|
|
1245
|
+
});
|
|
1246
|
+
|
|
1247
|
+
// Disconnected
|
|
1248
|
+
client.on("disconnected", (reason) => {
|
|
1249
|
+
console.log("Lost connection:", reason);
|
|
1250
|
+
});
|
|
1251
|
+
|
|
1252
|
+
// Reconnecting
|
|
1253
|
+
client.on("reconnecting", (attempt) => {
|
|
1254
|
+
console.log(`Reconnect attempt #${attempt}`);
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
// Error
|
|
1258
|
+
client.on("error", (error) => {
|
|
1259
|
+
console.error("Error:", error.message);
|
|
1260
|
+
});
|
|
1261
|
+
|
|
1262
|
+
// Session Saved
|
|
1263
|
+
client.on("session_saved", () => {
|
|
1264
|
+
console.log("Session persisted");
|
|
1265
|
+
});
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
## Error Handling
|
|
1269
|
+
|
|
1270
|
+
### Send Message Errors
|
|
1271
|
+
|
|
1272
|
+
```typescript
|
|
1273
|
+
const result = await client.sendText("1234567890", "Hello");
|
|
1274
|
+
|
|
1275
|
+
if (!result.success) {
|
|
1276
|
+
console.error("Failed to send:", result.error);
|
|
1277
|
+
|
|
1278
|
+
// Handle specific errors
|
|
1279
|
+
if (result.error?.includes("not connected")) {
|
|
1280
|
+
console.log("Wait for connection...");
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
### Global Error Handler
|
|
1286
|
+
|
|
1287
|
+
```typescript
|
|
1288
|
+
client.on("error", (error) => {
|
|
1289
|
+
console.error("Client error:", error.message);
|
|
1290
|
+
|
|
1291
|
+
// Log to monitoring service
|
|
1292
|
+
// Send alert
|
|
1293
|
+
// etc.
|
|
1294
|
+
});
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
### Connection Errors
|
|
1298
|
+
|
|
1299
|
+
```typescript
|
|
1300
|
+
client.on("disconnected", (reason) => {
|
|
1301
|
+
if (reason === "loggedOut") {
|
|
1302
|
+
console.log("Need to re-authenticate");
|
|
1303
|
+
// Delete session and restart
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
### Try-Catch Pattern
|
|
1309
|
+
|
|
1310
|
+
```typescript
|
|
1311
|
+
try {
|
|
1312
|
+
await client.connect();
|
|
1313
|
+
} catch (error) {
|
|
1314
|
+
console.error("Failed to connect:", error);
|
|
1315
|
+
// Handle startup errors
|
|
1316
|
+
}
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
## TypeScript Usage
|
|
1320
|
+
|
|
1321
|
+
Miaw Core is written in TypeScript with full type definitions:
|
|
1322
|
+
|
|
1323
|
+
### Import Types
|
|
1324
|
+
|
|
1325
|
+
```typescript
|
|
1326
|
+
import {
|
|
1327
|
+
MiawClient,
|
|
1328
|
+
MiawMessage,
|
|
1329
|
+
MiawClientOptions,
|
|
1330
|
+
ConnectionState,
|
|
1331
|
+
SendMessageResult,
|
|
1332
|
+
} from "miaw-core";
|
|
1333
|
+
```
|
|
1334
|
+
|
|
1335
|
+
### Type-Safe Configuration
|
|
1336
|
+
|
|
1337
|
+
```typescript
|
|
1338
|
+
const options: MiawClientOptions = {
|
|
1339
|
+
instanceId: "bot",
|
|
1340
|
+
sessionPath: "./sessions",
|
|
1341
|
+
debug: true,
|
|
1342
|
+
autoReconnect: true,
|
|
1343
|
+
maxReconnectAttempts: 10,
|
|
1344
|
+
reconnectDelay: 5000,
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1347
|
+
const client = new MiawClient(options);
|
|
1348
|
+
```
|
|
1349
|
+
|
|
1350
|
+
### Type-Safe Event Handlers
|
|
1351
|
+
|
|
1352
|
+
```typescript
|
|
1353
|
+
client.on("message", (msg: MiawMessage) => {
|
|
1354
|
+
// TypeScript knows the structure
|
|
1355
|
+
console.log(msg.text); // string | undefined
|
|
1356
|
+
console.log(msg.timestamp); // number
|
|
1357
|
+
console.log(msg.isGroup); // boolean
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
client.on("connection", (state: ConnectionState) => {
|
|
1361
|
+
// 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'qr_required'
|
|
1362
|
+
if (state === "connected") {
|
|
1363
|
+
console.log("Ready!");
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
### Type-Safe Result Handling
|
|
1369
|
+
|
|
1370
|
+
```typescript
|
|
1371
|
+
const result: SendMessageResult = await client.sendText("...", "Hello");
|
|
1372
|
+
|
|
1373
|
+
if (result.success) {
|
|
1374
|
+
// TypeScript knows messageId exists here
|
|
1375
|
+
console.log(result.messageId);
|
|
1376
|
+
} else {
|
|
1377
|
+
// TypeScript knows error exists here
|
|
1378
|
+
console.error(result.error);
|
|
1379
|
+
}
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
## Complete Example
|
|
1383
|
+
|
|
1384
|
+
For a full-featured bot demonstrating all current capabilities, see:
|
|
1385
|
+
|
|
1386
|
+
**[examples/simple-bot.ts](./examples/simple-bot.ts)**
|
|
1387
|
+
|
|
1388
|
+
The example includes:
|
|
1389
|
+
|
|
1390
|
+
- QR code authentication handling
|
|
1391
|
+
- Message receiving and command processing
|
|
1392
|
+
- Connection state monitoring
|
|
1393
|
+
- Auto-reconnection handling
|
|
1394
|
+
- Error handling
|
|
1395
|
+
- Graceful shutdown
|
|
1396
|
+
|
|
1397
|
+
---
|
|
1398
|
+
|
|
1399
|
+
For feature roadmap and planned capabilities, see [ROADMAP.md](./ROADMAP.md).
|