@green-api/greenapi-integration 0.8.1 → 0.10.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/dist/core/base-adapter.js +6 -0
- package/dist/core/green-api.client.d.ts +73 -7
- package/dist/core/green-api.client.js +143 -46
- package/dist/core/guard.js +4 -4
- package/dist/core/logger.js +0 -2
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.js +6 -0
- package/dist/types/types.d.ts +51 -4
- package/package.json +10 -13
|
@@ -61,6 +61,8 @@ class BaseAdapter {
|
|
|
61
61
|
return new green_api_client_1.GreenApiClient({
|
|
62
62
|
idInstance: instance.idInstance,
|
|
63
63
|
apiTokenInstance: instance.apiTokenInstance,
|
|
64
|
+
apiUrl: instance.apiUrl,
|
|
65
|
+
mediaUrl: instance.mediaUrl,
|
|
64
66
|
});
|
|
65
67
|
}
|
|
66
68
|
/**
|
|
@@ -110,6 +112,10 @@ class BaseAdapter {
|
|
|
110
112
|
return client.sendLocation(transformedMessage);
|
|
111
113
|
case "forward":
|
|
112
114
|
return client.forwardMessages(transformedMessage);
|
|
115
|
+
case "interactive-buttons":
|
|
116
|
+
return client.sendInteractiveButtons(transformedMessage);
|
|
117
|
+
case "interactive-buttons-reply":
|
|
118
|
+
return client.sendInteractiveButtonsReply(transformedMessage);
|
|
113
119
|
default:
|
|
114
120
|
throw new Error("Invalid file message format");
|
|
115
121
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Instance, Settings, SendMessage, SendFileByUrl, SendFileByUpload, SendPoll, StateInstance, Reboot, Logout, QR, SendResponse, SendFileByUploadResponse, SetSettingsResponse, GetAuthorizationCode, SetProfilePicture, WaSettings, UploadFile, SendLocation, SendContact, ForwardMessages, ForwardMessagesResponse, QueueMessage, ClearMessagesQueue, ReadChatResponse, ReadChat, CheckWhatsapp, CheckWhatsappResponse, GetAvatarResponse, GetAvatar, Contact, ContactInfo, ArchiveChat, UnarchiveChat, SetDisappearingChat, SetDisappearingChatResponse, CreateGroupResponse, CreateGroup, UpdateGroupName, UpdateGroupNameResponse, GetGroupData, GroupData, AddGroupParticipant, AddGroupParticipantResponse, RemoveGroupParticipant, RemoveGroupParticipantResponse, SetGroupAdmin, SetGroupAdminResponse, RemoveAdminResponse, RemoveAdmin, SetGroupPicture, SetGroupPictureResponse, LeaveGroup, LeaveGroupResponse, GetMessage, JournalResponse, GetChatHistory, IncomingJournalResponse, OutgoingJournalResponse, SendInteractiveButtons, SendInteractiveButtonsReply, SendTextStatus, SendVoiceStatus, SendMediaStatus, GetStatusStatisticResponse } from "../types/types";
|
|
1
|
+
import { Instance, Settings, SendMessage, SendFileByUrl, SendFileByUpload, SendPoll, StateInstance, Reboot, Logout, QR, SendResponse, SendFileByUploadResponse, SetSettingsResponse, GetAuthorizationCode, SetProfilePicture, WaSettings, AccountSettings, UploadFile, SendLocation, SendContact, ForwardMessages, ForwardMessagesResponse, QueueMessage, ClearMessagesQueue, ReadChatResponse, ReadChat, CheckWhatsapp, CheckWhatsappResponse, CheckAccount, CheckAccountResponse, GetAvatarResponse, GetAvatar, Contact, ContactInfo, ArchiveChat, UnarchiveChat, SetDisappearingChat, SetDisappearingChatResponse, CreateGroupResponse, CreateGroup, UpdateGroupName, UpdateGroupNameResponse, GetGroupData, GroupData, AddGroupParticipant, AddGroupParticipantResponse, RemoveGroupParticipant, RemoveGroupParticipantResponse, SetGroupAdmin, SetGroupAdminResponse, RemoveAdminResponse, RemoveAdmin, SetGroupPicture, SetGroupPictureResponse, LeaveGroup, LeaveGroupResponse, GetMessage, JournalResponse, GetChatHistory, IncomingJournalResponse, OutgoingJournalResponse, SendInteractiveButtons, SendInteractiveButtonsReply, SendTextStatus, SendVoiceStatus, SendMediaStatus, GetStatusStatisticResponse, GreenApiClientOptions, ReceiveNotificationResponse, DeleteNotificationResponse } from "../types/types";
|
|
2
2
|
/**
|
|
3
3
|
* Client for direct interaction with GREEN-API's WhatsApp gateway.
|
|
4
4
|
* Provides methods for sending messages, managing instances, and handling files.
|
|
@@ -22,16 +22,22 @@ import { Instance, Settings, SendMessage, SendFileByUrl, SendFileByUpload, SendP
|
|
|
22
22
|
export declare class GreenApiClient {
|
|
23
23
|
private instance;
|
|
24
24
|
private client;
|
|
25
|
+
private mediaClient;
|
|
25
26
|
private readonly baseUrl;
|
|
27
|
+
private readonly mediaBaseUrl;
|
|
26
28
|
private readonly gaLogger;
|
|
27
29
|
/**
|
|
28
30
|
* Creates a GREEN-API client instance.
|
|
29
31
|
*
|
|
30
|
-
* @param instance - Configuration containing idInstance and
|
|
32
|
+
* @param instance - Configuration containing idInstance, apiTokenInstance and optionally apiUrl and mediaUrl
|
|
33
|
+
* @param options - Client options, e.g. `logger: null` to disable request logging
|
|
31
34
|
*/
|
|
32
|
-
constructor(instance: Instance);
|
|
35
|
+
constructor(instance: Instance, options?: GreenApiClientOptions);
|
|
33
36
|
private buildUrl;
|
|
37
|
+
private toBlob;
|
|
38
|
+
private toBuffer;
|
|
34
39
|
private buildEndpoint;
|
|
40
|
+
private redactToken;
|
|
35
41
|
private makeRequest;
|
|
36
42
|
private makeFileUploadRequest;
|
|
37
43
|
/**
|
|
@@ -261,22 +267,37 @@ export declare class GreenApiClient {
|
|
|
261
267
|
*
|
|
262
268
|
* @returns Promise resolving to WhatsApp settings
|
|
263
269
|
*/
|
|
270
|
+
getAccountSettings(): Promise<AccountSettings>;
|
|
264
271
|
getWaSettings(): Promise<WaSettings>;
|
|
265
272
|
/**
|
|
266
273
|
* Sets the profile picture for the WhatsApp account.
|
|
267
274
|
*
|
|
268
|
-
* @param file - Image file to use as profile picture
|
|
275
|
+
* @param file - Image file (jpg) to use as profile picture
|
|
276
|
+
* @param fileName - File name with extension
|
|
269
277
|
* @returns Promise resolving to profile picture update response
|
|
270
278
|
*/
|
|
271
|
-
setProfilePicture(file: Blob | File): Promise<SetProfilePicture>;
|
|
279
|
+
setProfilePicture(file: Blob | File | Uint8Array, fileName?: string): Promise<SetProfilePicture>;
|
|
272
280
|
/**
|
|
273
281
|
* Uploads a file to GREEN-API servers.
|
|
274
282
|
*
|
|
275
283
|
* @param file - File to upload
|
|
276
|
-
* @param
|
|
284
|
+
* @param fileName - File name with extension
|
|
277
285
|
* @returns Promise resolving to upload response with file URL
|
|
278
286
|
*/
|
|
279
|
-
uploadFile(file: Blob | File,
|
|
287
|
+
uploadFile(file: Blob | File | Uint8Array, fileName?: string): Promise<UploadFile>;
|
|
288
|
+
/**
|
|
289
|
+
* Calls any GREEN-API method that takes a file.
|
|
290
|
+
*
|
|
291
|
+
* @param endpoint - GREEN-API method name, e.g. "setGroupPicture"
|
|
292
|
+
* @param file - File content and file name
|
|
293
|
+
* @param fields - Other form fields
|
|
294
|
+
* @returns Promise resolving to the raw response body
|
|
295
|
+
*/
|
|
296
|
+
requestWithFile<T = unknown>(endpoint: string, file: {
|
|
297
|
+
data: Blob | File | Uint8Array;
|
|
298
|
+
fileName: string;
|
|
299
|
+
}, fields?: Record<string, string | number | boolean>): Promise<T>;
|
|
300
|
+
private pictureFileName;
|
|
280
301
|
/**
|
|
281
302
|
* Gets authorization code for a phone number.
|
|
282
303
|
*
|
|
@@ -314,6 +335,43 @@ export declare class GreenApiClient {
|
|
|
314
335
|
* ```
|
|
315
336
|
*/
|
|
316
337
|
clearMessagesQueue(): Promise<ClearMessagesQueue>;
|
|
338
|
+
/**
|
|
339
|
+
* Calls any GREEN-API method by name.
|
|
340
|
+
*
|
|
341
|
+
* @param method - HTTP method
|
|
342
|
+
* @param endpoint - GREEN-API method name, e.g. "getContacts"
|
|
343
|
+
* @param data - Request body for POST
|
|
344
|
+
* @param queryParams - Query parameters
|
|
345
|
+
* @returns Promise resolving to the raw response body
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* ```typescript
|
|
349
|
+
* const contacts = await client.request("get", "getContacts");
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
request<T = unknown>(method: "get" | "post" | "delete", endpoint: string, data?: unknown, queryParams?: Record<string, string | number>): Promise<T>;
|
|
353
|
+
/**
|
|
354
|
+
* Receives the next notification from the instance queue.
|
|
355
|
+
*
|
|
356
|
+
* @param receiveTimeout - Seconds to wait for a notification, 5 to 60
|
|
357
|
+
* @returns Promise resolving to the notification, or null when the queue stayed empty
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```typescript
|
|
361
|
+
* const notification = await client.receiveNotification(20);
|
|
362
|
+
* if (notification) {
|
|
363
|
+
* await client.deleteNotification(notification.receiptId);
|
|
364
|
+
* }
|
|
365
|
+
* ```
|
|
366
|
+
*/
|
|
367
|
+
receiveNotification(receiveTimeout?: number): Promise<ReceiveNotificationResponse | null>;
|
|
368
|
+
/**
|
|
369
|
+
* Deletes a processed notification from the instance queue.
|
|
370
|
+
*
|
|
371
|
+
* @param receiptId - Receipt ID from receiveNotification
|
|
372
|
+
* @returns Promise resolving to deletion result
|
|
373
|
+
*/
|
|
374
|
+
deleteNotification(receiptId: number): Promise<DeleteNotificationResponse>;
|
|
317
375
|
/**
|
|
318
376
|
* Marks messages in a chat as read.
|
|
319
377
|
* For this to work, "Receive webhooks on incoming messages and files" setting must be enabled.
|
|
@@ -356,6 +414,14 @@ export declare class GreenApiClient {
|
|
|
356
414
|
* ```
|
|
357
415
|
*/
|
|
358
416
|
checkWhatsapp(params: CheckWhatsapp): Promise<CheckWhatsappResponse>;
|
|
417
|
+
/**
|
|
418
|
+
* Checks whether a messenger account exists for a phone number or username (Telegram, MAX).
|
|
419
|
+
*
|
|
420
|
+
* @param params - Phone number in international format, or a Telegram username starting with "@"
|
|
421
|
+
* @returns Promise resolving to the existence flag and, when the account exists, its chat id
|
|
422
|
+
* @throws {Error} If neither phoneNumber nor username is given
|
|
423
|
+
*/
|
|
424
|
+
checkAccount(params: CheckAccount): Promise<CheckAccountResponse>;
|
|
359
425
|
/**
|
|
360
426
|
* Gets a user or group chat avatar.
|
|
361
427
|
*
|
|
@@ -7,6 +7,7 @@ exports.GreenApiClient = void 0;
|
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const errors_1 = require("./errors");
|
|
9
9
|
const logger_1 = require("./logger");
|
|
10
|
+
const defaults_1 = require("../defaults");
|
|
10
11
|
/**
|
|
11
12
|
* Client for direct interaction with GREEN-API's WhatsApp gateway.
|
|
12
13
|
* Provides methods for sending messages, managing instances, and handling files.
|
|
@@ -31,47 +32,71 @@ class GreenApiClient {
|
|
|
31
32
|
/**
|
|
32
33
|
* Creates a GREEN-API client instance.
|
|
33
34
|
*
|
|
34
|
-
* @param instance - Configuration containing idInstance and
|
|
35
|
+
* @param instance - Configuration containing idInstance, apiTokenInstance and optionally apiUrl and mediaUrl
|
|
36
|
+
* @param options - Client options, e.g. `logger: null` to disable request logging
|
|
35
37
|
*/
|
|
36
|
-
constructor(instance) {
|
|
38
|
+
constructor(instance, options = {}) {
|
|
37
39
|
this.instance = instance;
|
|
38
|
-
this.baseUrl =
|
|
39
|
-
this.
|
|
40
|
+
this.baseUrl = (instance.apiUrl || defaults_1.DEFAULT_API_URL).replace(/\/+$/, "");
|
|
41
|
+
this.mediaBaseUrl = (instance.mediaUrl || this.baseUrl).replace(/\/+$/, "");
|
|
40
42
|
this.client = axios_1.default.create({
|
|
41
|
-
baseURL: this.buildUrl(),
|
|
43
|
+
baseURL: this.buildUrl(this.baseUrl),
|
|
42
44
|
});
|
|
45
|
+
this.mediaClient = axios_1.default.create({
|
|
46
|
+
baseURL: this.buildUrl(this.mediaBaseUrl),
|
|
47
|
+
});
|
|
48
|
+
this.gaLogger = options.logger === undefined ? logger_1.GreenApiLogger.getInstance(GreenApiClient.name) : options.logger;
|
|
49
|
+
}
|
|
50
|
+
buildUrl(host) {
|
|
51
|
+
return `${host}/waInstance${this.instance.idInstance}`;
|
|
43
52
|
}
|
|
44
|
-
|
|
45
|
-
return
|
|
53
|
+
toBlob(data) {
|
|
54
|
+
return data instanceof Blob ? data : new Blob([data]);
|
|
55
|
+
}
|
|
56
|
+
toBuffer(data) {
|
|
57
|
+
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
46
58
|
}
|
|
47
59
|
buildEndpoint(endpoint) {
|
|
48
60
|
return `/${endpoint}/${this.instance.apiTokenInstance}`;
|
|
49
61
|
}
|
|
50
|
-
|
|
62
|
+
redactToken(text) {
|
|
63
|
+
const token = this.instance.apiTokenInstance;
|
|
64
|
+
return token ? text.split(token).join(defaults_1.REDACTED_TOKEN) : text;
|
|
65
|
+
}
|
|
66
|
+
async makeRequest(method, endpoint, data, queryParams, config, pathAfterToken, host = "api") {
|
|
51
67
|
try {
|
|
52
|
-
this.gaLogger
|
|
68
|
+
this.gaLogger?.info("Making a request", {
|
|
53
69
|
idInstance: this.instance.idInstance,
|
|
54
70
|
endpoint,
|
|
55
71
|
method,
|
|
56
|
-
data,
|
|
72
|
+
data: Buffer.isBuffer(data) ? `${data.length} bytes` : data,
|
|
57
73
|
queryParams,
|
|
58
74
|
config,
|
|
59
75
|
});
|
|
60
|
-
const url = this.buildEndpoint(endpoint) + (queryParams ? "?" + new URLSearchParams(Object.entries(queryParams).map(([key, value]) => [key, value.toString()])).toString() : "");
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
76
|
+
const url = this.buildEndpoint(endpoint) + (pathAfterToken ? `/${pathAfterToken}` : "") + (queryParams ? "?" + new URLSearchParams(Object.entries(queryParams).map(([key, value]) => [key, value.toString()])).toString() : "");
|
|
77
|
+
const client = host === "media" ? this.mediaClient : this.client;
|
|
78
|
+
let response;
|
|
79
|
+
if (method === "get") {
|
|
80
|
+
response = await client.get(url, config);
|
|
81
|
+
}
|
|
82
|
+
else if (method === "delete") {
|
|
83
|
+
response = await client.delete(url, config);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
response = await client.post(url, data, config);
|
|
87
|
+
}
|
|
64
88
|
return response.data;
|
|
65
89
|
}
|
|
66
90
|
catch (error) {
|
|
67
|
-
|
|
91
|
+
const responseData = error.response?.data === undefined
|
|
92
|
+
? undefined
|
|
93
|
+
: JSON.parse(this.redactToken(JSON.stringify(error.response.data)));
|
|
94
|
+
const reason = this.redactToken(String(error.message));
|
|
95
|
+
throw new errors_1.IntegrationError(`Failed to ${endpoint.replace(/([A-Z])/g, " $1").toLowerCase()}: ${reason}${responseData === undefined ? "" : `. ${JSON.stringify(responseData)}`}`, "INTEGRATION_ERROR", error.response?.status ?? 500, responseData);
|
|
68
96
|
}
|
|
69
97
|
}
|
|
70
|
-
async makeFileUploadRequest(endpoint, formData,
|
|
71
|
-
return this.makeRequest("post", endpoint, formData, undefined, {
|
|
72
|
-
headers: { "Content-Type": "multipart/form-data" },
|
|
73
|
-
...headers,
|
|
74
|
-
});
|
|
98
|
+
async makeFileUploadRequest(endpoint, formData, host = "api") {
|
|
99
|
+
return this.makeRequest("post", endpoint, formData, undefined, { headers: { "Content-Type": "multipart/form-data" } }, undefined, host);
|
|
75
100
|
}
|
|
76
101
|
/**
|
|
77
102
|
* Sends a text message to a WhatsApp chat.
|
|
@@ -142,14 +167,14 @@ class GreenApiClient {
|
|
|
142
167
|
*/
|
|
143
168
|
async sendFileByUpload(message) {
|
|
144
169
|
const formData = new FormData();
|
|
145
|
-
formData.append("file", message.file.data);
|
|
170
|
+
formData.append("file", this.toBlob(message.file.data), message.file.fileName);
|
|
146
171
|
formData.append("chatId", message.chatId);
|
|
147
172
|
formData.append("fileName", message.file.fileName);
|
|
148
173
|
if (message.caption)
|
|
149
174
|
formData.append("caption", message.caption);
|
|
150
175
|
if (message.quotedMessageId)
|
|
151
176
|
formData.append("quotedMessageId", message.quotedMessageId);
|
|
152
|
-
return this.makeFileUploadRequest("sendFileByUpload", formData);
|
|
177
|
+
return this.makeFileUploadRequest("sendFileByUpload", formData, "media");
|
|
153
178
|
}
|
|
154
179
|
/**
|
|
155
180
|
* Creates a poll in a WhatsApp chat.
|
|
@@ -383,44 +408,59 @@ class GreenApiClient {
|
|
|
383
408
|
*
|
|
384
409
|
* @returns Promise resolving to WhatsApp settings
|
|
385
410
|
*/
|
|
411
|
+
async getAccountSettings() {
|
|
412
|
+
return this.makeRequest("get", "getAccountSettings");
|
|
413
|
+
}
|
|
386
414
|
async getWaSettings() {
|
|
387
415
|
return this.makeRequest("get", "getWaSettings");
|
|
388
416
|
}
|
|
389
417
|
/**
|
|
390
418
|
* Sets the profile picture for the WhatsApp account.
|
|
391
419
|
*
|
|
392
|
-
* @param file - Image file to use as profile picture
|
|
420
|
+
* @param file - Image file (jpg) to use as profile picture
|
|
421
|
+
* @param fileName - File name with extension
|
|
393
422
|
* @returns Promise resolving to profile picture update response
|
|
394
423
|
*/
|
|
395
|
-
async setProfilePicture(file) {
|
|
396
|
-
|
|
397
|
-
formData.append("file", file);
|
|
398
|
-
return this.makeFileUploadRequest("setProfilePicture", formData);
|
|
424
|
+
async setProfilePicture(file, fileName) {
|
|
425
|
+
return this.requestWithFile("setProfilePicture", { data: file, fileName: this.pictureFileName(file, fileName) });
|
|
399
426
|
}
|
|
400
427
|
/**
|
|
401
428
|
* Uploads a file to GREEN-API servers.
|
|
402
429
|
*
|
|
403
430
|
* @param file - File to upload
|
|
404
|
-
* @param
|
|
431
|
+
* @param fileName - File name with extension
|
|
405
432
|
* @returns Promise resolving to upload response with file URL
|
|
406
433
|
*/
|
|
407
|
-
async uploadFile(file,
|
|
408
|
-
const
|
|
409
|
-
formData.append("file", file);
|
|
434
|
+
async uploadFile(file, fileName) {
|
|
435
|
+
const mimeType = file instanceof Blob ? file.type : "";
|
|
410
436
|
const headers = {};
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
if (mimeType) {
|
|
414
|
-
headers["Content-Type"] = mimeType;
|
|
415
|
-
}
|
|
416
|
-
else if (customFileName) {
|
|
417
|
-
headers["GA-Filename"] = customFileName;
|
|
418
|
-
}
|
|
437
|
+
if (mimeType) {
|
|
438
|
+
headers["Content-Type"] = mimeType;
|
|
419
439
|
}
|
|
420
|
-
else if (
|
|
421
|
-
headers["GA-Filename"] =
|
|
440
|
+
else if (fileName) {
|
|
441
|
+
headers["GA-Filename"] = fileName;
|
|
422
442
|
}
|
|
423
|
-
|
|
443
|
+
const body = file instanceof Blob ? Buffer.from(await file.arrayBuffer()) : this.toBuffer(file);
|
|
444
|
+
return this.makeRequest("post", "uploadFile", body, undefined, { headers }, undefined, "media");
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Calls any GREEN-API method that takes a file.
|
|
448
|
+
*
|
|
449
|
+
* @param endpoint - GREEN-API method name, e.g. "setGroupPicture"
|
|
450
|
+
* @param file - File content and file name
|
|
451
|
+
* @param fields - Other form fields
|
|
452
|
+
* @returns Promise resolving to the raw response body
|
|
453
|
+
*/
|
|
454
|
+
async requestWithFile(endpoint, file, fields = {}) {
|
|
455
|
+
const formData = new FormData();
|
|
456
|
+
formData.append("file", this.toBlob(file.data), file.fileName);
|
|
457
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
458
|
+
formData.append(key, String(value));
|
|
459
|
+
}
|
|
460
|
+
return this.makeFileUploadRequest(endpoint, formData);
|
|
461
|
+
}
|
|
462
|
+
pictureFileName(file, fileName) {
|
|
463
|
+
return fileName || (file instanceof File && file.name ? file.name : defaults_1.DEFAULT_PICTURE_FILE_NAME);
|
|
424
464
|
}
|
|
425
465
|
/**
|
|
426
466
|
* Gets authorization code for a phone number.
|
|
@@ -468,6 +508,50 @@ class GreenApiClient {
|
|
|
468
508
|
async clearMessagesQueue() {
|
|
469
509
|
return this.makeRequest("get", "clearMessagesQueue");
|
|
470
510
|
}
|
|
511
|
+
/**
|
|
512
|
+
* Calls any GREEN-API method by name.
|
|
513
|
+
*
|
|
514
|
+
* @param method - HTTP method
|
|
515
|
+
* @param endpoint - GREEN-API method name, e.g. "getContacts"
|
|
516
|
+
* @param data - Request body for POST
|
|
517
|
+
* @param queryParams - Query parameters
|
|
518
|
+
* @returns Promise resolving to the raw response body
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```typescript
|
|
522
|
+
* const contacts = await client.request("get", "getContacts");
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
async request(method, endpoint, data, queryParams) {
|
|
526
|
+
return this.makeRequest(method, endpoint, data, queryParams);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Receives the next notification from the instance queue.
|
|
530
|
+
*
|
|
531
|
+
* @param receiveTimeout - Seconds to wait for a notification, 5 to 60
|
|
532
|
+
* @returns Promise resolving to the notification, or null when the queue stayed empty
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```typescript
|
|
536
|
+
* const notification = await client.receiveNotification(20);
|
|
537
|
+
* if (notification) {
|
|
538
|
+
* await client.deleteNotification(notification.receiptId);
|
|
539
|
+
* }
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
async receiveNotification(receiveTimeout) {
|
|
543
|
+
const response = await this.makeRequest("get", "receiveNotification", undefined, receiveTimeout === undefined ? undefined : { receiveTimeout });
|
|
544
|
+
return response || null;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Deletes a processed notification from the instance queue.
|
|
548
|
+
*
|
|
549
|
+
* @param receiptId - Receipt ID from receiveNotification
|
|
550
|
+
* @returns Promise resolving to deletion result
|
|
551
|
+
*/
|
|
552
|
+
async deleteNotification(receiptId) {
|
|
553
|
+
return this.makeRequest("delete", "deleteNotification", undefined, undefined, undefined, receiptId.toString());
|
|
554
|
+
}
|
|
471
555
|
/**
|
|
472
556
|
* Marks messages in a chat as read.
|
|
473
557
|
* For this to work, "Receive webhooks on incoming messages and files" setting must be enabled.
|
|
@@ -521,6 +605,22 @@ class GreenApiClient {
|
|
|
521
605
|
}
|
|
522
606
|
return this.makeRequest("post", "checkWhatsapp", params);
|
|
523
607
|
}
|
|
608
|
+
/**
|
|
609
|
+
* Checks whether a messenger account exists for a phone number or username (Telegram, MAX).
|
|
610
|
+
*
|
|
611
|
+
* @param params - Phone number in international format, or a Telegram username starting with "@"
|
|
612
|
+
* @returns Promise resolving to the existence flag and, when the account exists, its chat id
|
|
613
|
+
* @throws {Error} If neither phoneNumber nor username is given
|
|
614
|
+
*/
|
|
615
|
+
async checkAccount(params) {
|
|
616
|
+
if (params.phoneNumber === undefined && !params.username) {
|
|
617
|
+
throw new Error("Either phoneNumber or username is required");
|
|
618
|
+
}
|
|
619
|
+
if (params.phoneNumber !== undefined && !Number.isInteger(params.phoneNumber)) {
|
|
620
|
+
throw new Error("Phone number must contain only digits");
|
|
621
|
+
}
|
|
622
|
+
return this.makeRequest("post", "checkAccount", params);
|
|
623
|
+
}
|
|
524
624
|
/**
|
|
525
625
|
* Gets a user or group chat avatar.
|
|
526
626
|
*
|
|
@@ -653,10 +753,7 @@ class GreenApiClient {
|
|
|
653
753
|
* @returns Promise resolving to picture update status
|
|
654
754
|
*/
|
|
655
755
|
async setGroupPicture(params) {
|
|
656
|
-
|
|
657
|
-
formData.append("file", params.file);
|
|
658
|
-
formData.append("groupId", params.groupId);
|
|
659
|
-
return this.makeFileUploadRequest("setGroupPicture", formData);
|
|
756
|
+
return this.requestWithFile("setGroupPicture", { data: params.file, fileName: this.pictureFileName(params.file, params.fileName) }, { groupId: params.groupId });
|
|
660
757
|
}
|
|
661
758
|
/**
|
|
662
759
|
* Makes the current account leave a group chat.
|
package/dist/core/guard.js
CHANGED
|
@@ -56,22 +56,22 @@ class BaseGreenApiAuthGuard {
|
|
|
56
56
|
async validateRequest(request) {
|
|
57
57
|
const token = request.headers["authorization"];
|
|
58
58
|
if (!token) {
|
|
59
|
-
this.gaLogger.warn("Authentication header is missing", { body: request.body
|
|
59
|
+
this.gaLogger.warn("Authentication header is missing", { body: request.body });
|
|
60
60
|
throw new errors_1.AuthenticationError("Authentication header is missing");
|
|
61
61
|
}
|
|
62
62
|
this.gaLogger.info("Request from GREEN-API", { body: request.body });
|
|
63
63
|
const idInstance = request.body?.instanceData?.idInstance;
|
|
64
64
|
if (!idInstance) {
|
|
65
|
-
this.gaLogger.warn("Invalid webhook format", { body: request.body
|
|
65
|
+
this.gaLogger.warn("Invalid webhook format", { body: request.body });
|
|
66
66
|
throw new errors_1.AuthenticationError("Invalid webhook format");
|
|
67
67
|
}
|
|
68
68
|
const instance = await this.storage.getInstance(idInstance);
|
|
69
69
|
if (!instance) {
|
|
70
|
-
this.gaLogger.warn(`No instance with such ID ${idInstance}`, { body: request.body
|
|
70
|
+
this.gaLogger.warn(`No instance with such ID ${idInstance}`, { body: request.body });
|
|
71
71
|
throw new errors_1.AuthenticationError(`No instance with such ID ${idInstance}`);
|
|
72
72
|
}
|
|
73
73
|
if (instance.settings?.webhookUrlToken !== token.split(" ")[1]) {
|
|
74
|
-
this.gaLogger.warn("Invalid token", { body: request.body
|
|
74
|
+
this.gaLogger.warn("Invalid token", { body: request.body });
|
|
75
75
|
throw new errors_1.AuthenticationError("Invalid token");
|
|
76
76
|
}
|
|
77
77
|
return true;
|
package/dist/core/logger.js
CHANGED
|
@@ -195,9 +195,7 @@ class GreenApiLogger {
|
|
|
195
195
|
status: axiosError.response?.status,
|
|
196
196
|
statusText: axiosError.response?.statusText,
|
|
197
197
|
data: axiosError.response?.data,
|
|
198
|
-
url: axiosError.config?.url,
|
|
199
198
|
method: axiosError.config?.method,
|
|
200
|
-
headers: axiosError.response?.headers,
|
|
201
199
|
timestamp: new Date().toISOString(),
|
|
202
200
|
...additionalContext,
|
|
203
201
|
});
|
package/dist/defaults.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_PICTURE_FILE_NAME = exports.REDACTED_TOKEN = exports.DEFAULT_API_URL = void 0;
|
|
4
|
+
exports.DEFAULT_API_URL = "https://api.green-api.com";
|
|
5
|
+
exports.REDACTED_TOKEN = "***";
|
|
6
|
+
exports.DEFAULT_PICTURE_FILE_NAME = "picture.jpg";
|
package/dist/types/types.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface BaseInstance {
|
|
|
7
7
|
apiTokenInstance: string;
|
|
8
8
|
stateInstance?: InstanceState | null;
|
|
9
9
|
settings?: Settings | Record<string, any> | null;
|
|
10
|
+
apiUrl?: string | null;
|
|
11
|
+
mediaUrl?: string | null;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Extended instance interface that allows for additional platform-specific properties.
|
|
@@ -35,7 +37,7 @@ export interface SendMessage extends BaseMessage {
|
|
|
35
37
|
export interface SendFileByUpload extends BaseMessage {
|
|
36
38
|
caption?: string;
|
|
37
39
|
file: {
|
|
38
|
-
data: Blob | File;
|
|
40
|
+
data: Blob | File | Uint8Array;
|
|
39
41
|
fileName: string;
|
|
40
42
|
};
|
|
41
43
|
}
|
|
@@ -107,6 +109,10 @@ export type Message = (SendMessage & {
|
|
|
107
109
|
type: "contact";
|
|
108
110
|
}) | (ForwardMessages & {
|
|
109
111
|
type: "forward";
|
|
112
|
+
}) | (SendInteractiveButtons & {
|
|
113
|
+
type: "interactive-buttons";
|
|
114
|
+
}) | (SendInteractiveButtonsReply & {
|
|
115
|
+
type: "interactive-buttons-reply";
|
|
110
116
|
});
|
|
111
117
|
export type QueueMessageType = "sendMessage" | "sendPoll" | "sendFileByUrl" | "sendLocation" | "sendContact" | "ForwardMessages";
|
|
112
118
|
export type QueueMessageBody = SendMessage | SendPoll | SendFileByUrl | SendLocation | SendContact | ForwardMessages;
|
|
@@ -119,6 +125,19 @@ export interface QueueMessage {
|
|
|
119
125
|
export interface ClearMessagesQueue {
|
|
120
126
|
isCleared: boolean;
|
|
121
127
|
}
|
|
128
|
+
export interface ReceiveNotificationResponse {
|
|
129
|
+
receiptId: number;
|
|
130
|
+
body: GreenApiWebhook;
|
|
131
|
+
}
|
|
132
|
+
export interface DeleteNotificationResponse {
|
|
133
|
+
result: boolean;
|
|
134
|
+
}
|
|
135
|
+
export interface GreenApiClientLogger {
|
|
136
|
+
info(message: string, context?: Record<string, any>): void;
|
|
137
|
+
}
|
|
138
|
+
export interface GreenApiClientOptions {
|
|
139
|
+
logger?: GreenApiClientLogger | null;
|
|
140
|
+
}
|
|
122
141
|
export type MessageType = "textMessage" | "extendedTextMessage" | "imageMessage" | "videoMessage" | "documentMessage" | "audioMessage" | "contactMessage" | "locationMessage" | "contactsArrayMessage" | "pollMessage" | "reactionMessage" | "pollUpdateMessage" | "quotedMessage" | "stickerMessage" | "editedMessage" | "deletedMessage" | "buttonsMessage" | "listMessage" | "templateMessage" | "groupInviteMessage" | "interactiveButtons" | "interactiveButtonsReply" | "templateButtonsReplyMessage";
|
|
123
142
|
export interface GetMessage {
|
|
124
143
|
chatId: string;
|
|
@@ -510,6 +529,7 @@ export interface MessageWebhook {
|
|
|
510
529
|
chatName: string;
|
|
511
530
|
senderName: string;
|
|
512
531
|
senderContactName?: string;
|
|
532
|
+
senderPhoneNumber?: number;
|
|
513
533
|
};
|
|
514
534
|
messageData: WebhookMessageData & {
|
|
515
535
|
quotedMessage?: QuotedMessage;
|
|
@@ -538,6 +558,7 @@ export type GreenApiWebhook = MessageWebhook | OutgoingMessageStatusWebhook | St
|
|
|
538
558
|
*/
|
|
539
559
|
export interface Settings {
|
|
540
560
|
wid?: string;
|
|
561
|
+
typeInstance?: string;
|
|
541
562
|
webhookUrl?: string;
|
|
542
563
|
webhookUrlToken?: string;
|
|
543
564
|
delaySendMessagesMilliseconds?: number;
|
|
@@ -574,6 +595,18 @@ export interface CheckWhatsapp {
|
|
|
574
595
|
export interface CheckWhatsappResponse {
|
|
575
596
|
existsWhatsapp: boolean;
|
|
576
597
|
}
|
|
598
|
+
export interface CheckAccount {
|
|
599
|
+
phoneNumber?: number;
|
|
600
|
+
username?: string;
|
|
601
|
+
force?: boolean;
|
|
602
|
+
}
|
|
603
|
+
export interface CheckAccountResponse {
|
|
604
|
+
exist: boolean;
|
|
605
|
+
chatId: string;
|
|
606
|
+
username?: string;
|
|
607
|
+
phoneNumber?: number;
|
|
608
|
+
fromCache?: boolean;
|
|
609
|
+
}
|
|
577
610
|
export interface GetAvatar {
|
|
578
611
|
chatId: string;
|
|
579
612
|
}
|
|
@@ -583,10 +616,13 @@ export interface GetAvatarResponse {
|
|
|
583
616
|
}
|
|
584
617
|
export type ContactType = "user" | "group";
|
|
585
618
|
export interface Contact {
|
|
586
|
-
id
|
|
619
|
+
id?: string;
|
|
620
|
+
chatId?: string;
|
|
587
621
|
name: string;
|
|
588
622
|
contactName: string;
|
|
589
623
|
type: ContactType;
|
|
624
|
+
phoneNumber?: number;
|
|
625
|
+
username?: string;
|
|
590
626
|
}
|
|
591
627
|
export interface ProductImageUrls {
|
|
592
628
|
requested: string;
|
|
@@ -641,7 +677,7 @@ export interface SetDisappearingChatResponse {
|
|
|
641
677
|
/**
|
|
642
678
|
* Represents an instance state in the GREEN-API system.
|
|
643
679
|
*/
|
|
644
|
-
export type InstanceState = "notAuthorized" | "authorized" | "blocked" | "starting" | "yellowCard";
|
|
680
|
+
export type InstanceState = "notAuthorized" | "authorized" | "blocked" | "starting" | "yellowCard" | "suspended" | "pendingPassword";
|
|
645
681
|
export interface StateInstance {
|
|
646
682
|
stateInstance: InstanceState;
|
|
647
683
|
}
|
|
@@ -672,6 +708,16 @@ export interface WaSettings {
|
|
|
672
708
|
stateInstance: InstanceState;
|
|
673
709
|
deviceId: string;
|
|
674
710
|
}
|
|
711
|
+
export interface AccountSettings {
|
|
712
|
+
avatar: string;
|
|
713
|
+
phone: string;
|
|
714
|
+
stateInstance: InstanceState;
|
|
715
|
+
chatId: string;
|
|
716
|
+
historySyncProgress: number;
|
|
717
|
+
username?: string;
|
|
718
|
+
logoutProcess?: boolean;
|
|
719
|
+
suspendedUntil?: number;
|
|
720
|
+
}
|
|
675
721
|
export interface SetProfilePicture {
|
|
676
722
|
reason: string | null;
|
|
677
723
|
urlAvatar: string;
|
|
@@ -741,7 +787,8 @@ export interface RemoveAdminResponse {
|
|
|
741
787
|
}
|
|
742
788
|
export interface SetGroupPicture {
|
|
743
789
|
groupId: string;
|
|
744
|
-
file: Blob | File;
|
|
790
|
+
file: Blob | File | Uint8Array;
|
|
791
|
+
fileName?: string;
|
|
745
792
|
}
|
|
746
793
|
export interface SetGroupPictureResponse {
|
|
747
794
|
setGroupPicture: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@green-api/greenapi-integration",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "GREEN-API Integration library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,19 +24,16 @@
|
|
|
24
24
|
"author": "GREEN-API team",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@types/
|
|
28
|
-
"@types/
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"jest": "^29.
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"typedoc": "^0.27.6",
|
|
36
|
-
"typedoc-plugin-markdown": "^4.4.1",
|
|
37
|
-
"typescript": "^5.7.2"
|
|
27
|
+
"@types/jest": "^30.0.0",
|
|
28
|
+
"@types/node": "^22.20.5",
|
|
29
|
+
"jest": "^30.5.2",
|
|
30
|
+
"rimraf": "^6.1.3",
|
|
31
|
+
"ts-jest": "^29.4.15",
|
|
32
|
+
"typedoc": "^0.28.20",
|
|
33
|
+
"typedoc-plugin-markdown": "^4.14.1",
|
|
34
|
+
"typescript": "^6.0.3"
|
|
38
35
|
},
|
|
39
36
|
"dependencies": {
|
|
40
|
-
"axios": "^1.
|
|
37
|
+
"axios": "^1.20.0"
|
|
41
38
|
}
|
|
42
39
|
}
|