n8n-nodes-zalo-custom 1.0.9 → 1.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.
@@ -6,197 +6,8 @@ const zca_js_1 = require("zca-js");
6
6
  const helper_1 = require("../utils/helper");
7
7
  const zalo_helper_1 = require("../utils/zalo.helper");
8
8
  const ZaloNodeProperties_1 = require("../shared/ZaloNodeProperties");
9
- const reactionOptions = [
10
- { name: 'Heart', value: 'heart' },
11
- { name: 'Like', value: 'like' },
12
- { name: 'Haha', value: 'haha' },
13
- { name: 'Wow', value: 'wow' },
14
- { name: 'Cry', value: 'cry' },
15
- { name: 'Angry', value: 'angry' },
16
- { name: 'Kiss', value: 'kiss' },
17
- { name: 'Tears of Joy', value: 'tears_of_joy' },
18
- { name: 'Dislike', value: 'dislike' },
19
- { name: 'OK', value: 'ok' },
20
- { name: 'Thanks', value: 'thanks' },
21
- { name: 'Big Smile', value: 'big_smile' },
22
- { name: 'Sad', value: 'sad' },
23
- { name: 'Very Sad', value: 'very_sad' },
24
- { name: 'Rose', value: 'rose' },
25
- { name: 'Broken Heart', value: 'broken_heart' },
26
- { name: 'Love', value: 'love' },
27
- { name: 'Confused', value: 'confused' },
28
- { name: 'Wink', value: 'wink' },
29
- { name: 'Birthday', value: 'birthday' },
30
- { name: 'Bomb', value: 'bomb' },
31
- { name: 'Peace', value: 'peace' },
32
- { name: 'Pray', value: 'pray' },
33
- { name: 'No', value: 'no' },
34
- { name: 'Love You', value: 'love_you' },
35
- { name: 'Cool', value: 'cool' },
36
- { name: 'Nerd', value: 'nerd' },
37
- { name: 'Sunglasses', value: 'sunglasses' },
38
- { name: 'Neutral', value: 'neutral' },
39
- { name: 'Bye', value: 'bye' },
40
- { name: 'Sleepy', value: 'sleepy' },
41
- { name: 'Wipe', value: 'wipe' },
42
- { name: 'Dig', value: 'dig' },
43
- { name: 'Handclap', value: 'handclap' },
44
- { name: 'Silent', value: 'silent' },
45
- { name: 'Surprise', value: 'surprise' },
46
- { name: 'Embarrassed', value: 'embarrassed' },
47
- { name: 'Afraid', value: 'afraid' },
48
- { name: 'Big Laugh', value: 'big_laugh' },
49
- { name: 'Beer', value: 'beer' },
50
- ];
9
+ const ZaloSendMessageDescription_1 = require("./ZaloSendMessageDescription");
51
10
  let api;
