@green-api/greenapi-integration 0.2.0 → 0.4.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.md +65 -39
- package/README.ru.md +56 -39
- package/dist/core/base-adapter.d.ts +11 -4
- package/dist/core/base-adapter.js +26 -9
- package/dist/core/green-api.client.d.ts +225 -1
- package/dist/core/green-api.client.js +286 -5
- package/dist/core/storage-provider.d.ts +2 -3
- package/dist/types/types.d.ts +222 -4
- package/dist/utils/helpers.d.ts +32 -0
- package/dist/utils/helpers.js +64 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ Handles message format conversion between GREEN-API and your platform.
|
|
|
129
129
|
|
|
130
130
|
```typescript
|
|
131
131
|
abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
|
|
132
|
-
abstract toPlatformMessage(webhook:
|
|
132
|
+
abstract toPlatformMessage(webhook: GreenApiWebhook): TPlatformMessage;
|
|
133
133
|
|
|
134
134
|
abstract toGreenApiMessage(message: TPlatformWebhook): Message;
|
|
135
135
|
}
|
|
@@ -141,7 +141,7 @@ Interface for data persistence operations.
|
|
|
141
141
|
|
|
142
142
|
```typescript
|
|
143
143
|
abstract class StorageProvider<TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance> {
|
|
144
|
-
abstract createInstance(instance: BaseInstance, userId: bigint | number
|
|
144
|
+
abstract createInstance(instance: BaseInstance, userId: bigint | number): Promise<TInstance>;
|
|
145
145
|
|
|
146
146
|
abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
|
|
147
147
|
|
|
@@ -285,11 +285,11 @@ Create a transformer that converts messages between your platform's format and G
|
|
|
285
285
|
|
|
286
286
|
```typescript
|
|
287
287
|
// core/transformer.ts
|
|
288
|
-
import { MessageTransformer, Message,
|
|
288
|
+
import { MessageTransformer, Message, GreenApiWebhook } from '@green-api/greenapi-integration';
|
|
289
289
|
import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
|
|
290
290
|
|
|
291
291
|
export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
|
|
292
|
-
toPlatformMessage(webhook:
|
|
292
|
+
toPlatformMessage(webhook: GreenApiWebhook): YourPlatformMessage {
|
|
293
293
|
// Transform GREEN-API webhook to your platform format
|
|
294
294
|
return {
|
|
295
295
|
recipient: webhook.senderData.sender,
|
|
@@ -314,7 +314,7 @@ Create a storage provider to manage users and instances. You can use any databas
|
|
|
314
314
|
|
|
315
315
|
```typescript
|
|
316
316
|
// core/storage.ts
|
|
317
|
-
import { StorageProvider, BaseUser,
|
|
317
|
+
import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
|
|
318
318
|
import { PrismaClient } from '@prisma/client'; // Or your database client
|
|
319
319
|
|
|
320
320
|
export class YourStorage extends StorageProvider {
|
|
@@ -324,13 +324,13 @@ export class YourStorage extends StorageProvider {
|
|
|
324
324
|
this.db = new PrismaClient();
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
async createInstance(instance:
|
|
327
|
+
async createInstance(instance: Instance, userId: bigint) {
|
|
328
328
|
return this.db.instance.create({
|
|
329
329
|
data: {
|
|
330
330
|
idInstance: instance.idInstance,
|
|
331
331
|
apiTokenInstance: instance.apiTokenInstance,
|
|
332
332
|
userId,
|
|
333
|
-
settings: settings || {},
|
|
333
|
+
settings: instance.settings || {},
|
|
334
334
|
},
|
|
335
335
|
});
|
|
336
336
|
}
|
|
@@ -357,7 +357,7 @@ export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMe
|
|
|
357
357
|
});
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
-
async sendToPlatform(message: YourPlatformMessage, instance:
|
|
360
|
+
async sendToPlatform(message: YourPlatformMessage, instance: Instance) {
|
|
361
361
|
const client = await this.createPlatformClient(instance.config);
|
|
362
362
|
await client.sendMessage(message);
|
|
363
363
|
}
|
|
@@ -429,11 +429,12 @@ router.post('/instance', async (req, res) => {
|
|
|
429
429
|
|
|
430
430
|
const instance = await adapter.createInstance({
|
|
431
431
|
idInstance: Number(idInstance),
|
|
432
|
-
apiTokenInstance
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
432
|
+
apiTokenInstance,
|
|
433
|
+
settings: {
|
|
434
|
+
webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
|
|
435
|
+
webhookUrlToken: `token_${Date.now()}`,
|
|
436
|
+
incomingWebhook: 'yes'
|
|
437
|
+
}
|
|
437
438
|
}, userEmail);
|
|
438
439
|
|
|
439
440
|
res.status(200).json({
|
|
@@ -509,7 +510,7 @@ bootstrap();
|
|
|
509
510
|
"prepublishOnly": "npm run build"
|
|
510
511
|
},
|
|
511
512
|
"dependencies": {
|
|
512
|
-
"@green-api/greenapi-integration": "^
|
|
513
|
+
"@green-api/greenapi-integration": "^0.4.0",
|
|
513
514
|
"express": "^4.18.2"
|
|
514
515
|
// other dependencies
|
|
515
516
|
}
|
|
@@ -593,23 +594,33 @@ interface SimplePlatformMessage {
|
|
|
593
594
|
### simple-transformer.ts
|
|
594
595
|
|
|
595
596
|
```typescript
|
|
596
|
-
import {
|
|
597
|
+
import {
|
|
598
|
+
MessageTransformer,
|
|
599
|
+
Message,
|
|
600
|
+
GreenApiWebhook,
|
|
601
|
+
formatPhoneNumber,
|
|
602
|
+
IntegrationError,
|
|
603
|
+
} from "@green-api/greenapi-integration";
|
|
604
|
+
import { SimplePlatformMessage, SimplePlatformWebhook } from "./types";
|
|
597
605
|
|
|
598
606
|
export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
|
|
599
|
-
toPlatformMessage(webhook:
|
|
600
|
-
if (webhook.
|
|
601
|
-
|
|
602
|
-
|
|
607
|
+
toPlatformMessage(webhook: GreenApiWebhook): SimplePlatformMessage {
|
|
608
|
+
if (webhook.typeWebhook === "incomingMessageReceived") {
|
|
609
|
+
if (webhook.messageData.typeMessage !== "extendedTextMessage") {
|
|
610
|
+
throw new IntegrationError("Only text messages are supported", "BAD_REQUEST_ERROR", 400);
|
|
611
|
+
}
|
|
603
612
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
613
|
+
return {
|
|
614
|
+
to: webhook.senderData.sender,
|
|
615
|
+
content: webhook.messageData.extendedTextMessageData?.text || "",
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
throw new IntegrationError("Only incomingMessageReceived type webhooks are supported", "INTEGRATION_ERROR", 500);
|
|
608
619
|
}
|
|
609
620
|
|
|
610
621
|
toGreenApiMessage(message: SimplePlatformWebhook): Message {
|
|
611
622
|
return {
|
|
612
|
-
type:
|
|
623
|
+
type: "text",
|
|
613
624
|
chatId: formatPhoneNumber(message.from),
|
|
614
625
|
message: message.text,
|
|
615
626
|
};
|
|
@@ -620,25 +631,24 @@ export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook,
|
|
|
620
631
|
### simple-storage.ts
|
|
621
632
|
|
|
622
633
|
```typescript
|
|
623
|
-
import { StorageProvider, BaseUser,
|
|
634
|
+
import { StorageProvider, BaseUser, Instance } from '@green-api/greenapi-integration';
|
|
624
635
|
|
|
625
636
|
export class SimpleStorage extends StorageProvider {
|
|
626
637
|
private users: Map<string, BaseUser> = new Map();
|
|
627
|
-
private instances: Map<number,
|
|
638
|
+
private instances: Map<number, Instance> = new Map();
|
|
628
639
|
|
|
629
|
-
async createInstance(instance:
|
|
640
|
+
async createInstance(instance: Instance, userId: bigint): Promise<Instance> {
|
|
630
641
|
this.instances.set(Number(instance.idInstance), {
|
|
631
642
|
...instance,
|
|
632
|
-
settings: settings || {}
|
|
633
643
|
});
|
|
634
644
|
return instance;
|
|
635
645
|
}
|
|
636
646
|
|
|
637
|
-
async getInstance(idInstance: number): Promise<
|
|
647
|
+
async getInstance(idInstance: number): Promise<Instance | null> {
|
|
638
648
|
return this.instances.get(idInstance) || null;
|
|
639
649
|
}
|
|
640
650
|
|
|
641
|
-
async removeInstance(instanceId: number): Promise<
|
|
651
|
+
async removeInstance(instanceId: number): Promise<Instance> {
|
|
642
652
|
const instance = this.instances.get(instanceId);
|
|
643
653
|
if (!instance) throw new Error('Instance not found');
|
|
644
654
|
this.instances.delete(instanceId);
|
|
@@ -668,7 +678,8 @@ export class SimpleStorage extends StorageProvider {
|
|
|
668
678
|
### simple-adapter.ts
|
|
669
679
|
|
|
670
680
|
```typescript
|
|
671
|
-
import { BaseAdapter,
|
|
681
|
+
import { BaseAdapter, Instance } from "@green-api/greenapi-integration";
|
|
682
|
+
import { SimplePlatformMessage, SimplePlatformWebhook } from "./types";
|
|
672
683
|
import axios from 'axios';
|
|
673
684
|
|
|
674
685
|
export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
|
|
@@ -682,7 +693,7 @@ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlat
|
|
|
682
693
|
});
|
|
683
694
|
}
|
|
684
695
|
|
|
685
|
-
async sendToPlatform(message: SimplePlatformMessage, instance:
|
|
696
|
+
async sendToPlatform(message: SimplePlatformMessage, instance: Instance): Promise<void> {
|
|
686
697
|
// In a real implementation, we would send to the platform
|
|
687
698
|
// For demo, we'll just log and simulate a response
|
|
688
699
|
console.log('Platform received message:', message);
|
|
@@ -712,7 +723,7 @@ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlat
|
|
|
712
723
|
```typescript
|
|
713
724
|
import express from "express";
|
|
714
725
|
import bodyParser from "body-parser";
|
|
715
|
-
import { formatPhoneNumber, GreenApiClient } from "greenapi-integration";
|
|
726
|
+
import { formatPhoneNumber, GreenApiClient } from "@green-api/greenapi-integration";
|
|
716
727
|
import { SimpleTransformer } from "./simple-transformer";
|
|
717
728
|
import { SimpleStorage } from "./simple-storage";
|
|
718
729
|
import { SimpleAdapter } from "./simple-adapter";
|
|
@@ -736,6 +747,7 @@ async function main() {
|
|
|
736
747
|
idInstance: Number(process.env.AGENT_ID_INSTANCE),
|
|
737
748
|
apiTokenInstance: process.env.AGENT_API_TOKEN!,
|
|
738
749
|
};
|
|
750
|
+
console.log(visitorInstance, agentInstance);
|
|
739
751
|
|
|
740
752
|
// Create visitor's GREEN-API client (for sending initial message)
|
|
741
753
|
const visitorClient = new GreenApiClient(visitorInstance);
|
|
@@ -747,10 +759,12 @@ async function main() {
|
|
|
747
759
|
name: "Agent",
|
|
748
760
|
});
|
|
749
761
|
|
|
750
|
-
const instance = await adapter.createInstance(
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
762
|
+
const instance = await adapter.createInstance({
|
|
763
|
+
idInstance: agentInstance.idInstance, apiTokenInstance: agentInstance.apiTokenInstance, settings: {
|
|
764
|
+
webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
|
|
765
|
+
webhookUrlToken: "your-secure-token",
|
|
766
|
+
incomingWebhook: "yes",
|
|
767
|
+
},
|
|
754
768
|
}, user.email);
|
|
755
769
|
|
|
756
770
|
console.log("Waiting 2 minutes for settings to apply...");
|
|
@@ -774,7 +788,7 @@ async function main() {
|
|
|
774
788
|
});
|
|
775
789
|
|
|
776
790
|
// Start the server
|
|
777
|
-
const port = process.env.PORT || 3000;
|
|
791
|
+
const port = Number(process.env.PORT) || 3000;
|
|
778
792
|
app.listen(port, () => {
|
|
779
793
|
console.log(`Webhook server listening on port ${port}`);
|
|
780
794
|
});
|
|
@@ -817,7 +831,7 @@ The platform provides several utility functions:
|
|
|
817
831
|
|
|
818
832
|
```typescript
|
|
819
833
|
// Format phone numbers for GREEN-API
|
|
820
|
-
formatPhoneNumber('1234567890') // Returns '1234567890@c.us'
|
|
834
|
+
formatPhoneNumber('+1234567890') // Returns '1234567890@c.us'
|
|
821
835
|
|
|
822
836
|
// Generate secure random tokens
|
|
823
837
|
generateRandomToken(32) // Returns a 32-character random token
|
|
@@ -825,6 +839,18 @@ generateRandomToken(32) // Returns a 32-character random token
|
|
|
825
839
|
// Extract phone number from vcard
|
|
826
840
|
const vcard = 'BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD'
|
|
827
841
|
extractPhoneNumberFromVCard(vcard) // Returns '+1234567890'
|
|
842
|
+
|
|
843
|
+
// Validate settings values
|
|
844
|
+
isValidSettingValue('webhookUrl', 'https://example.com') // Returns true
|
|
845
|
+
|
|
846
|
+
// Clean settings
|
|
847
|
+
const input = {
|
|
848
|
+
webhookUrl: 'https://example.com',
|
|
849
|
+
outgoingWebhook: 'yes',
|
|
850
|
+
invalidKey: 'value',
|
|
851
|
+
delaySendMessagesMilliseconds: 'invalid'
|
|
852
|
+
}
|
|
853
|
+
validateAndCleanSettings(input) // Returns { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
|
|
828
854
|
```
|
|
829
855
|
|
|
830
856
|
## License
|
package/README.ru.md
CHANGED
|
@@ -128,7 +128,7 @@ app.post('/webhook/green-api', async (req, res) => {
|
|
|
128
128
|
|
|
129
129
|
```typescript
|
|
130
130
|
abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
|
|
131
|
-
abstract toPlatformMessage(webhook:
|
|
131
|
+
abstract toPlatformMessage(webhook: GreenApiWebhook): TPlatformMessage;
|
|
132
132
|
|
|
133
133
|
abstract toGreenApiMessage(message: TPlatformWebhook): Message;
|
|
134
134
|
}
|
|
@@ -140,7 +140,7 @@ abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
|
|
|
140
140
|
|
|
141
141
|
```typescript
|
|
142
142
|
abstract class StorageProvider<TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance> {
|
|
143
|
-
abstract createInstance(instance: BaseInstance, userId: bigint | number
|
|
143
|
+
abstract createInstance(instance: BaseInstance, userId: bigint | number): Promise<TInstance>;
|
|
144
144
|
|
|
145
145
|
abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
|
|
146
146
|
|
|
@@ -285,11 +285,11 @@ export interface YourPlatformMessage {
|
|
|
285
285
|
|
|
286
286
|
```typescript
|
|
287
287
|
// core/transformer.ts
|
|
288
|
-
import { MessageTransformer, Message,
|
|
288
|
+
import { MessageTransformer, Message, GreenApiWebhook } from '@green-api/greenapi-integration';
|
|
289
289
|
import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
|
|
290
290
|
|
|
291
291
|
export class YourTransformer extends MessageTransformer<YourPlatformWebhook, YourPlatformMessage> {
|
|
292
|
-
toPlatformMessage(webhook:
|
|
292
|
+
toPlatformMessage(webhook: GreenApiWebhook): YourPlatformMessage {
|
|
293
293
|
// Преобразование вебхука GREEN-API в формат вашей платформы
|
|
294
294
|
return {
|
|
295
295
|
recipient: webhook.senderData.sender,
|
|
@@ -315,7 +315,7 @@ ORM:
|
|
|
315
315
|
|
|
316
316
|
```typescript
|
|
317
317
|
// core/storage.ts
|
|
318
|
-
import { StorageProvider, BaseUser,
|
|
318
|
+
import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
|
|
319
319
|
import { PrismaClient } from '@prisma/client'; // Or your database client
|
|
320
320
|
|
|
321
321
|
export class YourStorage extends StorageProvider {
|
|
@@ -325,13 +325,13 @@ export class YourStorage extends StorageProvider {
|
|
|
325
325
|
this.db = new PrismaClient();
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
-
async createInstance(instance:
|
|
328
|
+
async createInstance(instance: Instance, userId: bigint) {
|
|
329
329
|
return this.db.instance.create({
|
|
330
330
|
data: {
|
|
331
331
|
idInstance: instance.idInstance,
|
|
332
332
|
apiTokenInstance: instance.apiTokenInstance,
|
|
333
333
|
userId,
|
|
334
|
-
settings: settings || {},
|
|
334
|
+
settings: instance.settings || {},
|
|
335
335
|
},
|
|
336
336
|
});
|
|
337
337
|
}
|
|
@@ -346,7 +346,7 @@ export class YourStorage extends StorageProvider {
|
|
|
346
346
|
|
|
347
347
|
```typescript
|
|
348
348
|
// core/adapter.ts
|
|
349
|
-
import { BaseAdapter,
|
|
349
|
+
import { BaseAdapter, Instance } from '@green-api/greenapi-integration';
|
|
350
350
|
import { YourPlatformClient } from 'your-platform-sdk';
|
|
351
351
|
import { YourPlatformWebhook, YourPlatformMessage } from '../types/types';
|
|
352
352
|
|
|
@@ -358,7 +358,7 @@ export class YourAdapter extends BaseAdapter<YourPlatformWebhook, YourPlatformMe
|
|
|
358
358
|
});
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
async sendToPlatform(message: YourPlatformMessage, instance:
|
|
361
|
+
async sendToPlatform(message: YourPlatformMessage, instance: Instance) {
|
|
362
362
|
const client = await this.createPlatformClient(instance.config);
|
|
363
363
|
await client.sendMessage(message);
|
|
364
364
|
}
|
|
@@ -430,11 +430,12 @@ router.post('/instance', async (req, res) => {
|
|
|
430
430
|
|
|
431
431
|
const instance = await adapter.createInstance({
|
|
432
432
|
idInstance: Number(idInstance),
|
|
433
|
-
apiTokenInstance
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
433
|
+
apiTokenInstance,
|
|
434
|
+
settings: {
|
|
435
|
+
webhookUrl: `${process.env.APP_URL}/webhook/green-api`,
|
|
436
|
+
webhookUrlToken: `token_${Date.now()}`,
|
|
437
|
+
incomingWebhook: 'yes'
|
|
438
|
+
}
|
|
438
439
|
}, userEmail);
|
|
439
440
|
|
|
440
441
|
res.status(200).json({
|
|
@@ -528,7 +529,7 @@ bootstrap();
|
|
|
528
529
|
"prepublishOnly": "npm run build"
|
|
529
530
|
},
|
|
530
531
|
"dependencies": {
|
|
531
|
-
"@green-api/greenapi-integration": "^
|
|
532
|
+
"@green-api/greenapi-integration": "^0.4.0",
|
|
532
533
|
"@prisma/client": "^5.0.0",
|
|
533
534
|
"express": "^4.18.2"
|
|
534
535
|
// другие зависимости
|
|
@@ -614,18 +615,21 @@ interface SimplePlatformMessage {
|
|
|
614
615
|
### simple-transformer.ts
|
|
615
616
|
|
|
616
617
|
```typescript
|
|
617
|
-
import { MessageTransformer, Message,
|
|
618
|
+
import { MessageTransformer, Message, GreenApiWebhook, formatPhoneNumber, IntegrationError } from '@green-api/greenapi-integration';
|
|
618
619
|
|
|
619
620
|
export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook, SimplePlatformMessage> {
|
|
620
|
-
toPlatformMessage(webhook:
|
|
621
|
-
if (webhook.
|
|
622
|
-
|
|
623
|
-
|
|
621
|
+
toPlatformMessage(webhook: GreenApiWebhook): SimplePlatformMessage {
|
|
622
|
+
if (webhook.typeWebhook === "incomingMessageReceived") {
|
|
623
|
+
if (webhook.messageData.typeMessage !== "extendedTextMessage") {
|
|
624
|
+
throw new IntegrationError("Поддерживаются только текстовые сообщения", "BAD_REQUEST_ERROR", 400);
|
|
625
|
+
}
|
|
624
626
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
627
|
+
return {
|
|
628
|
+
to: webhook.senderData.sender,
|
|
629
|
+
content: webhook.messageData.extendedTextMessageData?.text || "",
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
throw new IntegrationError("Поддерживаются только вебхуки вида incomingMessageReceived", "INTEGRATION_ERROR", 500);
|
|
629
633
|
}
|
|
630
634
|
|
|
631
635
|
toGreenApiMessage(message: SimplePlatformWebhook): Message {
|
|
@@ -641,25 +645,24 @@ export class SimpleTransformer extends MessageTransformer<SimplePlatformWebhook,
|
|
|
641
645
|
### simple-storage.ts
|
|
642
646
|
|
|
643
647
|
```typescript
|
|
644
|
-
import { StorageProvider, BaseUser,
|
|
648
|
+
import { StorageProvider, BaseUser, Instance, Settings } from '@green-api/greenapi-integration';
|
|
645
649
|
|
|
646
650
|
export class SimpleStorage extends StorageProvider {
|
|
647
651
|
private users: Map<string, BaseUser> = new Map();
|
|
648
|
-
private instances: Map<number,
|
|
652
|
+
private instances: Map<number, Instance> = new Map();
|
|
649
653
|
|
|
650
|
-
async createInstance(instance:
|
|
654
|
+
async createInstance(instance: Instance, userId: bigint): Promise<Instance> {
|
|
651
655
|
this.instances.set(Number(instance.idInstance), {
|
|
652
656
|
...instance,
|
|
653
|
-
settings: settings || {}
|
|
654
657
|
});
|
|
655
658
|
return instance;
|
|
656
659
|
}
|
|
657
660
|
|
|
658
|
-
async getInstance(idInstance: number): Promise<
|
|
661
|
+
async getInstance(idInstance: number): Promise<Instance | null> {
|
|
659
662
|
return this.instances.get(idInstance) || null;
|
|
660
663
|
}
|
|
661
664
|
|
|
662
|
-
async removeInstance(instanceId: number): Promise<
|
|
665
|
+
async removeInstance(instanceId: number): Promise<Instance> {
|
|
663
666
|
const instance = this.instances.get(instanceId);
|
|
664
667
|
if (!instance) throw new Error('Инстанс не найден');
|
|
665
668
|
this.instances.delete(instanceId);
|
|
@@ -689,7 +692,7 @@ export class SimpleStorage extends StorageProvider {
|
|
|
689
692
|
### simple-adapter.ts
|
|
690
693
|
|
|
691
694
|
```typescript
|
|
692
|
-
import { BaseAdapter,
|
|
695
|
+
import { BaseAdapter, Instance } from "@green-api/greenapi-integration";
|
|
693
696
|
import axios from 'axios';
|
|
694
697
|
|
|
695
698
|
export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlatformMessage> {
|
|
@@ -703,7 +706,7 @@ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlat
|
|
|
703
706
|
});
|
|
704
707
|
}
|
|
705
708
|
|
|
706
|
-
async sendToPlatform(message: SimplePlatformMessage, instance:
|
|
709
|
+
async sendToPlatform(message: SimplePlatformMessage, instance: Instance): Promise<void> {
|
|
707
710
|
// В реальной реализации мы бы отправляли сообщение на платформу
|
|
708
711
|
// Для демонстрации просто логируем и симулируем ответ
|
|
709
712
|
console.log('Платформа получила сообщение:', message);
|
|
@@ -733,7 +736,7 @@ export class SimpleAdapter extends BaseAdapter<SimplePlatformWebhook, SimplePlat
|
|
|
733
736
|
```typescript
|
|
734
737
|
import express from "express";
|
|
735
738
|
import bodyParser from "body-parser";
|
|
736
|
-
import { formatPhoneNumber, GreenApiClient } from "greenapi-integration";
|
|
739
|
+
import { formatPhoneNumber, GreenApiClient } from "@green-api/greenapi-integration";
|
|
737
740
|
import { SimpleTransformer } from "./simple-transformer";
|
|
738
741
|
import { SimpleStorage } from "./simple-storage";
|
|
739
742
|
import { SimpleAdapter } from "./simple-adapter";
|
|
@@ -768,10 +771,12 @@ async function main() {
|
|
|
768
771
|
name: "Agent",
|
|
769
772
|
});
|
|
770
773
|
|
|
771
|
-
const instance = await adapter.createInstance(
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
774
|
+
const instance = await adapter.createInstance({
|
|
775
|
+
idInstance: agentInstance.idInstance, apiTokenInstance: agentInstance.apiTokenInstance, settings: {
|
|
776
|
+
webhookUrl: process.env.WEBHOOK_URL + "/webhook/green-api",
|
|
777
|
+
webhookUrlToken: "your-secure-token",
|
|
778
|
+
incomingWebhook: "yes",
|
|
779
|
+
},
|
|
775
780
|
}, user.email);
|
|
776
781
|
|
|
777
782
|
console.log("Ожидание 2 минуты для применения настроек...");
|
|
@@ -795,7 +800,7 @@ async function main() {
|
|
|
795
800
|
});
|
|
796
801
|
|
|
797
802
|
// Запуск сервера
|
|
798
|
-
const port = process.env.PORT || 3000;
|
|
803
|
+
const port = Number(process.env.PORT) || 3000;
|
|
799
804
|
app.listen(port, () => {
|
|
800
805
|
console.log(`Сервер вебхуков запущен на порту ${port}`);
|
|
801
806
|
});
|
|
@@ -838,7 +843,7 @@ PORT=3000
|
|
|
838
843
|
|
|
839
844
|
```typescript
|
|
840
845
|
// Форматирование телефонных номеров для GREEN-API
|
|
841
|
-
formatPhoneNumber('1234567890') // Возвращает '1234567890@c.us'
|
|
846
|
+
formatPhoneNumber('+1234567890') // Возвращает '1234567890@c.us'
|
|
842
847
|
|
|
843
848
|
// Генерация безопасных случайных токенов
|
|
844
849
|
generateRandomToken(32) // Возвращает 32-символьный случайный токен
|
|
@@ -846,6 +851,18 @@ generateRandomToken(32) // Возвращает 32-символьный случ
|
|
|
846
851
|
// Извлечение номера телефона из vcard
|
|
847
852
|
const vcard = 'BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD'
|
|
848
853
|
extractPhoneNumberFromVCard(vcard) // Возвращает '+1234567890'
|
|
854
|
+
|
|
855
|
+
// Проверка значений настроек
|
|
856
|
+
isValidSettingValue('webhookUrl', 'https://example.com') // Возвращает true
|
|
857
|
+
|
|
858
|
+
// Очистка настроек
|
|
859
|
+
const input = {
|
|
860
|
+
webhookUrl: 'https://example.com',
|
|
861
|
+
outgoingWebhook: 'yes',
|
|
862
|
+
invalidKey: 'value',
|
|
863
|
+
delaySendMessagesMilliseconds: 'invalid'
|
|
864
|
+
}
|
|
865
|
+
validateAndCleanSettings(input) // Возвращает { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
|
|
849
866
|
```
|
|
850
867
|
|
|
851
868
|
## Лицензия
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GreenApiClient } from "./green-api.client";
|
|
2
2
|
import { MessageTransformer } from "./message-transformer";
|
|
3
|
-
import { BaseUser, ForwardMessagesResponse, GreenApiWebhook, Instance, SendResponse,
|
|
3
|
+
import { BaseUser, ForwardMessagesResponse, GreenApiWebhook, Instance, SendResponse, StateInstanceWebhook, WebhookType } from "../types/types";
|
|
4
4
|
import { StorageProvider } from "./storage-provider";
|
|
5
5
|
/**
|
|
6
6
|
* Base adapter for platform integrations with GREEN-API.
|
|
@@ -74,6 +74,14 @@ export declare abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage, TU
|
|
|
74
74
|
* ```
|
|
75
75
|
*/
|
|
76
76
|
abstract createPlatformClient(params: any): Promise<any>;
|
|
77
|
+
/**
|
|
78
|
+
* Handles instance state change webhooks from GREEN-API.
|
|
79
|
+
* Adapters MUST override this method if they need to handle instance state changes
|
|
80
|
+
*
|
|
81
|
+
* @param webhook - The state change webhook from GREEN-API
|
|
82
|
+
* @returns Promise resolving when the webhook is handled
|
|
83
|
+
*/
|
|
84
|
+
handleStateInstanceWebhook(webhook: StateInstanceWebhook): Promise<void>;
|
|
77
85
|
/**
|
|
78
86
|
* Creates a GREEN-API client instance.
|
|
79
87
|
*
|
|
@@ -107,18 +115,17 @@ export declare abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage, TU
|
|
|
107
115
|
* @throws {NotFoundError} If instance is not found
|
|
108
116
|
* @throws {IntegrationError} If webhook handling fails
|
|
109
117
|
*/
|
|
110
|
-
handleGreenApiWebhook(webhook: GreenApiWebhook, allowedTypes:
|
|
118
|
+
handleGreenApiWebhook(webhook: GreenApiWebhook, allowedTypes: WebhookType[]): Promise<void>;
|
|
111
119
|
/**
|
|
112
120
|
* Creates a new instance with specified settings.
|
|
113
121
|
*
|
|
114
122
|
* @param instance - The instance configuration
|
|
115
|
-
* @param settings - GREEN-API settings for the instance
|
|
116
123
|
* @param userCred - User credentials
|
|
117
124
|
* @returns Promise resolving to the created instance
|
|
118
125
|
* @throws {NotFoundError} If user is not found
|
|
119
126
|
* @throws {IntegrationError} If instance creation fails
|
|
120
127
|
*/
|
|
121
|
-
createInstance(instance: Instance,
|
|
128
|
+
createInstance(instance: Instance, userCred: any): Promise<TInstance>;
|
|
122
129
|
/**
|
|
123
130
|
* Removes an instance by ID.
|
|
124
131
|
*
|
|
@@ -38,6 +38,17 @@ class BaseAdapter {
|
|
|
38
38
|
this.transformer = transformer;
|
|
39
39
|
this.storage = storage;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Handles instance state change webhooks from GREEN-API.
|
|
43
|
+
* Adapters MUST override this method if they need to handle instance state changes
|
|
44
|
+
*
|
|
45
|
+
* @param webhook - The state change webhook from GREEN-API
|
|
46
|
+
* @returns Promise resolving when the webhook is handled
|
|
47
|
+
*/
|
|
48
|
+
async handleStateInstanceWebhook(webhook) {
|
|
49
|
+
// Default empty implementation
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
41
52
|
/**
|
|
42
53
|
* Creates a GREEN-API client instance.
|
|
43
54
|
*
|
|
@@ -117,12 +128,17 @@ class BaseAdapter {
|
|
|
117
128
|
return;
|
|
118
129
|
}
|
|
119
130
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
if (webhook.typeWebhook === "stateInstanceChanged") {
|
|
132
|
+
await this.handleStateInstanceWebhook(webhook);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const transformedMessage = await this.transformer.toPlatformMessage(webhook);
|
|
136
|
+
const instance = await this.storage.getInstance(webhook.instanceData.idInstance);
|
|
137
|
+
if (!instance) {
|
|
138
|
+
throw new errors_1.NotFoundError("Instance not found");
|
|
139
|
+
}
|
|
140
|
+
await this.sendToPlatform(transformedMessage, instance);
|
|
124
141
|
}
|
|
125
|
-
await this.sendToPlatform(transformedMessage, instance);
|
|
126
142
|
}
|
|
127
143
|
catch (error) {
|
|
128
144
|
this.handleError("Failed to handle GREEN-API webhook", error);
|
|
@@ -132,13 +148,12 @@ class BaseAdapter {
|
|
|
132
148
|
* Creates a new instance with specified settings.
|
|
133
149
|
*
|
|
134
150
|
* @param instance - The instance configuration
|
|
135
|
-
* @param settings - GREEN-API settings for the instance
|
|
136
151
|
* @param userCred - User credentials
|
|
137
152
|
* @returns Promise resolving to the created instance
|
|
138
153
|
* @throws {NotFoundError} If user is not found
|
|
139
154
|
* @throws {IntegrationError} If instance creation fails
|
|
140
155
|
*/
|
|
141
|
-
async createInstance(instance,
|
|
156
|
+
async createInstance(instance, userCred) {
|
|
142
157
|
try {
|
|
143
158
|
const user = await this.storage.findUser(userCred);
|
|
144
159
|
if (!user) {
|
|
@@ -151,8 +166,10 @@ class BaseAdapter {
|
|
|
151
166
|
catch (error) {
|
|
152
167
|
throw new errors_1.IntegrationError(`Failed to get settings for instance ${instance.idInstance}: ${error.message}`, "INTEGRATION_ERROR");
|
|
153
168
|
}
|
|
154
|
-
const createdInstance = await this.storage.createInstance(instance, user.id
|
|
155
|
-
|
|
169
|
+
const createdInstance = await this.storage.createInstance(instance, user.id);
|
|
170
|
+
if (instance.settings) {
|
|
171
|
+
await client.setSettings(instance.settings);
|
|
172
|
+
}
|
|
156
173
|
return createdInstance;
|
|
157
174
|
}
|
|
158
175
|
catch (error) {
|