@shoru/kitten 0.0.3 → 0.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 +595 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="left">
|
|
2
2
|
|
|
3
|
-
<img src="https://files.catbox.moe/j7dpni.png" align="right" width="
|
|
3
|
+
<img src="https://files.catbox.moe/j7dpni.png" align="right" width="220" alt="Kitten Logo">
|
|
4
4
|
|
|
5
5
|
<a name="-kitten"></a>
|
|
6
6
|
# **Kitten Framework**
|
|
@@ -15,10 +15,602 @@
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
1. [Introduction](#introduction)
|
|
21
|
+
2. [Getting Started](#getting-started)
|
|
22
|
+
3. [Configuration](#configuration)
|
|
23
|
+
4. [Plugin System](#plugin-system)
|
|
24
|
+
5. [Message Formatting](#message-formatting)
|
|
25
|
+
6. [Session Management](#session-management)
|
|
26
|
+
7. [Utilities](#utilities)
|
|
27
|
+
8. [API Reference](#api-reference)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Introduction
|
|
32
|
+
|
|
33
|
+
Kitten simplifies WhatsApp bot development by providing:
|
|
34
|
+
|
|
35
|
+
- **Persistent Sessions** — LMDB-powered storage with automatic recovery
|
|
36
|
+
- **Smart Reconnection** — Exponential backoff with configurable retry limits
|
|
37
|
+
- **Plugin System** — File-based plugins with Hot Module Replacement
|
|
38
|
+
- **Multi-Session** — Automatic restoration of all saved sessions
|
|
39
|
+
- **Flexible Auth** — QR code or pairing code authentication
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Getting Started
|
|
44
|
+
|
|
45
|
+
### Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @shoru/kitten
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Basic Usage
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import { getClient } from '@shoru/kitten';
|
|
55
|
+
|
|
56
|
+
const { sock, session, id } = await getClient();
|
|
57
|
+
|
|
58
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
59
|
+
const msg = messages[0];
|
|
60
|
+
if (msg.message?.conversation === 'ping') {
|
|
61
|
+
await sock.sendMessage(msg.key.remoteJid, { text: 'pong!' });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> **Note:** `getClient()` automatically restores all previously saved sessions in the background.
|
|
67
|
+
|
|
68
|
+
### With Options
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
import { getClient } from '@shoru/kitten';
|
|
72
|
+
|
|
73
|
+
const { sock, session, id } = await getClient({
|
|
74
|
+
id: 0, // Session ID (auto-generated if omitted)
|
|
75
|
+
maxRetries: 30, // Reconnection attempts
|
|
76
|
+
silent: false, // Suppress output
|
|
77
|
+
socketConfig: {}, // Baileys socket overrides
|
|
78
|
+
|
|
79
|
+
// Callbacks
|
|
80
|
+
onConnect: ({ client }) => {
|
|
81
|
+
console.log(`Connected with session ${client.id}`);
|
|
82
|
+
},
|
|
83
|
+
onReconnect: ({ client, attempts }) => {
|
|
84
|
+
console.log(`Reconnected after ${attempts} attempts`);
|
|
85
|
+
},
|
|
86
|
+
onDisconnect: ({ message, statusCode, recoverable }) => {
|
|
87
|
+
console.log(`Disconnected: ${message}`);
|
|
88
|
+
},
|
|
89
|
+
onStateChange: ({ oldState, newState }) => {
|
|
90
|
+
console.log(`State: ${oldState} → ${newState}`);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Custom Authentication
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
import qrcode from 'qrcode-terminal';
|
|
99
|
+
|
|
100
|
+
const { sock, id } = await getClient({
|
|
101
|
+
onPairing: async ({ qr, requestPairingCode }) => {
|
|
102
|
+
// Option 1: Display QR code
|
|
103
|
+
console.log('Scan QR:');
|
|
104
|
+
qrcode.generate(qr, { small: true });
|
|
105
|
+
|
|
106
|
+
// Option 2: Use pairing code
|
|
107
|
+
const code = await requestPairingCode('1234567890');
|
|
108
|
+
console.log('Enter this code in WhatsApp:', code);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Return Value
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
const { sock, session, id } = await getClient();
|
|
117
|
+
|
|
118
|
+
sock // Baileys WASocket instance
|
|
119
|
+
id // Numeric session identifier
|
|
120
|
+
session.id // Same as id
|
|
121
|
+
await session.delete() // Remove session from database
|
|
122
|
+
await session.clear() // Clear keys, keep credentials
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
Kitten uses [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig). Create one of:
|
|
130
|
+
|
|
131
|
+
- `kittenwa.config.js`
|
|
132
|
+
- `kittenwa.config.mjs`
|
|
133
|
+
- `.kittenwarc.json`
|
|
134
|
+
- `package.json` → `"kittenwa": {}`
|
|
135
|
+
|
|
136
|
+
### Default Values
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
export default {
|
|
140
|
+
socket: {
|
|
141
|
+
browser: Browsers.ubuntu('Chrome'),
|
|
142
|
+
markOnlineOnConnect: false,
|
|
143
|
+
syncFullHistory: false,
|
|
144
|
+
generateHighQualityLinkPreview: true,
|
|
145
|
+
logger: pino({ level: 'silent' })
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
db: {
|
|
149
|
+
path: './db',
|
|
150
|
+
compression: true,
|
|
151
|
+
mapSize: 2 * 1024 * 1024 * 1024 // 2GB
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
plugins: {
|
|
155
|
+
dir: 'plugins',
|
|
156
|
+
prefixes: ['.', '\\', '!'],
|
|
157
|
+
defaultEvent: 'messages.upsert',
|
|
158
|
+
hmr: {
|
|
159
|
+
enable: false,
|
|
160
|
+
debounce: 200,
|
|
161
|
+
debug: false
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
timeZone: 'Africa/Casablanca'
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Custom Configuration
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// kittenwa.config.js
|
|
173
|
+
export default {
|
|
174
|
+
plugins: {
|
|
175
|
+
dir: 'src/plugins',
|
|
176
|
+
prefixes: ['/', '!'],
|
|
177
|
+
hmr: { enable: true }
|
|
178
|
+
},
|
|
179
|
+
timeZone: 'America/New_York'
|
|
180
|
+
};
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Plugin System
|
|
186
|
+
|
|
187
|
+
File-based plugins with automatic loading and optional Hot Module Replacement.
|
|
188
|
+
|
|
189
|
+
### Directory Structure
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
plugins/
|
|
193
|
+
├── greetings/
|
|
194
|
+
│ ├── hello.js
|
|
195
|
+
│ └── goodbye.js
|
|
196
|
+
├── admin/
|
|
197
|
+
│ └── ban.js
|
|
198
|
+
└── utils.js
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Basic Plugin
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// plugins/ping.js
|
|
205
|
+
export function ping(sock, ctx, event) {
|
|
206
|
+
if (ctx.body === '!ping') {
|
|
207
|
+
sock.sendMessage(ctx.roomId, { text: 'pong!' });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Plugin with Options
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
// plugins/commands.js
|
|
216
|
+
export const help = async (sock, ctx) => {
|
|
217
|
+
await sock.sendMessage(ctx.roomId, {
|
|
218
|
+
text: 'Available: !help, !ping, !info'
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
help.match: ['help', 'h', '?'];
|
|
223
|
+
help.prefix: ['!', '/'];
|
|
224
|
+
help.events: ['messages.upsert'];
|
|
225
|
+
help.enabled: true;
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Options Reference
|
|
229
|
+
|
|
230
|
+
| Option | Type | Default | Description |
|
|
231
|
+
|--------|------|---------|-------------|
|
|
232
|
+
| `match` | `(string \| RegExp)[]` | `[]` | Command triggers |
|
|
233
|
+
| `prefix` | `string[] \| false` | Config value | Required prefixes |
|
|
234
|
+
| `events` | `string[]` | `['messages.upsert']` | Events to listen |
|
|
235
|
+
| `enabled` | `boolean` | `true` | Toggle plugin |
|
|
236
|
+
|
|
237
|
+
### Regex Matching
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
export const urlDetector = (sock, ctx) => {
|
|
241
|
+
const match = ctx._match.match; // RegExp exec result
|
|
242
|
+
console.log('URL found:', match[0]);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
urlDetector.match = [/https?:\/\/\S+/gi];
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Match Context
|
|
249
|
+
|
|
250
|
+
When a command matches, `ctx._match` is added:
|
|
251
|
+
|
|
252
|
+
```javascript
|
|
253
|
+
// User sends: "!help me"
|
|
254
|
+
ctx._match = {
|
|
255
|
+
match: 'help', // Matched string or RegExp result
|
|
256
|
+
prefix: '!' // Used prefix (null for regex)
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Supported Events
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
messages.upsert messages.update messages.delete
|
|
264
|
+
messages.reaction message-receipt.update messaging-history.set
|
|
265
|
+
chats.upsert chats.update chats.delete
|
|
266
|
+
contacts.upsert contacts.update groups.update
|
|
267
|
+
group-participants.update presence.update
|
|
268
|
+
connection.update creds.update call
|
|
269
|
+
blocklist.set blocklist.update
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Hot Module Replacement
|
|
273
|
+
|
|
274
|
+
Enable for development:
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
// kittenwa.config.js
|
|
278
|
+
export default {
|
|
279
|
+
plugins: {
|
|
280
|
+
hmr: {
|
|
281
|
+
enable: true,
|
|
282
|
+
debounce: 200,
|
|
283
|
+
debug: true
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Console output:
|
|
290
|
+
```
|
|
291
|
+
[HMR] Added: greetings/hello.js (2)
|
|
292
|
+
[HMR] Reloaded: commands.js (3)
|
|
293
|
+
[HMR] Unloaded: old-plugin.js (1)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Naming Rules
|
|
297
|
+
|
|
298
|
+
| Pattern | Status |
|
|
299
|
+
|---------|--------|
|
|
300
|
+
| `command.js` | ✅ Loaded |
|
|
301
|
+
| `command.ts` | ✅ Loaded |
|
|
302
|
+
| `_helper.js` | ❌ Ignored |
|
|
303
|
+
| `types.d.ts` | ❌ Ignored |
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Message Formatting
|
|
308
|
+
|
|
309
|
+
Normalize raw Baileys messages into a consistent structure.
|
|
310
|
+
|
|
311
|
+
### Usage
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
import { formatter } from '@shoru/kitten';
|
|
315
|
+
|
|
316
|
+
sock.ev.on('messages.upsert', ({ messages }) => {
|
|
317
|
+
const msg = formatter(sock, messages[0]);
|
|
318
|
+
|
|
319
|
+
console.log(msg.name); // Sender name
|
|
320
|
+
console.log(msg.body); // Text content
|
|
321
|
+
console.log(msg.isGroup); // Boolean
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Message Structure
|
|
326
|
+
|
|
327
|
+
```javascript
|
|
328
|
+
{
|
|
329
|
+
// Identity
|
|
330
|
+
type: 'conversation',
|
|
331
|
+
id: 'ABC123',
|
|
332
|
+
name: 'John',
|
|
333
|
+
jid: '123@s.whatsapp.net',
|
|
334
|
+
fromMe: false,
|
|
335
|
+
|
|
336
|
+
// Chat
|
|
337
|
+
roomId: '123@s.whatsapp.net',
|
|
338
|
+
isGroup: false,
|
|
339
|
+
broadcast: false,
|
|
340
|
+
|
|
341
|
+
// Content
|
|
342
|
+
body: 'Hello!',
|
|
343
|
+
mentions: [],
|
|
344
|
+
mimetype: 'image/jpeg',
|
|
345
|
+
fileName: 'photo.jpg',
|
|
346
|
+
fileLength: 12345,
|
|
347
|
+
hash: 'abc123...',
|
|
348
|
+
isViewOnce: false,
|
|
349
|
+
thumbnail: Buffer,
|
|
350
|
+
|
|
351
|
+
// Forwarding
|
|
352
|
+
isForwarded: false,
|
|
353
|
+
forwardingScore: 0,
|
|
354
|
+
|
|
355
|
+
// Timing
|
|
356
|
+
timestamp: 1699999999,
|
|
357
|
+
timeString: ['November 14, 2023', '12:26:39'],
|
|
358
|
+
|
|
359
|
+
// Device
|
|
360
|
+
device: 'android',
|
|
361
|
+
isLid: false,
|
|
362
|
+
|
|
363
|
+
// Raw data
|
|
364
|
+
key: { ... },
|
|
365
|
+
raw: { ... },
|
|
366
|
+
contextInfo: { ... },
|
|
367
|
+
|
|
368
|
+
// Methods
|
|
369
|
+
async load() → Buffer,
|
|
370
|
+
senderIs(jid) → boolean,
|
|
371
|
+
async pn() → string,
|
|
372
|
+
|
|
373
|
+
// Quoted message (when replying)
|
|
374
|
+
quoted: { /* same structure */ }
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Common Patterns
|
|
379
|
+
|
|
380
|
+
```javascript
|
|
381
|
+
// Download media
|
|
382
|
+
if (msg.mimetype?.startsWith('image/')) {
|
|
383
|
+
const buffer = await msg.load();
|
|
384
|
+
fs.writeFileSync('image.jpg', buffer);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Handle replies
|
|
388
|
+
if (msg.quoted) {
|
|
389
|
+
console.log('Replying to:', msg.quoted.body);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Check sender
|
|
393
|
+
if (msg.senderIs(adminJid)) {
|
|
394
|
+
// Execute admin command
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Get phone number
|
|
398
|
+
const phone = await msg.pn();
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Session Management
|
|
404
|
+
|
|
405
|
+
Sessions persist automatically in LMDB and are restored on startup.
|
|
406
|
+
|
|
407
|
+
### Automatic Restoration
|
|
408
|
+
|
|
409
|
+
When you call `getClient()`, all previously saved sessions are automatically restored in the background. No manual iteration required.
|
|
410
|
+
|
|
411
|
+
```javascript
|
|
412
|
+
import { getClient } from '@shoru/kitten';
|
|
413
|
+
|
|
414
|
+
// This connects the current session AND restores all others
|
|
415
|
+
const { sock } = await getClient({ id: 0 });
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Session Utilities
|
|
419
|
+
|
|
420
|
+
```javascript
|
|
421
|
+
import { listSessions, sessionExists } from '@shoru/kitten';
|
|
422
|
+
|
|
423
|
+
// List all saved session IDs
|
|
424
|
+
const ids = listSessions(); // [0, 1, 2]
|
|
425
|
+
|
|
426
|
+
// Check if a session exists
|
|
427
|
+
if (sessionExists(1)) {
|
|
428
|
+
console.log('Session 1 exists');
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Session Operations
|
|
433
|
+
|
|
434
|
+
```javascript
|
|
435
|
+
const { session } = await getClient();
|
|
436
|
+
|
|
437
|
+
session.id // Numeric identifier
|
|
438
|
+
await session.clear() // Clear keys, keep credentials
|
|
439
|
+
await session.delete() // Remove entire session
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## Utilities
|
|
445
|
+
|
|
446
|
+
### Logger
|
|
447
|
+
|
|
448
|
+
```javascript
|
|
449
|
+
import { logger } from '@shoru/kitten';
|
|
450
|
+
|
|
451
|
+
logger.info('Information');
|
|
452
|
+
logger.debug({ data }, 'Context');
|
|
453
|
+
logger.warn('Warning');
|
|
454
|
+
logger.error(err, 'Error');
|
|
455
|
+
logger.prompt('Direct output');
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### Database
|
|
459
|
+
|
|
460
|
+
```javascript
|
|
461
|
+
import { LMDBManager } from '@shoru/kitten';
|
|
462
|
+
|
|
463
|
+
const { db } = LMDBManager;
|
|
464
|
+
|
|
465
|
+
const value = db.get('key');
|
|
466
|
+
await db.put('key', 'value');
|
|
467
|
+
await db.remove('key');
|
|
468
|
+
|
|
469
|
+
LMDBManager.isOpen // Boolean
|
|
470
|
+
await LMDBManager.close();
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Configuration
|
|
474
|
+
|
|
475
|
+
```javascript
|
|
476
|
+
import { getConfig } from '@shoru/kitten';
|
|
477
|
+
|
|
478
|
+
const config = await getConfig();
|
|
479
|
+
console.log(config.plugins.dir);
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Serialization
|
|
483
|
+
|
|
484
|
+
```javascript
|
|
485
|
+
import { serialize, deserialize } from '@shoru/kitten';
|
|
486
|
+
|
|
487
|
+
const json = serialize({ buffer: Buffer.from('hello') });
|
|
488
|
+
const data = deserialize(json);
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Time Formatting
|
|
492
|
+
|
|
493
|
+
```javascript
|
|
494
|
+
import { getTimeString } from '@shoru/kitten';
|
|
495
|
+
|
|
496
|
+
const [date, time] = getTimeString(1699999999);
|
|
497
|
+
// ['November 14, 2023', '12:26:39']
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Type Helpers
|
|
501
|
+
|
|
502
|
+
```javascript
|
|
503
|
+
import { isString, toNumber, toBase64 } from '@shoru/kitten';
|
|
504
|
+
|
|
505
|
+
isString('hello') // true
|
|
506
|
+
toNumber(BigInt(123)) // 123
|
|
507
|
+
toBase64(Buffer.from('hi')) // 'aGk='
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Phone Number
|
|
511
|
+
|
|
512
|
+
```javascript
|
|
513
|
+
import { getPN } from '@shoru/kitten';
|
|
514
|
+
|
|
515
|
+
const phone = await getPN(sock, jid); // '1234567890'
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### Spinner
|
|
519
|
+
|
|
520
|
+
```javascript
|
|
521
|
+
import { spinner, pauseSpinner } from '@shoru/kitten';
|
|
522
|
+
|
|
523
|
+
spinner.start('Loading...');
|
|
524
|
+
spinner.stop();
|
|
525
|
+
|
|
526
|
+
// Pause during prompts
|
|
527
|
+
const result = await pauseSpinner(async () => {
|
|
528
|
+
return await askUser();
|
|
529
|
+
});
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## API Reference
|
|
535
|
+
|
|
536
|
+
### Primary
|
|
537
|
+
|
|
538
|
+
```javascript
|
|
539
|
+
import { getClient } from '@shoru/kitten';
|
|
540
|
+
|
|
541
|
+
await getClient(options?) → { sock, session, id }
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Sessions
|
|
545
|
+
|
|
546
|
+
```javascript
|
|
547
|
+
import { listSessions, sessionExists } from '@shoru/kitten';
|
|
548
|
+
|
|
549
|
+
listSessions() → number[]
|
|
550
|
+
sessionExists(id) → boolean
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Formatting
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
import { formatter } from '@shoru/kitten';
|
|
557
|
+
|
|
558
|
+
formatter(sock, rawMessage, eventName?) → FormattedMessage
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Infrastructure
|
|
562
|
+
|
|
563
|
+
```javascript
|
|
564
|
+
import {
|
|
565
|
+
getConfig,
|
|
566
|
+
logger,
|
|
567
|
+
LMDBManager,
|
|
568
|
+
spinner,
|
|
569
|
+
pauseSpinner
|
|
570
|
+
} from '@shoru/kitten';
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Utilities
|
|
574
|
+
|
|
575
|
+
```javascript
|
|
576
|
+
import {
|
|
577
|
+
serialize,
|
|
578
|
+
deserialize,
|
|
579
|
+
getTimeString,
|
|
580
|
+
isString,
|
|
581
|
+
toNumber,
|
|
582
|
+
toBase64,
|
|
583
|
+
getPN
|
|
584
|
+
} from '@shoru/kitten';
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## Complete Example
|
|
590
|
+
|
|
591
|
+
```javascript
|
|
592
|
+
import { getClient, logger } from '@shoru/kitten';
|
|
593
|
+
|
|
594
|
+
const { sock, id } = await getClient({
|
|
595
|
+
id: 0,
|
|
596
|
+
maxRetries: 15,
|
|
597
|
+
onConnect: ({ client }) => {
|
|
598
|
+
logger.info(`Session ${client.id} connected`);
|
|
599
|
+
},
|
|
600
|
+
onDisconnect: ({ message, recoverable }) => {
|
|
601
|
+
logger.warn(`Disconnected: ${message} (recoverable: ${recoverable})`);
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
logger.info(`Running as session ${id}`);
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
19
609
|
|
|
20
610
|
<div align="center">
|
|
21
611
|
|
|
612
|
+
</br>
|
|
613
|
+
|
|
614
|
+
**Made with ❤️ for Whatsapp Community by [Aymane Shoru](https://github.com/Mangaka-bot)**
|
|
22
615
|
|
|
23
|
-
**Made with ❤️ for Whatsapp community**
|
|
24
616
|
</div>
|