whatsapp-cloud-bot 1.0.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +561 -0
  3. package/dist/cjs/Dispatcher.js +153 -0
  4. package/dist/cjs/Dispatcher.js.map +1 -0
  5. package/dist/cjs/Handlers.js +206 -0
  6. package/dist/cjs/Handlers.js.map +1 -0
  7. package/dist/cjs/Markup.js +181 -0
  8. package/dist/cjs/Markup.js.map +1 -0
  9. package/dist/cjs/Message.js +204 -0
  10. package/dist/cjs/Message.js.map +1 -0
  11. package/dist/cjs/Update.js +28 -0
  12. package/dist/cjs/Update.js.map +1 -0
  13. package/dist/cjs/UserContext.js +70 -0
  14. package/dist/cjs/UserContext.js.map +1 -0
  15. package/dist/cjs/WhatsApp.js +125 -0
  16. package/dist/cjs/WhatsApp.js.map +1 -0
  17. package/dist/cjs/index.js +52 -0
  18. package/dist/cjs/index.js.map +1 -0
  19. package/dist/cjs/types/index.js +3 -0
  20. package/dist/cjs/types/index.js.map +1 -0
  21. package/dist/cjs/utils/helpers.js +69 -0
  22. package/dist/cjs/utils/helpers.js.map +1 -0
  23. package/dist/esm/Dispatcher.js +149 -0
  24. package/dist/esm/Dispatcher.js.map +1 -0
  25. package/dist/esm/Handlers.js +191 -0
  26. package/dist/esm/Handlers.js.map +1 -0
  27. package/dist/esm/Markup.js +171 -0
  28. package/dist/esm/Markup.js.map +1 -0
  29. package/dist/esm/Message.js +189 -0
  30. package/dist/esm/Message.js.map +1 -0
  31. package/dist/esm/Update.js +24 -0
  32. package/dist/esm/Update.js.map +1 -0
  33. package/dist/esm/UserContext.js +64 -0
  34. package/dist/esm/UserContext.js.map +1 -0
  35. package/dist/esm/WhatsApp.js +121 -0
  36. package/dist/esm/WhatsApp.js.map +1 -0
  37. package/dist/esm/index.js +10 -0
  38. package/dist/esm/index.js.map +1 -0
  39. package/dist/esm/types/index.js +2 -0
  40. package/dist/esm/types/index.js.map +1 -0
  41. package/dist/esm/utils/helpers.js +62 -0
  42. package/dist/esm/utils/helpers.js.map +1 -0
  43. package/dist/types/Dispatcher.d.ts +25 -0
  44. package/dist/types/Dispatcher.d.ts.map +1 -0
  45. package/dist/types/Handlers.d.ts +61 -0
  46. package/dist/types/Handlers.d.ts.map +1 -0
  47. package/dist/types/Markup.d.ts +50 -0
  48. package/dist/types/Markup.d.ts.map +1 -0
  49. package/dist/types/Message.d.ts +22 -0
  50. package/dist/types/Message.d.ts.map +1 -0
  51. package/dist/types/Update.d.ts +32 -0
  52. package/dist/types/Update.d.ts.map +1 -0
  53. package/dist/types/UserContext.d.ts +16 -0
  54. package/dist/types/UserContext.d.ts.map +1 -0
  55. package/dist/types/WhatsApp.d.ts +49 -0
  56. package/dist/types/WhatsApp.d.ts.map +1 -0
  57. package/dist/types/index.d.ts +11 -0
  58. package/dist/types/index.d.ts.map +1 -0
  59. package/dist/types/types/index.d.ts +194 -0
  60. package/dist/types/types/index.d.ts.map +1 -0
  61. package/dist/types/utils/helpers.d.ts +6 -0
  62. package/dist/types/utils/helpers.d.ts.map +1 -0
  63. package/package.json +81 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Radi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,561 @@
