@green-api/greenapi-integration 0.1.0 → 0.3.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.
@@ -1,77 +1,231 @@
1
- export interface BaseInstance {
1
+ /**
2
+ * Base interface for GREEN-API WhatsApp instances.
3
+ * Contains the essential credentials needed to interact with the API.
4
+ */
5
+ interface BaseInstance {
2
6
  idInstance: number | bigint;
3
7
  apiTokenInstance: string;
4
- settings?: any;
8
+ stateInstance?: InstanceState;
9
+ settings?: Settings | Record<string, any>;
5
10
  }
11
+ /**
12
+ * Extended instance interface that allows for additional platform-specific properties.
13
+ * Use this when you need to store extra data with your instance.
14
+ */
6
15
  export interface Instance extends BaseInstance {
7
16
  [key: string]: any;
8
17
  }
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 {
18
+ /**
19
+ * Union type representing all possible message formats that can be sent through GREEN-API.
20
+ * Each message type has its own specific structure and required fields.
21
+ */
22
+ export type Message = ({
17
23
  type: "text";
18
24
  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 {
25
+ } & BaseMessage) | ({
41
26
  type: "upload-file";
42
27
  caption?: string;
43
28
  file: {
44
29
  data: Blob | File;
45
30
  fileName: string;
46
31
  };
47
- }
48
- export interface SendFileByUrl extends BaseMessage {
32
+ } & BaseMessage) | ({
49
33
  type: "url-file";
50
34
  caption?: string;
51
35
  file: {
52
36
  url: string;
53
37
  fileName: string;
54
38
  };
55
- }
56
- export interface SendLocation extends BaseMessage {
39
+ } & BaseMessage) | ({
40
+ type: "poll";
41
+ message: string;
42
+ options: PollOption[];
43
+ multipleAnswers?: boolean;
44
+ } & BaseMessage) | ({
57
45
  type: "location";
58
46
  nameLocation?: string;
59
47
  address?: string;
60
48
  latitude: number;
61
49
  longitude: number;
50
+ } & BaseMessage) | ({
51
+ type: "contact";
52
+ contact: {
53
+ phoneContact: number;
54
+ firstName?: string;
55
+ middleName?: string;
56
+ lastName?: string;
57
+ company?: string;
58
+ };
59
+ } & BaseMessage) | {
60
+ type: "forward";
61
+ chatId: string;
62
+ chatIdFrom: string;
63
+ messages: string[];
64
+ };
65
+ /**
66
+ * Common properties shared by all message types.
67
+ */
68
+ export interface BaseMessage {
69
+ chatId: string;
70
+ quotedMessageId?: string;
71
+ }
72
+ export type SendMessageType = "text" | "upload-file" | "url-file" | "poll" | "location" | "contact" | "forward";
73
+ export interface ForwardMessagesResponse {
74
+ messages: string[];
62
75
  }
63
76
  export interface PollOption {
64
77
  optionName: string;
65
78
  }
66
- export interface SendPoll extends BaseMessage {
79
+ export type SendMessage = Extract<Message, {
80
+ type: "text";
81
+ }>;
82
+ export type SendFileByUpload = Extract<Message, {
83
+ type: "upload-file";
84
+ }>;
85
+ export type SendFileByUrl = Extract<Message, {
86
+ type: "url-file";
87
+ }>;
88
+ export type SendLocation = Extract<Message, {
89
+ type: "location";
90
+ }>;
91
+ export type SendContact = Extract<Message, {
92
+ type: "contact";
93
+ }>;
94
+ export type SendPoll = Extract<Message, {
67
95
  type: "poll";
68
- message: string;
96
+ }>;
97
+ export type ForwardMessages = Extract<Message, {
98
+ type: "forward";
99
+ }>;
100
+ export type MessageType = "textMessage" | "extendedTextMessage" | "imageMessage" | "videoMessage" | "documentMessage" | "audioMessage" | "contactMessage" | "locationMessage" | "pollMessage";
101
+ export interface ForwardableMessage {
102
+ forwardingScore: number;
103
+ isForwarded: boolean;
104
+ }
105
+ export interface MediaMessage extends ForwardableMessage {
106
+ jpegThumbnail: string;
107
+ }
108
+ export interface TextMessageData {
109
+ textMessage: string;
110
+ }
111
+ export interface ExtendedTextMessageData extends MediaMessage {
112
+ text: string;
113
+ description: string;
114
+ title: string;
115
+ }
116
+ export interface FileMessageData extends MediaMessage {
117
+ downloadUrl: string;
118
+ caption: string;
119
+ mimeType: string;
120
+ fileName: string;
121
+ }
122
+ export interface LocationMessageData extends MediaMessage {
123
+ nameLocation: string;
124
+ address: string;
125
+ latitude: number;
126
+ longitude: number;
127
+ }
128
+ export interface ContactMessageData extends ForwardableMessage {
129
+ displayName: string;
130
+ vcard: string;
131
+ }
132
+ export interface PollMessageData {
133
+ name: string;
69
134
  options: PollOption[];
70
- multipleAnswers?: boolean;
135
+ multipleAnswers: boolean;
136
+ }
137
+ type QuotedMessage = {
138
+ stanzaId: string;
139
+ participant: string;
140
+ typeMessage: MessageType;
141
+ } & ({
142
+ typeMessage: "textMessage";
143
+ textMessage: string;
144
+ } | {
145
+ typeMessage: "contactMessage";
146
+ contact: {
147
+ displayName: string;
148
+ vcard: string;
149
+ };
150
+ } | {
151
+ typeMessage: "locationMessage";
152
+ location: {
153
+ nameLocation: string;
154
+ address: string;
155
+ jpegThumbnail: string;
156
+ latitude: number;
157
+ longitude: number;
158
+ };
159
+ } | {
160
+ typeMessage: "imageMessage" | "videoMessage" | "documentMessage" | "audioMessage";
161
+ downloadUrl: string;
162
+ caption: string;
163
+ jpegThumbnail: string;
164
+ });
165
+ export interface PollVote {
166
+ optionName: string;
167
+ optionVoters: string[];
168
+ }
169
+ export interface PollUpdateMessageData {
170
+ stanzaId: string;
171
+ name: string;
172
+ votes: PollVote[];
173
+ multipleAnswers: boolean;
174
+ }
175
+ export type OutgoingMessageStatus = "sent" | "delivered" | "read" | "failed" | "noAccount" | "notInGroup" | "yellowCard";
176
+ export type WebhookType = "stateInstanceChanged" | "outgoingMessageStatus" | "outgoingAPIMessageReceived" | "outgoingMessageReceived" | "incomingMessageReceived";
177
+ /**
178
+ * Webhook payload received when a message status changes.
179
+ * Used to track delivery and read receipts.
180
+ */
181
+ export interface OutgoingMessageStatusWebhook {
182
+ typeWebhook: "outgoingMessageStatus";
183
+ chatId: string;
184
+ instanceData: {
185
+ idInstance: number;
186
+ wid: string;
187
+ typeInstance: string;
188
+ };
189
+ timestamp: number;
190
+ idMessage: string;
191
+ status: OutgoingMessageStatus;
192
+ description?: string;
193
+ sendByApi: boolean;
194
+ }
195
+ export interface StateInstanceWebhook {
196
+ typeWebhook: "stateInstanceChanged";
197
+ instanceData: {
198
+ idInstance: number;
199
+ wid: string;
200
+ typeInstance: string;
201
+ };
202
+ timestamp: number;
203
+ stateInstance: InstanceState;
71
204
  }
72
- export type MessageType = "textMessage" | "extendedTextMessage" | "imageMessage" | "videoMessage" | "documentMessage" | "audioMessage";
73
- export interface IncomingGreenApiWebhook {
74
- typeWebhook: string;
205
+ export type WebhookMessageData = {
206
+ typeMessage: "textMessage";
207
+ textMessageData: TextMessageData;
208
+ } | {
209
+ typeMessage: "extendedTextMessage";
210
+ extendedTextMessageData: ExtendedTextMessageData;
211
+ } | {
212
+ typeMessage: "imageMessage" | "videoMessage" | "documentMessage" | "audioMessage";
213
+ fileMessageData: FileMessageData;
214
+ } | {
215
+ typeMessage: "locationMessage";
216
+ locationMessageData: LocationMessageData;
217
+ } | {
218
+ typeMessage: "contactMessage";
219
+ contactMessageData: ContactMessageData;
220
+ } | {
221
+ typeMessage: "pollMessage";
222
+ pollMessageData: PollMessageData;
223
+ } | {
224
+ typeMessage: "pollUpdateMessage";
225
+ pollMessageData: PollUpdateMessageData;
226
+ };
227
+ export interface MessageWebhook {
228
+ typeWebhook: "incomingMessageReceived" | "outgoingMessageReceived" | "outgoingAPIMessageReceived";
75
229
  instanceData: {
76
230
  idInstance: number;
77
231
  wid: string;
@@ -82,34 +236,22 @@ export interface IncomingGreenApiWebhook {
82
236
  senderData: {
83
237
  chatId: string;
84
238
  sender: string;
85
- chatName?: string;
86
- senderName?: string;
239
+ chatName: string;
240
+ senderName: string;
87
241
  senderContactName?: string;
88
242
  };
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
- };
243
+ messageData: WebhookMessageData & {
244
+ quotedMessage?: QuotedMessage;
111
245
  };
112
246
  }
247
+ /**
248
+ * Primary webhook types received from GREEN-API.
249
+ */
250
+ export type GreenApiWebhook = MessageWebhook | OutgoingMessageStatusWebhook | StateInstanceWebhook;
251
+ /**
252
+ * Configuration settings for a GREEN-API instance.
253
+ * Controls webhook behavior, message handling, and other instance features.
254
+ */
113
255
  export interface Settings {
114
256
  wid?: string;
115
257
  webhookUrl?: string;
@@ -132,6 +274,9 @@ export interface Reboot {
132
274
  export interface Logout {
133
275
  isLogout: boolean;
134
276
  }
277
+ /**
278
+ * Represents an instance state in the GREEN-API system.
279
+ */
135
280
  export type InstanceState = "notAuthorized" | "authorized" | "blocked" | "starting" | "yellowCard";
136
281
  export interface StateInstance {
137
282
  stateInstance: InstanceState;
@@ -176,3 +321,4 @@ export interface BaseUser {
176
321
  id: number | bigint;
177
322
  [key: string]: any;
178
323
  }
324
+ export {};
@@ -1,2 +1,73 @@
1
- export declare function formatPhoneNumber(phone: string): string;
1
+ import { Settings } from "../types/types";
2
+ /**
3
+ * Utility functions for working with phone numbers, tokens, and vCards.
4
+ *
5
+ * @category Utilities
6
+ */
7
+ /**
8
+ * Formats a phone number into GREEN-API's expected format.
9
+ * Removes all non-digit characters and adds @c.us or @g.us suffix.
10
+ *
11
+ * @param phone - The phone number to format
12
+ * @param chatType - The type of a chat, can be either "group" or "private"
13
+ * @returns Formatted phone number with @c.us suffix
14
+ *
15
+ * @example
16
+ * formatPhoneNumber('+1 (234) 567-8900') // Returns '12345678900@c.us'
17
+ * formatPhoneNumber('1234567890') // Returns '1234567890@c.us'
18
+ */
19
+ export declare function formatPhoneNumber(phone: string, chatType?: "group" | "private"): string;
20
+ /**
21
+ * Generates a cryptographically secure random token.
22
+ *
23
+ * @param length - Length of the token in bytes (default: 32)
24
+ * @returns Hexadecimal string of the specified length
25
+ *
26
+ * @example
27
+ * generateRandomToken() // Returns a 64-character hex string (32 bytes)
28
+ * generateRandomToken(16) // Returns a 32-character hex string (16 bytes)
29
+ */
2
30
  export declare function generateRandomToken(length?: number): string;
31
+ /**
32
+ * Extracts a phone number from a vCard string format.
33
+ * Supports various vCard formats and phone number notations.
34
+ *
35
+ * @param vcard - The vCard string containing contact information
36
+ * @returns The extracted phone number or null if not found
37
+ *
38
+ * @example
39
+ * const vcard = `BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD`;
40
+ * extractPhoneNumberFromVCard(vcard) // Returns '+1234567890'
41
+ */
42
+ export declare function extractPhoneNumberFromVCard(vcard: string): string | null;
43
+ /**
44
+ * Validates if a value is appropriate for a specific Settings interface key.
45
+ * Checks type compatibility for numbers, strings, and yes/no enums.
46
+ *
47
+ * @param key - The settings key to validate
48
+ * @param value - The value to check against the key's expected type
49
+ * @returns Boolean indicating if the value is valid for the given key
50
+ *
51
+ * @example
52
+ * isValidSettingValue('delaySendMessagesMilliseconds', 1000) // Returns true
53
+ * isValidSettingValue('outgoingWebhook', 'maybe') // Returns false
54
+ * isValidSettingValue('webhookUrl', 'https://example.com') // Returns true
55
+ */
56
+ export declare function isValidSettingValue(key: keyof Settings, value: any): boolean;
57
+ /**
58
+ * Validates and cleans a settings object against the Settings interface.
59
+ * Removes any properties that don't match the interface or have invalid values.
60
+ *
61
+ * @param settings - The settings object to validate and clean
62
+ * @returns A new Settings object containing only valid properties and values
63
+ *
64
+ * @example
65
+ * const input = {
66
+ * webhookUrl: 'https://example.com',
67
+ * outgoingWebhook: 'yes',
68
+ * invalidKey: 'value',
69
+ * delaySendMessagesMilliseconds: 'invalid'
70
+ * };
71
+ * validateAndCleanSettings(input) // Returns { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
72
+ */
73
+ export declare function validateAndCleanSettings(settings: any): Settings;
@@ -35,11 +35,118 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.formatPhoneNumber = formatPhoneNumber;
37
37
  exports.generateRandomToken = generateRandomToken;
38
+ exports.extractPhoneNumberFromVCard = extractPhoneNumberFromVCard;
39
+ exports.isValidSettingValue = isValidSettingValue;
40
+ exports.validateAndCleanSettings = validateAndCleanSettings;
38
41
  const crypto = __importStar(require("crypto"));
39
- function formatPhoneNumber(phone) {
42
+ /**
43
+ * Utility functions for working with phone numbers, tokens, and vCards.
44
+ *
45
+ * @category Utilities
46
+ */
47
+ /**
48
+ * Formats a phone number into GREEN-API's expected format.
49
+ * Removes all non-digit characters and adds @c.us or @g.us suffix.
50
+ *
51
+ * @param phone - The phone number to format
52
+ * @param chatType - The type of a chat, can be either "group" or "private"
53
+ * @returns Formatted phone number with @c.us suffix
54
+ *
55
+ * @example
56
+ * formatPhoneNumber('+1 (234) 567-8900') // Returns '12345678900@c.us'
57
+ * formatPhoneNumber('1234567890') // Returns '1234567890@c.us'
58
+ */
59
+ function formatPhoneNumber(phone, chatType = "private") {
40
60
  const cleaned = phone.replace(/\D/g, "");
41
- return `${cleaned}@c.us`;
61
+ return chatType === "private" ? `${cleaned}@c.us` : `${cleaned}@g.us`;
42
62
  }
63
+ /**
64
+ * Generates a cryptographically secure random token.
65
+ *
66
+ * @param length - Length of the token in bytes (default: 32)
67
+ * @returns Hexadecimal string of the specified length
68
+ *
69
+ * @example
70
+ * generateRandomToken() // Returns a 64-character hex string (32 bytes)
71
+ * generateRandomToken(16) // Returns a 32-character hex string (16 bytes)
72
+ */
43
73
  function generateRandomToken(length = 32) {
44
74
  return crypto.randomBytes(length).toString("hex");
45
75
  }
76
+ /**
77
+ * Extracts a phone number from a vCard string format.
78
+ * Supports various vCard formats and phone number notations.
79
+ *
80
+ * @param vcard - The vCard string containing contact information
81
+ * @returns The extracted phone number or null if not found
82
+ *
83
+ * @example
84
+ * const vcard = `BEGIN:VCARD\nTEL:+1234567890\nEND:VCARD`;
85
+ * extractPhoneNumberFromVCard(vcard) // Returns '+1234567890'
86
+ */
87
+ function extractPhoneNumberFromVCard(vcard) {
88
+ const phoneMatch = vcard.match(/TEL(?:;[^:]+)?:([+\d\s-]+)/);
89
+ return phoneMatch ? phoneMatch[1] : null;
90
+ }
91
+ /**
92
+ * Validates if a value is appropriate for a specific Settings interface key.
93
+ * Checks type compatibility for numbers, strings, and yes/no enums.
94
+ *
95
+ * @param key - The settings key to validate
96
+ * @param value - The value to check against the key's expected type
97
+ * @returns Boolean indicating if the value is valid for the given key
98
+ *
99
+ * @example
100
+ * isValidSettingValue('delaySendMessagesMilliseconds', 1000) // Returns true
101
+ * isValidSettingValue('outgoingWebhook', 'maybe') // Returns false
102
+ * isValidSettingValue('webhookUrl', 'https://example.com') // Returns true
103
+ */
104
+ function isValidSettingValue(key, value) {
105
+ switch (key) {
106
+ case "delaySendMessagesMilliseconds":
107
+ return typeof value === "number";
108
+ case "wid":
109
+ case "webhookUrl":
110
+ case "webhookUrlToken":
111
+ return typeof value === "string";
112
+ case "markIncomingMessagesReaded":
113
+ case "markIncomingMessagesReadedOnReply":
114
+ case "outgoingWebhook":
115
+ case "outgoingMessageWebhook":
116
+ case "outgoingAPIMessageWebhook":
117
+ case "stateWebhook":
118
+ case "incomingWebhook":
119
+ case "keepOnlineStatus":
120
+ case "pollMessageWebhook":
121
+ case "incomingCallWebhook":
122
+ return value === "yes" || value === "no";
123
+ default:
124
+ return false;
125
+ }
126
+ }
127
+ /**
128
+ * Validates and cleans a settings object against the Settings interface.
129
+ * Removes any properties that don't match the interface or have invalid values.
130
+ *
131
+ * @param settings - The settings object to validate and clean
132
+ * @returns A new Settings object containing only valid properties and values
133
+ *
134
+ * @example
135
+ * const input = {
136
+ * webhookUrl: 'https://example.com',
137
+ * outgoingWebhook: 'yes',
138
+ * invalidKey: 'value',
139
+ * delaySendMessagesMilliseconds: 'invalid'
140
+ * };
141
+ * validateAndCleanSettings(input) // Returns { webhookUrl: 'https://example.com', outgoingWebhook: 'yes' }
142
+ */
143
+ function validateAndCleanSettings(settings) {
144
+ const validSettings = {};
145
+ const settingsKeys = Object.keys(settings);
146
+ for (const key of settingsKeys) {
147
+ if (key in validSettings && isValidSettingValue(key, settings[key])) {
148
+ validSettings[key] = settings[key];
149
+ }
150
+ }
151
+ return validSettings;
152
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@green-api/greenapi-integration",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "GREEN-API Integration library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,7 +11,9 @@
11
11
  "build": "tsc",
12
12
  "clean": "rimraf dist",
13
13
  "prebuild": "npm run clean",
14
- "prepare": "npm run build"
14
+ "prepare": "npm run build",
15
+ "docs": "typedoc",
16
+ "docs:watch": "typedoc --watch"
15
17
  },
16
18
  "keywords": [
17
19
  "green-api",
@@ -29,6 +31,8 @@
29
31
  "rimraf": "^6.0.1",
30
32
  "ts-jest": "^29.2.5",
31
33
  "ts-node": "^10.9.2",
34
+ "typedoc": "^0.27.6",
35
+ "typedoc-plugin-markdown": "^4.4.1",
32
36
  "typescript": "^5.7.2"
33
37
  },
34
38
  "dependencies": {