@green-api/greenapi-integration 0.6.0 → 0.6.2

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 (5) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1080 -1061
  3. package/README.ru.md +1092 -1068
  4. package/dist/types/types.d.ts +161 -6
  5. package/package.json +42 -41
package/README.md CHANGED
@@ -1,1061 +1,1080 @@
1
- # Universal Integration Platform for GREEN-API
2
-
3
- ## Support links
4
-
5
- [![Support](https://img.shields.io/badge/support@green--api.com-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:support@greenapi.com)
6
- [![Support](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/greenapi_support_eng_bot)
7
- [![Support](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/77273122366)
8
-
9
- ## Guides & News
10
-
11
- [![Guides](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white)](https://www.youtube.com/@greenapi-en)
12
- [![News](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/green_api)
13
- [![News](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://whatsapp.com/channel/0029VaLj6J4LNSa2B5Jx6s3h)
14
-
15
- - [Документация на русском языке](./README.ru.md)
16
-
17
- A flexible integration platform designed to simplify the process of connecting GREEN-API's WhatsApp gateway with various
18
- third-party services.
19
-
20
- ## Table of Contents
21
-
22
- - [Installation](#installation)
23
- - [Core Components](#core-components)
24
- - [Developer Guide](#developer-guide)
25
- - [Working Example](#working-example)
26
- - [Real-World Examples](#real-world-examples)
27
- - [Best Practices](#best-practices)
28
-
29
- ## Installation
30
-
31
- ```bash
32
- npm install @green-api/greenapi-integration
33
- ```
34
-
35
- ## Core Components
36
-
37
- ### 1. BaseAdapter
38
-
39
- The foundation of your integration. Handles message & instance management, and platform-specific logic.
40
-
41
- ```typescript
42
- abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage, TUser extends BaseUser = BaseUser, TInstance extends Instance = Instance> {
43
- private readonly gaLogger = GreenApiLogger.getInstance(this.constructor.name);
44
-
45
- public constructor(
46
- transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>,
47
- storage: StorageProvider<TUser, TInstance>,
48
- );
49
-
50
- public abstract createPlatformClient(params: any): Promise<any>;
51
-
52
- public abstract sendToPlatform(message: TPlatformMessage, instance: TInstance): Promise<void>;
53
- }
54
- ```
55
-
56
- #### Methods
57
-
58
- When extending BaseAdapter, your implementation has access to several methods:
59
-
60
- ##### Webhook Handling
61
-
62
- These webhook handling methods call your message transformation methods automatically, without the need to use them
63
- directly in your code.
64
-
65
- ```typescript
66
- // Handle webhooks from your platform
67
- await adapter.handlePlatformWebhook(webhookData, instanceId);
68
-
69
- // Handle webhooks from GREEN-API. The second parameter is telling the function to handle only specific webhooks.
70
- // The second parameter must be specified, otherwise webhooks will not be processed.
71
- await adapter.handleGreenApiWebhook(webhook, ['incomingMessageReceived']);
72
- ```
73
-
74
- ##### Instance Management
75
-
76
- ```typescript
77
- // Create new instance
78
- const instance = await adapter.createInstance(instanceData, settings, userEmail);
79
-
80
- // Get instance details
81
- const details = await adapter.getInstance(instanceId);
82
-
83
- // Remove instance
84
- await adapter.removeInstance(instanceId);
85
- ```
86
-
87
- ##### User Management
88
-
89
- ```typescript
90
- // Create new user
91
- const user = await adapter.createUser(userEmail, userData);
92
-
93
- // Update user
94
- await adapter.updateUser(userEmail, updateData);
95
- ```
96
-
97
- #### Webhook Implementation Example
98
-
99
- ```typescript
100
- // Platform webhook endpoint
101
- app.post('/webhook/platform', async (req, res) => {
102
- try {
103
- await adapter.handlePlatformWebhook(req.body, instanceId);
104
- res.status(200).send();
105
- } catch (error) {
106
- console.error('Failed to handle platform webhook:', error);
107
- res.status(500).send();
108
- }
109
- });
110
-
111
- // GREEN-API webhook endpoint
112
- app.post('/webhook/green-api', async (req, res) => {
113
- try {
114
- // Process specific webhook types
115
- await adapter.handleGreenApiWebhook(req.body, [
116
- 'incomingMessageReceived',
117
- 'outgoingMessageStatus'
118
- ]);
119
- res.status(200).send();
120
- } catch (error) {
121
- console.error('Failed to handle GREEN-API webhook:', error);
122
- res.status(500).send();
123
- }
124
- });
125
- ```
126
-
127
- ### 2. MessageTransformer
128
-
129
- Handles message format conversion between GREEN-API and your platform.
130
-
131
- ```typescript
132
- abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
133
- abstract toPlatformMessage(webhook: GreenApiWebhook): TPlatformMessage;
134
-
135
- abstract toGreenApiMessage(message: TPlatformWebhook): Message;
136
- }
137
- ```
138
-
139
- ### 3. StorageProvider
140
-
141
- Interface for data persistence operations.
142
-
143
- ```typescript
144
- abstract class StorageProvider<
145
- TUser extends BaseUser = BaseUser,
146
- TInstance extends Instance = Instance,
147
- TUserCreate extends Record<string, any> = any,
148
- TUserUpdate extends Record<string, any> = any
149
- > {
150
- abstract createInstance(instance: Instance): Promise<TInstance>;
151
-
152
- abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
153
-
154
- abstract removeInstance(instanceId: number | bigint): Promise<TInstance>;
155
-
156
- abstract createUser(data: TUserCreate): Promise<TUser>;
157
-
158
- abstract findUser(identifier: string): Promise<TUser | null>;
159
-
160
- abstract updateUser(identifier: string, data: Partial<TUserUpdate>): Promise<TUser>;
161
- }
162
- ```
163
-
164
- ### 4. BaseGreenApiAuthGuard
165
-
166
- Handles webhook authentication for incoming GREEN-API requests.
167
-
168
- ```typescript
169
- abstract class BaseGreenApiAuthGuard<T extends BaseRequest = BaseRequest> {
170
- private readonly gaLogger = GreenApiLogger.getInstance(this.constructor.name);
171
-
172
- constructor(protected storage: StorageProvider);
173
-
174
- // Validates incoming webhook requests
175
- async validateRequest(request: T): Promise<boolean>;
176
- }
177
- ```
178
-
179
- Example implementation of `BaseGreenApiAuthGuard`:
180
-
181
- ```typescript
182
- class YourAuthGuard extends BaseGreenApiAuthGuard<YourRequest> {
183
- constructor(storage: StorageProvider) {
184
- super(storage);
185
- }
186
- }
187
-
188
- // Using with Express
189
- app.post('/webhook', async (req, res) => {
190
- const guard = new YourAuthGuard(storage);
191
- try {
192
- await guard.validateRequest(req);
193
- // Process webhook
194
- } catch (error) {
195
- if (error instanceof AuthenticationError) {
196
- res.status(401).json({error: error.message});
197
- return;
198
- }
199
- res.status(500).json({error: 'Internal server error'});
200
- }
201
- });
202
- ```
203
-
204
- ### 5. GreenApiLogger
205
-
206
- A structured JSON logger with colored output. Provides consistent logging format across your application with
207
- proper error handling and serialization support.
208
-
209
- ```typescript
210
- const logger = GreenApiLogger.getInstance("YourComponent");
211
-
212
- // Basic logging
213
- logger.debug("Debug message", {someContext: "value"});
214
- logger.info("Info message", {userId: 123});
215
- logger.warn("Warning message", {alert: true});
216
- logger.error("Error occurred", {errorCode: 500});
217
- logger.fatal("Fatal error", {critical: true});
218
-
219
- // Error logging with full context
220
- try {
221
- await someOperation();
222
- } catch (error) {
223
- logger.logErrorResponse(error, "Operation failed", {
224
- operationId: "123",
225
- additionalInfo: "some context"
226
- });
227
- }
228
- ```
229
-
230
- #### Features
231
-
232
- - Structured JSON logging with consistent format
233
- - Colored output based on log level (debug=cyan, info=green, warn=yellow, error=red, fatal=magenta)
234
- - Built-in error handling with stack trace formatting
235
- - Automatic serialization
236
- - Framework agnostic - works with any Node.js application
237
- - Special handling for Axios errors with detailed request/response info
238
-
239
- #### Log Levels
240
-
241
- - `debug` - Detailed information for debugging
242
- - `info` - General information about system operation
243
- - `warn` - Warning messages for potentially harmful situations
244
- - `error` - Error messages for serious problems
245
- - `fatal` - Critical errors that require immediate attention
246
- - `log` - Alternative to info (for compatibility)
247
-
248
- #### Output Format
249
-
250
- ```json
251
- {
252
- "timestamp": "30/01/2025, 04:34:49",
253
- "level": "error",
254
- "context": "CoreService",
255
- "message": "Operation failed",
256
- "error": "Failed to process request",
257
- "stack": [
258
- "Error: Failed to process request",
259
- " at CoreService.process (/app/service.js:123:45)",
260
- " at async Router.handle (/app/router.js:67:89)"
261
- ],
262
- "additionalContext": {
263
- "requestId": "abc-123",
264
- "userId": "user_456"
265
- }
266
- }
267
- ```
268
-
269
- #### Error Handling
270
-
271
- ```typescript
272
- // Axios error handling
273
- try {
274
- await apiRequest();
275
- } catch (error) {
276
- logger.logErrorResponse(error, "API Request failed", {
277
- endpoint: "/users",
278
- method: "POST"
279
- });
280
- }
281
- ```
282
-
283
- // Will output detailed API error info:
284
-
285
- ```
286
- {
287
- "timestamp": "30/01/2025, 04:34:49",
288
- "level": "error",
289
- "context": "ApiService",
290
- "message": "API Request failed - API Error:",
291
- "status": 400,
292
- "statusText": "Bad Request",
293
- "data": { "error": "Invalid input" },
294
- "url": "https://api.example.com/users",
295
- "method": "POST",
296
- "endpoint": "/users"
297
- }
298
- ```
299
-
300
- #### Using with Frameworks
301
-
302
- The logger is framework-agnostic but can be easily integrated with any framework:
303
-
304
- ```typescript
305
- // NestJS example
306
- const app = await NestFactory.create(AppModule, {
307
- logger: GreenApiLogger.getInstance("NestJS")
308
- });
309
-
310
- // Express example
311
- app.use((err, req, res, next) => {
312
- const logger = GreenApiLogger.getInstance("Express");
313
- logger.error("Request failed", {
314
- path: req.path,
315
- method: req.method,
316
- error: err.message
317
- });
318
- next(err);
319
- });
320
- ```
321
-
322
- #### Methods
323
-
324
- ##### Basic Logging Methods
325
-
326
- - `debug(message: string, context?: Record<string, any>)`: Log debug level message
327
- - `info(message: string, context?: Record<string, any>)`: Log info level message
328
- - `warn(message: string, context?: Record<string, any>)`: Log warning level message
329
- - `error(message: string, context?: Record<string, any>)`: Log error level message
330
- - `fatal(message: string, context?: Record<string, any>)`: Log fatal level message
331
- - `log(message: string, context?: string)`: Alternative to info method
332
-
333
- ##### Special Methods
334
-
335
- - `logErrorResponse(error: any, context: string, additionalContext?: Record<string, any>)`:
336
- Enhanced error logging with special handling for Axios errors and stack traces
337
-
338
- ##### Utility Methods
339
-
340
- - `getInstance(context: string = "Global"): GreenApiLogger`: Get or create logger instance for specified context
341
-
342
- #### Best Practices
343
-
344
- 1. **Use Consistent Context Names**
345
-
346
- ```typescript
347
- // In your component/service
348
- private readonly logger = GreenApiLogger.getInstance(YourService.name);
349
- ```
350
-
351
- 2. **Include Relevant Context**
352
-
353
- ```typescript
354
- logger.info("User action completed", {
355
- userId: user.id,
356
- action: "profile_update",
357
- duration: timeTaken
358
- });
359
- ```
360
-
361
- 3. **Proper Error Handling**
362
-
363
- ```typescript
364
- try {
365
- await complexOperation();
366
- } catch (error) {
367
- logger.logErrorResponse(error, "Complex operation failed", {
368
- operationId: id,
369
- parameters: params
370
- });
371
- }
372
- ```
373
-
374
- 4. **Use Appropriate Log Levels**
375
-
376
- ```typescript
377
- // Debug for detailed information
378
- logger.debug("Processing chunk", {chunkId: 123, size: 1024});
379
-
380
- // Info for general operation
381
- logger.info("User logged in", {userId: 456});
382
-
383
- // Warn for potential issues
384
- logger.warn("High memory usage", {memoryUsage: "85%"});
385
-
386
- // Error for actual problems
387
- logger.error("Database connection failed", {dbHost: "primary"});
388
-
389
- // Fatal for critical issues
390
- logger.fatal("System shutdown required", {reason: "data corruption"});
391
- ```
392
-
393
- ### 6. GreenApiClient
394
-
395
- Direct interface to GREEN-API methods.
396
-
397
- ```typescript
398
- const client = new GreenApiClient({
399
- idInstance: 'your_instance_id',
400
- apiTokenInstance: 'your_token'
401
- });
402
-
403
- // Examples:
404
- await client.setProfilePicture(fileBlob);
405
- await client.getAuthorizationCode(phoneNumber);
406
- await client.getQR();
407
- ```
408
-
409
- ## Developer Guide
410
-
411
- This guide will walk you through creating your first integration with GREEN-API's WhatsApp gateway.
412
-
413
- ### Project Structure
414
-
415
- ```
416
- your-integration/
417
- ├── src/
418
- │ ├── core/
419
- │ │ ├── adapter.ts # Your platform adapter
420
- │ │ ├── transformer.ts # Message transformer
421
- │ │ ├── storage.ts # Data storage implementation
422
- │ │ └── router.ts # Webhook endpoints
423
- │ ├── types/
424
- │ │ └── types.ts # Platform-specific types
425
- │ └── main.ts # Main exports
426
- ├── package.json
427
- └── tsconfig.json
428
- ```
429
-
430
- ```mermaid
431
- graph TB
432
- subgraph "WhatsApp to Platform"
433
- WA[WhatsApp] -->|Send message| GA1[GREEN-API]
434
- GA1 -->|Webhook| INT1[Your Integration]
435
- INT1 -->|1 . Validate webhook| GD1[BaseGreenApiAuthGuard]
436
- INT1 -->|2 . Transform message| TR1[MessageTransformer]
437
- INT1 -->|3 . Send to platform| PL1[Your Platform]
438
- end
439
-
440
- subgraph "Platform to WhatsApp"
441
- PL2[Your Platform] -->|Webhook| INT2[Your Integration]
442
- INT2 -->|1 . Transform message| TR2[MessageTransformer]
443
- INT2 -->|2 . Send via API| GA2[GREEN-API]
444
- GA2 -->|Send message| WA2[WhatsApp]
445
- end
446
-
447
- subgraph "Components"
448
- style Components fill: #f9f9f9, stroke: #333, stroke-width: 2px
449
- TR[MessageTransformer]
450
- ST[StorageProvider]
451
- AD[BaseAdapter]
452
- GD[WebhookGuard]
453
- end
454
- ```
455
-
456
- ### Implementation Steps
457
-
458
- #### Step 1: Define Platform Types
459
-
460
- First, define the message types for your platform:
461
-
462
- ```typescript
463
- // types/types.ts
464
- export interface YourPlatformWebhook {
465
- id: string;
466
- from: string;
467
- message: string;
468
- timestamp: number;
469
- // Add other platform-specific fields
470
- }
471
-
472
- export interface YourPlatformMessage {
473
- recipient: string;
474
- content: string;
475
- // Add other platform-specific fields
476
- }
477
- ```
478
-
479
- #### Step 2: Create Message Transformer
480
-
481
- Create a transformer that converts messages between your platform's format and GREEN-API's format:
482
-
483
- ```typescript
484
- // core/transformer.ts
485
- import { MessageTransformer, Message, GreenApiWebhook } from '@green-api/greenapi-integration';
486
- import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
487
-
488
- export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
489
- toPlatformMessage(webhook: GreenApiWebhook): YourPlatformMessage {
490
- // Transform GREEN-API webhook to your platform format
491
- return {
492
- recipient: webhook.senderData.sender,
493
- content: webhook.messageData.textMessageData?.textMessage || '',
494
- };
495
- }
496
-
497
- toGreenApiMessage(message: YourPlatformWebhook): Message {
498
- // Transform your platform webhook to GREEN-API format
499
- return {
500
- type: 'text',
501
- chatId: message.from,
502
- message: message.message,
503
- };
504
- }
505
- }
506
- ```
507
-
508
- #### Step 3: Implement Storage Provider
509
-
510
- Create a storage provider to manage users and instances. You can use any database or ORM:
511
-
512
- ```typescript
513
- // core/storage.ts
514
- import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
515
- import { PrismaClient } from '@prisma/client'; // Or your database client
516
-
517
- export class YourStorage extends StorageProvider {
518
- private db: PrismaClient;
519
-
520
- constructor() {
521
- this.db = new PrismaClient();
522
- }
523
-
524
- async findUserByEmail(email: string) {
525
- return this.db.user.findUnique({where: {email}});
526
- }
527
-
528
- async createInstance(instance: Instance) {
529
- return this.db.instance.create({
530
- data: {
531
- idInstance: instance.idInstance,
532
- apiTokenInstance: instance.apiTokenInstance,
533
- userId: instance.userId,
534
- settings: instance.settings || {},
535
- },
536
- });
537
- }
538
-
539
- // Implement other required methods
540
- }
541
- ```
542
-
543
- #### Step 4: Create Your Platform Adapter
544
-
545
- The adapter handles the actual communication between platforms:
546
-
547
- ```typescript
548
- // core/adapter.ts
549
- import { BaseAdapter, BaseInstance } from '@green-api/greenapi-integration';
550
- import { YourPlatformClient } from 'your-platform-sdk';
551
- import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
552
-
553
- export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMessage> {
554
- async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
555
- return new YourPlatformClient({
556
- baseUrl: config.apiUrl,
557
- apiKey: config.apiKey,
558
- });
559
- }
560
-
561
- async sendToPlatform(message: YourPlatformMessage, instance: Instance) {
562
- const client = await this.createPlatformClient(instance.config);
563
- await client.sendMessage(message);
564
- }
565
- }
566
- ```
567
-
568
- #### Step 5: Implement Webhook Controller
569
-
570
- Define webhook endpoints that your application will listen to:
571
-
572
- ```typescript
573
- // core/webhook.ts
574
- import express from 'express';
575
- import { YourAdapter } from '../core/adapter';
576
- import { YourTransformer } from '../core/transformer';
577
- import { YourStorage } from '../core/storage';
578
-
579
- const router = express.Router();
580
- const storage = new YourStorage();
581
- const transformer = new YourTransformer();
582
- const adapter = new YourAdapter(transformer, storage);
583
-
584
- class WebhookGuard extends BaseGreenApiAuthGuard {
585
- constructor(storage: StorageProvider) {
586
- super(storage);
587
- }
588
- }
589
-
590
- const guard = new WebhookGuard(storage);
591
-
592
- // Webhook endpoints
593
- router.post('/green-api', async (req, res) => {
594
- try {
595
- // Validate webhook first
596
- await guard.validateRequest(req);
597
-
598
- // Process webhook if validation passed
599
- // As the second parameter, specfify the types of webhooks to be processed (otherwise skipped)
600
- await adapter.handleGreenApiWebhook(req.body, ['incomingMessageReceived']);
601
- res.status(200).json({status: 'ok'});
602
- } catch (error) {
603
- if (error instanceof AuthenticationError) {
604
- res.status(401).json({error: error.message});
605
- return;
606
- }
607
- console.error('Webhook error:', error);
608
- res.status(500).json({error: 'Internal server error'});
609
- }
610
- });
611
-
612
- router.post('/platform', async (req, res) => {
613
- try {
614
- const instanceId = req.query.instanceId;
615
- await adapter.handlePlatformWebhook(req.body, instanceId);
616
- res.status(200).json({status: 'ok'});
617
- } catch (error) {
618
- console.error('Platform webhook error:', error);
619
- res.status(500).json({error: 'Internal server error'});
620
- }
621
- });
622
-
623
- router.post('/instance', async (req, res) => {
624
- try {
625
- const {idInstance, apiTokenInstance, userEmail} = req.body;
626
-
627
- if (!idInstance || !apiTokenInstance || !userEmail) {
628
- throw new BadRequestError('Required fields missing');
629
- }
630
-
631
- const user = await storage.findUserByEmail(userEmail);
632
- const instance = await adapter.createInstance({
633
- idInstance: Number(idInstance),
634
- apiTokenInstance,
635
- settings: {
636
- webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
637
- webhookUrlToken: `token_${Date.now()}`,
638
- incomingWebhook: 'yes'
639
- },
640
- userId: user.id
641
- });
642
-
643
- res.status(200).json({
644
- status: 'ok',
645
- data: instance,
646
- message: 'Instance created successfully. Please wait 2 minutes for settings to apply.'
647
- });
648
-
649
- } catch (error) {
650
- console.error('Instance creation error:', error);
651
- res.status(500).json({error: 'Failed to create instance'});
652
- }
653
- });
654
-
655
- export default router;
656
- ```
657
-
658
- #### Step 6: Create Application Entry Point
659
-
660
- Put it all together in your entrypoint:
661
-
662
- ```typescript
663
- // main.ts
664
- import express from 'express';
665
- import bodyParser from 'body-parser';
666
- import dotenv from 'dotenv';
667
- import webhookRouter from './controllers/webhook';
668
- import { YourAdapter } from './core/adapter';
669
- import { YourTransformer } from './core/transformer';
670
- import { YourStorage } from './core/storage';
671
-
672
- // Load environment variables
673
- dotenv.config();
674
-
675
- async function bootstrap() {
676
- // Initialize components
677
- const storage = new YourStorage();
678
- const transformer = new YourTransformer();
679
- const adapter = new YourAdapter(transformer, storage);
680
-
681
- // Create Express application
682
- const app = express();
683
- app.use(bodyParser.json());
684
-
685
- // Set up webhook routes
686
- app.use('/webhook', webhookRouter);
687
-
688
- // Start server
689
- const port = process.env.PORT || 3000;
690
- app.listen(port, () => {
691
- console.log(`Server running on port ${port}`);
692
- });
693
-
694
- console.log('Integration platform ready!');
695
- }
696
-
697
- // Handle errors
698
- bootstrap();
699
- ```
700
-
701
- ### Publishing Your Integration
702
-
703
- 1. **Prepare package.json**
704
-
705
- ```json
706
- {
707
- "name": "greenapi-integration-yourplatform",
708
- "version": "1.0.0",
709
- "main": "dist/index.js",
710
- "types": "dist/index.d.ts",
711
- "scripts": {
712
- "build": "tsc",
713
- "prepublishOnly": "npm run build"
714
- },
715
- "dependencies": {
716
- "@green-api/greenapi-integration": "^0.4.0",
717
- "express": "^4.18.2"
718
- // other dependencies
719
- }
720
- }
721
- ```
722
-
723
- 2. **Build and Publish**
724
-
725
- ```bash
726
- npm run build
727
- npm publish
728
- ```
729
-
730
- ## Working Example
731
-
732
- Check out the `/examples/custom-adapter` directory for a complete working example showing:
733
-
734
- - Two-way message flow between WhatsApp and a custom platform
735
- - Webhook handling
736
- - Instance setup and configuration
737
- - Message transformation
738
- - Error handling
739
-
740
- ### Running the Example
741
-
742
- 1. Clone the repository
743
- 2. Update .env with your GREEN-API credentials:
744
-
745
- ```env
746
- VISITOR_ID_INSTANCE=your_visitor_instance_id
747
- VISITOR_API_TOKEN=your_visitor_instance_token
748
- AGENT_ID_INSTANCE=your_agent_instance_id
749
- AGENT_API_TOKEN=your_agent_instance_token
750
- AGENT_PHONE_NUMBER=your_agent_phone_number
751
- WEBHOOK_URL=your_webhook_url
752
- PORT=3000
753
- ```
754
-
755
- 3. Install dependencies and run:
756
-
757
- ```bash
758
- cd examples/custom-adapter
759
- npm install
760
- npm start
761
- ```
762
-
763
- ## Complete Example Implementation
764
-
765
- ### Project Structure
766
-
767
- ```
768
- examples/
769
- └── custom-adapter/
770
- ├── src/
771
- │ ├── main.ts
772
- │ ├── simple-adapter.ts
773
- │ ├── simple-transformer.ts
774
- │ ├── simple-storage.ts
775
- │ └── types.ts
776
- ├── .env
777
- └── package.json
778
- ```
779
-
780
- ### types.ts
781
-
782
- ```typescript
783
- interface SimplePlatformWebhook {
784
- messageId: string;
785
- from: string;
786
- text: string;
787
- timestamp: number;
788
- }
789
-
790
- interface SimplePlatformMessage {
791
- to: string;
792
- content: string;
793
- replyTo?: string;
794
- }
795
- ```
796
-
797
- ### simple-transformer.ts
798
-
799
- ```typescript
800
- import {
801
- MessageTransformer,
802
- Message,
803
- GreenApiWebhook,
804
- formatPhoneNumber,
805
- IntegrationError,
806
- } from "@green-api/greenapi-integration";
807
- import { SimplePlatformMessage, SimplePlatformWebhook } from "./types";
808
-
809
- export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
810
- toPlatformMessage(webhook: GreenApiWebhook): SimplePlatformMessage {
811
- if (webhook.typeWebhook === "incomingMessageReceived") {
812
- if (webhook.messageData.typeMessage !== "extendedTextMessage") {
813
- throw new IntegrationError("Only text messages are supported", "BAD_REQUEST_ERROR", 400);
814
- }
815
-
816
- return {
817
- to: webhook.senderData.sender,
818
- content: webhook.messageData.extendedTextMessageData?.text || "",
819
- };
820
- }
821
- throw new IntegrationError("Only incomingMessageReceived type webhooks are supported", "INTEGRATION_ERROR", 500);
822
- }
823
-
824
- toGreenApiMessage(message: SimplePlatformWebhook): Message {
825
- return {
826
- type: "text",
827
- chatId: formatPhoneNumber(message.from),
828
- message: message.text,
829
- };
830
- }
831
- }
832
- ```
833
-
834
- ### simple-storage.ts
835
-
836
- ```typescript
837
- import { StorageProvider, BaseUser, Instance } from '@green-api/greenapi-integration';
838
-
839
- export class SimpleStorage extends StorageProvider {
840
- private users: Map<string, BaseUser> = new Map();
841
- private instances: Map<number, Instance> = new Map();
842
-
843
- async createInstance(instance: Instance, userId: bigint): Promise<Instance> {
844
- this.instances.set(Number(instance.idInstance), {
845
- ...instance,
846
- });
847
- return instance;
848
- }
849
-
850
- async getInstance(idInstance: number): Promise<Instance | null> {
851
- return this.instances.get(idInstance) || null;
852
- }
853
-
854
- async removeInstance(instanceId: number): Promise<Instance> {
855
- const instance = this.instances.get(instanceId);
856
- if (!instance) throw new Error('Instance not found');
857
- this.instances.delete(instanceId);
858
- return instance;
859
- }
860
-
861
- async createUser(data: any): Promise<BaseUser> {
862
- const user = {id: Date.now(), ...data};
863
- this.users.set(data.email, user);
864
- return user;
865
- }
866
-
867
- async findUser(identifier: string): Promise<BaseUser | null> {
868
- return this.users.get(identifier) || null;
869
- }
870
-
871
- async updateUser(identifier: string, data: any): Promise<BaseUser> {
872
- const user = await this.findUser(identifier);
873
- if (!user) throw new Error('User not found');
874
- const updated = {...user, ...data};
875
- this.users.set(identifier, updated);
876
- return updated;
877
- }
878
- }
879
- ```
880
-
881
- ### simple-adapter.ts
882
-
883
- ```typescript
884
- import { BaseAdapter, Instance } from "@green-api/greenapi-integration";
885
- import { SimplePlatformMessage, SimplePlatformWebhook } from "./types";
886
- import axios from 'axios';
887
-
888
- export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
889
- async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
890
- return axios.create({
891
- baseURL: config.apiUrl,
892
- headers: {
893
- 'Authorization': `Bearer ${config.apiKey}`,
894
- 'Content-Type': 'application/json'
895
- }
896
- });
897
- }
898
-
899
- async sendToPlatform(message: SimplePlatformMessage, instance: Instance): Promise<void> {
900
- // In a real implementation, we would send to the platform
901
- // For demo, we'll just log and simulate a response
902
- console.log('Platform received message:', message);
903
-
904
- // Simulate platform processing and responding
905
- setTimeout(() => {
906
- console.log('Platform processing complete, sending response...');
907
- this.simulatePlatformResponse(message, instance.idInstance);
908
- }, 1000);
909
- }
910
-
911
- private async simulatePlatformResponse(originalMessage: SimplePlatformMessage, idInstance: number | bigint) {
912
- const platformWebhook: SimplePlatformWebhook = {
913
- messageId: `resp_${Date.now()}`,
914
- from: originalMessage.to.replace('@c.us', ''),
915
- text: `Thanks for your message: "${originalMessage.content}". This is an automated response.`,
916
- timestamp: Date.now()
917
- };
918
-
919
- await this.handlePlatformWebhook(platformWebhook, idInstance);
920
- }
921
- }
922
- ```
923
-
924
- ### main.ts
925
-
926
- ```typescript
927
- import express from "express";
928
- import bodyParser from "body-parser";
929
- import { formatPhoneNumber, GreenApiClient } from "@green-api/greenapi-integration";
930
- import { SimpleTransformer } from "./simple-transformer";
931
- import { SimpleStorage } from "./simple-storage";
932
- import { SimpleAdapter } from "./simple-adapter";
933
- import * as dotenv from "dotenv";
934
-
935
- dotenv.config();
936
-
937
- async function main() {
938
- // Initialize components
939
- const transformer = new SimpleTransformer();
940
- const storage = new SimpleStorage();
941
- const adapter = new SimpleAdapter(transformer, storage);
942
-
943
- // Configuration for both instances
944
- const visitorInstance = {
945
- idInstance: Number(process.env.VISITOR_ID_INSTANCE),
946
- apiTokenInstance: process.env.VISITOR_API_TOKEN!,
947
- };
948
-
949
- const agentInstance = {
950
- idInstance: Number(process.env.AGENT_ID_INSTANCE),
951
- apiTokenInstance: process.env.AGENT_API_TOKEN!,
952
- };
953
- console.log(visitorInstance, agentInstance);
954
-
955
- // Create visitor's GREEN-API client (for sending initial message)
956
- const visitorClient = new GreenApiClient(visitorInstance);
957
-
958
- // Set up agent instance
959
- console.log("Setting up agent instance...");
960
- const user = await adapter.createUser("agent@example.com", {
961
- email: "agent@example.com",
962
- name: "Agent",
963
- });
964
-
965
- const instance = await adapter.createInstance({
966
- idInstance: agentInstance.idInstance, apiTokenInstance: agentInstance.apiTokenInstance, settings: {
967
- webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
968
- webhookUrlToken: "your-secure-token",
969
- incomingWebhook: "yes",
970
- },
971
- }, user.email);
972
-
973
- console.log("Waiting 2 minutes for settings to apply...");
974
- await new Promise(resolve => setTimeout(resolve, 120000));
975
- console.log("Instance ready!");
976
-
977
- // Set up webhook server
978
- const app = express();
979
- app.use(bodyParser.json());
980
-
981
- // Handle GREEN-API webhooks
982
- app.post("/webhook/green-api", async (req, res) => {
983
- try {
984
- console.log("Received webhook from GREEN-API:", req.body);
985
- await adapter.handleGreenApiWebhook(req.body, ["incomingMessageReceived"]);
986
- res.status(200).json({status: "ok"});
987
- } catch (error) {
988
- console.error("Error handling webhook:", error);
989
- res.status(500).json({error: "Internal server error"});
990
- }
991
- });
992
-
993
- // Start the server
994
- const port = Number(process.env.PORT) || 3000;
995
- app.listen(port, () => {
996
- console.log(`Webhook server listening on port ${port}`);
997
- });
998
-
999
- // Send initial message from visitor
1000
- console.log("Sending initial message from visitor...");
1001
- await visitorClient.sendMessage({
1002
- chatId: formatPhoneNumber(process.env.AGENT_PHONE_NUMBER!),
1003
- message: "Hello! This is a test message from a visitor.",
1004
- type: "text",
1005
- });
1006
-
1007
- console.log("Initial message sent! Check the agent WhatsApp app to see the response.");
1008
- }
1009
-
1010
- main().catch(console.error);
1011
- ```
1012
-
1013
- ### .env
1014
-
1015
- ```env
1016
- VISITOR_ID_INSTANCE=your_visitor_instance_id
1017
- VISITOR_API_TOKEN=your_visitor_instance_token
1018
- AGENT_ID_INSTANCE=your_agent_instance_id
1019
- AGENT_API_TOKEN=your_agent_instance_token
1020
- AGENT_PHONE_NUMBER=your_agent_phone_number
1021
- WEBHOOK_URL=your_webhook_url
1022
- PORT=3000
1023
- ```
1024
-
1025
- ## Real-World Examples
1026
-
1027
- For complete real-world integration examples, check out:
1028
-
1029
- - [Rocket.Chat Integration](https://github.com/green-api/greenapi-integration-rocketchat)
1030
-
1031
- ## Utilities
1032
-
1033
- The platform provides several utility functions:
1034
-
1035
- ```typescript
1036
- // Format phone numbers for GREEN-API
1037
- formatPhoneNumber('+1234567890') // Returns '1234567890@c.us'
1038
-
1039
- // Generate secure random tokens
1040
- generateRandomToken(32) // Returns a 32-character random token
1041
-
1042
- // Extract phone number from vcard
1043
- const vcard = 'BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD'
1044
- extractPhoneNumberFromVCard(vcard) // Returns '+1234567890'
1045
-
1046
- // Validate settings values
1047
- isValidSettingValue('webhookUrl', 'https://example.com') // Returns true
1048
-
1049
- // Clean settings
1050
- const input = {
1051
- webhookUrl: 'https://example.com',
1052
- outgoingWebhook: 'yes',
1053
- invalidKey: 'value',
1054
- delaySendMessagesMilliseconds: 'invalid'
1055
- }
1056
- validateAndCleanSettings(input) // Returns { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
1057
- ```
1058
-
1059
- ## License
1060
-
1061
- MIT
1
+ # Universal Integration Platform for GREEN-API
2
+
3
+ ## Support links
4
+
5
+ [![Support](https://img.shields.io/badge/support@green--api.com-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:support@greenapi.com)
6
+ [![Support](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/greenapi_support_eng_bot)
7
+ [![Support](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/77273122366)
8
+
9
+ ## Guides & News
10
+
11
+ [![Guides](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white)](https://www.youtube.com/@greenapi-en)
12
+ [![News](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/green_api)
13
+ [![News](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://whatsapp.com/channel/0029VaLj6J4LNSa2B5Jx6s3h)
14
+
15
+ [![NPM Version](https://img.shields.io/npm/v/@green-api/greenapi-integration)](https://www.npmjs.com/package/@green-api/whatsapp-chatbot-js-v2)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
17
+
18
+ - [Документация на русском языке](./README.ru.md)
19
+
20
+ A flexible integration platform designed to simplify the process of connecting GREEN-API's WhatsApp gateway with various
21
+ third-party services.
22
+
23
+ ## Table of Contents
24
+
25
+ - [Installation](#installation)
26
+ - [Core Components](#core-components)
27
+ - [Developer Guide](#developer-guide)
28
+ - [Working Example](#working-example)
29
+ - [Real-World Examples](#real-world-examples)
30
+ - [Best Practices](#best-practices)
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ npm install @green-api/greenapi-integration
36
+ ```
37
+
38
+ ## Core Components
39
+
40
+ ### 1. BaseAdapter
41
+
42
+ The foundation of your integration. Handles message & instance management, and platform-specific logic.
43
+
44
+ ```typescript
45
+ abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage, TUser extends BaseUser = BaseUser, TInstance extends Instance = Instance> {
46
+ private readonly gaLogger = GreenApiLogger.getInstance(this.constructor.name);
47
+
48
+ public constructor(
49
+ transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>,
50
+ storage: StorageProvider<TUser, TInstance>,
51
+ );
52
+
53
+ public abstract createPlatformClient(params: any): Promise<any>;
54
+
55
+ public abstract sendToPlatform(message: TPlatformMessage, instance: TInstance): Promise<void>;
56
+ }
57
+ ```
58
+
59
+ #### Methods
60
+
61
+ When extending BaseAdapter, your implementation has access to several methods:
62
+
63
+ ##### Webhook Handling
64
+
65
+ These webhook handling methods call your message transformation methods automatically, without the need to use them
66
+ directly in your code.
67
+
68
+ ```typescript
69
+ // Handle webhooks from your platform
70
+ await adapter.handlePlatformWebhook(webhookData, instanceId);
71
+
72
+ // Handle webhooks from GREEN-API. The second parameter is telling the function to handle only specific webhooks.
73
+ // The second parameter must be specified, otherwise webhooks will not be processed.
74
+ await adapter.handleGreenApiWebhook(webhook, ['incomingMessageReceived']);
75
+ ```
76
+
77
+ ##### Instance Management
78
+
79
+ ```typescript
80
+ // Create new instance
81
+ const instance = await adapter.createInstance(instanceData, settings, userEmail);
82
+
83
+ // Get instance details
84
+ const details = await adapter.getInstance(instanceId);
85
+
86
+ // Remove instance
87
+ await adapter.removeInstance(instanceId);
88
+ ```
89
+
90
+ ##### User Management
91
+
92
+ ```typescript
93
+ // Create new user
94
+ const user = await adapter.createUser(userEmail, userData);
95
+
96
+ // Update user
97
+ await adapter.updateUser(userEmail, updateData);
98
+ ```
99
+
100
+ #### Webhook Implementation Example
101
+
102
+ ```typescript
103
+ // Platform webhook endpoint
104
+ app.post('/webhook/platform', async (req, res) => {
105
+ try {
106
+ await adapter.handlePlatformWebhook(req.body, instanceId);
107
+ res.status(200).send();
108
+ } catch (error) {
109
+ console.error('Failed to handle platform webhook:', error);
110
+ res.status(500).send();
111
+ }
112
+ });
113
+
114
+ // GREEN-API webhook endpoint
115
+ app.post('/webhook/green-api', async (req, res) => {
116
+ try {
117
+ // Process specific webhook types
118
+ await adapter.handleGreenApiWebhook(req.body, [
119
+ 'incomingMessageReceived',
120
+ 'outgoingMessageStatus'
121
+ ]);
122
+ res.status(200).send();
123
+ } catch (error) {
124
+ console.error('Failed to handle GREEN-API webhook:', error);
125
+ res.status(500).send();
126
+ }
127
+ });
128
+ ```
129
+
130
+ ### 2. MessageTransformer
131
+
132
+ Handles message format conversion between GREEN-API and your platform.
133
+
134
+ ```typescript
135
+ abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
136
+ abstract toPlatformMessage(webhook: GreenApiWebhook): TPlatformMessage;
137
+
138
+ abstract toGreenApiMessage(message: TPlatformWebhook): Message;
139
+ }
140
+ ```
141
+
142
+ ### 3. StorageProvider
143
+
144
+ Interface for data persistence operations.
145
+
146
+ ```typescript
147
+ abstract class StorageProvider<
148
+ TUser extends BaseUser = BaseUser,
149
+ TInstance extends Instance = Instance,
150
+ TUserCreate extends Record<string, any> = any,
151
+ TUserUpdate extends Record<string, any> = any
152
+ > {
153
+ abstract createInstance(instance: Instance): Promise<TInstance>;
154
+
155
+ abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
156
+
157
+ abstract removeInstance(instanceId: number | bigint): Promise<TInstance>;
158
+
159
+ abstract createUser(data: TUserCreate): Promise<TUser>;
160
+
161
+ abstract findUser(identifier: string): Promise<TUser | null>;
162
+
163
+ abstract updateUser(identifier: string, data: Partial<TUserUpdate>): Promise<TUser>;
164
+ }
165
+ ```
166
+
167
+ ### 4. BaseGreenApiAuthGuard
168
+
169
+ Handles webhook authentication for incoming GREEN-API requests.
170
+
171
+ ```typescript
172
+ abstract class BaseGreenApiAuthGuard<T extends BaseRequest = BaseRequest> {
173
+ private readonly gaLogger = GreenApiLogger.getInstance(this.constructor.name);
174
+
175
+ constructor(protected storage: StorageProvider);
176
+
177
+ // Validates incoming webhook requests
178
+ async validateRequest(request: T): Promise<boolean>;
179
+ }
180
+ ```
181
+
182
+ Example implementation of `BaseGreenApiAuthGuard`:
183
+
184
+ ```typescript
185
+ class YourAuthGuard extends BaseGreenApiAuthGuard<YourRequest> {
186
+ constructor(storage: StorageProvider) {
187
+ super(storage);
188
+ }
189
+ }
190
+
191
+ // Using with Express
192
+ app.post('/webhook', async (req, res) => {
193
+ const guard = new YourAuthGuard(storage);
194
+ try {
195
+ await guard.validateRequest(req);
196
+ // Process webhook
197
+ } catch (error) {
198
+ if (error instanceof AuthenticationError) {
199
+ res.status(401).json({error: error.message});
200
+ return;
201
+ }
202
+ res.status(500).json({error: 'Internal server error'});
203
+ }
204
+ });
205
+ ```
206
+
207
+ ### 5. GreenApiLogger
208
+
209
+ A structured JSON logger with colored output. Provides consistent logging format across your application with
210
+ proper error handling and serialization support.
211
+
212
+ ```typescript
213
+ const logger = GreenApiLogger.getInstance("YourComponent");
214
+
215
+ // Basic logging
216
+ logger.debug("Debug message", {someContext: "value"});
217
+ logger.info("Info message", {userId: 123});
218
+ logger.warn("Warning message", {alert: true});
219
+ logger.error("Error occurred", {errorCode: 500});
220
+ logger.fatal("Fatal error", {critical: true});
221
+
222
+ // Error logging with full context
223
+ try {
224
+ await someOperation();
225
+ } catch (error) {
226
+ logger.logErrorResponse(error, "Operation failed", {
227
+ operationId: "123",
228
+ additionalInfo: "some context"
229
+ });
230
+ }
231
+ ```
232
+
233
+ #### Features
234
+
235
+ - Structured JSON logging with consistent format
236
+ - Colored output based on log level (debug=cyan, info=green, warn=yellow, error=red, fatal=magenta)
237
+ - Built-in error handling with stack trace formatting
238
+ - Automatic serialization
239
+ - Framework agnostic - works with any Node.js application
240
+ - Special handling for Axios errors with detailed request/response info
241
+
242
+ #### Log Levels
243
+
244
+ - `debug` - Detailed information for debugging
245
+ - `info` - General information about system operation
246
+ - `warn` - Warning messages for potentially harmful situations
247
+ - `error` - Error messages for serious problems
248
+ - `fatal` - Critical errors that require immediate attention
249
+ - `log` - Alternative to info (for compatibility)
250
+
251
+ #### Output Format
252
+
253
+ ```json
254
+ {
255
+ "timestamp": "30/01/2025, 04:34:49",
256
+ "level": "error",
257
+ "context": "CoreService",
258
+ "message": "Operation failed",
259
+ "error": "Failed to process request",
260
+ "stack": [
261
+ "Error: Failed to process request",
262
+ " at CoreService.process (/app/service.js:123:45)",
263
+ " at async Router.handle (/app/router.js:67:89)"
264
+ ],
265
+ "additionalContext": {
266
+ "requestId": "abc-123",
267
+ "userId": "user_456"
268
+ }
269
+ }
270
+ ```
271
+
272
+ #### Error Handling
273
+
274
+ ```typescript
275
+ // Axios error handling
276
+ try {
277
+ await apiRequest();
278
+ } catch (error) {
279
+ logger.logErrorResponse(error, "API Request failed", {
280
+ endpoint: "/users",
281
+ method: "POST"
282
+ });
283
+ }
284
+ ```
285
+
286
+ // Will output detailed API error info:
287
+
288
+ ```
289
+ {
290
+ "timestamp": "30/01/2025, 04:34:49",
291
+ "level": "error",
292
+ "context": "ApiService",
293
+ "message": "API Request failed - API Error:",
294
+ "status": 400,
295
+ "statusText": "Bad Request",
296
+ "data": { "error": "Invalid input" },
297
+ "url": "https://api.example.com/users",
298
+ "method": "POST",
299
+ "endpoint": "/users"
300
+ }
301
+ ```
302
+
303
+ #### Using with Frameworks
304
+
305
+ The logger is framework-agnostic but can be easily integrated with any framework:
306
+
307
+ ```typescript
308
+ // Express example
309
+ app.use((err, req, res, next) => {
310
+ const logger = GreenApiLogger.getInstance("Express");
311
+ logger.error("Request failed", {
312
+ path: req.path,
313
+ method: req.method,
314
+ error: err.message
315
+ });
316
+ next(err);
317
+ });
318
+ ```
319
+
320
+ #### Important Note on Logger Usage
321
+
322
+ While you can use this logger alongside other logging solutions, it's recommended to disable your
323
+ framework's built-in logger to avoid duplicate or malformed logs.
324
+
325
+ For example, when using NestJS, you can disable its built-in logger like this:
326
+
327
+ ```typescript
328
+ // main.ts
329
+ const app = await NestFactory.create(AppModule, {
330
+ logger: false // Disable NestJS logger
331
+ });
332
+ ```
333
+
334
+ And then use it in your class like this:
335
+
336
+ ```typescript
337
+ gaLogger = GreenApiLogger.getInstance(YourClass.name);
338
+ ```
339
+
340
+ #### Methods
341
+
342
+ ##### Basic Logging Methods
343
+
344
+ - `debug(message: string, context?: Record<string, any>)`: Log debug level message
345
+ - `info(message: string, context?: Record<string, any>)`: Log info level message
346
+ - `warn(message: string, context?: Record<string, any>)`: Log warning level message
347
+ - `error(message: string, context?: Record<string, any>)`: Log error level message
348
+ - `fatal(message: string, context?: Record<string, any>)`: Log fatal level message
349
+ - `log(message: string, context?: string)`: Alternative to info method
350
+
351
+ ##### Special Methods
352
+
353
+ - `logErrorResponse(error: any, context: string, additionalContext?: Record<string, any>)`:
354
+ Enhanced error logging with special handling for Axios errors and stack traces
355
+
356
+ ##### Utility Methods
357
+
358
+ - `getInstance(context: string = "Global"): GreenApiLogger`: Get or create logger instance for specified context
359
+
360
+ #### Best Practices
361
+
362
+ 1. **Use Consistent Context Names**
363
+
364
+ ```typescript
365
+ // In your component/service
366
+ private readonly
367
+ logger = GreenApiLogger.getInstance(YourService.name);
368
+ ```
369
+
370
+ 2. **Include Relevant Context**
371
+
372
+ ```typescript
373
+ logger.info("User action completed", {
374
+ userId: user.id,
375
+ action: "profile_update",
376
+ duration: timeTaken
377
+ });
378
+ ```
379
+
380
+ 3. **Proper Error Handling**
381
+
382
+ ```typescript
383
+ try {
384
+ await complexOperation();
385
+ } catch (error) {
386
+ logger.logErrorResponse(error, "Complex operation failed", {
387
+ operationId: id,
388
+ parameters: params
389
+ });
390
+ }
391
+ ```
392
+
393
+ 4. **Use Appropriate Log Levels**
394
+
395
+ ```typescript
396
+ // Debug for detailed information
397
+ logger.debug("Processing chunk", {chunkId: 123, size: 1024});
398
+
399
+ // Info for general operation
400
+ logger.info("User logged in", {userId: 456});
401
+
402
+ // Warn for potential issues
403
+ logger.warn("High memory usage", {memoryUsage: "85%"});
404
+
405
+ // Error for actual problems
406
+ logger.error("Database connection failed", {dbHost: "primary"});
407
+
408
+ // Fatal for critical issues
409
+ logger.fatal("System shutdown required", {reason: "data corruption"});
410
+ ```
411
+
412
+ ### 6. GreenApiClient
413
+
414
+ Direct interface to GREEN-API methods.
415
+
416
+ ```typescript
417
+ const client = new GreenApiClient({
418
+ idInstance: 'your_instance_id',
419
+ apiTokenInstance: 'your_token'
420
+ });
421
+
422
+ // Examples:
423
+ await client.setProfilePicture(fileBlob);
424
+ await client.getAuthorizationCode(phoneNumber);
425
+ await client.getQR();
426
+ ```
427
+
428
+ ## Developer Guide
429
+
430
+ This guide will walk you through creating your first integration with GREEN-API's WhatsApp gateway.
431
+
432
+ ### Project Structure
433
+
434
+ ```
435
+ your-integration/
436
+ ├── src/
437
+ │ ├── core/
438
+ │ │ ├── adapter.ts # Your platform adapter
439
+ │ │ ├── transformer.ts # Message transformer
440
+ │ │ ├── storage.ts # Data storage implementation
441
+ │ │ └── router.ts # Webhook endpoints
442
+ │ ├── types/
443
+ │ │ └── types.ts # Platform-specific types
444
+ │ └── main.ts # Main exports
445
+ ├── package.json
446
+ └── tsconfig.json
447
+ ```
448
+
449
+ ```mermaid
450
+ graph TB
451
+ subgraph "WhatsApp to Platform"
452
+ WA[WhatsApp] -->|Send message| GA1[GREEN-API]
453
+ GA1 -->|Webhook| INT1[Your Integration]
454
+ INT1 -->|1 . Validate webhook| GD1[BaseGreenApiAuthGuard]
455
+ INT1 -->|2 . Transform message| TR1[MessageTransformer]
456
+ INT1 -->|3 . Send to platform| PL1[Your Platform]
457
+ end
458
+
459
+ subgraph "Platform to WhatsApp"
460
+ PL2[Your Platform] -->|Webhook| INT2[Your Integration]
461
+ INT2 -->|1 . Transform message| TR2[MessageTransformer]
462
+ INT2 -->|2 . Send via API| GA2[GREEN-API]
463
+ GA2 -->|Send message| WA2[WhatsApp]
464
+ end
465
+
466
+ subgraph "Components"
467
+ style Components fill: #f9f9f9, stroke: #333, stroke-width: 2px
468
+ TR[MessageTransformer]
469
+ ST[StorageProvider]
470
+ AD[BaseAdapter]
471
+ GD[WebhookGuard]
472
+ end
473
+ ```
474
+
475
+ ### Implementation Steps
476
+
477
+ #### Step 1: Define Platform Types
478
+
479
+ First, define the message types for your platform:
480
+
481
+ ```typescript
482
+ // types/types.ts
483
+ export interface YourPlatformWebhook {
484
+ id: string;
485
+ from: string;
486
+ message: string;
487
+ timestamp: number;
488
+ // Add other platform-specific fields
489
+ }
490
+
491
+ export interface YourPlatformMessage {
492
+ recipient: string;
493
+ content: string;
494
+ // Add other platform-specific fields
495
+ }
496
+ ```
497
+
498
+ #### Step 2: Create Message Transformer
499
+
500
+ Create a transformer that converts messages between your platform's format and GREEN-API's format:
501
+
502
+ ```typescript
503
+ // core/transformer.ts
504
+ import { MessageTransformer, Message, GreenApiWebhook } from '@green-api/greenapi-integration';
505
+ import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
506
+
507
+ export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
508
+ toPlatformMessage(webhook: GreenApiWebhook): YourPlatformMessage {
509
+ // Transform GREEN-API webhook to your platform format
510
+ return {
511
+ recipient: webhook.senderData.sender,
512
+ content: webhook.messageData.textMessageData?.textMessage || '',
513
+ };
514
+ }
515
+
516
+ toGreenApiMessage(message: YourPlatformWebhook): Message {
517
+ // Transform your platform webhook to GREEN-API format
518
+ return {
519
+ type: 'text',
520
+ chatId: message.from,
521
+ message: message.message,
522
+ };
523
+ }
524
+ }
525
+ ```
526
+
527
+ #### Step 3: Implement Storage Provider
528
+
529
+ Create a storage provider to manage users and instances. You can use any database or ORM:
530
+
531
+ ```typescript
532
+ // core/storage.ts
533
+ import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
534
+ import { PrismaClient } from '@prisma/client'; // Or your database client
535
+
536
+ export class YourStorage extends StorageProvider {
537
+ private db: PrismaClient;
538
+
539
+ constructor() {
540
+ this.db = new PrismaClient();
541
+ }
542
+
543
+ async findUserByEmail(email: string) {
544
+ return this.db.user.findUnique({where: {email}});
545
+ }
546
+
547
+ async createInstance(instance: Instance) {
548
+ return this.db.instance.create({
549
+ data: {
550
+ idInstance: instance.idInstance,
551
+ apiTokenInstance: instance.apiTokenInstance,
552
+ userId: instance.userId,
553
+ settings: instance.settings || {},
554
+ },
555
+ });
556
+ }
557
+
558
+ // Implement other required methods
559
+ }
560
+ ```
561
+
562
+ #### Step 4: Create Your Platform Adapter
563
+
564
+ The adapter handles the actual communication between platforms:
565
+
566
+ ```typescript
567
+ // core/adapter.ts
568
+ import { BaseAdapter, BaseInstance } from '@green-api/greenapi-integration';
569
+ import { YourPlatformClient } from 'your-platform-sdk';
570
+ import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
571
+
572
+ export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMessage> {
573
+ async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
574
+ return new YourPlatformClient({
575
+ baseUrl: config.apiUrl,
576
+ apiKey: config.apiKey,
577
+ });
578
+ }
579
+
580
+ async sendToPlatform(message: YourPlatformMessage, instance: Instance) {
581
+ const client = await this.createPlatformClient(instance.config);
582
+ await client.sendMessage(message);
583
+ }
584
+ }
585
+ ```
586
+
587
+ #### Step 5: Implement Webhook Controller
588
+
589
+ Define webhook endpoints that your application will listen to:
590
+
591
+ ```typescript
592
+ // core/webhook.ts
593
+ import express from 'express';
594
+ import { YourAdapter } from '../core/adapter';
595
+ import { YourTransformer } from '../core/transformer';
596
+ import { YourStorage } from '../core/storage';
597
+
598
+ const router = express.Router();
599
+ const storage = new YourStorage();
600
+ const transformer = new YourTransformer();
601
+ const adapter = new YourAdapter(transformer, storage);
602
+
603
+ class WebhookGuard extends BaseGreenApiAuthGuard {
604
+ constructor(storage: StorageProvider) {
605
+ super(storage);
606
+ }
607
+ }
608
+
609
+ const guard = new WebhookGuard(storage);
610
+
611
+ // Webhook endpoints
612
+ router.post('/green-api', async (req, res) => {
613
+ try {
614
+ // Validate webhook first
615
+ await guard.validateRequest(req);
616
+
617
+ // Process webhook if validation passed
618
+ // As the second parameter, specfify the types of webhooks to be processed (otherwise skipped)
619
+ await adapter.handleGreenApiWebhook(req.body, ['incomingMessageReceived']);
620
+ res.status(200).json({status: 'ok'});
621
+ } catch (error) {
622
+ if (error instanceof AuthenticationError) {
623
+ res.status(401).json({error: error.message});
624
+ return;
625
+ }
626
+ console.error('Webhook error:', error);
627
+ res.status(500).json({error: 'Internal server error'});
628
+ }
629
+ });
630
+
631
+ router.post('/platform', async (req, res) => {
632
+ try {
633
+ const instanceId = req.query.instanceId;
634
+ await adapter.handlePlatformWebhook(req.body, instanceId);
635
+ res.status(200).json({status: 'ok'});
636
+ } catch (error) {
637
+ console.error('Platform webhook error:', error);
638
+ res.status(500).json({error: 'Internal server error'});
639
+ }
640
+ });
641
+
642
+ router.post('/instance', async (req, res) => {
643
+ try {
644
+ const {idInstance, apiTokenInstance, userEmail} = req.body;
645
+
646
+ if (!idInstance || !apiTokenInstance || !userEmail) {
647
+ throw new BadRequestError('Required fields missing');
648
+ }
649
+
650
+ const user = await storage.findUserByEmail(userEmail);
651
+ const instance = await adapter.createInstance({
652
+ idInstance: Number(idInstance),
653
+ apiTokenInstance,
654
+ settings: {
655
+ webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
656
+ webhookUrlToken: `token_${Date.now()}`,
657
+ incomingWebhook: 'yes'
658
+ },
659
+ userId: user.id
660
+ });
661
+
662
+ res.status(200).json({
663
+ status: 'ok',
664
+ data: instance,
665
+ message: 'Instance created successfully. Please wait 2 minutes for settings to apply.'
666
+ });
667
+
668
+ } catch (error) {
669
+ console.error('Instance creation error:', error);
670
+ res.status(500).json({error: 'Failed to create instance'});
671
+ }
672
+ });
673
+
674
+ export default router;
675
+ ```
676
+
677
+ #### Step 6: Create Application Entry Point
678
+
679
+ Put it all together in your entrypoint:
680
+
681
+ ```typescript
682
+ // main.ts
683
+ import express from 'express';
684
+ import bodyParser from 'body-parser';
685
+ import dotenv from 'dotenv';
686
+ import webhookRouter from './controllers/webhook';
687
+ import { YourAdapter } from './core/adapter';
688
+ import { YourTransformer } from './core/transformer';
689
+ import { YourStorage } from './core/storage';
690
+
691
+ // Load environment variables
692
+ dotenv.config();
693
+
694
+ async function bootstrap() {
695
+ // Initialize components
696
+ const storage = new YourStorage();
697
+ const transformer = new YourTransformer();
698
+ const adapter = new YourAdapter(transformer, storage);
699
+
700
+ // Create Express application
701
+ const app = express();
702
+ app.use(bodyParser.json());
703
+
704
+ // Set up webhook routes
705
+ app.use('/webhook', webhookRouter);
706
+
707
+ // Start server
708
+ const port = process.env.PORT || 3000;
709
+ app.listen(port, () => {
710
+ console.log(`Server running on port ${port}`);
711
+ });
712
+
713
+ console.log('Integration platform ready!');
714
+ }
715
+
716
+ // Handle errors
717
+ bootstrap();
718
+ ```
719
+
720
+ ### Publishing Your Integration
721
+
722
+ 1. **Prepare package.json**
723
+
724
+ ```json
725
+ {
726
+ "name": "greenapi-integration-yourplatform",
727
+ "version": "1.0.0",
728
+ "main": "dist/index.js",
729
+ "types": "dist/index.d.ts",
730
+ "scripts": {
731
+ "build": "tsc",
732
+ "prepublishOnly": "npm run build"
733
+ },
734
+ "dependencies": {
735
+ "@green-api/greenapi-integration": "^0.4.0",
736
+ "express": "^4.18.2"
737
+ // other dependencies
738
+ }
739
+ }
740
+ ```
741
+
742
+ 2. **Build and Publish**
743
+
744
+ ```bash
745
+ npm run build
746
+ npm publish
747
+ ```
748
+
749
+ ## Working Example
750
+
751
+ Check out the `/examples/custom-adapter` directory for a complete working example showing:
752
+
753
+ - Two-way message flow between WhatsApp and a custom platform
754
+ - Webhook handling
755
+ - Instance setup and configuration
756
+ - Message transformation
757
+ - Error handling
758
+
759
+ ### Running the Example
760
+
761
+ 1. Clone the repository
762
+ 2. Update .env with your GREEN-API credentials:
763
+
764
+ ```env
765
+ VISITOR_ID_INSTANCE=your_visitor_instance_id
766
+ VISITOR_API_TOKEN=your_visitor_instance_token
767
+ AGENT_ID_INSTANCE=your_agent_instance_id
768
+ AGENT_API_TOKEN=your_agent_instance_token
769
+ AGENT_PHONE_NUMBER=your_agent_phone_number
770
+ WEBHOOK_URL=your_webhook_url
771
+ PORT=3000
772
+ ```
773
+
774
+ 3. Install dependencies and run:
775
+
776
+ ```bash
777
+ cd examples/custom-adapter
778
+ npm install
779
+ npm start
780
+ ```
781
+
782
+ ## Complete Example Implementation
783
+
784
+ ### Project Structure
785
+
786
+ ```
787
+ examples/
788
+ └── custom-adapter/
789
+ ├── src/
790
+ │ ├── main.ts
791
+ │ ├── simple-adapter.ts
792
+ │ ├── simple-transformer.ts
793
+ │ ├── simple-storage.ts
794
+ │ └── types.ts
795
+ ├── .env
796
+ └── package.json
797
+ ```
798
+
799
+ ### types.ts
800
+
801
+ ```typescript
802
+ interface SimplePlatformWebhook {
803
+ messageId: string;
804
+ from: string;
805
+ text: string;
806
+ timestamp: number;
807
+ }
808
+
809
+ interface SimplePlatformMessage {
810
+ to: string;
811
+ content: string;
812
+ replyTo?: string;
813
+ }
814
+ ```
815
+
816
+ ### simple-transformer.ts
817
+
818
+ ```typescript
819
+ import {
820
+ MessageTransformer,
821
+ Message,
822
+ GreenApiWebhook,
823
+ formatPhoneNumber,
824
+ IntegrationError,
825
+ } from "@green-api/greenapi-integration";
826
+ import { SimplePlatformMessage, SimplePlatformWebhook } from "./types";
827
+
828
+ export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
829
+ toPlatformMessage(webhook: GreenApiWebhook): SimplePlatformMessage {
830
+ if (webhook.typeWebhook === "incomingMessageReceived") {
831
+ if (webhook.messageData.typeMessage !== "extendedTextMessage") {
832
+ throw new IntegrationError("Only text messages are supported", "BAD_REQUEST_ERROR", 400);
833
+ }
834
+
835
+ return {
836
+ to: webhook.senderData.sender,
837
+ content: webhook.messageData.extendedTextMessageData?.text || "",
838
+ };
839
+ }
840
+ throw new IntegrationError("Only incomingMessageReceived type webhooks are supported", "INTEGRATION_ERROR", 500);
841
+ }
842
+
843
+ toGreenApiMessage(message: SimplePlatformWebhook): Message {
844
+ return {
845
+ type: "text",
846
+ chatId: formatPhoneNumber(message.from),
847
+ message: message.text,
848
+ };
849
+ }
850
+ }
851
+ ```
852
+
853
+ ### simple-storage.ts
854
+
855
+ ```typescript
856
+ import { StorageProvider, BaseUser, Instance } from '@green-api/greenapi-integration';
857
+
858
+ export class SimpleStorage extends StorageProvider {
859
+ private users: Map<string, BaseUser> = new Map();
860
+ private instances: Map<number, Instance> = new Map();
861
+
862
+ async createInstance(instance: Instance, userId: bigint): Promise<Instance> {
863
+ this.instances.set(Number(instance.idInstance), {
864
+ ...instance,
865
+ });
866
+ return instance;
867
+ }
868
+
869
+ async getInstance(idInstance: number): Promise<Instance | null> {
870
+ return this.instances.get(idInstance) || null;
871
+ }
872
+
873
+ async removeInstance(instanceId: number): Promise<Instance> {
874
+ const instance = this.instances.get(instanceId);
875
+ if (!instance) throw new Error('Instance not found');
876
+ this.instances.delete(instanceId);
877
+ return instance;
878
+ }
879
+
880
+ async createUser(data: any): Promise<BaseUser> {
881
+ const user = {id: Date.now(), ...data};
882
+ this.users.set(data.email, user);
883
+ return user;
884
+ }
885
+
886
+ async findUser(identifier: string): Promise<BaseUser | null> {
887
+ return this.users.get(identifier) || null;
888
+ }
889
+
890
+ async updateUser(identifier: string, data: any): Promise<BaseUser> {
891
+ const user = await this.findUser(identifier);
892
+ if (!user) throw new Error('User not found');
893
+ const updated = {...user, ...data};
894
+ this.users.set(identifier, updated);
895
+ return updated;
896
+ }
897
+ }
898
+ ```
899
+
900
+ ### simple-adapter.ts
901
+
902
+ ```typescript
903
+ import { BaseAdapter, Instance } from "@green-api/greenapi-integration";
904
+ import { SimplePlatformMessage, SimplePlatformWebhook } from "./types";
905
+ import axios from 'axios';
906
+
907
+ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
908
+ async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
909
+ return axios.create({
910
+ baseURL: config.apiUrl,
911
+ headers: {
912
+ 'Authorization': `Bearer ${config.apiKey}`,
913
+ 'Content-Type': 'application/json'
914
+ }
915
+ });
916
+ }
917
+
918
+ async sendToPlatform(message: SimplePlatformMessage, instance: Instance): Promise<void> {
919
+ // In a real implementation, we would send to the platform
920
+ // For demo, we'll just log and simulate a response
921
+ console.log('Platform received message:', message);
922
+
923
+ // Simulate platform processing and responding
924
+ setTimeout(() => {
925
+ console.log('Platform processing complete, sending response...');
926
+ this.simulatePlatformResponse(message, instance.idInstance);
927
+ }, 1000);
928
+ }
929
+
930
+ private async simulatePlatformResponse(originalMessage: SimplePlatformMessage, idInstance: number | bigint) {
931
+ const platformWebhook: SimplePlatformWebhook = {
932
+ messageId: `resp_${Date.now()}`,
933
+ from: originalMessage.to.replace('@c.us', ''),
934
+ text: `Thanks for your message: "${originalMessage.content}". This is an automated response.`,
935
+ timestamp: Date.now()
936
+ };
937
+
938
+ await this.handlePlatformWebhook(platformWebhook, idInstance);
939
+ }
940
+ }
941
+ ```
942
+
943
+ ### main.ts
944
+
945
+ ```typescript
946
+ import express from "express";
947
+ import bodyParser from "body-parser";
948
+ import { formatPhoneNumber, GreenApiClient } from "@green-api/greenapi-integration";
949
+ import { SimpleTransformer } from "./simple-transformer";
950
+ import { SimpleStorage } from "./simple-storage";
951
+ import { SimpleAdapter } from "./simple-adapter";
952
+ import * as dotenv from "dotenv";
953
+
954
+ dotenv.config();
955
+
956
+ async function main() {
957
+ // Initialize components
958
+ const transformer = new SimpleTransformer();
959
+ const storage = new SimpleStorage();
960
+ const adapter = new SimpleAdapter(transformer, storage);
961
+
962
+ // Configuration for both instances
963
+ const visitorInstance = {
964
+ idInstance: Number(process.env.VISITOR_ID_INSTANCE),
965
+ apiTokenInstance: process.env.VISITOR_API_TOKEN!,
966
+ };
967
+
968
+ const agentInstance = {
969
+ idInstance: Number(process.env.AGENT_ID_INSTANCE),
970
+ apiTokenInstance: process.env.AGENT_API_TOKEN!,
971
+ };
972
+ console.log(visitorInstance, agentInstance);
973
+
974
+ // Create visitor's GREEN-API client (for sending initial message)
975
+ const visitorClient = new GreenApiClient(visitorInstance);
976
+
977
+ // Set up agent instance
978
+ console.log("Setting up agent instance...");
979
+ const user = await adapter.createUser("agent@example.com", {
980
+ email: "agent@example.com",
981
+ name: "Agent",
982
+ });
983
+
984
+ const instance = await adapter.createInstance({
985
+ idInstance: agentInstance.idInstance, apiTokenInstance: agentInstance.apiTokenInstance, settings: {
986
+ webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
987
+ webhookUrlToken: "your-secure-token",
988
+ incomingWebhook: "yes",
989
+ },
990
+ }, user.email);
991
+
992
+ console.log("Waiting 2 minutes for settings to apply...");
993
+ await new Promise(resolve => setTimeout(resolve, 120000));
994
+ console.log("Instance ready!");
995
+
996
+ // Set up webhook server
997
+ const app = express();
998
+ app.use(bodyParser.json());
999
+
1000
+ // Handle GREEN-API webhooks
1001
+ app.post("/webhook/green-api", async (req, res) => {
1002
+ try {
1003
+ console.log("Received webhook from GREEN-API:", req.body);
1004
+ await adapter.handleGreenApiWebhook(req.body, ["incomingMessageReceived"]);
1005
+ res.status(200).json({status: "ok"});
1006
+ } catch (error) {
1007
+ console.error("Error handling webhook:", error);
1008
+ res.status(500).json({error: "Internal server error"});
1009
+ }
1010
+ });
1011
+
1012
+ // Start the server
1013
+ const port = Number(process.env.PORT) || 3000;
1014
+ app.listen(port, () => {
1015
+ console.log(`Webhook server listening on port ${port}`);
1016
+ });
1017
+
1018
+ // Send initial message from visitor
1019
+ console.log("Sending initial message from visitor...");
1020
+ await visitorClient.sendMessage({
1021
+ chatId: formatPhoneNumber(process.env.AGENT_PHONE_NUMBER!),
1022
+ message: "Hello! This is a test message from a visitor.",
1023
+ type: "text",
1024
+ });
1025
+
1026
+ console.log("Initial message sent! Check the agent WhatsApp app to see the response.");
1027
+ }
1028
+
1029
+ main().catch(console.error);
1030
+ ```
1031
+
1032
+ ### .env
1033
+
1034
+ ```env
1035
+ VISITOR_ID_INSTANCE=your_visitor_instance_id
1036
+ VISITOR_API_TOKEN=your_visitor_instance_token
1037
+ AGENT_ID_INSTANCE=your_agent_instance_id
1038
+ AGENT_API_TOKEN=your_agent_instance_token
1039
+ AGENT_PHONE_NUMBER=your_agent_phone_number
1040
+ WEBHOOK_URL=your_webhook_url
1041
+ PORT=3000
1042
+ ```
1043
+
1044
+ ## Real-World Examples
1045
+
1046
+ For complete real-world integration examples, check out:
1047
+
1048
+ - [Rocket.Chat Integration](https://github.com/green-api/greenapi-integration-rocketchat)
1049
+
1050
+ ## Utilities
1051
+
1052
+ The platform provides several utility functions:
1053
+
1054
+ ```typescript
1055
+ // Format phone numbers for GREEN-API
1056
+ formatPhoneNumber('+1234567890') // Returns '1234567890@c.us'
1057
+
1058
+ // Generate secure random tokens
1059
+ generateRandomToken(32) // Returns a 32-character random token
1060
+
1061
+ // Extract phone number from vcard
1062
+ const vcard = 'BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD'
1063
+ extractPhoneNumberFromVCard(vcard) // Returns '+1234567890'
1064
+
1065
+ // Validate settings values
1066
+ isValidSettingValue('webhookUrl', 'https://example.com') // Returns true
1067
+
1068
+ // Clean settings
1069
+ const input = {
1070
+ webhookUrl: 'https://example.com',
1071
+ outgoingWebhook: 'yes',
1072
+ invalidKey: 'value',
1073
+ delaySendMessagesMilliseconds: 'invalid'
1074
+ }
1075
+ validateAndCleanSettings(input) // Returns { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
1076
+ ```
1077
+
1078
+ ## License
1079
+
1080
+ MIT