1
+ # WhatsApp Bot Client
2
+
3
+ A powerful, fully-typed TypeScript/JavaScript library for building WhatsApp bots using the [WhatsApp Business Cloud API](https://developers.facebook.com/docs/whatsapp/cloud-api).
4
+
5
+ [![npm version](https://img.shields.io/npm/v/whatsapp-cloud-bot-ts.svg)](https://www.npmjs.com/package/whatsapp-cloud-bot-ts)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.2-blue.svg)](https://www.typescriptlang.org/)
8
+
9
+ ## Features
10
+
11
+ ✨ **Fully Typed** - Complete TypeScript support with comprehensive type definitions
12
+ 🚀 **Async/Await** - Modern async JavaScript architecture built from the ground up
13
+ 📦 **Dual Package** - Works with both ESM and CommonJS
14
+ 🎯 **Event-Driven** - Elegant handler-based message routing
15
+ 💬 **Interactive Messages** - Support for buttons, lists, and location requests
16
+ 📸 **Media Support** - Send and receive images, videos, audio, documents, and stickers
17
+ 🔄 **Conversation Flow** - Built-in context management and next-step handlers
18
+ 🧪 **Well Tested** - Comprehensive test suite included
19
+ 📚 **Great Documentation** - Detailed guides and API reference
20
+
21
+ ## Table of Contents
22
+
23
+ - [Installation](#installation)
24
+ - [Quick Start](#quick-start)
25
+ - [Getting WhatsApp Credentials](#getting-whatsapp-credentials)
26
+ - [Usage Examples](#usage-examples)
27
+ - [API Reference](#api-reference)
28
+ - [TypeScript Usage](#typescript-usage)
29
+ - [Contributing](#contributing)
30
+ - [License](#license)
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ npm install whatsapp-cloud-bot
36
+
37
+ # or with yarn
38
+ yarn add whatsapp-cloud-bot
39
+
40
+ # or with pnpm
41
+ pnpm add whatsapp-cloud-bot
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ```typescript
47
+ import { WhatsApp } from 'whatsapp-cloud-bot';
48
+
49
+ // Initialize the client
50
+ const client = new WhatsApp({
51
+ numberId: 'YOUR_PHONE_NUMBER_ID',
52
+ token: 'YOUR_ACCESS_TOKEN',
53
+ });
54
+
55
+ // Register a message handler
56
+ client.onMessage(async (update, context) => {
57
+ console.log(`Message from ${update.userDisplayName}: ${update.messageText}`);
58
+ await update.replyMessage('Hello! Thanks for your message.');
59
+ });
60
+
61
+ // Process incoming webhook (in your Express/HTTP server)
62
+ app.post('/webhook', async (req, res) => {
63
+ await client.processUpdate(req.body);
64
+ res.sendStatus(200);
65
+ });
66
+ ```
67
+
68
+ ## Getting WhatsApp Credentials
69
+
70
+ To use this library, you need to obtain a **Phone Number ID** and **Access Token** from the [Facebook Developer Portal](https://developers.facebook.com/).
71
+
72
+ ### Step-by-Step Guide:
73
+
74
+ 1. **Create a Meta/Facebook Developer Account**
75
+ - Go to [developers.facebook.com](https://developers.facebook.com/)
76
+ - Create an account or log in
77
+
78
+ 2. **Create a New App**
79
+ - Click "Create App"
80
+ - Select "Business" as the app type
81
+ - Fill in the required details
82
+
83
+ 3. **Add WhatsApp Product**
84
+ - In your app dashboard, click "Add Product"
85
+ - Find "WhatsApp" and click "Set Up"
86
+
87
+ 4. **Get Your Credentials**
88
+ - **Phone Number ID**: Found in the WhatsApp > Getting Started section
89
+ - **Temporary Token**: Also in the Getting Started section (valid for 24 hours)
90
+ - **Permanent Token**: Follow [this guide](https://developers.facebook.com/docs/whatsapp/business-management-api/get-started#1--acquire-an-access-token-using-a-system-user-or-facebook-login) to create a permanent token
91
+
92
+ 5. **Set Up Webhook** (for receiving messages)
93
+ - In WhatsApp > Configuration
94
+ - Add your webhook URL (must be HTTPS)
95
+ - Subscribe to message events
96
+ - Verify the webhook
97
+
98
+ ### Testing Your Setup
99
+
100
+ WhatsApp provides a test phone number you can use immediately. For production, you'll need to:
101
+ - Add a real phone number
102
+ - Complete business verification
103
+ - Get your app approved
104
+
105
+ ## Usage Examples
106
+
107
+ ### Sending Different Types of Messages
108
+
109
+ #### Text Messages
110
+
111
+ ```typescript
112
+ // Simple text message
113
+ await client.sendMessage('1234567890', 'Hello, World!');
114
+
115
+ // With web preview
116
+ await client.sendMessage('1234567890', 'Check this out: https://example.com', {
117
+ webPagePreview: true
118
+ });
119
+ ```
120
+
121
+ #### Interactive Messages with Buttons
122
+
123
+ ```typescript
124
+ import { InlineKeyboard } from 'whatsapp-cloud-bot';
125
+
126
+ await client.sendMessage(
127
+ '1234567890',
128
+ 'Choose an option:',
129
+ {
130
+ replyMarkup: new InlineKeyboard(['Option 1', 'Option 2', 'Option 3'])
131
+ }
132
+ );
133
+ ```
134
+
135
+ #### Interactive Lists
136
+
137
+ ```typescript
138
+ import { InlineList, ListItem, ListSection } from 'whatsapp-cloud-bot';
139
+
140
+ // Simple list
141
+ const list = new InlineList('Select item', [
142
+ new ListItem('Item 1', 'item_1'),
143
+ new ListItem('Item 2', 'item_2')
144
+ ]);
145
+
146
+ // List with sections
147
+ const sectionedList = new InlineList('Choose category', [
148
+ new ListSection('Fruits', ['Apple', 'Banana', 'Orange']),
149
+ new ListSection('Vegetables', ['Carrot', 'Broccoli', 'Spinach'])
150
+ ]);
151
+
152
+ await client.sendMessage('1234567890', 'Here are your options:', {
153
+ replyMarkup: sectionedList
154
+ });
155
+ ```
156
+
157
+ #### Media Messages
158
+
159
+ ```typescript
160
+ // Send image
161
+ await client.sendImage('1234567890', 'https://example.com/image.jpg', 'Check this out!');
162
+
163
+ // Send video
164
+ await client.sendVideo('1234567890', 'https://example.com/video.mp4');
165
+
166
+ // Send document
167
+ await client.sendDocument('1234567890', 'https://example.com/doc.pdf', 'Here is the file');
168
+
169
+ // Send audio
170
+ await client.sendAudio('1234567890', 'https://example.com/audio.mp3');
171
+ ```
172
+
173
+ #### Location Messages
174
+
175
+ ```typescript
176
+ await client.sendLocation(
177
+ '1234567890',
178
+ 37.7749, // latitude
179
+ -122.4194, // longitude
180
+ 'San Francisco',
181
+ '123 Market St, San Francisco, CA'
182
+ );
183
+ ```
184
+
185
+ #### Template Messages
186
+
187
+ ```typescript
188
+ await client.sendTemplateMessage(
189
+ '1234567890',
190
+ 'hello_world', // template name
191
+ [], // components
192
+ 'en_US' // language code
193
+ );
194
+ ```
195
+
196
+ ### Handling Incoming Messages
197
+
198
+ #### Basic Message Handler
199
+
200
+ ```typescript
201
+ client.onMessage(async (update, context) => {
202
+ console.log(`Received: ${update.messageText}`);
203
+ await update.replyMessage('Got your message!');
204
+ });
205
+ ```
206
+
207
+ #### With Regex Filter
208
+
209
+ ```typescript
210
+ // Only respond to messages matching regex
211
+ client.onMessage(
212
+ async (update, context) => {
213
+ await update.replyMessage('You said hello!');
214
+ },
215
+ { regex: /^(hi|hello|hey)/i }
216
+ );
217
+ ```
218
+
219
+ #### With Custom Filter
220
+
221
+ ```typescript
222
+ client.onMessage(
223
+ async (update, context) => {
224
+ await update.replyMessage('Processing your order...');
225
+ },
226
+ {
227
+ filter: (text) => text.toLowerCase().includes('order')
228
+ }
229
+ );
230
+ ```
231
+
232
+ #### Interactive Message Handler
233
+
234
+ ```typescript
235
+ client.onInteractiveMessage(async (update, context) => {
236
+ if (update.messageText === 'option_1') {
237
+ await update.replyMessage('You selected Option 1');
238
+ }
239
+ });
240
+ ```
241
+
242
+ #### Media Handlers
243
+
244
+ ```typescript
245
+ // Handle images
246
+ client.onImageMessage(async (update, context) => {
247
+ console.log(`Image caption: ${update.messageText}`);
248
+ console.log(`Image ID: ${update.mediaFileId}`);
249
+
250
+ // Download the image
251
+ const filePath = await client.downloadMedia(update.mediaFileId);
252
+ console.log(`Image saved to: ${filePath}`);
253
+ });
254
+
255
+ // Handle videos
256
+ client.onVideoMessage(async (update, context) => {
257
+ await update.replyMessage('Thanks for the video!');
258
+ });
259
+
260
+ // Handle audio
261
+ client.onAudioMessage(async (update, context) => {
262
+ if (update.mediaVoice) {
263
+ await update.replyMessage('Got your voice message!');
264
+ }
265
+ });
266
+
267
+ // Handle documents
268
+ client.onDocumentMessage(async (update, context) => {
269
+ const buffer = await client.downloadMediaData(update.mediaFileId);
270
+ // Process document...
271
+ });
272
+ ```
273
+
274
+ #### Location Handler
275
+
276
+ ```typescript
277
+ client.onLocationMessage(async (update, context) => {
278
+ const { locLatitude, locLongitude, locName } = update;
279
+ await update.replyMessage(
280
+ `Got your location: ${locName || 'Unknown'} (${locLatitude}, ${locLongitude})`
281
+ );
282
+ });
283
+ ```
284
+
285
+ ### Conversation Flow Management
286
+
287
+ #### Using Context
288
+
289
+ ```typescript
290
+ client.onMessage(async (update, context) => {
291
+ if (!context.has('name')) {
292
+ context.set('name', update.messageText);
293
+ await update.replyMessage('Nice to meet you! How old are you?');
294
+ } else if (!context.has('age')) {
295
+ context.set('age', parseInt(update.messageText));
296
+ const name = context.get('name');
297
+ const age = context.get('age');
298
+ await update.replyMessage(`Hello ${name}, you are ${age} years old!`);
299
+ context.clear(); // Reset conversation
300
+ }
301
+ });
302
+ ```
303
+
304
+ #### Using Next Step Handler
305
+
306
+ ```typescript
307
+ import { MessageHandler } from 'whatsapp-cloud-bot';
308
+
309
+ client.onMessage(async (update, context) => {
310
+ if (update.messageText === 'start survey') {
311
+ await update.replyMessage('What is your name?');
312
+
313
+ // Set next handler for this user only
314
+ client.setNextStep(
315
+ update,
316
+ new MessageHandler(async (nextUpdate, nextContext) => {
317
+ const name = nextUpdate.messageText;
318
+ await nextUpdate.replyMessage(`Hello ${name}! Survey complete.`);
319
+ })
320
+ );
321
+ }
322
+ });
323
+ ```
324
+
325
+ ## API Reference
326
+
327
+ ### WhatsApp Client
328
+
329
+ #### Constructor
330
+
331
+ ```typescript
332
+ const client = new WhatsApp(config: WhatsAppConfig);
333
+ ```
334
+
335
+ **Configuration Options:**
336
+ - `numberId` (required): Your WhatsApp Phone Number ID
337
+ - `token` (required): Your WhatsApp Access Token
338
+ - `markAsRead` (optional, default: `true`): Auto-mark messages as read
339
+ - `version` (optional, default: `21`): WhatsApp API version
340
+
341
+ #### Methods
342
+
343
+ **Sending Messages:**
344
+ - `sendMessage(phoneNumber, text, options?)` - Send text message
345
+ - `sendTemplateMessage(phoneNumber, templateName, components?, languageCode?)` - Send template
346
+ - `sendImage(phoneNumber, imagePath, caption?)` - Send image
347
+ - `sendVideo(phoneNumber, videoPath, caption?)` - Send video
348
+ - `sendAudio(phoneNumber, audioPath)` - Send audio
349
+ - `sendDocument(phoneNumber, docPath, caption?)` - Send document
350
+ - `sendLocation(phoneNumber, latitude, longitude, name?, address?)` - Send location
351
+
352
+ **Media Management:**
353
+ - `getMediaUrl(mediaId)` - Get media URL from media ID
354
+ - `downloadMedia(mediaId, filePath?)` - Download media to file
355
+ - `downloadMediaData(mediaId)` - Download media as Buffer
356
+
357
+ **Handler Registration:**
358
+ - `onMessage(action, options?)` - Register text message handler
359
+ - `onInteractiveMessage(action, options?)` - Register interactive handler
360
+ - `onImageMessage(action, options?)` - Register image handler
361
+ - `onAudioMessage(action, options?)` - Register audio handler
362
+ - `onVideoMessage(action, options?)` - Register video handler
363
+ - `onDocumentMessage(action, options?)` - Register document handler
364
+ - `onStickerMessage(action, options?)` - Register sticker handler
365
+ - `onLocationMessage(action, options?)` - Register location handler
366
+
367
+ **Flow Control:**
368
+ - `setNextStep(update, handler, fallback?, fallbackRegex?)` - Set next step handler
369
+ - `clearNextStep(phoneNumber)` - Clear next step handler
370
+
371
+ **Webhook Processing:**
372
+ - `processUpdate(webhookPayload)` - Process incoming webhook
373
+
374
+ ### Update Object
375
+
376
+ Available in all handler functions as the first parameter:
377
+
378
+ ```typescript
379
+ interface Update {
380
+ bot: WhatsApp;
381
+ userDisplayName: string;
382
+ userPhoneNumber: string;
383
+ messageId: string;
384
+ messageText?: string;
385
+ message: WhatsAppMessage;
386
+
387
+ // Media properties (when applicable)
388
+ mediaMimeType?: string;
389
+ mediaFileId?: string;
390
+ mediaHash?: string;
391
+ mediaVoice?: boolean;
392
+
393
+ // Location properties (when applicable)
394
+ locLatitude?: number;
395
+ locLongitude?: number;
396
+ locName?: string;
397
+ locAddress?: string;
398
+
399
+ // Methods
400
+ replyMessage(text, options?): Promise<AxiosResponse>;
401
+ replyMedia(mediaPath, options?): Promise<AxiosResponse>;
402
+ replyTemplate(templateName, components?, languageCode?): Promise<AxiosResponse>;
403
+ }
404
+ ```
405
+
406
+ ### UserContext Object
407
+
408
+ Available in all handler functions as the second parameter:
409
+
410
+ ```typescript
411
+ interface UserContext {
412
+ userData: Record<string, any>;
413
+
414
+ set(key: string, value: any): void;
415
+ get<T>(key: string, defaultValue?: T): T | undefined;
416
+ has(key: string): boolean;
417
+ delete(key: string): void;
418
+ clear(): void;
419
+ keys(): string[];
420
+ size(): number;
421
+ }
422
+ ```
423
+
424
+ ## TypeScript Usage
425
+
426
+ The library is written in TypeScript and provides full type definitions:
427
+
428
+ ```typescript
429
+ import {
430
+ WhatsApp,
431
+ Update,
432
+ UserContext,
433
+ InlineKeyboard,
434
+ HandlerFunction,
435
+ } from 'whatsapp-cloud-bot';
436
+
437
+ // Type-safe handler
438
+ const myHandler: HandlerFunction = async (
439
+ update: Update,
440
+ context?: UserContext
441
+ ) => {
442
+ // Full autocomplete and type checking
443
+ const text: string | undefined = update.messageText;
444
+ await update.replyMessage('Hello!');
445
+ };
446
+
447
+ client.onMessage(myHandler);
448
+ ```
449
+
450
+ ## Setting Up a Webhook Server
451
+
452
+ ### Express.js Example
453
+
454
+ ```typescript
455
+ import express from 'express';
456
+ import { WhatsApp } from 'whatsapp-cloud-bot';
457
+
458
+ const app = express();
459
+ const client = new WhatsApp({
460
+ numberId: process.env.WA_PHONE_NUMBER_ID!,
461
+ token: process.env.WA_TOKEN!,
462
+ });
463
+
464
+ // Webhook verification (GET)
465
+ app.get('/webhook', (req, res) => {
466
+ const mode = req.query['hub.mode'];
467
+ const token = req.query['hub.verify_token'];
468
+ const challenge = req.query['hub.challenge'];
469
+
470
+ if (mode === 'subscribe' && token === process.env.WEBHOOK_VERIFY_TOKEN) {
471
+ res.status(200).send(challenge);
472
+ } else {
473
+ res.sendStatus(403);
474
+ }
475
+ });
476
+
477
+ // Webhook handler (POST)
478
+ app.post('/webhook', express.json(), async (req, res) => {
479
+ try {
480
+ await client.processUpdate(req.body);
481
+ res.sendStatus(200);
482
+ } catch (error) {
483
+ console.error('Webhook error:', error);
484
+ res.sendStatus(500);
485
+ }
486
+ });
487
+
488
+ // Register handlers
489
+ client.onMessage(async (update) => {
490
+ await update.replyMessage('Hello from Express!');
491
+ });
492
+
493
+ app.listen(3000, () => {
494
+ console.log('Webhook server running on port 3000');
495
+ });
496
+ ```
497
+
498
+ ## Best Practices
499
+
500
+ 1. **Use Environment Variables** for sensitive data:
501
+ ```typescript
502
+ const client = new WhatsApp({
503
+ numberId: process.env.WA_PHONE_NUMBER_ID!,
504
+ token: process.env.WA_TOKEN!,
505
+ });
506
+ ```
507
+
508
+ 2. **Handle Errors Gracefully**:
509
+ ```typescript
510
+ client.onMessage(async (update) => {
511
+ try {
512
+ await update.replyMessage('Hello!');
513
+ } catch (error) {
514
+ console.error('Failed to send message:', error);
515
+ }
516
+ });
517
+ ```
518
+
519
+ 3. **Use Context for Stateful Conversations**:
520
+ ```typescript
521
+ client.onMessage(async (update, context) => {
522
+ if (!context.has('started')) {
523
+ context.set('started', true);
524
+ await update.replyMessage('Welcome! What is your name?');
525
+ }
526
+ });
527
+ ```
528
+
529
+ 4. **Format Phone Numbers Consistently**:
530
+ ```typescript
531
+ // Library handles formatting, but ensure you include country code
532
+ await client.sendMessage('1234567890', 'Hello'); // Good
533
+ ```
534
+
535
+ ## Contributing
536
+
537
+ Contributions are welcome! Please feel free to submit a Pull Request.
538
+
539
+ ## License
540
+
541
+ MIT © [Radi](https://github.com/Radi-dev)
542
+
543
+ ## Links
544
+
545
+ - [WhatsApp Business API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api)
546
+ - [GitHub Repository](https://github.com/Radi-dev/whatsapp-cloud-bot-ts)
547
+ - [NPM Package](https://www.npmjs.com/package/whatsapp-cloud-bot-ts)
548
+ - [Issue Tracker](https://github.com/Radi-dev/whatsapp-cloud-bot-ts/issues)
549
+
550
+ ## Support
551
+
552
+ If you find this library useful, please consider:
553
+ - ⭐ Starring the repository
554
+ - 🐛 Reporting bugs
555
+ - 💡 Suggesting new features
556
+ - 📖 Improving documentation
557
+ - 🤝 Contributing code
558
+
559
+ ---
560
+
561
+ Made with ❤️ by the community