@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.md +771 -0
- package/README.ru.md +774 -0
- package/dist/core/base-adapter.d.ts +23 -0
- package/dist/core/base-adapter.js +135 -0
- package/dist/core/errors.d.ts +15 -0
- package/dist/core/errors.js +31 -0
- package/dist/core/green-api.client.d.ts +28 -0
- package/dist/core/green-api.client.js +150 -0
- package/dist/core/guard.d.ts +7 -0
- package/dist/core/guard.js +28 -0
- package/dist/core/message-transformer.d.ts +5 -0
- package/dist/core/message-transformer.js +6 -0
- package/dist/core/storage-provider.d.ts +9 -0
- package/dist/core/storage-provider.js +6 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +29 -0
- package/dist/types/types.d.ts +178 -0
- package/dist/types/types.js +2 -0
- package/dist/utils/helpers.d.ts +2 -0
- package/dist/utils/helpers.js +45 -0
- package/package.json +37 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { GreenApiClient } from "./green-api.client";
|
|
2
|
+
import { MessageTransformer } from "./message-transformer";
|
|
3
|
+
import { BaseInstance, BaseUser, ForwardMessagesResponse, IncomingGreenApiWebhook, Instance, SendResponse, Settings } from "../types/types";
|
|
4
|
+
import { StorageProvider } from "./storage-provider";
|
|
5
|
+
export declare abstract class BaseAdapter<TPlatformWebhook, TPlatformMessage, TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance> {
|
|
6
|
+
protected transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>;
|
|
7
|
+
protected storage: StorageProvider<TUser, TInstance>;
|
|
8
|
+
constructor(transformer: MessageTransformer<TPlatformWebhook, TPlatformMessage>, storage: StorageProvider<TUser, TInstance>);
|
|
9
|
+
abstract sendToPlatform(message: TPlatformMessage, instance: TInstance): Promise<void>;
|
|
10
|
+
createGreenApiClient(instance: BaseInstance): GreenApiClient;
|
|
11
|
+
private handleError;
|
|
12
|
+
abstract createPlatformClient(params: any): Promise<any>;
|
|
13
|
+
handlePlatformWebhook(message: TPlatformWebhook, idInstance: number | bigint): Promise<SendResponse | ForwardMessagesResponse>;
|
|
14
|
+
handleGreenApiWebhook(webhook: IncomingGreenApiWebhook, allowedTypes: string[]): Promise<void>;
|
|
15
|
+
createInstance(instance: Instance, settings: Settings, userCred: any): Promise<TInstance>;
|
|
16
|
+
removeInstance(idInstance: number | bigint): Promise<TInstance>;
|
|
17
|
+
getInstance(idInstance: number | bigint): Promise<TInstance | null>;
|
|
18
|
+
updateUser(userCred: any, userUpdateData: any): Promise<{
|
|
19
|
+
status: string;
|
|
20
|
+
message: string;
|
|
21
|
+
}>;
|
|
22
|
+
createUser(userCred: any, data: any): Promise<TUser>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseAdapter = void 0;
|
|
4
|
+
const green_api_client_1 = require("./green-api.client");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
class BaseAdapter {
|
|
7
|
+
constructor(transformer, storage) {
|
|
8
|
+
this.transformer = transformer;
|
|
9
|
+
this.storage = storage;
|
|
10
|
+
}
|
|
11
|
+
createGreenApiClient(instance) {
|
|
12
|
+
return new green_api_client_1.GreenApiClient({
|
|
13
|
+
idInstance: instance.idInstance,
|
|
14
|
+
apiTokenInstance: instance.apiTokenInstance,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
handleError(context, error) {
|
|
18
|
+
if (error instanceof errors_1.IntegrationError) {
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
22
|
+
throw new errors_1.IntegrationError(`${context}: ${errorMessage}`, "UNEXPECTED_ERROR", 500, { originalError: error });
|
|
23
|
+
}
|
|
24
|
+
async handlePlatformWebhook(message, idInstance) {
|
|
25
|
+
try {
|
|
26
|
+
const instance = await this.storage.getInstance(idInstance);
|
|
27
|
+
if (!instance) {
|
|
28
|
+
throw new errors_1.IntegrationError("Instance not found", "INSTANCE_NOT_FOUND", 404);
|
|
29
|
+
}
|
|
30
|
+
const client = this.createGreenApiClient(instance);
|
|
31
|
+
const transformedMessage = this.transformer.toGreenApiMessage(message);
|
|
32
|
+
switch (transformedMessage.type) {
|
|
33
|
+
case "url-file":
|
|
34
|
+
return client.sendFileByUrl(transformedMessage);
|
|
35
|
+
case "upload-file":
|
|
36
|
+
return client.sendFileByUpload(transformedMessage);
|
|
37
|
+
case "text":
|
|
38
|
+
return client.sendMessage(transformedMessage);
|
|
39
|
+
case "poll":
|
|
40
|
+
return client.sendPoll(transformedMessage);
|
|
41
|
+
case "contact":
|
|
42
|
+
return client.sendContact(transformedMessage);
|
|
43
|
+
case "location":
|
|
44
|
+
return client.sendLocation(transformedMessage);
|
|
45
|
+
case "forward":
|
|
46
|
+
return client.forwardMessages(transformedMessage);
|
|
47
|
+
default:
|
|
48
|
+
throw new Error("Invalid file message format");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
this.handleError("Failed to handle incoming message", error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async handleGreenApiWebhook(webhook, allowedTypes) {
|
|
56
|
+
if (!allowedTypes.includes(webhook.typeWebhook)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const transformedMessage = await this.transformer.toPlatformMessage(webhook);
|
|
61
|
+
const instance = await this.storage.getInstance(webhook.instanceData.idInstance);
|
|
62
|
+
if (!instance) {
|
|
63
|
+
throw new errors_1.NotFoundError("Instance not found");
|
|
64
|
+
}
|
|
65
|
+
await this.sendToPlatform(transformedMessage, instance);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
this.handleError("Failed to handle GREEN-API webhook", error);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async createInstance(instance, settings, userCred) {
|
|
72
|
+
console.log(instance, settings, userCred);
|
|
73
|
+
try {
|
|
74
|
+
const user = await this.storage.findUser(userCred);
|
|
75
|
+
if (!user) {
|
|
76
|
+
throw new errors_1.NotFoundError("No user with such credentials");
|
|
77
|
+
}
|
|
78
|
+
const client = this.createGreenApiClient(instance);
|
|
79
|
+
try {
|
|
80
|
+
await client.getSettings();
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new errors_1.IntegrationError(`Failed to get settings for instance ${instance.idInstance}: ${error.message}`, "INTEGRATION_ERROR");
|
|
84
|
+
}
|
|
85
|
+
const createdInstance = await this.storage.createInstance(instance, user.id, settings);
|
|
86
|
+
await client.setSettings(settings);
|
|
87
|
+
return createdInstance;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
this.handleError("Failed to add instance", error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async removeInstance(idInstance) {
|
|
94
|
+
try {
|
|
95
|
+
const instance = await this.storage.getInstance(idInstance);
|
|
96
|
+
if (!instance) {
|
|
97
|
+
throw new errors_1.NotFoundError("No instance with such ID");
|
|
98
|
+
}
|
|
99
|
+
return this.storage.removeInstance(idInstance);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
this.handleError("Failed to remove instance", error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async getInstance(idInstance) {
|
|
106
|
+
try {
|
|
107
|
+
return this.storage.getInstance(idInstance);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
this.handleError("Failed to remove instance", error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async updateUser(userCred, userUpdateData) {
|
|
114
|
+
try {
|
|
115
|
+
await this.storage.updateUser(userCred, userUpdateData);
|
|
116
|
+
return { status: "ok", message: "Token updated successfully" };
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
this.handleError(`Failed to update user ${userCred}`, error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async createUser(userCred, data) {
|
|
123
|
+
const existingUser = await this.storage.findUser(userCred);
|
|
124
|
+
if (existingUser) {
|
|
125
|
+
throw new errors_1.BadRequestError("User already created");
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
return this.storage.createUser(data);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.handleError(`Failed to create user ${userCred}`, error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.BaseAdapter = BaseAdapter;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class IntegrationError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly statusCode: number;
|
|
4
|
+
readonly details?: unknown | undefined;
|
|
5
|
+
constructor(message: string, code: string, statusCode?: number, details?: unknown | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare class BadRequestError extends IntegrationError {
|
|
8
|
+
constructor(message: string, details?: unknown);
|
|
9
|
+
}
|
|
10
|
+
export declare class AuthenticationError extends IntegrationError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class NotFoundError extends IntegrationError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotFoundError = exports.AuthenticationError = exports.BadRequestError = exports.IntegrationError = void 0;
|
|
4
|
+
class IntegrationError extends Error {
|
|
5
|
+
constructor(message, code, statusCode = 500, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.details = details;
|
|
10
|
+
this.name = "IntegrationError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.IntegrationError = IntegrationError;
|
|
14
|
+
class BadRequestError extends IntegrationError {
|
|
15
|
+
constructor(message, details) {
|
|
16
|
+
super(message, "VALIDATION_ERROR", 400, details);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.BadRequestError = BadRequestError;
|
|
20
|
+
class AuthenticationError extends IntegrationError {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message, "AUTHENTICATION_ERROR", 401);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.AuthenticationError = AuthenticationError;
|
|
26
|
+
class NotFoundError extends IntegrationError {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message, "NOT_FOUND_ERROR", 404);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.NotFoundError = NotFoundError;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Instance, Settings, SendMessage, SendFileByUrl, SendFileByUpload, SendPoll, StateInstance, Reboot, Logout, QR, SendResponse, SendFileByUploadResponse, SetSettingsResponse, GetAuthorizationCode, SetProfilePicture, WaSettings, UploadFile, SendLocation, SendContact, ForwardMessages, ForwardMessagesResponse } from "../types/types";
|
|
2
|
+
export declare class GreenApiClient {
|
|
3
|
+
private instance;
|
|
4
|
+
private client;
|
|
5
|
+
private readonly baseUrl;
|
|
6
|
+
constructor(instance: Instance);
|
|
7
|
+
private buildUrl;
|
|
8
|
+
private buildEndpoint;
|
|
9
|
+
private makeRequest;
|
|
10
|
+
private makeFileUploadRequest;
|
|
11
|
+
sendMessage(message: SendMessage): Promise<SendResponse>;
|
|
12
|
+
sendFileByUrl(message: SendFileByUrl): Promise<SendResponse>;
|
|
13
|
+
sendFileByUpload(message: SendFileByUpload): Promise<SendFileByUploadResponse>;
|
|
14
|
+
sendPoll(message: SendPoll): Promise<SendResponse>;
|
|
15
|
+
forwardMessages(request: ForwardMessages): Promise<ForwardMessagesResponse>;
|
|
16
|
+
sendLocation(message: SendLocation): Promise<SendResponse>;
|
|
17
|
+
sendContact(message: SendContact): Promise<SendResponse>;
|
|
18
|
+
reboot(): Promise<Reboot>;
|
|
19
|
+
logout(): Promise<Logout>;
|
|
20
|
+
getStateInstance(): Promise<StateInstance>;
|
|
21
|
+
getQR(): Promise<QR>;
|
|
22
|
+
getSettings(): Promise<Settings>;
|
|
23
|
+
setSettings(settings: Settings): Promise<SetSettingsResponse>;
|
|
24
|
+
getWaSettings(): Promise<WaSettings>;
|
|
25
|
+
setProfilePicture(file: Blob | File): Promise<SetProfilePicture>;
|
|
26
|
+
uploadFile(file: Blob | File, customFileName?: string): Promise<UploadFile>;
|
|
27
|
+
getAuthorizationCode(phoneNumber: number): Promise<GetAuthorizationCode>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GreenApiClient = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
class GreenApiClient {
|
|
9
|
+
constructor(instance) {
|
|
10
|
+
this.instance = instance;
|
|
11
|
+
this.baseUrl = "https://api.green-api.com";
|
|
12
|
+
this.client = axios_1.default.create({
|
|
13
|
+
baseURL: this.buildUrl(),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
buildUrl() {
|
|
17
|
+
return `${this.baseUrl}/waInstance${this.instance.idInstance}`;
|
|
18
|
+
}
|
|
19
|
+
buildEndpoint(endpoint) {
|
|
20
|
+
return `/${endpoint}/${this.instance.apiTokenInstance}`;
|
|
21
|
+
}
|
|
22
|
+
async makeRequest(method, endpoint, data, config) {
|
|
23
|
+
try {
|
|
24
|
+
const response = await (method === "get"
|
|
25
|
+
? this.client.get(this.buildEndpoint(endpoint), config)
|
|
26
|
+
: this.client.post(this.buildEndpoint(endpoint), data, config));
|
|
27
|
+
return response.data;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw new Error(`Failed to ${endpoint.replace(/([A-Z])/g, " $1").toLowerCase()}: ${error.message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async makeFileUploadRequest(endpoint, formData, headers) {
|
|
34
|
+
return this.makeRequest("post", endpoint, formData, {
|
|
35
|
+
headers: { "Content-Type": "multipart/form-data" },
|
|
36
|
+
...headers,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async sendMessage(message) {
|
|
40
|
+
return this.makeRequest("post", "sendMessage", {
|
|
41
|
+
chatId: message.chatId,
|
|
42
|
+
message: message.message,
|
|
43
|
+
quotedMessageId: message.quotedMessageId,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async sendFileByUrl(message) {
|
|
47
|
+
return this.makeRequest("post", "sendFileByUrl", {
|
|
48
|
+
chatId: message.chatId,
|
|
49
|
+
urlFile: message.file.url,
|
|
50
|
+
fileName: message.file.fileName,
|
|
51
|
+
caption: message.caption,
|
|
52
|
+
quotedMessageId: message.quotedMessageId,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async sendFileByUpload(message) {
|
|
56
|
+
const formData = new FormData();
|
|
57
|
+
formData.append("file", message.file.data);
|
|
58
|
+
formData.append("chatId", message.chatId);
|
|
59
|
+
formData.append("fileName", message.file.fileName);
|
|
60
|
+
if (message.caption)
|
|
61
|
+
formData.append("caption", message.caption);
|
|
62
|
+
if (message.quotedMessageId)
|
|
63
|
+
formData.append("quotedMessageId", message.quotedMessageId);
|
|
64
|
+
return this.makeFileUploadRequest("sendFileByUpload", formData);
|
|
65
|
+
}
|
|
66
|
+
async sendPoll(message) {
|
|
67
|
+
return this.makeRequest("post", "sendPoll", {
|
|
68
|
+
chatId: message.chatId,
|
|
69
|
+
message: message.message,
|
|
70
|
+
options: message.options,
|
|
71
|
+
multipleAnswers: message.multipleAnswers,
|
|
72
|
+
quotedMessageId: message.quotedMessageId,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async forwardMessages(request) {
|
|
76
|
+
return this.makeRequest("post", "forwardMessages", {
|
|
77
|
+
chatId: request.chatId,
|
|
78
|
+
chatIdFrom: request.chatIdFrom,
|
|
79
|
+
messages: request.messages,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async sendLocation(message) {
|
|
83
|
+
return this.makeRequest("post", "sendLocation", {
|
|
84
|
+
chatId: message.chatId,
|
|
85
|
+
nameLocation: message.nameLocation,
|
|
86
|
+
address: message.address,
|
|
87
|
+
latitude: message.latitude,
|
|
88
|
+
longitude: message.longitude,
|
|
89
|
+
quotedMessageId: message.quotedMessageId,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async sendContact(message) {
|
|
93
|
+
return this.makeRequest("post", "sendContact", {
|
|
94
|
+
chatId: message.chatId,
|
|
95
|
+
contact: message.contact,
|
|
96
|
+
quotedMessageId: message.quotedMessageId,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
async reboot() {
|
|
100
|
+
return this.makeRequest("get", "reboot");
|
|
101
|
+
}
|
|
102
|
+
async logout() {
|
|
103
|
+
return this.makeRequest("get", "logout");
|
|
104
|
+
}
|
|
105
|
+
async getStateInstance() {
|
|
106
|
+
return this.makeRequest("get", "getStateInstance");
|
|
107
|
+
}
|
|
108
|
+
async getQR() {
|
|
109
|
+
return this.makeRequest("get", "qr");
|
|
110
|
+
}
|
|
111
|
+
async getSettings() {
|
|
112
|
+
return this.makeRequest("get", "getSettings");
|
|
113
|
+
}
|
|
114
|
+
async setSettings(settings) {
|
|
115
|
+
return this.makeRequest("post", "setSettings", settings);
|
|
116
|
+
}
|
|
117
|
+
async getWaSettings() {
|
|
118
|
+
return this.makeRequest("get", "getWaSettings");
|
|
119
|
+
}
|
|
120
|
+
async setProfilePicture(file) {
|
|
121
|
+
const formData = new FormData();
|
|
122
|
+
formData.append("file", file);
|
|
123
|
+
return this.makeFileUploadRequest("setProfilePicture", formData);
|
|
124
|
+
}
|
|
125
|
+
async uploadFile(file, customFileName) {
|
|
126
|
+
const formData = new FormData();
|
|
127
|
+
formData.append("file", file);
|
|
128
|
+
const headers = {};
|
|
129
|
+
if (file instanceof File) {
|
|
130
|
+
const mimeType = file.type;
|
|
131
|
+
if (mimeType) {
|
|
132
|
+
headers["Content-Type"] = mimeType;
|
|
133
|
+
}
|
|
134
|
+
else if (customFileName) {
|
|
135
|
+
headers["GA-Filename"] = customFileName;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else if (customFileName) {
|
|
139
|
+
headers["GA-Filename"] = customFileName;
|
|
140
|
+
}
|
|
141
|
+
return this.makeFileUploadRequest("uploadFile", formData, headers);
|
|
142
|
+
}
|
|
143
|
+
async getAuthorizationCode(phoneNumber) {
|
|
144
|
+
if (!Number.isInteger(phoneNumber)) {
|
|
145
|
+
throw new Error("Phone number must contain only digits");
|
|
146
|
+
}
|
|
147
|
+
return this.makeRequest("post", "getAuthorizationCode", { phoneNumber });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.GreenApiClient = GreenApiClient;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BaseRequest } from "../types/types";
|
|
2
|
+
import { StorageProvider } from "./storage-provider";
|
|
3
|
+
export declare abstract class BaseGreenApiAuthGuard<T extends BaseRequest = BaseRequest> {
|
|
4
|
+
protected storage: StorageProvider;
|
|
5
|
+
constructor(storage: StorageProvider);
|
|
6
|
+
validateRequest(request: T): Promise<boolean>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseGreenApiAuthGuard = void 0;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
class BaseGreenApiAuthGuard {
|
|
6
|
+
constructor(storage) {
|
|
7
|
+
this.storage = storage;
|
|
8
|
+
}
|
|
9
|
+
async validateRequest(request) {
|
|
10
|
+
const token = request.headers["authorization"];
|
|
11
|
+
if (!token) {
|
|
12
|
+
throw new errors_1.AuthenticationError("Authentication header is missing");
|
|
13
|
+
}
|
|
14
|
+
const idInstance = request.body?.instanceData?.idInstance;
|
|
15
|
+
if (!idInstance) {
|
|
16
|
+
throw new errors_1.AuthenticationError("Invalid webhook format");
|
|
17
|
+
}
|
|
18
|
+
const instance = await this.storage.getInstance(idInstance);
|
|
19
|
+
if (!instance) {
|
|
20
|
+
throw new errors_1.AuthenticationError("No instance with such ID");
|
|
21
|
+
}
|
|
22
|
+
if (instance.settings?.webhookUrlToken !== token.split(" ")[1]) {
|
|
23
|
+
throw new errors_1.AuthenticationError("Invalid token");
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.BaseGreenApiAuthGuard = BaseGreenApiAuthGuard;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { IncomingGreenApiWebhook, Message } from "../types/types";
|
|
2
|
+
export declare abstract class MessageTransformer<TPlatformWebhook, TPlatformMessage> {
|
|
3
|
+
abstract toPlatformMessage(webhook: IncomingGreenApiWebhook): TPlatformMessage;
|
|
4
|
+
abstract toGreenApiMessage(message: TPlatformWebhook): Message;
|
|
5
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseInstance, BaseUser, Instance, Settings } from "../types/types";
|
|
2
|
+
export declare abstract class StorageProvider<TUser extends BaseUser = BaseUser, TInstance extends BaseInstance = Instance, TUserCreate extends Record<string, any> = any, TUserUpdate extends Record<string, any> = any> {
|
|
3
|
+
abstract createInstance(instance: BaseInstance, userId: bigint | number, settings?: Settings): Promise<TInstance>;
|
|
4
|
+
abstract getInstance(idInstance: number | bigint): Promise<TInstance | null>;
|
|
5
|
+
abstract removeInstance(instanceId: number | bigint): Promise<TInstance>;
|
|
6
|
+
abstract createUser(data: TUserCreate): Promise<TUser>;
|
|
7
|
+
abstract findUser(identifier: string): Promise<TUser | null>;
|
|
8
|
+
abstract updateUser(identifier: string, data: Partial<TUserUpdate>): Promise<TUser>;
|
|
9
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./types/types";
|
|
2
|
+
export { BaseAdapter } from "./core/base-adapter";
|
|
3
|
+
export { GreenApiClient } from "./core/green-api.client";
|
|
4
|
+
export { MessageTransformer } from "./core/message-transformer";
|
|
5
|
+
export { BaseGreenApiAuthGuard } from "./core/guard";
|
|
6
|
+
export { StorageProvider } from "./core/storage-provider";
|
|
7
|
+
export * from "./utils/helpers";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.StorageProvider = exports.BaseGreenApiAuthGuard = exports.MessageTransformer = exports.GreenApiClient = exports.BaseAdapter = void 0;
|
|
18
|
+
__exportStar(require("./types/types"), exports);
|
|
19
|
+
var base_adapter_1 = require("./core/base-adapter");
|
|
20
|
+
Object.defineProperty(exports, "BaseAdapter", { enumerable: true, get: function () { return base_adapter_1.BaseAdapter; } });
|
|
21
|
+
var green_api_client_1 = require("./core/green-api.client");
|
|
22
|
+
Object.defineProperty(exports, "GreenApiClient", { enumerable: true, get: function () { return green_api_client_1.GreenApiClient; } });
|
|
23
|
+
var message_transformer_1 = require("./core/message-transformer");
|
|
24
|
+
Object.defineProperty(exports, "MessageTransformer", { enumerable: true, get: function () { return message_transformer_1.MessageTransformer; } });
|
|
25
|
+
var guard_1 = require("./core/guard");
|
|
26
|
+
Object.defineProperty(exports, "BaseGreenApiAuthGuard", { enumerable: true, get: function () { return guard_1.BaseGreenApiAuthGuard; } });
|
|
27
|
+
var storage_provider_1 = require("./core/storage-provider");
|
|
28
|
+
Object.defineProperty(exports, "StorageProvider", { enumerable: true, get: function () { return storage_provider_1.StorageProvider; } });
|
|
29
|
+
__exportStar(require("./utils/helpers"), exports);
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
export interface BaseInstance {
|
|
2
|
+
idInstance: number | bigint;
|
|
3
|
+
apiTokenInstance: string;
|
|
4
|
+
settings?: any;
|
|
5
|
+
}
|
|
6
|
+
export interface Instance extends BaseInstance {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
export type Message = SendMessage | SendFileByUpload | SendFileByUrl | SendPoll | SendLocation | SendContact | ForwardMessages;
|
|
10
|
+
export interface BaseMessage {
|
|
11
|
+
type: SendMessageType;
|
|
12
|
+
chatId: string;
|
|
13
|
+
quotedMessageId?: string;
|
|
14
|
+
}
|
|
15
|
+
export type SendMessageType = "text" | "upload-file" | "url-file" | "poll" | "location" | "contact" | "forward";
|
|
16
|
+
export interface SendMessage extends BaseMessage {
|
|
17
|
+
type: "text";
|
|
18
|
+
message: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ForwardMessages {
|
|
21
|
+
type: "forward";
|
|
22
|
+
chatId: string;
|
|
23
|
+
chatIdFrom: string;
|
|
24
|
+
messages: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface ForwardMessagesResponse {
|
|
27
|
+
messages: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface Contact {
|
|
30
|
+
phoneContact: number;
|
|
31
|
+
firstName?: string;
|
|
32
|
+
middleName?: string;
|
|
33
|
+
lastName?: string;
|
|
34
|
+
company?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface SendContact extends BaseMessage {
|
|
37
|
+
type: "contact";
|
|
38
|
+
contact: Contact;
|
|
39
|
+
}
|
|
40
|
+
export interface SendFileByUpload extends BaseMessage {
|
|
41
|
+
type: "upload-file";
|
|
42
|
+
caption?: string;
|
|
43
|
+
file: {
|
|
44
|
+
data: Blob | File;
|
|
45
|
+
fileName: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface SendFileByUrl extends BaseMessage {
|
|
49
|
+
type: "url-file";
|
|
50
|
+
caption?: string;
|
|
51
|
+
file: {
|
|
52
|
+
url: string;
|
|
53
|
+
fileName: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface SendLocation extends BaseMessage {
|
|
57
|
+
type: "location";
|
|
58
|
+
nameLocation?: string;
|
|
59
|
+
address?: string;
|
|
60
|
+
latitude: number;
|
|
61
|
+
longitude: number;
|
|
62
|
+
}
|
|
63
|
+
export interface PollOption {
|
|
64
|
+
optionName: string;
|
|
65
|
+
}
|
|
66
|
+
export interface SendPoll extends BaseMessage {
|
|
67
|
+
type: "poll";
|
|
68
|
+
message: string;
|
|
69
|
+
options: PollOption[];
|
|
70
|
+
multipleAnswers?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export type MessageType = "textMessage" | "extendedTextMessage" | "imageMessage" | "videoMessage" | "documentMessage" | "audioMessage";
|
|
73
|
+
export interface IncomingGreenApiWebhook {
|
|
74
|
+
typeWebhook: string;
|
|
75
|
+
instanceData: {
|
|
76
|
+
idInstance: number;
|
|
77
|
+
wid: string;
|
|
78
|
+
typeInstance: string;
|
|
79
|
+
};
|
|
80
|
+
timestamp: number;
|
|
81
|
+
idMessage: string;
|
|
82
|
+
senderData: {
|
|
83
|
+
chatId: string;
|
|
84
|
+
sender: string;
|
|
85
|
+
chatName?: string;
|
|
86
|
+
senderName?: string;
|
|
87
|
+
senderContactName?: string;
|
|
88
|
+
};
|
|
89
|
+
messageData: {
|
|
90
|
+
typeMessage: MessageType;
|
|
91
|
+
textMessageData?: {
|
|
92
|
+
textMessage: string;
|
|
93
|
+
};
|
|
94
|
+
extendedTextMessageData?: {
|
|
95
|
+
text: string;
|
|
96
|
+
description?: string;
|
|
97
|
+
title?: string;
|
|
98
|
+
jpegThumbnail?: string;
|
|
99
|
+
forwardingScore?: number;
|
|
100
|
+
isForwarded?: boolean;
|
|
101
|
+
};
|
|
102
|
+
fileMessageData?: {
|
|
103
|
+
downloadUrl: string;
|
|
104
|
+
caption?: string;
|
|
105
|
+
jpegThumbnail?: string;
|
|
106
|
+
mimeType: string;
|
|
107
|
+
forwardingScore?: number;
|
|
108
|
+
isForwarded?: boolean;
|
|
109
|
+
fileName: string;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export interface Settings {
|
|
114
|
+
wid?: string;
|
|
115
|
+
webhookUrl?: string;
|
|
116
|
+
webhookUrlToken?: string;
|
|
117
|
+
delaySendMessagesMilliseconds?: number;
|
|
118
|
+
markIncomingMessagesReaded?: "yes" | "no";
|
|
119
|
+
markIncomingMessagesReadedOnReply?: "yes" | "no";
|
|
120
|
+
outgoingWebhook?: "yes" | "no";
|
|
121
|
+
outgoingMessageWebhook?: "yes" | "no";
|
|
122
|
+
outgoingAPIMessageWebhook?: "yes" | "no";
|
|
123
|
+
stateWebhook?: "yes" | "no";
|
|
124
|
+
incomingWebhook?: "yes" | "no";
|
|
125
|
+
keepOnlineStatus?: "yes" | "no";
|
|
126
|
+
pollMessageWebhook?: "yes" | "no";
|
|
127
|
+
incomingCallWebhook?: "yes" | "no";
|
|
128
|
+
}
|
|
129
|
+
export interface Reboot {
|
|
130
|
+
isReboot: boolean;
|
|
131
|
+
}
|
|
132
|
+
export interface Logout {
|
|
133
|
+
isLogout: boolean;
|
|
134
|
+
}
|
|
135
|
+
export type InstanceState = "notAuthorized" | "authorized" | "blocked" | "starting" | "yellowCard";
|
|
136
|
+
export interface StateInstance {
|
|
137
|
+
stateInstance: InstanceState;
|
|
138
|
+
}
|
|
139
|
+
export interface SendResponse {
|
|
140
|
+
idMessage: string;
|
|
141
|
+
}
|
|
142
|
+
export interface SendFileByUploadResponse {
|
|
143
|
+
idMessage: string;
|
|
144
|
+
urlFile: string;
|
|
145
|
+
}
|
|
146
|
+
export interface SetSettingsResponse {
|
|
147
|
+
saveSettings: boolean;
|
|
148
|
+
}
|
|
149
|
+
export interface QR {
|
|
150
|
+
type: "qrCode" | "error" | "alreadyLogged";
|
|
151
|
+
message: string;
|
|
152
|
+
}
|
|
153
|
+
export interface GetAuthorizationCode {
|
|
154
|
+
status: boolean;
|
|
155
|
+
code: string;
|
|
156
|
+
}
|
|
157
|
+
export interface UploadFile {
|
|
158
|
+
urlFile: string;
|
|
159
|
+
}
|
|
160
|
+
export interface WaSettings {
|
|
161
|
+
avatar: string;
|
|
162
|
+
phone: string;
|
|
163
|
+
stateInstance: InstanceState;
|
|
164
|
+
deviceId: string;
|
|
165
|
+
}
|
|
166
|
+
export interface SetProfilePicture {
|
|
167
|
+
reason: string | null;
|
|
168
|
+
urlAvatar: string;
|
|
169
|
+
setProfilePicture: boolean;
|
|
170
|
+
}
|
|
171
|
+
export interface BaseRequest {
|
|
172
|
+
headers: Record<string, any>;
|
|
173
|
+
body: any;
|
|
174
|
+
}
|
|
175
|
+
export interface BaseUser {
|
|
176
|
+
id: number | bigint;
|
|
177
|
+
[key: string]: any;
|
|
178
|
+
}
|