@green-api/greenapi-integration 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ru.md ADDED
@@ -0,0 +1,774 @@
1
+ # Универсальная интеграционная платформа для GREEN-API
2
+
3
+ ## Поддержка
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_bot)
7
+ [![Support](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/77273122366)
8
+
9
+ ## Руководства и новости
10
+
11
+ [![Guides](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=YouTube&logoColor=white)](https://www.youtube.com/@green-api)
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
+ - [Documentation in English](./README.md)
16
+
17
+ Гибкая интеграционная платформа, разработанная для упрощения процесса подключения WhatsApp шлюза GREEN-API к различным
18
+ сторонним сервисам.
19
+
20
+ ## Содержание
21
+
22
+ - [Установка](#установка)
23
+ - [Основные компоненты](#основные-компоненты)
24
+ - [Руководство разработчика](#руководство-разработчика)
25
+ - [Рабочий пример](#рабочий-пример)
26
+ - [Реальные примеры](#реальные-примеры)
27
+ - [Лучшие практики](#лучшие-практики)
28
+
29
+ ## Установка
30
+
31
+ ```bash
32
+ npm install @green-api/greenapi-integration
33
+ ```
34
+
35
+ ## Основные компоненты
36
+
37
+ ### 1. BaseAdapter
38
+
39
+ Основа вашей интеграции. Управляет сообщениями и инстансами, а также логикой взаимодействия с платформой.
40
+ BaseAdapter внутренне использует GreenApiClient для всех общих операций, поэтому в большинстве случаев вам не нужно
41
+ использовать
42
+ методы GreenApiClient напрямую.
43
+
44
+ **Когда использовать BaseAdapter, а когда GreenApiClient**:
45
+
46
+ ✅ Используйте методы BaseAdapter для всех стандартных операций (отправка сообщений, обработка вебхуков, управление
47
+ инстансами)
48
+
49
+ ⚠️ Используйте GreenApiClient напрямую только для специальных операций, не покрытых BaseAdapter (например,
50
+ setProfilePicture, getAuthorizationCode)
51
+
52
+ ```typescript
53
+ abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage> {
54
+ public constructor(
55
+ transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>,
56
+ storage: StorageProvider
57
+ );
58
+
59
+ public abstract createPlatformClient(params: any): Promise<any>;
60
+
61
+ public abstract sendToPlatform(message: TPlatformMessage, instance: TInstance): Promise<void>;
62
+ }
63
+ ```
64
+
65
+ **Пример правильного использования:**
66
+
67
+ ```typescript
68
+ // ✅ ПРАВИЛЬНО: Использование BaseAdapter для стандартных операций
69
+ const adapter = new YourAdapter(transformer, storage);
70
+ await adapter.handlePlatformWebhook(webhook, instanceId);
71
+ await adapter.createInstance(instance, settings, userCred);
72
+ await adapter.sendMessage(transformedWebhook);
73
+
74
+ // ⚠️ ТОЛЬКО ПРИ НЕОБХОДИМОСТИ: Прямое использование GreenApiClient для специальных операций
75
+ const client = new GreenApiClient(instance);
76
+ await client.setProfilePicture(fileBlob);
77
+ await client.getAuthorizationCode(phoneNumber);
78
+ ```
79
+
80
+ ### 2. MessageTransformer
81
+
82
+ Преобразовывает форматы сообщений между GREEN-API и вашей платформой.
83
+
84
+ ```typescript
85
+ abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
86
+ abstract toPlatformMessage(webhook: IncomingGreenApiWebhook): TPlatformMessage;
87
+
88
+ abstract toGreenApiMessage(message: TPlatformWebhook): Message;
89
+ }
90
+ ```
91
+
92
+ ### 3. StorageProvider
93
+
94
+ Интерфейс для операций с хранением данных.
95
+
96
+ ```typescript
97
+ abstract class StorageProvider<TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance> {
98
+ abstract createInstance(instance: BaseInstance, userId: bigint | number, settings?: Settings): Promise<TInstance>;
99
+
100
+ abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
101
+
102
+ abstract removeInstance(instanceId: number | bigint): Promise<TInstance>;
103
+
104
+ abstract createUser(data: any): Promise<TUser>;
105
+
106
+ abstract findUser(identifier: string): Promise<TUser | null>;
107
+
108
+ abstract updateUser(identifier: string, data: any): Promise<TUser>;
109
+ }
110
+ ```
111
+
112
+ ### 4. BaseGreenApiAuthGuard
113
+
114
+ Аутентифицирует входящие вебхуки от GREEN-API.
115
+
116
+ ```typescript
117
+ abstract class BaseGreenApiAuthGuard<T extends BaseRequest = BaseRequest> {
118
+ constructor(protected storage: StorageProvider);
119
+
120
+ // Валидация входящих вебхуков
121
+ async validateRequest(request: T): Promise<boolean>;
122
+ }
123
+ ```
124
+
125
+ Пример использования `BaseGreenApiAuthGuard`:
126
+
127
+ ```typescript
128
+ class YourAuthGuard extends BaseGreenApiAuthGuard<YourRequest> {
129
+ constructor(storage: StorageProvider) {
130
+ super(storage);
131
+ }
132
+ }
133
+
134
+ // Использование с Express
135
+ app.post('/webhook', async (req, res) => {
136
+ const guard = new YourAuthGuard(storage);
137
+ try {
138
+ await guard.validateRequest(req);
139
+ // Обработка вебхука ...
140
+ } catch (error) {
141
+ if (error instanceof AuthenticationError) {
142
+ res.status(401).json({error: error.message});
143
+ return;
144
+ }
145
+ res.status(500).json({error: 'Internal server error'});
146
+ }
147
+ });
148
+ ```
149
+
150
+ ### 5. GreenApiClient
151
+
152
+ Прямой интерфейс к эндпоинтам GREEN-API. Хотя большинство операций должны выполняться через BaseAdapter, GreenApiClient
153
+ может использоваться напрямую для операций, непокрытых в `BaseAdapter`.
154
+
155
+ ```typescript
156
+ const client = new GreenApiClient({
157
+ idInstance: 'your_instance_id',
158
+ apiTokenInstance: 'your_token'
159
+ });
160
+
161
+ // Примеры специальных операций:
162
+ await client.setProfilePicture(fileBlob);
163
+ await client.getAuthorizationCode(phoneNumber);
164
+ await client.getQR();
165
+ ```
166
+
167
+ ## Руководство разработчика
168
+
169
+ ### Структура проекта
170
+
171
+ ```
172
+ your-integration/
173
+ ├── src/
174
+ │ ├── core/
175
+ │ │ ├── adapter.ts # Адаптер платформы
176
+ │ │ ├── transformer.ts # Преобразователь сообщений
177
+ │ │ ├── storage.ts # Реализация хранилища
178
+ │ │ └── router.ts # Эндпоинты для вебхуков
179
+ │ ├── types/
180
+ │ │ └── types.ts # Типы
181
+ │ └── main.ts # Точка запуска приложения
182
+ ├── package.json
183
+ └── tsconfig.json
184
+ ```
185
+
186
+ ### Этапы реализации
187
+
188
+ 1. **Определение типов платформы**
189
+
190
+ ```typescript
191
+ // types/types.ts
192
+ export interface YourPlatformWebhook {
193
+ id: string;
194
+ from: string;
195
+ message: string;
196
+ timestamp: number;
197
+ // Добавьте другие поля, специфичные для вашей платформы
198
+ }
199
+
200
+ export interface YourPlatformMessage {
201
+ recipient: string;
202
+ content: string;
203
+ // Добавьте другие поля, специфичные для вашей платформы
204
+ }
205
+ ```
206
+
207
+ 2. **Создание преобразователя сообщений**
208
+
209
+ ```typescript
210
+ // core/transformer.ts
211
+ import { MessageTransformer, Message, IncomingGreenApiWebhook } from '@green-api/greenapi-integration';
212
+ import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
213
+
214
+ export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
215
+ toPlatformMessage(webhook: IncomingGreenApiWebhook): YourPlatformMessage {
216
+ // Преобразование вебхука GREEN-API в формат вашей платформы
217
+ return {
218
+ recipient: webhook.senderData.sender,
219
+ content: webhook.messageData.textMessageData?.textMessage || '',
220
+ };
221
+ }
222
+
223
+ toGreenApiMessage(message: YourPlatformWebhook): Message {
224
+ // Преобразование вебхука вашей платформы в формат GREEN-API
225
+ return {
226
+ type: 'text',
227
+ chatId: message.from,
228
+ message: message.message,
229
+ };
230
+ }
231
+ }
232
+ ```
233
+
234
+ 3. **Реализация хранилища**
235
+
236
+ ```typescript
237
+ // core/storage.ts
238
+ import { StorageProvider, BaseUser, BaseInstance, Settings } from '@green-api/greenapi-integration';
239
+ import { PrismaClient } from '@prisma/client'; // Or your database client
240
+
241
+ export class YourStorage extends StorageProvider {
242
+ private db: PrismaClient;
243
+
244
+ constructor() {
245
+ this.db = new PrismaClient();
246
+ }
247
+
248
+ async createInstance(instance: BaseInstance, userId: bigint, settings?: Settings) {
249
+ return this.db.instance.create({
250
+ data: {
251
+ idInstance: instance.idInstance,
252
+ apiTokenInstance: instance.apiTokenInstance,
253
+ userId,
254
+ settings: settings || {},
255
+ },
256
+ });
257
+ }
258
+
259
+ // Остальные методы
260
+ }
261
+ ```
262
+
263
+ 4. **Создание адаптера платформы**
264
+
265
+ ```typescript
266
+ // core/adapter.ts
267
+ import { BaseAdapter, BaseInstance } from '@green-api/greenapi-integration';
268
+ import { YourPlatformClient } from 'your-platform-sdk';
269
+ import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
270
+
271
+ export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMessage> {
272
+ async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
273
+ return new YourPlatformClient({
274
+ baseUrl: config.apiUrl,
275
+ apiKey: config.apiKey,
276
+ });
277
+ }
278
+
279
+ async sendToPlatform(message: YourPlatformMessage, instance: BaseInstance) {
280
+ const client = await this.createPlatformClient(instance.config);
281
+ await client.sendMessage(message);
282
+ }
283
+ }
284
+ ```
285
+
286
+ 5. **Реализация контроллера вебхуков**
287
+
288
+ ```typescript
289
+ // core/webhook.ts
290
+ import express from 'express';
291
+ import { YourAdapter } from '../core/adapter';
292
+ import { YourTransformer } from '../core/transformer';
293
+ import { YourStorage } from '../core/storage';
294
+
295
+ const router = express.Router();
296
+ const storage = new YourStorage();
297
+ const transformer = new YourTransformer();
298
+ const adapter = new YourAdapter(transformer, storage);
299
+
300
+ class WebhookGuard extends BaseGreenApiAuthGuard {
301
+ constructor(storage: StorageProvider) {
302
+ super(storage);
303
+ }
304
+ }
305
+
306
+ const guard = new WebhookGuard(storage);
307
+
308
+ // Эндпоинты для вебхуков
309
+ router.post('/green-api', async (req, res) => {
310
+ try {
311
+ // Проверка вебхука
312
+ await guard.validateRequest(req);
313
+
314
+ // Обработка вебхука после проверки.
315
+ // В списке вторым параметром укажите типы вебхуков, которые необходимо обработать
316
+ await adapter.handleGreenApiWebhook(req.body, ['incomingMessageReceived']);
317
+ res.status(200).json({status: 'ok'});
318
+ } catch (error) {
319
+ if (error instanceof AuthenticationError) {
320
+ res.status(401).json({error: 'Ошибка аутентификации'});
321
+ return;
322
+ }
323
+ console.error('Ошибка обработки вебхука:', error);
324
+ res.status(500).json({error: 'Внутренняя ошибка сервера'});
325
+ }
326
+ });
327
+
328
+ router.post('/platform', async (req, res) => {
329
+ try {
330
+ const instanceId = req.query.instanceId;
331
+ await adapter.handlePlatformWebhook(req.body, instanceId);
332
+ res.status(200).json({status: 'ok'});
333
+ } catch (error) {
334
+ console.error('Ошибка обработки вебхука платформы:', error);
335
+ res.status(500).json({error: 'Внутренняя ошибка сервера'});
336
+ }
337
+ });
338
+
339
+ router.post('/instance', async (req, res) => {
340
+ try {
341
+ const {idInstance, apiTokenInstance, userEmail} = req.body;
342
+
343
+ if (!idInstance || !apiTokenInstance || !userEmail) {
344
+ throw new BadRequestError('Отсутствуют обязательные поля');
345
+ }
346
+
347
+ const instance = await adapter.createInstance({
348
+ idInstance: Number(idInstance),
349
+ apiTokenInstance
350
+ }, {
351
+ webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
352
+ webhookUrlToken: `token_${Date.now()}`, // В продакшене используйте безопасный генератор токенов
353
+ incomingWebhook: 'yes'
354
+ }, userEmail);
355
+
356
+ res.status(200).json({
357
+ status: 'ok',
358
+ data: instance,
359
+ message: 'Инстанс успешно создан. Подождите 2 минуты для применения настроек.'
360
+ });
361
+
362
+ } catch (error) {
363
+ console.error('Ошибка создания инстанса:', error);
364
+ res.status(500).json({error: 'Не удалось создать инстанс'});
365
+ }
366
+ });
367
+
368
+ export default router;
369
+ ```
370
+
371
+ 6. **Создание точки входа приложения**
372
+
373
+ ```typescript
374
+ // main.ts
375
+ import express from 'express';
376
+ import bodyParser from 'body-parser';
377
+ import dotenv from 'dotenv';
378
+ import webhookRouter from './controllers/webhook';
379
+ import { YourAdapter } from './core/adapter';
380
+ import { YourTransformer } from './core/transformer';
381
+ import { YourStorage } from './core/storage';
382
+
383
+ // Загрузка переменных окружения
384
+ dotenv.config();
385
+
386
+ async function bootstrap() {
387
+ // Инициализация компонентов
388
+ const storage = new YourStorage();
389
+ const transformer = new YourTransformer();
390
+ const adapter = new YourAdapter(transformer, storage);
391
+
392
+ // Создание Express приложения
393
+ const app = express();
394
+ app.use(bodyParser.json());
395
+
396
+ // Настройка маршрутов для вебхуков
397
+ app.use('/webhook', webhookRouter);
398
+
399
+ // Запуск сервера
400
+ const port = process.env.PORT || 3000;
401
+ app.listen(port, () => {
402
+ console.log(`Сервер запущен на порту ${port}`);
403
+ });
404
+
405
+ console.log('Интеграционная платформа готова!');
406
+ }
407
+
408
+ // Обработка ошибок
409
+ bootstrap();
410
+ ```
411
+
412
+ Или с NestJS:
413
+
414
+ ```typescript
415
+ // main.ts
416
+ import { NestFactory } from '@nestjs/core';
417
+ import { AppModule } from './app.module';
418
+ import helmet from 'helmet';
419
+
420
+ async function bootstrap() {
421
+ const app = await NestFactory.create(AppModule);
422
+ app.setGlobalPrefix('api');
423
+ app.use(helmet());
424
+ await app.listen(process.env.PORT ?? 3000);
425
+ }
426
+
427
+ bootstrap();
428
+ ```
429
+
430
+ ### Сборка приложения
431
+
432
+ 1. **Подготовка package.json**
433
+
434
+ ```json
435
+ {
436
+ "name": "greenapi-integration-yourplatform",
437
+ "version": "1.0.0",
438
+ "main": "dist/index.js",
439
+ "types": "dist/index.d.ts",
440
+ "scripts": {
441
+ "build": "tsc",
442
+ "prepublishOnly": "npm run build"
443
+ },
444
+ "dependencies": {
445
+ "@green-api/greenapi-integration": "^1.0.0",
446
+ "@prisma/client": "^5.0.0",
447
+ "express": "^4.18.2"
448
+ // другие зависимости
449
+ }
450
+ }
451
+ ```
452
+
453
+ 2. **Сборка**
454
+
455
+ ```bash
456
+ npm run build
457
+ npm publish
458
+ ```
459
+
460
+ ## Рабочий пример
461
+
462
+ В директории `/examples/custom-adapter` вы найдете полный рабочий пример, демонстрирующий:
463
+
464
+ - Двустороннюю передачу сообщений между WhatsApp и пользовательской платформой
465
+ - Обработку вебхуков
466
+ - Настройку и конфигурацию инстанса
467
+ - Преобразование сообщений
468
+ - Обработку ошибок
469
+
470
+ ### Запуск примера
471
+
472
+ 1. Клонируйте репозиторий
473
+ 2. Обновите .env данными ваших инстансов GREEN-API:
474
+
475
+ ```env
476
+ VISITOR_ID_INSTANCE=your_visitor_instance_id
477
+ VISITOR_API_TOKEN=your_visitor_instance_token
478
+ AGENT_ID_INSTANCE=your_agent_instance_id
479
+ AGENT_API_TOKEN=your_agent_instance_token
480
+ AGENT_PHONE_NUMBER=your_agent_phone_number
481
+ WEBHOOK_URL=your_webhook_url
482
+ PORT=3000
483
+ ```
484
+
485
+ 3. Установите зависимости и запустите:
486
+
487
+ ```bash
488
+ cd examples/custom-adapter
489
+ npm install
490
+ npm start
491
+ ```
492
+
493
+ # Полная реализация примера
494
+
495
+ ### Структура проекта
496
+
497
+ ```
498
+ examples/
499
+ └── custom-adapter/
500
+ ├── src/
501
+ │ ├── main.ts
502
+ │ ├── simple-adapter.ts
503
+ │ ├── simple-transformer.ts
504
+ │ ├── simple-storage.ts
505
+ │ └── types.ts
506
+ ├── .env
507
+ ├── package.json
508
+ └── tsconfig.json
509
+ ```
510
+
511
+ ### types.ts
512
+
513
+ ```typescript
514
+ interface SimplePlatformWebhook {
515
+ messageId: string;
516
+ from: string;
517
+ text: string;
518
+ timestamp: number;
519
+ }
520
+
521
+ interface SimplePlatformMessage {
522
+ to: string;
523
+ content: string;
524
+ replyTo?: string;
525
+ }
526
+ ```
527
+
528
+ ### simple-transformer.ts
529
+
530
+ ```typescript
531
+ import { MessageTransformer, Message, IncomingGreenApiWebhook, formatPhoneNumber } from 'greenapi-integration';
532
+
533
+ export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
534
+ toPlatformMessage(webhook: IncomingGreenApiWebhook): SimplePlatformMessage {
535
+ if (webhook.messageData.typeMessage !== 'extendedTextMessage') {
536
+ throw new Error('Поддерживаются только текстовые сообщения');
537
+ }
538
+
539
+ return {
540
+ to: webhook.senderData.sender,
541
+ content: webhook.messageData.extendedTextMessageData?.text || '',
542
+ };
543
+ }
544
+
545
+ toGreenApiMessage(message: SimplePlatformWebhook): Message {
546
+ return {
547
+ type: 'text',
548
+ chatId: formatPhoneNumber(message.from),
549
+ message: message.text,
550
+ };
551
+ }
552
+ }
553
+ ```
554
+
555
+ ### simple-storage.ts
556
+
557
+ ```typescript
558
+ import { StorageProvider, BaseUser, BaseInstance, Settings } from 'greenapi-integration';
559
+
560
+ export class SimpleStorage extends StorageProvider {
561
+ private users: Map<string, BaseUser> = new Map();
562
+ private instances: Map<number, BaseInstance> = new Map();
563
+
564
+ async createInstance(instance: BaseInstance, userId: bigint, settings?: Settings): Promise<BaseInstance> {
565
+ this.instances.set(Number(instance.idInstance), {
566
+ ...instance,
567
+ settings: settings || {}
568
+ });
569
+ return instance;
570
+ }
571
+
572
+ async getInstance(idInstance: number): Promise<BaseInstance | null> {
573
+ return this.instances.get(idInstance) || null;
574
+ }
575
+
576
+ async removeInstance(instanceId: number): Promise<BaseInstance> {
577
+ const instance = this.instances.get(instanceId);
578
+ if (!instance) throw new Error('Инстанс не найден');
579
+ this.instances.delete(instanceId);
580
+ return instance;
581
+ }
582
+
583
+ async createUser(data: any): Promise<BaseUser> {
584
+ const user = {id: Date.now(), ...data};
585
+ this.users.set(data.email, user);
586
+ return user;
587
+ }
588
+
589
+ async findUser(identifier: string): Promise<BaseUser | null> {
590
+ return this.users.get(identifier) || null;
591
+ }
592
+
593
+ async updateUser(identifier: string, data: any): Promise<BaseUser> {
594
+ const user = await this.findUser(identifier);
595
+ if (!user) throw new Error('Пользователь не найден');
596
+ const updated = {...user, ...data};
597
+ this.users.set(identifier, updated);
598
+ return updated;
599
+ }
600
+ }
601
+ ```
602
+
603
+ ### simple-adapter.ts
604
+
605
+ ```typescript
606
+ import { BaseAdapter, BaseInstance } from "greenapi-integration";
607
+ import axios from 'axios';
608
+
609
+ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
610
+ async createPlatformClient(config: { apiKey: string, apiUrl: string }) {
611
+ return axios.create({
612
+ baseURL: config.apiUrl,
613
+ headers: {
614
+ 'Authorization': `Bearer ${config.apiKey}`,
615
+ 'Content-Type': 'application/json'
616
+ }
617
+ });
618
+ }
619
+
620
+ async sendToPlatform(message: SimplePlatformMessage, instance: BaseInstance): Promise<void> {
621
+ // В реальной реализации мы бы отправляли сообщение на платформу
622
+ // Для демонстрации просто логируем и симулируем ответ
623
+ console.log('Платформа получила сообщение:', message);
624
+
625
+ // Симулируем обработку и ответ платформы
626
+ setTimeout(() => {
627
+ console.log('Обработка платформой завершена, отправляем ответ...');
628
+ this.simulatePlatformResponse(message, instance.idInstance);
629
+ }, 1000);
630
+ }
631
+
632
+ private async simulatePlatformResponse(originalMessage: SimplePlatformMessage, idInstance: number | bigint) {
633
+ const platformWebhook: SimplePlatformWebhook = {
634
+ messageId: `resp_${Date.now()}`,
635
+ from: originalMessage.to.replace('@c.us', ''),
636
+ text: `Спасибо за ваше сообщение: "${originalMessage.content}". Это автоматический ответ.`,
637
+ timestamp: Date.now()
638
+ };
639
+
640
+ await this.handlePlatformWebhook(platformWebhook, idInstance);
641
+ }
642
+ }
643
+ ```
644
+
645
+ ### main.ts
646
+
647
+ ```typescript
648
+ import express from "express";
649
+ import bodyParser from "body-parser";
650
+ import { formatPhoneNumber, GreenApiClient } from "greenapi-integration";
651
+ import { SimpleTransformer } from "./simple-transformer";
652
+ import { SimpleStorage } from "./simple-storage";
653
+ import { SimpleAdapter } from "./simple-adapter";
654
+ import * as dotenv from "dotenv";
655
+
656
+ dotenv.config();
657
+
658
+ async function main() {
659
+ // Инициализация компонентов
660
+ const transformer = new SimpleTransformer();
661
+ const storage = new SimpleStorage();
662
+ const adapter = new SimpleAdapter(transformer, storage);
663
+
664
+ // Конфигурация обоих инстансов
665
+ const visitorInstance = {
666
+ idInstance: Number(process.env.VISITOR_ID_INSTANCE),
667
+ apiTokenInstance: process.env.VISITOR_API_TOKEN!,
668
+ };
669
+
670
+ const agentInstance = {
671
+ idInstance: Number(process.env.AGENT_ID_INSTANCE),
672
+ apiTokenInstance: process.env.AGENT_API_TOKEN!,
673
+ };
674
+
675
+ // Создание клиента GREEN-API для посетителя (для отправки начального сообщения)
676
+ const visitorClient = new GreenApiClient(visitorInstance);
677
+
678
+ // Настройка инстанса агента
679
+ console.log("Настройка инстанса агента...");
680
+ const user = await adapter.createUser("agent@example.com", {
681
+ email: "agent@example.com",
682
+ name: "Agent",
683
+ });
684
+
685
+ const instance = await adapter.createInstance(agentInstance, {
686
+ webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
687
+ webhookUrlToken: "your-secure-token",
688
+ incomingWebhook: "yes",
689
+ }, user.email);
690
+
691
+ console.log("Ожидание 2 минуты для применения настроек...");
692
+ await new Promise(resolve => setTimeout(resolve, 120000));
693
+ console.log("Инстанс готов!");
694
+
695
+ // Настройка веб-сервера
696
+ const app = express();
697
+ app.use(bodyParser.json());
698
+
699
+ // Обработка вебхуков от GREEN-API
700
+ app.post("/webhook/green-api", async (req, res) => {
701
+ try {
702
+ console.log("Получен вебхук от GREEN-API:", req.body);
703
+ await adapter.handleGreenApiWebhook(req.body, ["incomingMessageReceived"]);
704
+ res.status(200).json({status: "ok"});
705
+ } catch (error) {
706
+ console.error("Ошибка обработки вебхука:", error);
707
+ res.status(500).json({error: "Внутренняя ошибка сервера"});
708
+ }
709
+ });
710
+
711
+ // Запуск сервера
712
+ const port = process.env.PORT || 3000;
713
+ app.listen(port, () => {
714
+ console.log(`Сервер вебхуков запущен на порту ${port}`);
715
+ });
716
+
717
+ // Отправка начального сообщения от посетителя
718
+ console.log("Отправка начального сообщения от посетителя...");
719
+ await visitorClient.sendMessage({
720
+ chatId: formatPhoneNumber(process.env.AGENT_PHONE_NUMBER!),
721
+ message: "Здравствуйте! Это тестовое сообщение от посетителя.",
722
+ type: "text",
723
+ });
724
+
725
+ console.log("Начальное сообщение отправлено! Проверьте WhatsApp агента для просмотра ответа.");
726
+ }
727
+
728
+ main().catch(console.error);
729
+ ```
730
+
731
+ ### .env
732
+
733
+ ```env
734
+ VISITOR_ID_INSTANCE=your_visitor_instance_id
735
+ VISITOR_API_TOKEN=your_visitor_instance_token
736
+ AGENT_ID_INSTANCE=your_agent_instance_id
737
+ AGENT_API_TOKEN=your_agent_instance_token
738
+ AGENT_PHONE_NUMBER=your_agent_phone_number
739
+ WEBHOOK_URL=your_webhook_url
740
+ PORT=3000
741
+ ```
742
+
743
+ ## Реальные примеры
744
+
745
+ Для полных примеров реальных интеграций, смотрите:
746
+
747
+ - [Интеграция с Rocket.Chat](link-to-rocket-chat-repo)
748
+
749
+ ## Лучшие практики
750
+
751
+ 1. **Преобразование сообщений**:
752
+ - Обрабатывайте только релевантные типы сообщений
753
+
754
+ 2. **Безопасность**:
755
+ - Проверяйте все входящие вебхуки
756
+ - Используйте безопасные вебхук-токены
757
+ - Реализуйте ограничение частоты запросов
758
+ - Используйте HTTPS для всех эндпоинтов
759
+
760
+ ## Утилиты
761
+
762
+ Платформа предоставляет несколько вспомогательных функций:
763
+
764
+ ```typescript
765
+ // Форматирование телефонных номеров для GREEN-API
766
+ formatPhoneNumber('1234567890') // Возвращает '1234567890@c.us'
767
+
768
+ // Генерация безопасных случайных токенов
769
+ generateRandomToken(32) // Возвращает 32-символьный случайный токен
770
+ ```
771
+
772
+ ## Лицензия
773
+
774
+ MIT