n8n-nodes-nvk-browser 1.0.113 → 1.0.115
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,8 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.nvkBrowserFields = void 0;
|
|
4
|
+
const CreateProfile_description_1 = require("../ProfileManagement/CreateProfile/CreateProfile.description");
|
|
5
|
+
const DeleteProfile_description_1 = require("../ProfileManagement/DeleteProfile/DeleteProfile.description");
|
|
6
|
+
const StartProfile_description_1 = require("../ProfileManagement/StartProfile/StartProfile.description");
|
|
7
|
+
const StopProfile_description_1 = require("../ProfileManagement/StopProfile/StopProfile.description");
|
|
8
|
+
const MoveAndClick_description_1 = require("../PageInteraction/MoveAndClick/MoveAndClick.description");
|
|
9
|
+
const RunJavaScript_description_1 = require("../PageInteraction/RunJavaScript/RunJavaScript.description");
|
|
10
|
+
const GetNetworkResponse_description_1 = require("../PageInteraction/GetNetworkResponse/GetNetworkResponse.description");
|
|
11
|
+
const BrowserHttpRequest_description_1 = require("../PageInteraction/BrowserHttpRequest/BrowserHttpRequest.description");
|
|
12
|
+
// Update displayOptions for all fields to use new resource/operation values
|
|
13
|
+
const updateDisplayOptions = (fields, resource, operation) => {
|
|
14
|
+
return fields.map(field => ({
|
|
15
|
+
...field,
|
|
16
|
+
displayOptions: {
|
|
17
|
+
show: {
|
|
18
|
+
resource: [resource],
|
|
19
|
+
operation: [operation],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
};
|
|
4
24
|
exports.nvkBrowserFields = [
|
|
5
|
-
// ===== Resource =====
|
|
6
25
|
{
|
|
7
26
|
displayName: 'Resource',
|
|
8
27
|
name: 'resource',
|
|
@@ -19,18 +38,13 @@ exports.nvkBrowserFields = [
|
|
|
19
38
|
},
|
|
20
39
|
],
|
|
21
40
|
default: 'profileManagement',
|
|
41
|
+
description: 'Select a resource',
|
|
22
42
|
},
|
|
23
|
-
// ===== Operation =====
|
|
24
43
|
{
|
|
25
44
|
displayName: 'Operation',
|
|
26
45
|
name: 'operation',
|
|
27
46
|
type: 'options',
|
|
28
47
|
noDataExpression: true,
|
|
29
|
-
displayOptions: {
|
|
30
|
-
show: {
|
|
31
|
-
resource: ['profileManagement'],
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
48
|
options: [
|
|
35
49
|
{
|
|
36
50
|
name: 'Create Profile',
|
|
@@ -58,20 +72,20 @@ exports.nvkBrowserFields = [
|
|
|
58
72
|
},
|
|
59
73
|
],
|
|
60
74
|
default: 'createProfile',
|
|
75
|
+
displayOptions: {
|
|
76
|
+
show: {
|
|
77
|
+
resource: ['profileManagement'],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
61
80
|
},
|
|
62
81
|
{
|
|
63
82
|
displayName: 'Operation',
|
|
64
83
|
name: 'operation',
|
|
65
84
|
type: 'options',
|
|
66
85
|
noDataExpression: true,
|
|
67
|
-
displayOptions: {
|
|
68
|
-
show: {
|
|
69
|
-
resource: ['pageInteraction'],
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
86
|
options: [
|
|
73
87
|
{
|
|
74
|
-
name: 'Move
|
|
88
|
+
name: 'Move and Click',
|
|
75
89
|
value: 'moveAndClick',
|
|
76
90
|
description: 'Move mouse and click on an element',
|
|
77
91
|
action: 'Move and click',
|
|
@@ -79,919 +93,37 @@ exports.nvkBrowserFields = [
|
|
|
79
93
|
{
|
|
80
94
|
name: 'Run JavaScript',
|
|
81
95
|
value: 'runJavaScript',
|
|
82
|
-
description: 'Execute JavaScript code',
|
|
96
|
+
description: 'Execute JavaScript code in the browser',
|
|
83
97
|
action: 'Run JavaScript',
|
|
84
98
|
},
|
|
85
99
|
{
|
|
86
100
|
name: 'Get Network Response',
|
|
87
101
|
value: 'getNetworkResponse',
|
|
88
|
-
description: '
|
|
102
|
+
description: 'Capture network request responses',
|
|
89
103
|
action: 'Get network response',
|
|
90
104
|
},
|
|
91
105
|
{
|
|
92
106
|
name: 'Browser HTTP Request',
|
|
93
107
|
value: 'browserHttpRequest',
|
|
94
|
-
description: 'Make HTTP
|
|
108
|
+
description: 'Make HTTP requests using browser cookies',
|
|
95
109
|
action: 'Make HTTP request',
|
|
96
110
|
},
|
|
97
111
|
],
|
|
98
112
|
default: 'moveAndClick',
|
|
99
|
-
},
|
|
100
|
-
// ===== Profile Management: Create Profile =====
|
|
101
|
-
{
|
|
102
|
-
displayName: 'Profile Name',
|
|
103
|
-
name: 'profileName',
|
|
104
|
-
type: 'string',
|
|
105
|
-
required: true,
|
|
106
|
-
default: '',
|
|
107
|
-
description: 'Name of the profile to create',
|
|
108
|
-
displayOptions: {
|
|
109
|
-
show: {
|
|
110
|
-
resource: ['profileManagement'],
|
|
111
|
-
operation: ['createProfile'],
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
displayName: 'Proxy',
|
|
117
|
-
name: 'proxy',
|
|
118
|
-
type: 'string',
|
|
119
|
-
default: '',
|
|
120
|
-
placeholder: 'http:127.0.0.1:8080:user:pass hoặc socks5:127.0.0.1:1080:user:pass',
|
|
121
|
-
description: 'Proxy format: http://myip:port:user:pass or socks5://myip:port:user:pass (hoặc không có ://)',
|
|
122
|
-
displayOptions: {
|
|
123
|
-
show: {
|
|
124
|
-
resource: ['profileManagement'],
|
|
125
|
-
operation: ['createProfile'],
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
displayName: 'Note',
|
|
131
|
-
name: 'note',
|
|
132
|
-
type: 'string',
|
|
133
|
-
default: '',
|
|
134
|
-
description: 'Optional note for this profile',
|
|
135
|
-
displayOptions: {
|
|
136
|
-
show: {
|
|
137
|
-
resource: ['profileManagement'],
|
|
138
|
-
operation: ['createProfile'],
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
displayName: 'Extensions',
|
|
144
|
-
name: 'extensions',
|
|
145
|
-
type: 'string',
|
|
146
|
-
typeOptions: {
|
|
147
|
-
rows: 4,
|
|
148
|
-
},
|
|
149
|
-
default: '',
|
|
150
|
-
placeholder: 'Nháºp ID extension Chrome Store hoặc đưá»ng dẫn tá»›i extension local, má»—i extension má»™t dòng',
|
|
151
|
-
description: 'Enter Chrome Store extension ID or path to local extension, one extension per line',
|
|
152
|
-
displayOptions: {
|
|
153
|
-
show: {
|
|
154
|
-
resource: ['profileManagement'],
|
|
155
|
-
operation: ['createProfile'],
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
// ===== Profile Management: Delete Profile =====
|
|
160
|
-
{
|
|
161
|
-
displayName: 'Profile ID',
|
|
162
|
-
name: 'profileId',
|
|
163
|
-
type: 'string',
|
|
164
|
-
required: true,
|
|
165
|
-
default: '',
|
|
166
|
-
description: 'ID of the profile to delete',
|
|
167
|
-
displayOptions: {
|
|
168
|
-
show: {
|
|
169
|
-
resource: ['profileManagement'],
|
|
170
|
-
operation: ['deleteProfile'],
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
// ===== Profile Management: Start Profile =====
|
|
175
|
-
{
|
|
176
|
-
displayName: 'Profile ID',
|
|
177
|
-
name: 'profileId',
|
|
178
|
-
type: 'string',
|
|
179
|
-
required: true,
|
|
180
|
-
default: '',
|
|
181
|
-
description: 'ID of the profile to start',
|
|
182
|
-
displayOptions: {
|
|
183
|
-
show: {
|
|
184
|
-
resource: ['profileManagement'],
|
|
185
|
-
operation: ['startProfile'],
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
displayName: 'Window Scale',
|
|
191
|
-
name: 'winScale',
|
|
192
|
-
type: 'number',
|
|
193
|
-
typeOptions: {
|
|
194
|
-
minValue: 0.5,
|
|
195
|
-
maxValue: 3,
|
|
196
|
-
numberStepSize: 0.1,
|
|
197
|
-
},
|
|
198
|
-
default: 1,
|
|
199
|
-
description: 'Window scale factor',
|
|
200
|
-
displayOptions: {
|
|
201
|
-
show: {
|
|
202
|
-
resource: ['profileManagement'],
|
|
203
|
-
operation: ['startProfile'],
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
displayName: 'Window Position',
|
|
209
|
-
name: 'winPosition',
|
|
210
|
-
type: 'fixedCollection',
|
|
211
|
-
typeOptions: {
|
|
212
|
-
multipleValues: false,
|
|
213
|
-
},
|
|
214
|
-
default: {},
|
|
215
|
-
description: 'Window position on screen',
|
|
216
|
-
displayOptions: {
|
|
217
|
-
show: {
|
|
218
|
-
resource: ['profileManagement'],
|
|
219
|
-
operation: ['startProfile'],
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
options: [
|
|
223
|
-
{
|
|
224
|
-
name: 'position',
|
|
225
|
-
displayName: 'Position',
|
|
226
|
-
values: [
|
|
227
|
-
{
|
|
228
|
-
displayName: 'X',
|
|
229
|
-
name: 'x',
|
|
230
|
-
type: 'number',
|
|
231
|
-
default: 0,
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
displayName: 'Y',
|
|
235
|
-
name: 'y',
|
|
236
|
-
type: 'number',
|
|
237
|
-
default: 0,
|
|
238
|
-
},
|
|
239
|
-
],
|
|
240
|
-
},
|
|
241
|
-
],
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
displayName: 'Window Size',
|
|
245
|
-
name: 'winSize',
|
|
246
|
-
type: 'fixedCollection',
|
|
247
|
-
typeOptions: {
|
|
248
|
-
multipleValues: false,
|
|
249
|
-
},
|
|
250
|
-
default: {},
|
|
251
|
-
description: 'Window size',
|
|
252
|
-
displayOptions: {
|
|
253
|
-
show: {
|
|
254
|
-
resource: ['profileManagement'],
|
|
255
|
-
operation: ['startProfile'],
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
options: [
|
|
259
|
-
{
|
|
260
|
-
name: 'size',
|
|
261
|
-
displayName: 'Size',
|
|
262
|
-
values: [
|
|
263
|
-
{
|
|
264
|
-
displayName: 'Width',
|
|
265
|
-
name: 'width',
|
|
266
|
-
type: 'number',
|
|
267
|
-
default: 1280,
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
displayName: 'Height',
|
|
271
|
-
name: 'height',
|
|
272
|
-
type: 'number',
|
|
273
|
-
default: 720,
|
|
274
|
-
},
|
|
275
|
-
],
|
|
276
|
-
},
|
|
277
|
-
],
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
displayName: 'Headless Mode',
|
|
281
|
-
name: 'headless',
|
|
282
|
-
type: 'boolean',
|
|
283
|
-
default: false,
|
|
284
|
-
description: 'Run browser in headless mode',
|
|
285
|
-
displayOptions: {
|
|
286
|
-
show: {
|
|
287
|
-
resource: ['profileManagement'],
|
|
288
|
-
operation: ['startProfile'],
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
// ===== Profile Management: Stop Profile =====
|
|
293
|
-
{
|
|
294
|
-
displayName: 'Profile ID',
|
|
295
|
-
name: 'profileId',
|
|
296
|
-
type: 'string',
|
|
297
|
-
required: true,
|
|
298
|
-
default: '',
|
|
299
|
-
description: 'ID of the profile to stop',
|
|
300
|
-
displayOptions: {
|
|
301
|
-
show: {
|
|
302
|
-
resource: ['profileManagement'],
|
|
303
|
-
operation: ['stopProfile'],
|
|
304
|
-
},
|
|
305
|
-
},
|
|
306
|
-
},
|
|
307
|
-
// ===== Page Interaction: Move And Click =====
|
|
308
|
-
{
|
|
309
|
-
displayName: 'Profile ID',
|
|
310
|
-
name: 'profileId',
|
|
311
|
-
type: 'string',
|
|
312
|
-
required: true,
|
|
313
|
-
default: '',
|
|
314
|
-
description: 'ID of the running profile',
|
|
315
|
-
displayOptions: {
|
|
316
|
-
show: {
|
|
317
|
-
resource: ['pageInteraction'],
|
|
318
|
-
operation: ['moveAndClick'],
|
|
319
|
-
},
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
displayName: 'Selector',
|
|
324
|
-
name: 'selector',
|
|
325
|
-
type: 'string',
|
|
326
|
-
required: true,
|
|
327
|
-
default: '',
|
|
328
|
-
description: 'For Puppeteer: CSS selector, XPath (with >XPATH> prefix), or paste the full Puppeteer code from Chrome Recorder (export as "Puppeteer"). The node will automatically detect and execute .click() or .fill() actions from Locator.race() blocks. Examples: "textarea", ">XPATH>/html/body/div", or full code with puppeteer.Locator.race([...]).click()/.fill(). For Javascript: CSS selector only. Note: The node only executes click/fill actions, not goto() or other navigation actions.',
|
|
329
|
-
typeOptions: {
|
|
330
|
-
rows: 4,
|
|
331
|
-
},
|
|
332
|
-
displayOptions: {
|
|
333
|
-
show: {
|
|
334
|
-
resource: ['pageInteraction'],
|
|
335
|
-
operation: ['moveAndClick'],
|
|
336
|
-
},
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
displayName: 'Timeout (Milliseconds)',
|
|
341
|
-
name: 'timeout',
|
|
342
|
-
type: 'number',
|
|
343
|
-
default: 30000,
|
|
344
|
-
description: 'Timeout in milliseconds for waiting for the element',
|
|
345
|
-
displayOptions: {
|
|
346
|
-
show: {
|
|
347
|
-
resource: ['pageInteraction'],
|
|
348
|
-
operation: ['moveAndClick'],
|
|
349
|
-
},
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
{
|
|
353
|
-
displayName: 'Click Method',
|
|
354
|
-
name: 'clickMethod',
|
|
355
|
-
type: 'options',
|
|
356
|
-
options: [
|
|
357
|
-
{
|
|
358
|
-
name: 'Use Puppeteer',
|
|
359
|
-
value: 'puppeteer',
|
|
360
|
-
},
|
|
361
|
-
{
|
|
362
|
-
name: 'Use Javascript Click',
|
|
363
|
-
value: 'javascript',
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
default: 'puppeteer',
|
|
367
|
-
description: 'Method to use for clicking',
|
|
368
|
-
displayOptions: {
|
|
369
|
-
show: {
|
|
370
|
-
resource: ['pageInteraction'],
|
|
371
|
-
operation: ['moveAndClick'],
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
},
|
|
375
|
-
{
|
|
376
|
-
displayName: 'Wait For Click (Milliseconds)',
|
|
377
|
-
name: 'waitForClick',
|
|
378
|
-
type: 'number',
|
|
379
|
-
default: 500,
|
|
380
|
-
description: 'Wait time before clicking in milliseconds',
|
|
381
|
-
displayOptions: {
|
|
382
|
-
show: {
|
|
383
|
-
resource: ['pageInteraction'],
|
|
384
|
-
operation: ['moveAndClick'],
|
|
385
|
-
clickMethod: ['puppeteer'],
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
},
|
|
389
|
-
{
|
|
390
|
-
displayName: 'Button',
|
|
391
|
-
name: 'button',
|
|
392
|
-
type: 'options',
|
|
393
|
-
options: [
|
|
394
|
-
{
|
|
395
|
-
name: 'Left',
|
|
396
|
-
value: 'left',
|
|
397
|
-
},
|
|
398
|
-
{
|
|
399
|
-
name: 'Right',
|
|
400
|
-
value: 'right',
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
name: 'Middle',
|
|
404
|
-
value: 'middle',
|
|
405
|
-
},
|
|
406
|
-
],
|
|
407
|
-
default: 'left',
|
|
408
|
-
description: 'Mouse button to use',
|
|
409
|
-
displayOptions: {
|
|
410
|
-
show: {
|
|
411
|
-
resource: ['pageInteraction'],
|
|
412
|
-
operation: ['moveAndClick'],
|
|
413
|
-
clickMethod: ['puppeteer'],
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
displayName: 'Click Count',
|
|
419
|
-
name: 'clickCount',
|
|
420
|
-
type: 'number',
|
|
421
|
-
default: 1,
|
|
422
|
-
typeOptions: {
|
|
423
|
-
minValue: 1,
|
|
424
|
-
},
|
|
425
|
-
description: 'Number of times to click',
|
|
426
|
-
displayOptions: {
|
|
427
|
-
show: {
|
|
428
|
-
resource: ['pageInteraction'],
|
|
429
|
-
operation: ['moveAndClick'],
|
|
430
|
-
clickMethod: ['puppeteer'],
|
|
431
|
-
},
|
|
432
|
-
},
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
displayName: 'Tab Index',
|
|
436
|
-
name: 'tabIndex',
|
|
437
|
-
type: 'number',
|
|
438
|
-
default: 0,
|
|
439
|
-
description: 'Index of the tab to interact with (0 = first tab)',
|
|
440
|
-
displayOptions: {
|
|
441
|
-
show: {
|
|
442
|
-
resource: ['pageInteraction'],
|
|
443
|
-
operation: ['moveAndClick'],
|
|
444
|
-
},
|
|
445
|
-
},
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
displayName: 'Auto Start Profile',
|
|
449
|
-
name: 'autoStart',
|
|
450
|
-
type: 'boolean',
|
|
451
|
-
default: false,
|
|
452
|
-
description: 'Automatically start the profile if it is not running',
|
|
453
|
-
displayOptions: {
|
|
454
|
-
show: {
|
|
455
|
-
resource: ['pageInteraction'],
|
|
456
|
-
operation: ['moveAndClick'],
|
|
457
|
-
},
|
|
458
|
-
},
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
displayName: 'Use Binary File from n8n',
|
|
462
|
-
name: 'useBinaryFile',
|
|
463
|
-
type: 'boolean',
|
|
464
|
-
default: false,
|
|
465
|
-
description: 'Use binary file from n8n instead of file path in fill action',
|
|
466
|
-
displayOptions: {
|
|
467
|
-
show: {
|
|
468
|
-
resource: ['pageInteraction'],
|
|
469
|
-
operation: ['moveAndClick'],
|
|
470
|
-
clickMethod: ['puppeteer'],
|
|
471
|
-
},
|
|
472
|
-
},
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
displayName: 'Binary Property Name',
|
|
476
|
-
name: 'binaryPropertyName',
|
|
477
|
-
type: 'string',
|
|
478
|
-
default: 'data',
|
|
479
|
-
description: 'Name of the binary property containing the file to upload',
|
|
480
|
-
displayOptions: {
|
|
481
|
-
show: {
|
|
482
|
-
resource: ['pageInteraction'],
|
|
483
|
-
operation: ['moveAndClick'],
|
|
484
|
-
clickMethod: ['puppeteer'],
|
|
485
|
-
useBinaryFile: [true],
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
},
|
|
489
|
-
// ===== Page Interaction: Run JavaScript =====
|
|
490
|
-
{
|
|
491
|
-
displayName: 'Profile ID',
|
|
492
|
-
name: 'profileId',
|
|
493
|
-
type: 'string',
|
|
494
|
-
required: true,
|
|
495
|
-
default: '',
|
|
496
|
-
description: 'ID of the running profile',
|
|
497
|
-
displayOptions: {
|
|
498
|
-
show: {
|
|
499
|
-
resource: ['pageInteraction'],
|
|
500
|
-
operation: ['runJavaScript'],
|
|
501
|
-
},
|
|
502
|
-
},
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
displayName: 'Tab Index',
|
|
506
|
-
name: 'tabIndex',
|
|
507
|
-
type: 'number',
|
|
508
|
-
default: 0,
|
|
509
|
-
description: 'Index of the tab to run JavaScript on (0 = first tab)',
|
|
510
|
-
displayOptions: {
|
|
511
|
-
show: {
|
|
512
|
-
resource: ['pageInteraction'],
|
|
513
|
-
operation: ['runJavaScript'],
|
|
514
|
-
},
|
|
515
|
-
},
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
displayName: 'JavaScript Code',
|
|
519
|
-
name: 'javascriptCode',
|
|
520
|
-
type: 'string',
|
|
521
|
-
typeOptions: {
|
|
522
|
-
rows: 10,
|
|
523
|
-
},
|
|
524
|
-
required: true,
|
|
525
|
-
default: '',
|
|
526
|
-
description: 'JavaScript code to execute. If code uses Puppeteer API (page.goto, page.click, etc.), it will run in Node.js context with page object available. Otherwise, it runs in browser context.',
|
|
527
|
-
displayOptions: {
|
|
528
|
-
show: {
|
|
529
|
-
resource: ['pageInteraction'],
|
|
530
|
-
operation: ['runJavaScript'],
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
},
|
|
534
|
-
{
|
|
535
|
-
displayName: 'Auto Start Profile',
|
|
536
|
-
name: 'autoStart',
|
|
537
|
-
type: 'boolean',
|
|
538
|
-
default: false,
|
|
539
|
-
description: 'Automatically start the profile if it is not running',
|
|
540
|
-
displayOptions: {
|
|
541
|
-
show: {
|
|
542
|
-
resource: ['pageInteraction'],
|
|
543
|
-
operation: ['runJavaScript'],
|
|
544
|
-
},
|
|
545
|
-
},
|
|
546
|
-
},
|
|
547
|
-
// ===== Page Interaction: Get Network Response =====
|
|
548
|
-
{
|
|
549
|
-
displayName: 'Profile ID',
|
|
550
|
-
name: 'profileId',
|
|
551
|
-
type: 'string',
|
|
552
|
-
required: true,
|
|
553
|
-
default: '',
|
|
554
|
-
description: 'ID of the running profile',
|
|
555
|
-
displayOptions: {
|
|
556
|
-
show: {
|
|
557
|
-
resource: ['pageInteraction'],
|
|
558
|
-
operation: ['getNetworkResponse'],
|
|
559
|
-
},
|
|
560
|
-
},
|
|
561
|
-
},
|
|
562
|
-
{
|
|
563
|
-
displayName: 'Request Name or URL',
|
|
564
|
-
name: 'requestFilter',
|
|
565
|
-
type: 'string',
|
|
566
|
-
required: true,
|
|
567
|
-
default: '',
|
|
568
|
-
description: 'Name of the request (e.g., "create") or URL pattern to match. Can be partial match.',
|
|
569
|
-
displayOptions: {
|
|
570
|
-
show: {
|
|
571
|
-
resource: ['pageInteraction'],
|
|
572
|
-
operation: ['getNetworkResponse'],
|
|
573
|
-
},
|
|
574
|
-
},
|
|
575
|
-
},
|
|
576
|
-
{
|
|
577
|
-
displayName: 'Match Type',
|
|
578
|
-
name: 'matchType',
|
|
579
|
-
type: 'options',
|
|
580
|
-
options: [
|
|
581
|
-
{
|
|
582
|
-
name: 'Contains',
|
|
583
|
-
value: 'contains',
|
|
584
|
-
description: 'Request name or URL contains the filter text',
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
name: 'Exact',
|
|
588
|
-
value: 'exact',
|
|
589
|
-
description: 'Request name or URL exactly matches the filter text',
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
name: 'Starts With',
|
|
593
|
-
value: 'startsWith',
|
|
594
|
-
description: 'Request name or URL starts with the filter text',
|
|
595
|
-
},
|
|
596
|
-
{
|
|
597
|
-
name: 'Ends With',
|
|
598
|
-
value: 'endsWith',
|
|
599
|
-
description: 'Request name or URL ends with the filter text',
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
name: 'Regex',
|
|
603
|
-
value: 'regex',
|
|
604
|
-
description: 'Request name or URL matches the regex pattern',
|
|
605
|
-
},
|
|
606
|
-
],
|
|
607
|
-
default: 'contains',
|
|
608
|
-
description: 'How to match the request',
|
|
609
|
-
displayOptions: {
|
|
610
|
-
show: {
|
|
611
|
-
resource: ['pageInteraction'],
|
|
612
|
-
operation: ['getNetworkResponse'],
|
|
613
|
-
},
|
|
614
|
-
},
|
|
615
|
-
},
|
|
616
|
-
{
|
|
617
|
-
displayName: 'Timeout (Milliseconds)',
|
|
618
|
-
name: 'timeout',
|
|
619
|
-
type: 'number',
|
|
620
|
-
default: 30000,
|
|
621
|
-
description: 'Maximum time to wait for the request to appear (in milliseconds)',
|
|
622
|
-
displayOptions: {
|
|
623
|
-
show: {
|
|
624
|
-
resource: ['pageInteraction'],
|
|
625
|
-
operation: ['getNetworkResponse'],
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
},
|
|
629
|
-
{
|
|
630
|
-
displayName: 'Wait For Request',
|
|
631
|
-
name: 'waitForRequest',
|
|
632
|
-
type: 'boolean',
|
|
633
|
-
default: true,
|
|
634
|
-
description: 'Wait for the request to appear if it has not been made yet',
|
|
635
|
-
displayOptions: {
|
|
636
|
-
show: {
|
|
637
|
-
resource: ['pageInteraction'],
|
|
638
|
-
operation: ['getNetworkResponse'],
|
|
639
|
-
},
|
|
640
|
-
},
|
|
641
|
-
},
|
|
642
|
-
{
|
|
643
|
-
displayName: 'Tab Index',
|
|
644
|
-
name: 'tabIndex',
|
|
645
|
-
type: 'number',
|
|
646
|
-
default: 0,
|
|
647
|
-
description: 'Index of the tab to monitor (0 = first tab)',
|
|
648
|
-
displayOptions: {
|
|
649
|
-
show: {
|
|
650
|
-
resource: ['pageInteraction'],
|
|
651
|
-
operation: ['getNetworkResponse'],
|
|
652
|
-
},
|
|
653
|
-
},
|
|
654
|
-
},
|
|
655
|
-
{
|
|
656
|
-
displayName: 'Auto Start Profile',
|
|
657
|
-
name: 'autoStart',
|
|
658
|
-
type: 'boolean',
|
|
659
|
-
default: false,
|
|
660
|
-
description: 'Automatically start the profile if it is not running',
|
|
661
|
-
displayOptions: {
|
|
662
|
-
show: {
|
|
663
|
-
resource: ['pageInteraction'],
|
|
664
|
-
operation: ['getNetworkResponse'],
|
|
665
|
-
},
|
|
666
|
-
},
|
|
667
|
-
},
|
|
668
|
-
// ===== Page Interaction: Browser HTTP Request =====
|
|
669
|
-
{
|
|
670
|
-
displayName: 'Profile ID',
|
|
671
|
-
name: 'profileId',
|
|
672
|
-
type: 'string',
|
|
673
|
-
required: true,
|
|
674
|
-
default: '',
|
|
675
|
-
description: 'ID of the running profile to use for cookies and headers',
|
|
676
|
-
displayOptions: {
|
|
677
|
-
show: {
|
|
678
|
-
resource: ['pageInteraction'],
|
|
679
|
-
operation: ['browserHttpRequest'],
|
|
680
|
-
},
|
|
681
|
-
},
|
|
682
|
-
},
|
|
683
|
-
{
|
|
684
|
-
displayName: 'Method',
|
|
685
|
-
name: 'method',
|
|
686
|
-
type: 'options',
|
|
687
|
-
options: [
|
|
688
|
-
{
|
|
689
|
-
name: 'GET',
|
|
690
|
-
value: 'GET',
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
name: 'POST',
|
|
694
|
-
value: 'POST',
|
|
695
|
-
},
|
|
696
|
-
],
|
|
697
|
-
default: 'GET',
|
|
698
|
-
description: 'HTTP method to use',
|
|
699
|
-
displayOptions: {
|
|
700
|
-
show: {
|
|
701
|
-
resource: ['pageInteraction'],
|
|
702
|
-
operation: ['browserHttpRequest'],
|
|
703
|
-
},
|
|
704
|
-
},
|
|
705
|
-
},
|
|
706
|
-
{
|
|
707
|
-
displayName: 'URL',
|
|
708
|
-
name: 'url',
|
|
709
|
-
type: 'string',
|
|
710
|
-
required: true,
|
|
711
|
-
default: '',
|
|
712
|
-
description: 'The URL to make the request to',
|
|
713
|
-
displayOptions: {
|
|
714
|
-
show: {
|
|
715
|
-
resource: ['pageInteraction'],
|
|
716
|
-
operation: ['browserHttpRequest'],
|
|
717
|
-
},
|
|
718
|
-
},
|
|
719
|
-
},
|
|
720
|
-
{
|
|
721
|
-
displayName: 'Send Body',
|
|
722
|
-
name: 'sendBody',
|
|
723
|
-
type: 'boolean',
|
|
724
|
-
default: false,
|
|
725
|
-
description: 'Whether to send a body in the request',
|
|
726
|
-
displayOptions: {
|
|
727
|
-
show: {
|
|
728
|
-
resource: ['pageInteraction'],
|
|
729
|
-
operation: ['browserHttpRequest'],
|
|
730
|
-
method: ['POST'],
|
|
731
|
-
},
|
|
732
|
-
},
|
|
733
|
-
},
|
|
734
|
-
{
|
|
735
|
-
displayName: 'Body Content Type',
|
|
736
|
-
name: 'bodyContentType',
|
|
737
|
-
type: 'options',
|
|
738
|
-
options: [
|
|
739
|
-
{
|
|
740
|
-
name: 'JSON',
|
|
741
|
-
value: 'json',
|
|
742
|
-
},
|
|
743
|
-
{
|
|
744
|
-
name: 'Raw',
|
|
745
|
-
value: 'raw',
|
|
746
|
-
},
|
|
747
|
-
{
|
|
748
|
-
name: 'Form Data',
|
|
749
|
-
value: 'formData',
|
|
750
|
-
},
|
|
751
|
-
{
|
|
752
|
-
name: 'n8n Binary File',
|
|
753
|
-
value: 'binary',
|
|
754
|
-
},
|
|
755
|
-
],
|
|
756
|
-
default: 'json',
|
|
757
|
-
description: 'Content type of the body',
|
|
758
|
-
displayOptions: {
|
|
759
|
-
show: {
|
|
760
|
-
resource: ['pageInteraction'],
|
|
761
|
-
operation: ['browserHttpRequest'],
|
|
762
|
-
method: ['POST'],
|
|
763
|
-
sendBody: [true],
|
|
764
|
-
},
|
|
765
|
-
},
|
|
766
|
-
},
|
|
767
|
-
{
|
|
768
|
-
displayName: 'JSON Body',
|
|
769
|
-
name: 'jsonBody',
|
|
770
|
-
type: 'string',
|
|
771
|
-
typeOptions: {
|
|
772
|
-
rows: 4,
|
|
773
|
-
},
|
|
774
|
-
default: '',
|
|
775
|
-
description: 'JSON body to send',
|
|
776
|
-
displayOptions: {
|
|
777
|
-
show: {
|
|
778
|
-
resource: ['pageInteraction'],
|
|
779
|
-
operation: ['browserHttpRequest'],
|
|
780
|
-
method: ['POST'],
|
|
781
|
-
sendBody: [true],
|
|
782
|
-
bodyContentType: ['json'],
|
|
783
|
-
},
|
|
784
|
-
},
|
|
785
|
-
},
|
|
786
|
-
{
|
|
787
|
-
displayName: 'Raw Body',
|
|
788
|
-
name: 'rawBody',
|
|
789
|
-
type: 'string',
|
|
790
|
-
typeOptions: {
|
|
791
|
-
rows: 4,
|
|
792
|
-
},
|
|
793
|
-
default: '',
|
|
794
|
-
description: 'Raw body to send',
|
|
795
|
-
displayOptions: {
|
|
796
|
-
show: {
|
|
797
|
-
resource: ['pageInteraction'],
|
|
798
|
-
operation: ['browserHttpRequest'],
|
|
799
|
-
method: ['POST'],
|
|
800
|
-
sendBody: [true],
|
|
801
|
-
bodyContentType: ['raw'],
|
|
802
|
-
},
|
|
803
|
-
},
|
|
804
|
-
},
|
|
805
|
-
{
|
|
806
|
-
displayName: 'Input Data Field Name',
|
|
807
|
-
name: 'binaryPropertyName',
|
|
808
|
-
type: 'string',
|
|
809
|
-
default: 'data',
|
|
810
|
-
description: 'The name of the binary property which contains the data for the file to be uploaded',
|
|
811
|
-
displayOptions: {
|
|
812
|
-
show: {
|
|
813
|
-
resource: ['pageInteraction'],
|
|
814
|
-
operation: ['browserHttpRequest'],
|
|
815
|
-
method: ['POST'],
|
|
816
|
-
sendBody: [true],
|
|
817
|
-
bodyContentType: ['binary'],
|
|
818
|
-
},
|
|
819
|
-
},
|
|
820
|
-
},
|
|
821
|
-
{
|
|
822
|
-
displayName: 'Form Data',
|
|
823
|
-
name: 'formData',
|
|
824
|
-
type: 'fixedCollection',
|
|
825
|
-
typeOptions: {
|
|
826
|
-
multipleValues: true,
|
|
827
|
-
},
|
|
828
|
-
default: {},
|
|
829
|
-
description: 'Form data to send',
|
|
830
|
-
displayOptions: {
|
|
831
|
-
show: {
|
|
832
|
-
resource: ['pageInteraction'],
|
|
833
|
-
operation: ['browserHttpRequest'],
|
|
834
|
-
method: ['POST'],
|
|
835
|
-
sendBody: [true],
|
|
836
|
-
bodyContentType: ['formData'],
|
|
837
|
-
},
|
|
838
|
-
},
|
|
839
|
-
options: [
|
|
840
|
-
{
|
|
841
|
-
displayName: 'Parameter',
|
|
842
|
-
name: 'parameter',
|
|
843
|
-
values: [
|
|
844
|
-
{
|
|
845
|
-
displayName: 'Parameter Type',
|
|
846
|
-
name: 'parameterType',
|
|
847
|
-
type: 'options',
|
|
848
|
-
options: [
|
|
849
|
-
{
|
|
850
|
-
name: 'Form Data',
|
|
851
|
-
value: 'formData',
|
|
852
|
-
},
|
|
853
|
-
{
|
|
854
|
-
name: 'n8n Binary File',
|
|
855
|
-
value: 'binary',
|
|
856
|
-
},
|
|
857
|
-
],
|
|
858
|
-
default: 'formData',
|
|
859
|
-
description: 'Type of parameter',
|
|
860
|
-
},
|
|
861
|
-
{
|
|
862
|
-
displayName: 'Name',
|
|
863
|
-
name: 'name',
|
|
864
|
-
type: 'string',
|
|
865
|
-
default: '',
|
|
866
|
-
displayOptions: {
|
|
867
|
-
show: {
|
|
868
|
-
parameterType: ['formData', 'binary'],
|
|
869
|
-
},
|
|
870
|
-
},
|
|
871
|
-
},
|
|
872
|
-
{
|
|
873
|
-
displayName: 'Value',
|
|
874
|
-
name: 'value',
|
|
875
|
-
type: 'string',
|
|
876
|
-
default: '',
|
|
877
|
-
displayOptions: {
|
|
878
|
-
show: {
|
|
879
|
-
parameterType: ['formData'],
|
|
880
|
-
},
|
|
881
|
-
},
|
|
882
|
-
},
|
|
883
|
-
{
|
|
884
|
-
displayName: 'Input Data Field Name',
|
|
885
|
-
name: 'binaryPropertyName',
|
|
886
|
-
type: 'string',
|
|
887
|
-
default: 'data',
|
|
888
|
-
description: 'The name of the binary property which contains the data for the file to be uploaded',
|
|
889
|
-
displayOptions: {
|
|
890
|
-
show: {
|
|
891
|
-
parameterType: ['binary'],
|
|
892
|
-
},
|
|
893
|
-
},
|
|
894
|
-
},
|
|
895
|
-
],
|
|
896
|
-
},
|
|
897
|
-
],
|
|
898
|
-
},
|
|
899
|
-
{
|
|
900
|
-
displayName: 'Query Parameters',
|
|
901
|
-
name: 'queryParameters',
|
|
902
|
-
type: 'fixedCollection',
|
|
903
|
-
typeOptions: {
|
|
904
|
-
multipleValues: true,
|
|
905
|
-
},
|
|
906
|
-
default: {},
|
|
907
|
-
description: 'Query parameters to send',
|
|
908
|
-
displayOptions: {
|
|
909
|
-
show: {
|
|
910
|
-
resource: ['pageInteraction'],
|
|
911
|
-
operation: ['browserHttpRequest'],
|
|
912
|
-
},
|
|
913
|
-
},
|
|
914
|
-
options: [
|
|
915
|
-
{
|
|
916
|
-
displayName: 'Parameter',
|
|
917
|
-
name: 'parameter',
|
|
918
|
-
values: [
|
|
919
|
-
{
|
|
920
|
-
displayName: 'Name',
|
|
921
|
-
name: 'name',
|
|
922
|
-
type: 'string',
|
|
923
|
-
default: '',
|
|
924
|
-
},
|
|
925
|
-
{
|
|
926
|
-
displayName: 'Value',
|
|
927
|
-
name: 'value',
|
|
928
|
-
type: 'string',
|
|
929
|
-
default: '',
|
|
930
|
-
},
|
|
931
|
-
],
|
|
932
|
-
},
|
|
933
|
-
],
|
|
934
|
-
},
|
|
935
|
-
{
|
|
936
|
-
displayName: 'Additional Headers',
|
|
937
|
-
name: 'additionalHeaders',
|
|
938
|
-
type: 'fixedCollection',
|
|
939
|
-
typeOptions: {
|
|
940
|
-
multipleValues: true,
|
|
941
|
-
},
|
|
942
|
-
default: {},
|
|
943
|
-
description: 'Additional headers to send (will be merged with browser headers)',
|
|
944
|
-
displayOptions: {
|
|
945
|
-
show: {
|
|
946
|
-
resource: ['pageInteraction'],
|
|
947
|
-
operation: ['browserHttpRequest'],
|
|
948
|
-
},
|
|
949
|
-
},
|
|
950
|
-
options: [
|
|
951
|
-
{
|
|
952
|
-
displayName: 'Header',
|
|
953
|
-
name: 'header',
|
|
954
|
-
values: [
|
|
955
|
-
{
|
|
956
|
-
displayName: 'Name',
|
|
957
|
-
name: 'name',
|
|
958
|
-
type: 'string',
|
|
959
|
-
default: '',
|
|
960
|
-
},
|
|
961
|
-
{
|
|
962
|
-
displayName: 'Value',
|
|
963
|
-
name: 'value',
|
|
964
|
-
type: 'string',
|
|
965
|
-
default: '',
|
|
966
|
-
},
|
|
967
|
-
],
|
|
968
|
-
},
|
|
969
|
-
],
|
|
970
|
-
},
|
|
971
|
-
{
|
|
972
|
-
displayName: 'Tab Index',
|
|
973
|
-
name: 'tabIndex',
|
|
974
|
-
type: 'number',
|
|
975
|
-
default: 0,
|
|
976
|
-
description: 'Index of the tab to get cookies and headers from (0 = first tab)',
|
|
977
|
-
displayOptions: {
|
|
978
|
-
show: {
|
|
979
|
-
resource: ['pageInteraction'],
|
|
980
|
-
operation: ['browserHttpRequest'],
|
|
981
|
-
},
|
|
982
|
-
},
|
|
983
|
-
},
|
|
984
|
-
{
|
|
985
|
-
displayName: 'Auto Start Profile',
|
|
986
|
-
name: 'autoStart',
|
|
987
|
-
type: 'boolean',
|
|
988
|
-
default: false,
|
|
989
|
-
description: 'Automatically start the profile if it is not running',
|
|
990
113
|
displayOptions: {
|
|
991
114
|
show: {
|
|
992
115
|
resource: ['pageInteraction'],
|
|
993
|
-
operation: ['browserHttpRequest'],
|
|
994
116
|
},
|
|
995
117
|
},
|
|
996
118
|
},
|
|
119
|
+
// Profile Management Fields
|
|
120
|
+
...updateDisplayOptions(CreateProfile_description_1.createProfileFields, 'profileManagement', 'createProfile'),
|
|
121
|
+
...updateDisplayOptions(DeleteProfile_description_1.deleteProfileFields, 'profileManagement', 'deleteProfile'),
|
|
122
|
+
...updateDisplayOptions(StartProfile_description_1.startProfileFields, 'profileManagement', 'startProfile'),
|
|
123
|
+
...updateDisplayOptions(StopProfile_description_1.stopProfileFields, 'profileManagement', 'stopProfile'),
|
|
124
|
+
// Page Interaction Fields
|
|
125
|
+
...updateDisplayOptions(MoveAndClick_description_1.moveAndClickFields, 'pageInteraction', 'moveAndClick'),
|
|
126
|
+
...updateDisplayOptions(RunJavaScript_description_1.runJavaScriptFields, 'pageInteraction', 'runJavaScript'),
|
|
127
|
+
...updateDisplayOptions(GetNetworkResponse_description_1.getNetworkResponseFields, 'pageInteraction', 'getNetworkResponse'),
|
|
128
|
+
...updateDisplayOptions(BrowserHttpRequest_description_1.browserHttpRequestFields, 'pageInteraction', 'browserHttpRequest'),
|
|
997
129
|
];
|
|
@@ -30,6 +30,7 @@ exports.NvkBrowser = void 0;
|
|
|
30
30
|
const BrowserManager_1 = require("../../utils/BrowserManager");
|
|
31
31
|
const ProfileManager_1 = require("../../utils/ProfileManager");
|
|
32
32
|
const ExtensionHandler_1 = require("../../utils/ExtensionHandler");
|
|
33
|
+
const ProxyHandler_1 = require("../../utils/ProxyHandler");
|
|
33
34
|
const NvkBrowser_description_1 = require("./NvkBrowser.description");
|
|
34
35
|
const path = __importStar(require("path"));
|
|
35
36
|
const fs = __importStar(require("fs"));
|
|
@@ -85,6 +86,9 @@ class NvkBrowser {
|
|
|
85
86
|
case 'stopProfile':
|
|
86
87
|
await executeStopProfile.call(this, i, browserManager, returnData);
|
|
87
88
|
break;
|
|
89
|
+
case 'updateProfile':
|
|
90
|
+
await executeUpdateProfile.call(this, i, profileManager, returnData);
|
|
91
|
+
break;
|
|
88
92
|
default:
|
|
89
93
|
throw new Error(`Unknown operation: ${operation}`);
|
|
90
94
|
}
|
|
@@ -412,6 +416,7 @@ async function executeStartProfile(i, browserManager, returnData) {
|
|
|
412
416
|
const winPosition = this.getNodeParameter('winPosition', i);
|
|
413
417
|
const winSize = this.getNodeParameter('winSize', i);
|
|
414
418
|
const headless = this.getNodeParameter('headless', i);
|
|
419
|
+
const initialUrl = this.getNodeParameter('initialUrl', i);
|
|
415
420
|
const windowConfig = {};
|
|
416
421
|
if (winScale !== undefined) {
|
|
417
422
|
windowConfig.scale = winScale;
|
|
@@ -432,12 +437,27 @@ async function executeStartProfile(i, browserManager, returnData) {
|
|
|
432
437
|
windowConfig.headless = headless;
|
|
433
438
|
}
|
|
434
439
|
const instance = await browserManager.startProfile(profileId, windowConfig);
|
|
440
|
+
// Navigate to URL nếu có
|
|
441
|
+
if (initialUrl && initialUrl.trim() !== '') {
|
|
442
|
+
try {
|
|
443
|
+
const page = await browserManager.getPage(profileId, 0);
|
|
444
|
+
if (page) {
|
|
445
|
+
await page.goto(initialUrl.trim(), { waitUntil: 'networkidle2' });
|
|
446
|
+
console.log(`[NvkBrowser] Navigated to ${initialUrl}`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
catch (navError) {
|
|
450
|
+
console.error(`[NvkBrowser] Error navigating to ${initialUrl}:`, navError);
|
|
451
|
+
// Không throw error, chỉ log vì profile đã start thành công
|
|
452
|
+
}
|
|
453
|
+
}
|
|
435
454
|
returnData.push({
|
|
436
455
|
json: {
|
|
437
456
|
success: true,
|
|
438
457
|
profileId: instance.profileId,
|
|
439
458
|
debugPort: instance.debugPort,
|
|
440
459
|
message: 'Profile started successfully',
|
|
460
|
+
initialUrl: initialUrl && initialUrl.trim() !== '' ? initialUrl.trim() : undefined,
|
|
441
461
|
},
|
|
442
462
|
});
|
|
443
463
|
}
|
|
@@ -452,6 +472,130 @@ async function executeStopProfile(i, browserManager, returnData) {
|
|
|
452
472
|
},
|
|
453
473
|
});
|
|
454
474
|
}
|
|
475
|
+
async function executeUpdateProfile(i, profileManager, returnData) {
|
|
476
|
+
const profileId = this.getNodeParameter('profileId', i);
|
|
477
|
+
// Kiểm tra profile có tồn tại không
|
|
478
|
+
const existingProfile = profileManager.getProfile(profileId);
|
|
479
|
+
if (!existingProfile) {
|
|
480
|
+
throw new Error(`Profile with ID ${profileId} not found`);
|
|
481
|
+
}
|
|
482
|
+
// Lấy các giá trị cần cập nhật (chỉ lấy nếu có giá trị)
|
|
483
|
+
const updates = {};
|
|
484
|
+
const profileName = this.getNodeParameter('profileName', i);
|
|
485
|
+
if (profileName !== undefined && profileName !== '') {
|
|
486
|
+
updates.name = profileName;
|
|
487
|
+
}
|
|
488
|
+
const proxy = this.getNodeParameter('proxy', i);
|
|
489
|
+
if (proxy !== undefined && proxy !== '') {
|
|
490
|
+
updates.proxy = proxy;
|
|
491
|
+
}
|
|
492
|
+
else if (proxy === '') {
|
|
493
|
+
// Cho phép xóa proxy bằng cách truyền chuỗi rỗng
|
|
494
|
+
updates.proxy = undefined;
|
|
495
|
+
}
|
|
496
|
+
const note = this.getNodeParameter('note', i);
|
|
497
|
+
if (note !== undefined && note !== '') {
|
|
498
|
+
updates.note = note;
|
|
499
|
+
}
|
|
500
|
+
else if (note === '') {
|
|
501
|
+
// Cho phép xóa note bằng cách truyền chuỗi rỗng
|
|
502
|
+
updates.note = undefined;
|
|
503
|
+
}
|
|
504
|
+
const extensionsInput = this.getNodeParameter('extensions', i);
|
|
505
|
+
if (extensionsInput !== undefined && extensionsInput !== '') {
|
|
506
|
+
updates.extensions = ExtensionHandler_1.ExtensionHandler.parseExtensions(extensionsInput);
|
|
507
|
+
}
|
|
508
|
+
// Cập nhật profile
|
|
509
|
+
const updatedProfile = profileManager.updateProfile(profileId, updates);
|
|
510
|
+
if (!updatedProfile) {
|
|
511
|
+
throw new Error(`Failed to update profile ${profileId}`);
|
|
512
|
+
}
|
|
513
|
+
// Xử lý proxy authentication nếu có proxy mới
|
|
514
|
+
if (updates.proxy !== undefined && updates.proxy) {
|
|
515
|
+
console.log(`[NvkBrowser] Processing proxy: ${updates.proxy}`);
|
|
516
|
+
const proxyConfig = ProxyHandler_1.ProxyHandler.parseProxyString(updates.proxy);
|
|
517
|
+
if (proxyConfig) {
|
|
518
|
+
console.log(`[NvkBrowser] Parsed proxy config successfully:`, {
|
|
519
|
+
type: proxyConfig.type,
|
|
520
|
+
host: proxyConfig.host,
|
|
521
|
+
port: proxyConfig.port,
|
|
522
|
+
username: proxyConfig.username || 'N/A',
|
|
523
|
+
password: proxyConfig.password ? '***' : 'N/A',
|
|
524
|
+
});
|
|
525
|
+
const profilePath = profileManager.getProfilePath(profileId);
|
|
526
|
+
console.log(`[NvkBrowser] Profile path: ${profilePath}`);
|
|
527
|
+
console.log(`[NvkBrowser] Calling saveProxyAuthToProfile...`);
|
|
528
|
+
try {
|
|
529
|
+
ProxyHandler_1.ProxyHandler.saveProxyAuthToProfile(profilePath, proxyConfig);
|
|
530
|
+
console.log(`[NvkBrowser] saveProxyAuthToProfile completed successfully`);
|
|
531
|
+
}
|
|
532
|
+
catch (saveError) {
|
|
533
|
+
console.error(`[NvkBrowser] ERROR in saveProxyAuthToProfile:`, saveError);
|
|
534
|
+
throw new Error(`Failed to save proxy authentication: ${saveError instanceof Error ? saveError.message : String(saveError)}`);
|
|
535
|
+
}
|
|
536
|
+
// Validation: Đọc lại file Preferences để verify
|
|
537
|
+
const prefsPath = path.join(profilePath, 'Default', 'Preferences');
|
|
538
|
+
if (fs.existsSync(prefsPath)) {
|
|
539
|
+
try {
|
|
540
|
+
const verifyContent = fs.readFileSync(prefsPath, 'utf-8');
|
|
541
|
+
const verifyPrefs = JSON.parse(verifyContent);
|
|
542
|
+
// Verify proxy_config
|
|
543
|
+
if (!verifyPrefs.proxy_config || !verifyPrefs.proxy_config.server) {
|
|
544
|
+
console.error(`[NvkBrowser] VALIDATION FAILED: proxy_config not found in Preferences`);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
console.log(`[NvkBrowser] ✓ Validation passed: proxy_config.server = ${verifyPrefs.proxy_config.server}`);
|
|
548
|
+
}
|
|
549
|
+
// Verify gologin.proxy
|
|
550
|
+
if (!verifyPrefs.gologin || !verifyPrefs.gologin.proxy) {
|
|
551
|
+
console.error(`[NvkBrowser] VALIDATION FAILED: gologin.proxy not found in Preferences`);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
const hasUsername = !!verifyPrefs.gologin.proxy.username;
|
|
555
|
+
const hasPassword = !!verifyPrefs.gologin.proxy.password;
|
|
556
|
+
if (proxyConfig.username && !hasUsername) {
|
|
557
|
+
console.error(`[NvkBrowser] VALIDATION FAILED: username not saved in gologin.proxy`);
|
|
558
|
+
}
|
|
559
|
+
if (proxyConfig.password && !hasPassword) {
|
|
560
|
+
console.error(`[NvkBrowser] VALIDATION FAILED: password not saved in gologin.proxy`);
|
|
561
|
+
}
|
|
562
|
+
if ((!proxyConfig.username || hasUsername) && (!proxyConfig.password || hasPassword)) {
|
|
563
|
+
console.log(`[NvkBrowser] ✓ Validation passed: gologin.proxy has required fields`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
catch (verifyError) {
|
|
568
|
+
console.error(`[NvkBrowser] VALIDATION ERROR: Failed to verify Preferences file: ${verifyError instanceof Error ? verifyError.message : String(verifyError)}`);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
console.error(`[NvkBrowser] VALIDATION FAILED: Preferences file does not exist at ${prefsPath}`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
console.error(`[NvkBrowser] ERROR: Failed to parse proxy string: ${updates.proxy}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else if (updates.proxy === undefined && existingProfile.proxy) {
|
|
580
|
+
// Nếu proxy bị xóa (undefined), cần xử lý xóa proxy config
|
|
581
|
+
console.log(`[NvkBrowser] Proxy removed, cleaning up proxy configuration`);
|
|
582
|
+
// Có thể cần thêm logic để xóa proxy config khỏi Preferences nếu cần
|
|
583
|
+
}
|
|
584
|
+
returnData.push({
|
|
585
|
+
json: {
|
|
586
|
+
success: true,
|
|
587
|
+
profile: {
|
|
588
|
+
id: updatedProfile.id,
|
|
589
|
+
name: updatedProfile.name,
|
|
590
|
+
proxy: updatedProfile.proxy,
|
|
591
|
+
note: updatedProfile.note,
|
|
592
|
+
extensions: updatedProfile.extensions,
|
|
593
|
+
createdAt: updatedProfile.createdAt,
|
|
594
|
+
updatedAt: updatedProfile.updatedAt,
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
});
|
|
598
|
+
}
|
|
455
599
|
async function executeMoveAndClick(i, browserManager, returnData) {
|
|
456
600
|
const profileId = this.getNodeParameter('profileId', i);
|
|
457
601
|
const selector = this.getNodeParameter('selector', i);
|
|
@@ -988,10 +1132,11 @@ async function executeMoveAndClick(i, browserManager, returnData) {
|
|
|
988
1132
|
if (waitForClick > 0) {
|
|
989
1133
|
await page.waitForTimeout(waitForClick);
|
|
990
1134
|
}
|
|
991
|
-
|
|
1135
|
+
const clickOptions = {
|
|
992
1136
|
button: button,
|
|
993
1137
|
clickCount: clickCount,
|
|
994
|
-
}
|
|
1138
|
+
};
|
|
1139
|
+
await page.click(selectorTrimmed, clickOptions);
|
|
995
1140
|
}
|
|
996
1141
|
}
|
|
997
1142
|
}
|
|
@@ -1011,12 +1156,12 @@ async function executeMoveAndClick(i, browserManager, returnData) {
|
|
|
1011
1156
|
action: actionType || 'click',
|
|
1012
1157
|
};
|
|
1013
1158
|
if (executedActionsInfo && executedActionsInfo.length > 0) {
|
|
1014
|
-
const allSuccess = executedActionsInfo.every(a => a.success);
|
|
1159
|
+
const allSuccess = executedActionsInfo.every((a) => a.success);
|
|
1015
1160
|
returnJson.success = allSuccess;
|
|
1016
1161
|
returnJson.message = `Executed ${executedActionsInfo.length} action(s)`;
|
|
1017
1162
|
returnJson.actions = executedActionsInfo;
|
|
1018
1163
|
returnJson.totalActions = executedActionsInfo.length;
|
|
1019
|
-
returnJson.successfulActions = executedActionsInfo.filter(a => a.success).length;
|
|
1164
|
+
returnJson.successfulActions = executedActionsInfo.filter((a) => a.success).length;
|
|
1020
1165
|
}
|
|
1021
1166
|
else {
|
|
1022
1167
|
returnJson.message = actionType === 'fill' ? 'Fill performed successfully' : 'Click performed successfully';
|
|
@@ -1241,7 +1386,7 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
1241
1386
|
throw new Error(`Could not get page for profile ${profileId}`);
|
|
1242
1387
|
}
|
|
1243
1388
|
const cookies = await page.cookies();
|
|
1244
|
-
const cookieString = cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ');
|
|
1389
|
+
const cookieString = cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');
|
|
1245
1390
|
const userAgent = await page.evaluate(() => navigator.userAgent);
|
|
1246
1391
|
const browserHeaders = {
|
|
1247
1392
|
'User-Agent': userAgent,
|
|
@@ -1327,7 +1472,7 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
|
|
|
1327
1472
|
else if (bodyContentType === 'formData') {
|
|
1328
1473
|
const formDataParam = this.getNodeParameter('formData', i);
|
|
1329
1474
|
if (formDataParam?.parameter) {
|
|
1330
|
-
const hasBinary = formDataParam.parameter.some(p => p.parameterType === 'binary');
|
|
1475
|
+
const hasBinary = formDataParam.parameter.some((p) => p.parameterType === 'binary');
|
|
1331
1476
|
if (hasBinary) {
|
|
1332
1477
|
// Handle FormData with binary files
|
|
1333
1478
|
const formDataItems = [];
|
package/package.json
CHANGED