n8n-nodes-zalo-custom 1.0.10 → 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.
- package/README.md +51 -48
- package/nodes/ZaloGroup/ZaloGroup.node.js +127 -136
- package/nodes/ZaloGroup/ZaloGroupDescription.js +79 -70
- package/nodes/ZaloSendMessage/ZaloSendMessage.node.js +3 -532
- package/nodes/ZaloSendMessage/ZaloSendMessageDescription.js +389 -0
- package/nodes/ZaloUploadAttachment/ZaloUploadAttachment.node.js +24 -26
- package/nodes/ZaloUploadAttachment/ZaloUploadAttachmentDescription.js +1 -1
- package/nodes/ZaloUser/ZaloUser.node.js +95 -1
- package/nodes/ZaloUser/ZaloUserDescription.js +297 -47
- package/nodes/utils/helper.js +148 -0
- package/nodes/utils/zalo.helper.js +12 -6
- package/package.json +1 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ZaloSendMessageDescription = exports.reactionOptions = void 0;
|
|
4
|
+
exports.reactionOptions = [
|
|
5
|
+
{ name: 'Heart', value: 'heart' },
|
|
6
|
+
{ name: 'Like', value: 'like' },
|
|
7
|
+
{ name: 'Haha', value: 'haha' },
|
|
8
|
+
{ name: 'Wow', value: 'wow' },
|
|
9
|
+
{ name: 'Cry', value: 'cry' },
|
|
10
|
+
{ name: 'Angry', value: 'angry' },
|
|
11
|
+
{ name: 'Kiss', value: 'kiss' },
|
|
12
|
+
{ name: 'Tears of Joy', value: 'tears_of_joy' },
|
|
13
|
+
{ name: 'Dislike', value: 'dislike' },
|
|
14
|
+
{ name: 'OK', value: 'ok' },
|
|
15
|
+
{ name: 'Thanks', value: 'thanks' },
|
|
16
|
+
{ name: 'Big Smile', value: 'big_smile' },
|
|
17
|
+
{ name: 'Sad', value: 'sad' },
|
|
18
|
+
{ name: 'Very Sad', value: 'very_sad' },
|
|
19
|
+
{ name: 'Rose', value: 'rose' },
|
|
20
|
+
{ name: 'Broken Heart', value: 'broken_heart' },
|
|
21
|
+
{ name: 'Love', value: 'love' },
|
|
22
|
+
{ name: 'Confused', value: 'confused' },
|
|
23
|
+
{ name: 'Wink', value: 'wink' },
|
|
24
|
+
{ name: 'Birthday', value: 'birthday' },
|
|
25
|
+
{ name: 'Bomb', value: 'bomb' },
|
|
26
|
+
{ name: 'Peace', value: 'peace' },
|
|
27
|
+
{ name: 'Pray', value: 'pray' },
|
|
28
|
+
{ name: 'No', value: 'no' },
|
|
29
|
+
{ name: 'Love You', value: 'love_you' },
|
|
30
|
+
{ name: 'Cool', value: 'cool' },
|
|
31
|
+
{ name: 'Nerd', value: 'nerd' },
|
|
32
|
+
{ name: 'Sunglasses', value: 'sunglasses' },
|
|
33
|
+
{ name: 'Neutral', value: 'neutral' },
|
|
34
|
+
{ name: 'Bye', value: 'bye' },
|
|
35
|
+
{ name: 'Sleepy', value: 'sleepy' },
|
|
36
|
+
{ name: 'Wipe', value: 'wipe' },
|
|
37
|
+
{ name: 'Dig', value: 'dig' },
|
|
38
|
+
{ name: 'Handclap', value: 'handclap' },
|
|
39
|
+
{ name: 'Silent', value: 'silent' },
|
|
40
|
+
{ name: 'Surprise', value: 'surprise' },
|
|
41
|
+
{ name: 'Embarrassed', value: 'embarrassed' },
|
|
42
|
+
{ name: 'Afraid', value: 'afraid' },
|
|
43
|
+
{ name: 'Big Laugh', value: 'big_laugh' },
|
|
44
|
+
{ name: 'Beer', value: 'beer' },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
exports.ZaloSendMessageDescription = [
|
|
48
|
+
{
|
|
49
|
+
displayName: 'Thread ID',
|
|
50
|
+
name: 'threadId',
|
|
51
|
+
type: 'string',
|
|
52
|
+
default: '',
|
|
53
|
+
required: true,
|
|
54
|
+
description: 'ID của thread để gửi tin nhắn',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
displayName: 'Type',
|
|
58
|
+
name: 'type',
|
|
59
|
+
type: 'options',
|
|
60
|
+
options: [
|
|
61
|
+
{
|
|
62
|
+
name: 'User',
|
|
63
|
+
value: 0,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'Group',
|
|
67
|
+
value: 1,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
default: 0,
|
|
71
|
+
description: 'Tin nhắn gửi đến (người dùng hoặc nhóm)',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
displayName: 'Message',
|
|
75
|
+
name: 'message',
|
|
76
|
+
type: 'string',
|
|
77
|
+
default: '',
|
|
78
|
+
required: true,
|
|
79
|
+
description: 'Nội dung tin nhắn cần gửi',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
displayName: 'Message Format',
|
|
83
|
+
name: 'messageFormat',
|
|
84
|
+
type: 'options',
|
|
85
|
+
options: [
|
|
86
|
+
{
|
|
87
|
+
name: 'Plain Text',
|
|
88
|
+
value: 'plain',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'HTML',
|
|
92
|
+
value: 'html',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
default: 'plain',
|
|
96
|
+
description: 'Định dạng mặc định hoặc HTML',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
displayName: 'Urgency',
|
|
100
|
+
name: 'urgency',
|
|
101
|
+
type: 'options',
|
|
102
|
+
options: [
|
|
103
|
+
{
|
|
104
|
+
name: 'Default',
|
|
105
|
+
value: 0,
|
|
106
|
+
description: 'Tin nhắn mặc định',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Important',
|
|
110
|
+
value: 1,
|
|
111
|
+
description: 'Đánh dấu tin nhắn quan trọng',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'Urgent',
|
|
115
|
+
value: 2,
|
|
116
|
+
description: 'Người nhận được thông báo nhiều lần trong vài phút',
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
default: 0,
|
|
120
|
+
description: 'Mức độ khẩn cấp của tin nhắn',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
displayName: 'Image URLs',
|
|
124
|
+
name: 'attachmentUrls',
|
|
125
|
+
type: 'string',
|
|
126
|
+
default: '',
|
|
127
|
+
placeholder: 'https://../img1.jpg, https://../img2.png',
|
|
128
|
+
description: 'Nhập 1 hoặc nhiều url ảnh cách nhau với dấu (,)',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
displayName: 'Send "Typing..." Event',
|
|
132
|
+
name: 'sendTypingEvent',
|
|
133
|
+
type: 'boolean',
|
|
134
|
+
default: true,
|
|
135
|
+
description: 'Gửi sự kiện "Đang soạn tin..." (tự động chờ 1 chút trước khi gửi tin)',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
displayName: 'Reaction',
|
|
139
|
+
name: 'reaction',
|
|
140
|
+
type: 'fixedCollection',
|
|
141
|
+
typeOptions: {
|
|
142
|
+
multipleValues: false,
|
|
143
|
+
},
|
|
144
|
+
placeholder: 'Add Reaction',
|
|
145
|
+
default: {},
|
|
146
|
+
options: [
|
|
147
|
+
{
|
|
148
|
+
displayName: 'Reaction Settings',
|
|
149
|
+
name: 'reactionValue',
|
|
150
|
+
values: [
|
|
151
|
+
{
|
|
152
|
+
displayName: 'Reaction Icon',
|
|
153
|
+
name: 'reactionIcon',
|
|
154
|
+
type: 'options',
|
|
155
|
+
options: exports.reactionOptions,
|
|
156
|
+
default: 'heart',
|
|
157
|
+
description: 'Biểu tượng cảm xúc',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
displayName: 'Message ID',
|
|
161
|
+
name: 'reactionMsgId',
|
|
162
|
+
type: 'string',
|
|
163
|
+
default: '',
|
|
164
|
+
description: 'msgId của tin nhắn hiện có để reaction',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
displayName: 'Client Message ID',
|
|
168
|
+
name: 'reactionCliMsgId',
|
|
169
|
+
type: 'string',
|
|
170
|
+
default: '',
|
|
171
|
+
description: 'cliMsgId của tin nhắn hiện có để reaction',
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
displayName: 'Quote Message',
|
|
179
|
+
name: 'quote',
|
|
180
|
+
type: 'fixedCollection',
|
|
181
|
+
typeOptions: {
|
|
182
|
+
multipleValues: false,
|
|
183
|
+
},
|
|
184
|
+
placeholder: 'Add Quote',
|
|
185
|
+
default: {},
|
|
186
|
+
options: [
|
|
187
|
+
{
|
|
188
|
+
displayName: 'Quote Details',
|
|
189
|
+
name: 'quoteValue',
|
|
190
|
+
values: [
|
|
191
|
+
{
|
|
192
|
+
displayName: 'User ID',
|
|
193
|
+
name: 'uidFrom',
|
|
194
|
+
type: 'string',
|
|
195
|
+
default: '',
|
|
196
|
+
description: 'ID của người gửi tin nhắn (không phải threadId của group)',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
displayName: 'Message ID',
|
|
200
|
+
name: 'msgId',
|
|
201
|
+
type: 'string',
|
|
202
|
+
default: '',
|
|
203
|
+
description: 'msgId của tin nhắn cần trích dẫn',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
displayName: 'Client Message ID',
|
|
207
|
+
name: 'cliMsgId',
|
|
208
|
+
type: 'string',
|
|
209
|
+
default: '',
|
|
210
|
+
description: 'cliMsgId của tin nhắn cần trích dẫn',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
displayName: 'Content',
|
|
214
|
+
name: 'content',
|
|
215
|
+
type: 'string',
|
|
216
|
+
default: '',
|
|
217
|
+
description: 'Nội dung tin nhắn trích dẫn',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
displayName: 'Timestamp',
|
|
221
|
+
name: 'ts',
|
|
222
|
+
type: 'number',
|
|
223
|
+
default: 0,
|
|
224
|
+
description: 'Timestamp (ms) của tin nhắn cần trích dẫn',
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
displayName: 'Message Type',
|
|
228
|
+
name: 'msgType',
|
|
229
|
+
type: 'number',
|
|
230
|
+
default: 1,
|
|
231
|
+
description: 'Loại tin nhắn được trích dẫn (ví dụ: 1 cho text)',
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
displayName: 'Mentions',
|
|
239
|
+
name: 'mentions',
|
|
240
|
+
type: 'fixedCollection',
|
|
241
|
+
typeOptions: {
|
|
242
|
+
multipleValues: false,
|
|
243
|
+
},
|
|
244
|
+
placeholder: 'Add Mention',
|
|
245
|
+
default: {},
|
|
246
|
+
options: [
|
|
247
|
+
{
|
|
248
|
+
displayName: 'Mention Details',
|
|
249
|
+
name: 'mentionValue',
|
|
250
|
+
values: [
|
|
251
|
+
{
|
|
252
|
+
displayName: 'User ID',
|
|
253
|
+
name: 'uid',
|
|
254
|
+
type: 'string',
|
|
255
|
+
default: '',
|
|
256
|
+
description: 'ID của người dùng được mention',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
displayName: 'Position',
|
|
260
|
+
name: 'pos',
|
|
261
|
+
type: 'number',
|
|
262
|
+
default: 0,
|
|
263
|
+
description: 'Vị trí mention trong tin nhắn',
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
displayName: 'Length',
|
|
267
|
+
name: 'len',
|
|
268
|
+
type: 'number',
|
|
269
|
+
default: 0,
|
|
270
|
+
description: 'Độ dài của mention',
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
displayName: 'Text Styles',
|
|
278
|
+
name: 'styles',
|
|
279
|
+
type: 'fixedCollection',
|
|
280
|
+
typeOptions: {
|
|
281
|
+
multipleValues: true,
|
|
282
|
+
},
|
|
283
|
+
placeholder: 'Add Text Style',
|
|
284
|
+
default: {},
|
|
285
|
+
options: [
|
|
286
|
+
{
|
|
287
|
+
name: 'style',
|
|
288
|
+
displayName: 'Style',
|
|
289
|
+
values: [
|
|
290
|
+
{
|
|
291
|
+
displayName: 'Style Type',
|
|
292
|
+
name: 'st',
|
|
293
|
+
type: 'options',
|
|
294
|
+
options: [
|
|
295
|
+
{
|
|
296
|
+
name: 'Big Font',
|
|
297
|
+
value: 'f_18',
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'Bold',
|
|
301
|
+
value: 'b',
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: 'Green Color',
|
|
305
|
+
value: 'c_15a85f',
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
name: 'Indent',
|
|
309
|
+
value: 'ind_$',
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: 'Italic',
|
|
313
|
+
value: 'i',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: 'Orange Color',
|
|
317
|
+
value: 'c_f27806',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: 'Ordered List',
|
|
321
|
+
value: 'lst_2',
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: 'Red Color',
|
|
325
|
+
value: 'c_db342e',
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: 'Small Font',
|
|
329
|
+
value: 'f_13',
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: 'Strike Through',
|
|
333
|
+
value: 's',
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
name: 'Underline',
|
|
337
|
+
value: 'u',
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: 'Unordered List',
|
|
341
|
+
value: 'lst_1',
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
name: 'Yellow Color',
|
|
345
|
+
value: 'c_f7b503',
|
|
346
|
+
},
|
|
347
|
+
],
|
|
348
|
+
default: 'b',
|
|
349
|
+
description: 'Loại style áp dụng cho text',
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
displayName: 'Start Position',
|
|
353
|
+
name: 'start',
|
|
354
|
+
type: 'number',
|
|
355
|
+
default: 0,
|
|
356
|
+
description: 'Vị trí bắt đầu áp dụng style (tính từ 0)',
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
displayName: 'End Position',
|
|
360
|
+
name: 'end',
|
|
361
|
+
type: 'number',
|
|
362
|
+
default: 0,
|
|
363
|
+
description: 'Vị trí kết thúc áp dụng style',
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
displayName: 'Indent Size',
|
|
367
|
+
name: 'indentSize',
|
|
368
|
+
type: 'number',
|
|
369
|
+
default: 1,
|
|
370
|
+
displayOptions: {
|
|
371
|
+
show: {
|
|
372
|
+
'st': ['ind_$'],
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
description: 'Kích thước indent (chỉ dùng cho Indent style)',
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
description: 'Định dạng text với các style khác nhau',
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
displayName: 'TTL (Time To Live)',
|
|
384
|
+
name: 'ttl',
|
|
385
|
+
type: 'number',
|
|
386
|
+
default: 0,
|
|
387
|
+
description: 'Thời gian tồn tại của tin nhắn (giây). 0 = vĩnh viễn.',
|
|
388
|
+
},
|
|
389
|
+
];
|
|
@@ -7,6 +7,7 @@ exports.ZaloUploadAttachment = void 0;
|
|
|
7
7
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
8
8
|
const zca_js_1 = require("zca-js");
|
|
9
9
|
const helper_1 = require("../utils/helper");
|
|
10
|
+
const zalo_helper_1 = require("../utils/zalo.helper");
|
|
10
11
|
const fs_1 = __importDefault(require("fs"));
|
|
11
12
|
let api;
|
|
12
13
|
class ZaloUploadAttachment {
|
|
@@ -149,34 +150,16 @@ class ZaloUploadAttachment {
|
|
|
149
150
|
async execute() {
|
|
150
151
|
const returnData = [];
|
|
151
152
|
const items = this.getInputData();
|
|
152
|
-
const zaloCred = await this.getCredentials('zaloApi');
|
|
153
|
-
const cookieFromCred = JSON.parse(zaloCred.cookie);
|
|
154
|
-
const imeiFromCred = zaloCred.imei;
|
|
155
|
-
const userAgentFromCred = zaloCred.userAgent;
|
|
156
153
|
try {
|
|
157
|
-
|
|
158
|
-
selfListen: false,
|
|
159
|
-
logging: true,
|
|
160
|
-
imageMetadataGetter: async (filePath) => {
|
|
161
|
-
return {
|
|
162
|
-
width: 0,
|
|
163
|
-
height: 0,
|
|
164
|
-
size: 0
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
api = await zalo.login({
|
|
169
|
-
cookie: cookieFromCred,
|
|
170
|
-
imei: imeiFromCred,
|
|
171
|
-
userAgent: userAgentFromCred
|
|
172
|
-
});
|
|
154
|
+
api = await (0, zalo_helper_1.getZaloApiClient)(this, { needsImageMetadataGetter: true, selfListen: true });
|
|
173
155
|
if (!api) {
|
|
174
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to initialize Zalo API. Check
|
|
156
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to initialize Zalo API. Check credentials or User ID.');
|
|
175
157
|
}
|
|
176
158
|
}
|
|
177
159
|
catch (error) {
|
|
178
160
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Zalo login error: ${error.message}`);
|
|
179
161
|
}
|
|
162
|
+
|
|
180
163
|
for (let i = 0; i < items.length; i++) {
|
|
181
164
|
try {
|
|
182
165
|
const threadId = this.getNodeParameter('threadId', i);
|
|
@@ -188,12 +171,29 @@ class ZaloUploadAttachment {
|
|
|
188
171
|
}
|
|
189
172
|
const sources = [];
|
|
190
173
|
const tempFiles = [];
|
|
174
|
+
|
|
175
|
+
const path_1 = __importDefault(require("path"));
|
|
176
|
+
const os_1 = __importDefault(require("os"));
|
|
177
|
+
const n8nUserFolder = process.env.N8N_USER_FOLDER || path_1.default.join(os_1.default.homedir(), '.n8n');
|
|
178
|
+
|
|
191
179
|
for (const sourceConfig of sourcesData.source) {
|
|
192
180
|
let source;
|
|
193
181
|
if (sourceConfig.type === 'filePath') {
|
|
194
|
-
|
|
182
|
+
let filePath = sourceConfig.filePath;
|
|
195
183
|
if (!fs_1.default.existsSync(filePath)) {
|
|
196
|
-
|
|
184
|
+
const relativePath = path_1.default.join(n8nUserFolder, filePath);
|
|
185
|
+
const tempPath = path_1.default.join(n8nUserFolder, 'temp_files', path_1.default.basename(filePath));
|
|
186
|
+
|
|
187
|
+
if (fs_1.default.existsSync(relativePath)) {
|
|
188
|
+
filePath = relativePath;
|
|
189
|
+
this.logger.info(`Resolved relative path: ${filePath}`);
|
|
190
|
+
} else if (fs_1.default.existsSync(tempPath)) {
|
|
191
|
+
filePath = tempPath;
|
|
192
|
+
this.logger.info(`Resolved temp path: ${filePath}`);
|
|
193
|
+
} else {
|
|
194
|
+
this.logger.error(`File path not found: ${sourceConfig.filePath}`);
|
|
195
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `File không tồn tại: ${sourceConfig.filePath}. (Đã thử tìm tại: ${relativePath})`);
|
|
196
|
+
}
|
|
197
197
|
}
|
|
198
198
|
source = filePath;
|
|
199
199
|
}
|
|
@@ -203,6 +203,7 @@ class ZaloUploadAttachment {
|
|
|
203
203
|
if (!tempFilePath) {
|
|
204
204
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Không thể tải file từ URL: ${fileUrl}`);
|
|
205
205
|
}
|
|
206
|
+
this.logger.info(`Downloaded URL to temp file: ${tempFilePath}`);
|
|
206
207
|
tempFiles.push(tempFilePath);
|
|
207
208
|
source = tempFilePath;
|
|
208
209
|
}
|
|
@@ -226,9 +227,6 @@ class ZaloUploadAttachment {
|
|
|
226
227
|
sources.push(source);
|
|
227
228
|
}
|
|
228
229
|
this.logger.info(`Uploading ${sources.length} file(s) to thread ${threadId} (${threadTypeStr})`);
|
|
229
|
-
if (!api) {
|
|
230
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Zalo API not initialized');
|
|
231
|
-
}
|
|
232
230
|
const uploadResults = await api.uploadAttachment(sources, threadId, threadType);
|
|
233
231
|
for (const tempFile of tempFiles) {
|
|
234
232
|
(0, helper_1.removeFile)(tempFile);
|
|
@@ -6,6 +6,7 @@ const n8n_workflow_1 = require("n8n-workflow");
|
|
|
6
6
|
const ZaloNodeProperties_1 = require("../shared/ZaloNodeProperties");
|
|
7
7
|
const ZaloUserDescription_1 = require("./ZaloUserDescription");
|
|
8
8
|
const zalo_helper_1 = require("../utils/zalo.helper");
|
|
9
|
+
const helper_1 = require("../utils/helper");
|
|
9
10
|
let api;
|
|
10
11
|
class ZaloUser {
|
|
11
12
|
constructor() {
|
|
@@ -47,8 +48,14 @@ class ZaloUser {
|
|
|
47
48
|
const items = this.getInputData();
|
|
48
49
|
const returnData = [];
|
|
49
50
|
|
|
51
|
+
const needsImageMetadataGetter = items.some((_, i) => {
|
|
52
|
+
try {
|
|
53
|
+
return this.getNodeParameter('operation', i) === 'changeAccountAvatar';
|
|
54
|
+
} catch (e) { return false; }
|
|
55
|
+
});
|
|
56
|
+
|
|
50
57
|
try {
|
|
51
|
-
api = await (0, zalo_helper_1.getZaloApiClient)(this, {});
|
|
58
|
+
api = await (0, zalo_helper_1.getZaloApiClient)(this, { needsImageMetadataGetter });
|
|
52
59
|
if (!api) {
|
|
53
60
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to initialize Zalo API. Check credentials or User ID.');
|
|
54
61
|
}
|
|
@@ -265,6 +272,93 @@ class ZaloUser {
|
|
|
265
272
|
returnData.push({ json: { success: true, ...processedResponse }, pairedItem: { item: i } });
|
|
266
273
|
break;
|
|
267
274
|
}
|
|
275
|
+
case 'setMute': {
|
|
276
|
+
const threadId = this.getNodeParameter('threadId', i);
|
|
277
|
+
const muteAction = this.getNodeParameter('muteAction', i);
|
|
278
|
+
const type = this.getNodeParameter('threadType', i);
|
|
279
|
+
let duration = -1;
|
|
280
|
+
if (muteAction === 1) {
|
|
281
|
+
const durationParam = this.getNodeParameter('muteDuration', i);
|
|
282
|
+
if (durationParam === -2) {
|
|
283
|
+
duration = this.getNodeParameter('customMuteDuration', i) * 60;
|
|
284
|
+
console.log(duration)
|
|
285
|
+
} else {
|
|
286
|
+
duration = durationParam;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const params = {
|
|
290
|
+
action: muteAction,
|
|
291
|
+
duration: duration,
|
|
292
|
+
};
|
|
293
|
+
const response = await api.setMute(params, threadId, type);
|
|
294
|
+
returnData.push({ json: { success: true, response }, pairedItem: { item: i } });
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
case 'deleteMessage': {
|
|
298
|
+
const threadId = this.getNodeParameter('threadId', i);
|
|
299
|
+
const uidFrom = this.getNodeParameter('userId', i);
|
|
300
|
+
const msgId = this.getNodeParameter('msgId', i);
|
|
301
|
+
const cliMsgId = this.getNodeParameter('cliMsgId', i);
|
|
302
|
+
const onlyMe = this.getNodeParameter('onlyMe', i, true);
|
|
303
|
+
const type = this.getNodeParameter('threadType', i);
|
|
304
|
+
const dest = {
|
|
305
|
+
data: { cliMsgId, msgId, uidFrom },
|
|
306
|
+
threadId: threadId,
|
|
307
|
+
type: type,
|
|
308
|
+
};
|
|
309
|
+
const response = await api.deleteMessage(dest, onlyMe);
|
|
310
|
+
returnData.push({ json: { success: true, response }, pairedItem: { item: i } });
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
case 'updateSettings': {
|
|
314
|
+
const settings = this.getNodeParameter('updateSettingsOptions', i);
|
|
315
|
+
const results = {};
|
|
316
|
+
const keys = Object.keys(settings);
|
|
317
|
+
for (let k = 0; k < keys.length; k++) {
|
|
318
|
+
const key = keys[k];
|
|
319
|
+
const value = settings[key];
|
|
320
|
+
try {
|
|
321
|
+
const response = await api.updateSettings(key, value);
|
|
322
|
+
results[key] = { success: true, response };
|
|
323
|
+
} catch (error) {
|
|
324
|
+
results[key] = { success: false, error: error.message };
|
|
325
|
+
}
|
|
326
|
+
if (k < keys.length - 1) {
|
|
327
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
returnData.push({ json: { success: true, results }, pairedItem: { item: i } });
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
case 'changeAccountAvatar': {
|
|
334
|
+
const imageUrl = this.getNodeParameter('imageUrl', i);
|
|
335
|
+
let finalAvatarSource;
|
|
336
|
+
let tempFilePath;
|
|
337
|
+
try {
|
|
338
|
+
if (!imageUrl) {
|
|
339
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Image URL is required for changing account avatar.', { itemIndex: i });
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
new URL(imageUrl);
|
|
343
|
+
this.logger.info(`Downloading image from URL for avatar: ${imageUrl}`);
|
|
344
|
+
tempFilePath = await (0, helper_1.saveFile)(imageUrl);
|
|
345
|
+
finalAvatarSource = tempFilePath;
|
|
346
|
+
}
|
|
347
|
+
catch (urlError) {
|
|
348
|
+
this.logger.info(`Treating image URL as local file path for avatar: ${imageUrl}`);
|
|
349
|
+
finalAvatarSource = imageUrl;
|
|
350
|
+
}
|
|
351
|
+
const response = await api.changeAccountAvatar(finalAvatarSource);
|
|
352
|
+
returnData.push({ json: { success: true, response }, pairedItem: { item: i } });
|
|
353
|
+
}
|
|
354
|
+
finally {
|
|
355
|
+
if (tempFilePath) {
|
|
356
|
+
await (0, helper_1.removeFile)(tempFilePath);
|
|
357
|
+
this.logger.info(`Successfully removed temporary avatar file: ${tempFilePath}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
268
362
|
}
|
|
269
363
|
}
|
|
270
364
|
}
|