52
- function parseHtmlToStyles(html) {
53
- var _a, _b;
54
- let workingHtml = html
55
- .replace(/"/g, '"')
56
- .replace(/'/g, "'")
57
- .replace(/&lt;/g, '<')
58
- .replace(/&gt;/g, '>')
59
- .replace(/&amp;/g, '&')
60
- .replace(/&nbsp;/g, ' ');
61
- workingHtml = workingHtml.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '$2');
62
- workingHtml = workingHtml.replace(/<br\s*\/?>/gi, '___BR___');
63
- workingHtml = workingHtml.replace(/>\s+</g, '><');
64
- workingHtml = workingHtml.replace(/___BR___/g, '<br>');
65
- const styles = [];
66
- const tagMappings = {
67
- 'b': 'b',
68
- 'strong': 'b',
69
- 'i': 'i',
70
- 'em': 'i',
71
- 'u': 'u',
72
- 's': 's',
73
- 'strike': 's',
74
- 'del': 's',
75
- 'small': 'f_13',
76
- 'big': 'f_18',
77
- 'red': 'c_db342e',
78
- 'orange': 'c_f27806',
79
- 'yellow': 'c_f7b503',
80
- 'green': 'c_15a85f',
81
- };
82
- const openTags = [];
83
- let cleanText = '';
84
- let htmlIndex = 0;
85
- let textIndex = 0;
86
- while (htmlIndex < workingHtml.length) {
87
- const char = workingHtml[htmlIndex];
88
- if (char === '<') {
89
- const tagEndIndex = workingHtml.indexOf('>', htmlIndex);
90
- if (tagEndIndex === -1) {
91
- cleanText += char;
92
- textIndex++;
93
- htmlIndex++;
94
- continue;
95
- }
96
- const tagContent = workingHtml.substring(htmlIndex + 1, tagEndIndex);
97
- const isClosingTag = tagContent.startsWith('/');
98
- const tagName = (isClosingTag ? tagContent.substring(1) : tagContent.split(/\s/)[0]).toLowerCase();
99
- if (tagName === 'br') {
100
- cleanText += '\n';
101
- textIndex++;
102
- }
103
- else if (tagName === 'p') {
104
- if (isClosingTag) {
105
- cleanText += '\n\n';
106
- textIndex += 2;
107
- }
108
- }
109
- else if (tagName === 'div') {
110
- if (isClosingTag) {
111
- cleanText += '\n';
112
- textIndex++;
113
- }
114
- }
115
- else if (tagName.match(/^h[1-6]$/)) {
116
- if (isClosingTag) {
117
- cleanText += '\n';
118
- textIndex++;
119
- }
120
- }
121
- else if (tagName === 'li') {
122
- if (!isClosingTag) {
123
- cleanText += '• ';
124
- textIndex += 2;
125
- }
126
- else {
127
- cleanText += '\n';
128
- textIndex++;
129
- }
130
- }
131
- else if (tagName === 'ul' || tagName === 'ol') {
132
- if (!isClosingTag) {
133
- cleanText += '\n';
134
- textIndex++;
135
- }
136
- else {
137
- cleanText += '\n';
138
- textIndex++;
139
- }
140
- }
141
- else {
142
- const styleType = tagMappings[tagName];
143
- if (styleType) {
144
- if (isClosingTag) {
145
- for (let i = openTags.length - 1; i >= 0; i--) {
146
- if (openTags[i].tagName === tagName) {
147
- const openTag = openTags[i];
148
- if (textIndex > openTag.startPos) {
149
- styles.push({
150
- st: openTag.styleType,
151
- start: openTag.startPos,
152
- end: textIndex
153
- });
154
- }
155
- openTags.splice(i, 1);
156
- break;
157
- }
158
- }
159
- }
160
- else {
161
- openTags.push({
162
- tagName: tagName,
163
- styleType: styleType,
164
- startPos: textIndex
165
- });
166
- }
167
- }
168
- }
169
- htmlIndex = tagEndIndex + 1;
170
- }
171
- else {
172
- cleanText += char;
173
- textIndex++;
174
- htmlIndex++;
175
- }
176
- }
177
- for (const openTag of openTags) {
178
- if (textIndex > openTag.startPos) {
179
- styles.push({
180
- st: openTag.styleType,
181
- start: openTag.startPos,
182
- end: textIndex
183
- });
184
- }
185
- }
186
- cleanText = cleanText
187
- .replace(/\n\s*\n\s*\n/g, '\n\n')
188
- .replace(/[ \t]+/g, ' ');
189
- const trimStart = ((_b = (_a = cleanText.match(/^\s*/)) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.length) || 0;
190
- cleanText = cleanText.replace(/^\s+|\s+$/g, '');
191
- if (trimStart > 0) {
192
- for (const style of styles) {
193
- style.start = Math.max(0, style.start - trimStart);
194
- style.end = Math.max(style.start, style.end - trimStart);
195
- }
196
- }
197
- return { cleanText, styles };
198
- }
199
-
200
11
  class ZaloSendMessage {
201
12
  constructor() {
202
13
  this.description = {
@@ -214,346 +25,7 @@ class ZaloSendMessage {
214
25
  credentials: [...ZaloNodeProperties_1.zaloApiCredential],
215
26
  properties: [
216
27
  ...ZaloNodeProperties_1.zaloSessionProperties,
217
- {
218
- displayName: 'Thread ID',
219
- name: 'threadId',
220
- type: 'string',
221
- default: '',
222
- required: true,
223
- description: 'ID của thread để gửi tin nhắn',
224
- },
225
- {
226
- displayName: 'Type',
227
- name: 'type',
228
- type: 'options',
229
- options: [
230
- {
231
- name: 'User',
232
- value: 0,
233
- },
234
- {
235
- name: 'Group',
236
- value: 1,
237
- },
238
- ],
239
- default: 0,
240
- description: 'Tin nhắn gửi đến (người dùng hoặc nhóm)',
241
- },
242
- {
243
- displayName: 'Message',
244
- name: 'message',
245
- type: 'string',
246
- default: '',
247
- required: true,
248
- description: 'Nội dung tin nhắn cần gửi',
249
- },
250
- {
251
- displayName: 'Message Format',
252
- name: 'messageFormat',
253
- type: 'options',
254
- options: [
255
- {
256
- name: 'Plain Text',
257
- value: 'plain',
258
- },
259
- {
260
- name: 'HTML (Auto Convert)',
261
- value: 'html',
262
- },
263
- ],
264
- default: 'plain',
265
- description: 'Định dạng tin nhắn: Plain text hoặc HTML tự động chuyển đổi',
266
- },
267
- {
268
- displayName: 'Urgency',
269
- name: 'urgency',
270
- type: 'options',
271
- options: [
272
- {
273
- name: 'Default',
274
- value: 0,
275
- },
276
- {
277
- name: 'Important',
278
- value: 1,
279
- },
280
- {
281
- name: 'Urgent',
282
- value: 2,
283
- },
284
- ],
285
- default: 0,
286
- description: 'Mức độ khẩn cấp của tin nhắn',
287
- },
288
- {
289
- displayName: 'Image URLs',
290
- name: 'attachmentUrls',
291
- type: 'string',
292
- default: '',
293
- placeholder: 'https://../img1.jpg, https://../img2.png',
294
- description: 'Nhập 1 hoặc nhiều url ảnh cách nhau với dấu (,)',
295
- },
296
- {
297
- displayName: 'Send "Typing..." Event',
298
- name: 'sendTypingEvent',
299
- type: 'boolean',
300
- default: true,
301
- description: 'Gửi sự kiện "Đang soạn tin..." và đợi một chút trước khi gửi tin nhắn để mô phỏng hành vi của người dùng',
302
- },
303
- // reaction
304
- {
305
- displayName: 'Reaction',
306
- name: 'reaction',
307
- type: 'fixedCollection',
308
- typeOptions: {
309
- multipleValues: false,
310
- },
311
- placeholder: 'Add Reaction',
312
- default: {},
313
- options: [
314
- {
315
- displayName: 'Reaction Settings',
316
- name: 'reactionValue',
317
- values: [
318
- {
319
- displayName: 'Reaction Icon',
320
- name: 'reactionIcon',
321
- type: 'options',
322
- options: reactionOptions,
323
- default: 'heart',
324
- description: 'Biểu tượng cảm xúc để thể hiện',
325
- },
326
- {
327
- displayName: 'Message ID',
328
- name: 'reactionMsgId',
329
- type: 'string',
330
- default: '',
331
- description: 'msgId của tin nhắn hiện có để reaction',
332
- },
333
- {
334
- displayName: 'Client Message ID',
335
- name: 'reactionCliMsgId',
336
- type: 'string',
337
- default: '',
338
- description: 'cliMsgId của tin nhắn hiện có để reaction',
339
- },
340
- ],
341
- },
342
- ],
343
- },
344
-
345
- {
346
- displayName: 'Quote Message',
347
- name: 'quote',
348
- type: 'fixedCollection',
349
- typeOptions: {
350
- multipleValues: false,
351
- },
352
- placeholder: 'Add Quote',
353
- default: {},
354
- options: [
355
- {
356
- displayName: 'Quote Details',
357
- name: 'quoteValue',
358
- values: [
359
- {
360
- displayName: 'User ID',
361
- name: 'uidFrom',
362
- type: 'string',
363
- default: '',
364
- description: 'ID của người gửi tin nhắn (không phải threadId của group)',
365
- },
366
- {
367
- displayName: 'Message ID',
368
- name: 'msgId',
369
- type: 'string',
370
- default: '',
371
- description: 'msgId của tin nhắn cần trích dẫn',
372
- },
373
- {
374
- displayName: 'Client Message ID',
375
- name: 'cliMsgId',
376
- type: 'string',
377
- default: '',
378
- description: 'cliMsgId của tin nhắn cần trích dẫn',
379
- },
380
- {
381
- displayName: 'Content',
382
- name: 'content',
383
- type: 'string',
384
- default: '',
385
- description: 'Nội dung tin nhắn trích dẫn',
386
- },
387
- {
388
- displayName: 'Timestamp',
389
- name: 'ts',
390
- type: 'number',
391
- default: 0,
392
- description: 'Timestamp (ms) của tin nhắn cần trích dẫn',
393
- },
394
- {
395
- displayName: 'Message Type',
396
- name: 'msgType',
397
- type: 'number',
398
- default: 1,
399
- description: 'Loại tin nhắn được trích dẫn (ví dụ: 1 cho text)',
400
- },
401
- ],
402
- },
403
- ],
404
- },
405
- {
406
- displayName: 'Mentions',
407
- name: 'mentions',
408
- type: 'fixedCollection',
409
- typeOptions: {
410
- multipleValues: false,
411
- },
412
- placeholder: 'Add Mention',
413
- default: {},
414
- options: [
415
- {
416
- displayName: 'Mention Details',
417
- name: 'mentionValue',
418
- values: [
419
- {
420
- displayName: 'User ID',
421
- name: 'uid',
422
- type: 'string',
423
- default: '',
424
- description: 'ID của người dùng được mention',
425
- },
426
- {
427
- displayName: 'Position',
428
- name: 'pos',
429
- type: 'number',
430
- default: 0,
431
- description: 'Vị trí mention trong tin nhắn',
432
- },
433
- {
434
- displayName: 'Length',
435
- name: 'len',
436
- type: 'number',
437
- default: 0,
438
- description: 'Độ dài của mention',
439
- },
440
- ],
441
- },
442
- ],
443
- },
444
- {
445
- displayName: 'Text Styles',
446
- name: 'styles',
447
- type: 'fixedCollection',
448
- typeOptions: {
449
- multipleValues: true,
450
- },
451
- placeholder: 'Add Text Style',
452
- default: {},
453
- options: [
454
- {
455
- name: 'style',
456
- displayName: 'Style',
457
- values: [
458
- {
459
- displayName: 'Style Type',
460
- name: 'st',
461
- type: 'options',
462
- options: [
463
- {
464
- name: 'Big Font',
465
- value: 'f_18',
466
- },
467
- {
468
- name: 'Bold',
469
- value: 'b',
470
- },
471
- {
472
- name: 'Green Color',
473
- value: 'c_15a85f',
474
- },
475
- {
476
- name: 'Indent',
477
- value: 'ind_$',
478
- },
479
- {
480
- name: 'Italic',
481
- value: 'i',
482
- },
483
- {
484
- name: 'Orange Color',
485
- value: 'c_f27806',
486
- },
487
- {
488
- name: 'Ordered List',
489
- value: 'lst_2',
490
- },
491
- {
492
- name: 'Red Color',
493
- value: 'c_db342e',
494
- },
495
- {
496
- name: 'Small Font',
497
- value: 'f_13',
498
- },
499
- {
500
- name: 'Strike Through',
501
- value: 's',
502
- },
503
- {
504
- name: 'Underline',
505
- value: 'u',
506
- },
507
- {
508
- name: 'Unordered List',
509
- value: 'lst_1',
510
- },
511
- {
512
- name: 'Yellow Color',
513
- value: 'c_f7b503',
514
- },
515
- ],
516
- default: 'b',
517
- description: 'Loại style áp dụng cho text',
518
- },
519
- {
520
- displayName: 'Start Position',
521
- name: 'start',
522
- type: 'number',
523
- default: 0,
524
- description: 'Vị trí bắt đầu áp dụng style (tính từ 0)',
525
- },
526
- {
527
- displayName: 'End Position',
528
- name: 'end',
529
- type: 'number',
530
- default: 0,
531
- description: 'Vị trí kết thúc áp dụng style',
532
- },
533
- {
534
- displayName: 'Indent Size',
535
- name: 'indentSize',
536
- type: 'number',
537
- default: 1,
538
- displayOptions: {
539
- show: {
540
- 'st': ['ind_$'],
541
- },
542
- },
543
- description: 'Kích thước indent (chỉ dùng cho Indent style)',
544
- },
545
- ],
546
- },
547
- ],
548
- description: 'Định dạng text với các style khác nhau',
549
- },
550
- {
551
- displayName: 'TTL (Time To Live)',
552
- name: 'ttl',
553
- type: 'number',
554
- default: 0,
555
- description: 'Thời gian tồn tại của tin nhắn (giây). 0 = vĩnh viễn.',
556
- },
28
+ ...ZaloSendMessageDescription_1.ZaloSendMessageDescription,
557
29
  ],
558
30
  };
559
31
  }
@@ -561,10 +33,8 @@ class ZaloSendMessage {
561
33
  const returnData = [];
562
34
  const items = this.getInputData();
563
35
  try {
564
- // Use the new helper function to get the API client
565
36
  api = await (0, zalo_helper_1.getZaloApiClient)(this, { needsImageMetadataGetter: true });
566
37
  if (!api) {
567
- // The helper function will throw an error, but as a fallback:
568
38
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to initialize Zalo API. Check credentials or User ID.');
569
39
  }
570
40
  }
@@ -577,7 +47,6 @@ class ZaloSendMessage {
577
47
  },
578
48
  });
579
49
  return [returnData]
580
- // throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Zalo login error: ${error.message}`);
581
50
  }
582
51
  for (let i = 0; i < items.length; i++) {
583
52
  try {
@@ -595,7 +64,6 @@ class ZaloSendMessage {
595
64
  const attachmentUrls = this.getNodeParameter('attachmentUrls', i, '');
596
65
  const reactionParam = this.getNodeParameter('reaction', i, {});
597
66
 
598
- // return json
599
67
  const returnJson = {
600
68
  threadId,
601
69
  threadType: type
@@ -614,7 +82,7 @@ class ZaloSendMessage {
614
82
  let message = rawMessage;
615
83
  let styles = manualStyles;
616
84
  if (messageFormat === 'html') {
617
- const parsed = parseHtmlToStyles(rawMessage);
85
+ const parsed = helper_1.parseHtmlToStyles(rawMessage);
618
86
  message = parsed.cleanText;
619
87
  const htmlStyles = parsed.styles;
620
88
  const manualStylesArray = manualStyles && manualStyles.style ? manualStyles.style : [];
@@ -677,20 +145,16 @@ class ZaloSendMessage {
677
145
  messageContent.attachments = [];
678
146
  for (const url of urls) {
679
147
  try {
680
- // Validate URL format
681
148
  new URL(url);
682
- // Download file and get its local path
683
149
  const fileData = await (0, helper_1.saveFile)(url);
684
150
  messageContent.attachments.push(fileData);
685
151
  this.logger.info(`Successfully prepared attachment from URL: ${url}`);
686
152
  }
687
153
  catch (e) {
688
- // Log a warning and skip if the URL is invalid or the file can't be downloaded
689
154
  this.logger.warn(`Skipping invalid or inaccessible attachment URL: ${url}. Error: ${e.message}`);
690
155
  }
691
156
  }
692
157
  }
693
-
694
158
  this.logger.info(`Sending message with parameters: ${JSON.stringify(messageContent)}`);
695
159
  this.logger.info(`Final styles being sent: ${JSON.stringify(messageContent.styles || 'No styles')}`);
696
160
  if (!api) {