n8n-nodes-upload-post 0.1.8 → 0.1.11

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,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UploadPost = void 0;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
4
  class UploadPost {
6
5
  constructor() {
7
6
  this.description = {
@@ -23,12 +22,6 @@ class UploadPost {
23
22
  required: true,
24
23
  },
25
24
  ],
26
- requestDefaults: {
27
- baseURL: 'https://api.upload-post.com/api',
28
- headers: {
29
- 'Accept': 'application/json',
30
- },
31
- },
32
25
  properties: [
33
26
  {
34
27
  displayName: 'Operation',
@@ -40,37 +33,19 @@ class UploadPost {
40
33
  name: 'Upload Photo(s)',
41
34
  value: 'uploadPhotos',
42
35
  action: 'Upload photos',
43
- description: 'Upload one or more photos',
44
- routing: {
45
- request: {
46
- method: 'POST',
47
- url: '/upload_photos',
48
- },
49
- },
36
+ description: 'Upload one or more photos (Supports: TikTok, Instagram, LinkedIn, Facebook, X, Threads)',
50
37
  },
51
38
  {
52
39
  name: 'Upload Video',
53
40
  value: 'uploadVideo',
54
41
  action: 'Upload a video',
55
- description: 'Upload a single video',
56
- routing: {
57
- request: {
58
- method: 'POST',
59
- url: '/upload',
60
- },
61
- },
42
+ description: 'Upload a single video (Supports: TikTok, Instagram, LinkedIn, YouTube, Facebook, X, Threads)',
62
43
  },
63
44
  {
64
45
  name: 'Upload Text',
65
46
  value: 'uploadText',
66
47
  action: 'Upload a text post',
67
- description: 'Upload a text-based post',
68
- routing: {
69
- request: {
70
- method: 'POST',
71
- url: '/upload_text',
72
- },
73
- },
48
+ description: 'Upload a text-based post (Supports: X, LinkedIn, Facebook, Threads)',
74
49
  },
75
50
  ],
76
51
  default: 'uploadPhotos',
@@ -81,13 +56,7 @@ class UploadPost {
81
56
  type: 'string',
82
57
  required: true,
83
58
  default: '',
84
- description: 'User identifier for Upload-Post',
85
- routing: {
86
- send: {
87
- type: 'body',
88
- property: 'user',
89
- }
90
- }
59
+ description: 'The Profile Name you created in your upload-post.com account. You can find it in the \'Manage Users\' section (e.g., app.upload-post.com/manage-users).',
91
60
  },
92
61
  {
93
62
  displayName: 'Platform(s)',
@@ -104,27 +73,15 @@ class UploadPost {
104
73
  { name: 'YouTube', value: 'youtube' },
105
74
  ],
106
75
  default: [],
107
- description: 'Platform(s) to upload to',
108
- routing: {
109
- send: {
110
- type: 'body',
111
- property: 'platform[]',
112
- }
113
- }
76
+ description: 'Platform(s) to upload to. Supported platforms vary by operation.',
114
77
  },
115
78
  {
116
- displayName: 'Title',
79
+ displayName: 'Title / Main Content',
117
80
  name: 'title',
118
81
  type: 'string',
119
82
  required: true,
120
83
  default: '',
121
- description: 'Title of the post/video/text',
122
- routing: {
123
- send: {
124
- type: 'body',
125
- property: 'title',
126
- }
127
- }
84
+ description: 'Title of the post. For Upload Text, this is the main text content. For some video platforms, this acts as a fallback for description if a specific description is not provided.',
128
85
  },
129
86
  {
130
87
  displayName: 'Photos (Files or URLs)',
@@ -132,41 +89,24 @@ class UploadPost {
132
89
  type: 'string',
133
90
  required: true,
134
91
  default: '',
135
- description: 'Array of photo files or photo URLs. For files, use binary property names like {{$binary.dataPropertyName}}. For URLs, provide direct HTTPS URLs as strings. Multiple items can be added via "Add Field".',
92
+ description: 'Provide photo files or URLs as a comma-separated list (e.g., data,https://example.com/image.jpg,otherImage). For files, enter the binary property name (e.g., data, myImage). For URLs, provide direct HTTP/HTTPS URLs.',
136
93
  displayOptions: {
137
94
  show: {
138
95
  operation: ['uploadPhotos'],
139
96
  },
140
97
  },
141
- typeOptions: {
142
- multiple: true,
143
- multipleValueButtonText: 'Add Photo',
144
- },
145
- routing: {
146
- send: {
147
- type: 'body',
148
- property: 'photos[]',
149
- value: '={{ $value.startsWith("http") ? $value : { "data": $value, "isBinary": true } }}',
150
- }
151
- }
152
98
  },
153
99
  {
154
- displayName: 'Caption',
100
+ displayName: 'Caption (Photo/Video Commentary)',
155
101
  name: 'caption',
156
102
  type: 'string',
157
103
  default: '',
158
- description: 'Caption/description for the photos (post commentary)',
104
+ description: 'General caption/commentary for Photo or Video posts. For some video platforms, a specific \'Description\' field might be used instead (see platform-specific options). Not used for Upload Text.',
159
105
  displayOptions: {
160
106
  show: {
161
- operation: ['uploadPhotos'],
107
+ operation: ['uploadPhotos', 'uploadVideo'],
162
108
  },
163
109
  },
164
- routing: {
165
- send: {
166
- type: 'body',
167
- property: 'caption',
168
- }
169
- }
170
110
  },
171
111
  {
172
112
  displayName: 'Video (File or URL)',
@@ -174,19 +114,12 @@ class UploadPost {
174
114
  type: 'string',
175
115
  required: true,
176
116
  default: '',
177
- description: 'The video file to upload or a video URL. For files, use binary property name like {{$binary.dataPropertyName}}.',
117
+ description: 'The video file to upload or a video URL. For files, enter the binary property name (e.g., data).',
178
118
  displayOptions: {
179
119
  show: {
180
120
  operation: ['uploadVideo'],
181
121
  },
182
122
  },
183
- routing: {
184
- send: {
185
- type: 'body',
186
- property: 'video',
187
- value: '={{ $value.startsWith("http") ? $value : { "data": $value, "isBinary": true } }}',
188
- }
189
- }
190
123
  },
191
124
  {
192
125
  displayName: 'LinkedIn Visibility',
@@ -194,62 +127,44 @@ class UploadPost {
194
127
  type: 'options',
195
128
  options: [
196
129
  { name: 'Public', value: 'PUBLIC' },
197
- { name: 'Connections', value: 'CONNECTIONS', displayOptions: { show: { operation: ['uploadVideo'] } } },
130
+ { name: 'Connections', value: 'CONNECTIONS' },
198
131
  { name: 'Logged In', value: 'LOGGED_IN', displayOptions: { show: { operation: ['uploadVideo'] } } },
199
132
  { name: 'Container', value: 'CONTAINER', displayOptions: { show: { operation: ['uploadVideo'] } } },
200
133
  ],
201
134
  default: 'PUBLIC',
202
- description: 'Visibility setting for the LinkedIn post',
135
+ description: 'Visibility for LinkedIn. For Photos, only PUBLIC is supported by API. For Video, CONNECTIONS, PUBLIC, LOGGED_IN, CONTAINER. Not used for Upload Text.',
203
136
  displayOptions: {
204
137
  show: {
205
- operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
138
+ operation: ['uploadPhotos', 'uploadVideo'],
206
139
  platform: ['linkedin']
207
140
  },
208
141
  },
209
- routing: {
210
- send: {
211
- type: 'body',
212
- property: 'visibility',
213
- }
214
- }
215
142
  },
216
143
  {
217
144
  displayName: 'Target LinkedIn Page ID',
218
145
  name: 'targetLinkedinPageId',
219
146
  type: 'string',
220
147
  default: '',
221
- description: 'LinkedIn page ID to upload to an organization (optional)',
148
+ description: 'LinkedIn page ID to upload to an organization (optional). Used for Photos, Video, and Text operations.',
222
149
  displayOptions: {
223
150
  show: {
224
151
  operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
225
152
  platform: ['linkedin']
226
153
  },
227
154
  },
228
- routing: {
229
- send: {
230
- type: 'body',
231
- property: 'target_linkedin_page_id',
232
- }
233
- }
234
155
  },
235
156
  {
236
- displayName: 'LinkedIn Description',
157
+ displayName: 'LinkedIn Video Description',
237
158
  name: 'linkedinDescription',
238
159
  type: 'string',
239
160
  default: '',
240
- description: 'The user generated commentary for the post (LinkedIn Video/Text). If not provided, title is used for video.',
161
+ description: 'User commentary for LinkedIn Video. If not provided, Title is used. Not for Photos/Text.',
241
162
  displayOptions: {
242
163
  show: {
243
- operation: ['uploadVideo', 'uploadText'],
164
+ operation: ['uploadVideo'],
244
165
  platform: ['linkedin']
245
166
  },
246
167
  },
247
- routing: {
248
- send: {
249
- type: 'body',
250
- property: 'description',
251
- }
252
- }
253
168
  },
254
169
  {
255
170
  displayName: 'Facebook Page ID',
@@ -257,38 +172,26 @@ class UploadPost {
257
172
  type: 'string',
258
173
  required: true,
259
174
  default: '',
260
- description: 'Facebook Page ID where the content will be posted',
175
+ description: 'Facebook Page ID. Required for Photos, Video, and Text operations.',
261
176
  displayOptions: {
262
177
  show: {
263
178
  operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
264
179
  platform: ['facebook']
265
180
  },
266
181
  },
267
- routing: {
268
- send: {
269
- type: 'body',
270
- property: 'facebook_page_id',
271
- }
272
- }
273
182
  },
274
183
  {
275
184
  displayName: 'Facebook Video Description',
276
185
  name: 'facebookVideoDescription',
277
186
  type: 'string',
278
187
  default: '',
279
- description: 'Description of the video for Facebook. If not provided, title is used.',
188
+ description: 'Description for Facebook Video. If not provided, Title is used. Not for Photos/Text.',
280
189
  displayOptions: {
281
190
  show: {
282
191
  operation: ['uploadVideo'],
283
192
  platform: ['facebook']
284
193
  },
285
194
  },
286
- routing: {
287
- send: {
288
- type: 'body',
289
- property: 'description',
290
- }
291
- }
292
195
  },
293
196
  {
294
197
  displayName: 'Facebook Video State',
@@ -300,95 +203,65 @@ class UploadPost {
300
203
  { name: 'Scheduled', value: 'SCHEDULED' },
301
204
  ],
302
205
  default: 'PUBLISHED',
303
- description: 'Desired state of the video on Facebook',
206
+ description: 'State for Facebook Video (DRAFT, PUBLISHED, SCHEDULED). Not for Photos/Text.',
304
207
  displayOptions: {
305
208
  show: {
306
209
  operation: ['uploadVideo'],
307
210
  platform: ['facebook']
308
211
  },
309
212
  },
310
- routing: {
311
- send: {
312
- type: 'body',
313
- property: 'video_state',
314
- }
315
- }
316
213
  },
317
214
  {
318
- displayName: 'TikTok Auto Add Music',
215
+ displayName: 'TikTok Auto Add Music (Photo)',
319
216
  name: 'tiktokAutoAddMusic',
320
217
  type: 'boolean',
321
218
  default: false,
322
- description: 'Whether to automatically add background music to photos on TikTok',
219
+ description: 'Whether to auto add music to TikTok photos. Only for Upload Photos.',
323
220
  displayOptions: {
324
221
  show: {
325
222
  operation: ['uploadPhotos'],
326
223
  platform: ['tiktok']
327
224
  },
328
225
  },
329
- routing: {
330
- send: {
331
- type: 'body',
332
- property: 'auto_add_music',
333
- }
334
- }
335
226
  },
336
227
  {
337
228
  displayName: 'TikTok Disable Comment',
338
229
  name: 'tiktokDisableComment',
339
230
  type: 'boolean',
340
231
  default: false,
341
- description: 'Whether to disable comments on the TikTok post',
232
+ description: 'Whether to disable comments on TikTok post. For Photos & Video.',
342
233
  displayOptions: {
343
234
  show: {
344
235
  operation: ['uploadPhotos', 'uploadVideo'],
345
236
  platform: ['tiktok']
346
237
  },
347
238
  },
348
- routing: {
349
- send: {
350
- type: 'body',
351
- property: 'disable_comment',
352
- }
353
- }
354
239
  },
355
240
  {
356
241
  displayName: 'TikTok Branded Content (Photo)',
357
242
  name: 'tiktokBrandedContentPhoto',
358
243
  type: 'boolean',
359
244
  default: false,
360
- description: 'Whether to indicate if the photo post is branded content (requires Disclose Commercial to be true)',
245
+ description: 'Whether to indicate photo post is branded content (requires Disclose Commercial). Only for Upload Photos.',
361
246
  displayOptions: {
362
247
  show: {
363
248
  operation: ['uploadPhotos'],
364
249
  platform: ['tiktok']
365
250
  },
366
251
  },
367
- routing: {
368
- send: {
369
- type: 'body',
370
- property: 'branded_content',
371
- }
372
- }
373
252
  },
374
253
  {
375
254
  displayName: 'TikTok Disclose Commercial (Photo)',
376
255
  name: 'tiktokDiscloseCommercialPhoto',
377
256
  type: 'boolean',
378
257
  default: false,
379
- description: 'Whether to disclose the commercial nature of the photo post (used with Branded Content)',
258
+ description: 'Whether to disclose commercial nature of photo post. Only for Upload Photos.',
380
259
  displayOptions: {
381
260
  show: {
382
261
  operation: ['uploadPhotos'],
383
262
  platform: ['tiktok']
384
263
  },
385
264
  },
386
- routing: {
387
- send: {
388
- type: 'body',
389
- property: 'disclose_commercial',
390
- }
391
- }
392
265
  },
393
266
  {
394
267
  displayName: 'TikTok Photo Cover Index',
@@ -396,41 +269,29 @@ class UploadPost {
396
269
  type: 'number',
397
270
  default: 0,
398
271
  typeOptions: { minValue: 0 },
399
- description: 'Index (starting at 0) of the photo to use as the cover/thumbnail for the TikTok photo post',
272
+ description: 'Index (0-based) of photo to use as cover for TikTok photo post. Only for Upload Photos.',
400
273
  displayOptions: {
401
274
  show: {
402
275
  operation: ['uploadPhotos'],
403
276
  platform: ['tiktok']
404
277
  },
405
278
  },
406
- routing: {
407
- send: {
408
- type: 'body',
409
- property: 'photo_cover_index',
410
- }
411
- }
412
279
  },
413
280
  {
414
281
  displayName: 'TikTok Photo Description',
415
282
  name: 'tiktokPhotoDescription',
416
283
  type: 'string',
417
284
  default: '',
418
- description: 'Description for the TikTok photo post. If not provided, the common Title value will be used.',
285
+ description: 'Description for TikTok photo post. If not provided, Title is used. Only for Upload Photos.',
419
286
  displayOptions: {
420
287
  show: {
421
288
  operation: ['uploadPhotos'],
422
289
  platform: ['tiktok']
423
290
  },
424
291
  },
425
- routing: {
426
- send: {
427
- type: 'body',
428
- property: 'description',
429
- }
430
- }
431
292
  },
432
293
  {
433
- displayName: 'TikTok Privacy Level',
294
+ displayName: 'TikTok Privacy Level (Video)',
434
295
  name: 'tiktokPrivacyLevel',
435
296
  type: 'options',
436
297
  options: [
@@ -440,408 +301,265 @@ class UploadPost {
440
301
  { name: 'Self Only', value: 'SELF_ONLY' },
441
302
  ],
442
303
  default: 'PUBLIC_TO_EVERYONE',
443
- description: 'Privacy setting for the TikTok video',
304
+ description: 'Privacy setting for TikTok video (PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, etc.). Only for Upload Video.',
444
305
  displayOptions: {
445
306
  show: {
446
307
  operation: ['uploadVideo'],
447
308
  platform: ['tiktok']
448
309
  },
449
310
  },
450
- routing: {
451
- send: {
452
- type: 'body',
453
- property: 'privacy_level',
454
- }
455
- }
456
311
  },
457
312
  {
458
- displayName: 'TikTok Disable Duet',
313
+ displayName: 'TikTok Disable Duet (Video)',
459
314
  name: 'tiktokDisableDuet',
460
315
  type: 'boolean',
461
316
  default: false,
462
- description: 'Whether to disable duet feature for the TikTok video',
317
+ description: 'Whether to disable duet for TikTok video. Only for Upload Video.',
463
318
  displayOptions: {
464
319
  show: {
465
320
  operation: ['uploadVideo'],
466
321
  platform: ['tiktok']
467
322
  },
468
323
  },
469
- routing: {
470
- send: {
471
- type: 'body',
472
- property: 'disable_duet',
473
- }
474
- }
475
324
  },
476
325
  {
477
- displayName: 'TikTok Disable Stitch',
326
+ displayName: 'TikTok Disable Stitch (Video)',
478
327
  name: 'tiktokDisableStitch',
479
328
  type: 'boolean',
480
329
  default: false,
481
- description: 'Whether to disable stitch feature for the TikTok video',
330
+ description: 'Whether to disable stitch for TikTok video. Only for Upload Video.',
482
331
  displayOptions: {
483
332
  show: {
484
333
  operation: ['uploadVideo'],
485
334
  platform: ['tiktok']
486
335
  },
487
336
  },
488
- routing: {
489
- send: {
490
- type: 'body',
491
- property: 'disable_stitch',
492
- }
493
- }
494
337
  },
495
338
  {
496
- displayName: 'TikTok Cover Timestamp (Ms)',
339
+ displayName: 'TikTok Cover Timestamp (Ms, Video)',
497
340
  name: 'tiktokCoverTimestamp',
498
341
  type: 'number',
499
342
  default: 1000,
500
- description: 'Timestamp in milliseconds for video cover on TikTok',
343
+ description: 'Timestamp (ms) for video cover on TikTok. Only for Upload Video.',
501
344
  displayOptions: {
502
345
  show: {
503
346
  operation: ['uploadVideo'],
504
347
  platform: ['tiktok']
505
348
  },
506
349
  },
507
- routing: {
508
- send: {
509
- type: 'body',
510
- property: 'cover_timestamp',
511
- }
512
- }
513
350
  },
514
351
  {
515
- displayName: 'TikTok Brand Content Toggle',
352
+ displayName: 'TikTok Brand Content Toggle (Video)',
516
353
  name: 'tiktokBrandContentToggle',
517
354
  type: 'boolean',
518
355
  default: false,
519
- description: 'Whether to enable branded content for TikTok video',
356
+ description: 'Whether to enable branded content for TikTok video. Only for Upload Video.',
520
357
  displayOptions: {
521
358
  show: {
522
359
  operation: ['uploadVideo'],
523
360
  platform: ['tiktok']
524
361
  },
525
362
  },
526
- routing: {
527
- send: {
528
- type: 'body',
529
- property: 'brand_content_toggle',
530
- }
531
- }
532
363
  },
533
364
  {
534
- displayName: 'TikTok Brand Organic',
365
+ displayName: 'TikTok Brand Organic (Video)',
535
366
  name: 'tiktokBrandOrganic',
536
367
  type: 'boolean',
537
368
  default: false,
538
- description: 'Whether to enable organic branded content for TikTok video',
369
+ description: 'Whether to enable organic branded content for TikTok video. Only for Upload Video.',
539
370
  displayOptions: {
540
371
  show: {
541
372
  operation: ['uploadVideo'],
542
373
  platform: ['tiktok']
543
374
  },
544
375
  },
545
- routing: {
546
- send: {
547
- type: 'body',
548
- property: 'brand_organic',
549
- }
550
- }
551
376
  },
552
377
  {
553
378
  displayName: 'TikTok Branded Content (Video)',
554
379
  name: 'tiktokBrandedContentVideo',
555
380
  type: 'boolean',
556
381
  default: false,
557
- description: 'Whether to enable branded content with disclosure for TikTok video',
382
+ description: 'Whether to enable branded content with disclosure for TikTok video. Only for Upload Video.',
558
383
  displayOptions: {
559
384
  show: {
560
385
  operation: ['uploadVideo'],
561
386
  platform: ['tiktok']
562
387
  },
563
388
  },
564
- routing: {
565
- send: {
566
- type: 'body',
567
- property: 'branded_content',
568
- }
569
- }
570
389
  },
571
390
  {
572
- displayName: 'TikTok Brand Organic Toggle',
391
+ displayName: 'TikTok Brand Organic Toggle (Video)',
573
392
  name: 'tiktokBrandOrganicToggle',
574
393
  type: 'boolean',
575
394
  default: false,
576
- description: 'Whether to enable organic branded content toggle for TikTok video',
395
+ description: 'Whether to enable organic branded content toggle for TikTok video. Only for Upload Video.',
577
396
  displayOptions: {
578
397
  show: {
579
398
  operation: ['uploadVideo'],
580
399
  platform: ['tiktok']
581
400
  },
582
401
  },
583
- routing: {
584
- send: {
585
- type: 'body',
586
- property: 'brand_organic_toggle',
587
- }
588
- }
589
402
  },
590
403
  {
591
- displayName: 'TikTok Is AIGC',
404
+ displayName: 'TikTok Is AIGC (Video)',
592
405
  name: 'tiktokIsAigc',
593
406
  type: 'boolean',
594
407
  default: false,
595
- description: 'Whether to indicate if content is AI-generated for TikTok video',
408
+ description: 'Whether to indicate if content is AI-generated for TikTok video. Only for Upload Video.',
596
409
  displayOptions: {
597
410
  show: {
598
411
  operation: ['uploadVideo'],
599
412
  platform: ['tiktok']
600
413
  },
601
414
  },
602
- routing: {
603
- send: {
604
- type: 'body',
605
- property: 'is_aigc',
606
- }
607
- }
608
415
  },
609
416
  {
610
- displayName: 'Instagram Photo Media Type',
611
- name: 'instagramPhotoMediaType',
417
+ displayName: 'Instagram Media Type',
418
+ name: 'instagramMediaType',
612
419
  type: 'options',
613
420
  options: [
614
- { name: 'Image (Feed)', value: 'IMAGE' },
615
- { name: 'Stories', value: 'STORIES' },
421
+ { name: 'Image (Feed - Photo)', value: 'IMAGE', displayOptions: { show: { operation: ['uploadPhotos'] } } },
422
+ { name: 'Stories (Photo/Video)', value: 'STORIES' },
423
+ { name: 'Reels (Video)', value: 'REELS', displayOptions: { show: { operation: ['uploadVideo'] } } },
616
424
  ],
617
425
  default: 'IMAGE',
618
- description: 'Type of media for Instagram photo upload',
619
- displayOptions: {
620
- show: {
621
- operation: ['uploadPhotos'],
622
- platform: ['instagram']
623
- },
624
- },
625
- routing: {
626
- send: {
627
- type: 'body',
628
- property: 'media_type',
629
- }
630
- }
631
- },
632
- {
633
- displayName: 'Instagram Video Media Type',
634
- name: 'instagramVideoMediaType',
635
- type: 'options',
636
- options: [
637
- { name: 'Reels', value: 'REELS' },
638
- { name: 'Stories', value: 'STORIES' },
639
- ],
640
- default: 'REELS',
641
- description: 'Type of media for Instagram video upload',
426
+ description: 'Type of media for Instagram. IMAGE/STORIES for Photos. REELS/STORIES for Video.',
642
427
  displayOptions: {
643
428
  show: {
644
- operation: ['uploadVideo'],
429
+ operation: ['uploadPhotos', 'uploadVideo'],
645
430
  platform: ['instagram']
646
431
  },
647
432
  },
648
- routing: {
649
- send: {
650
- type: 'body',
651
- property: 'media_type',
652
- }
653
- }
654
433
  },
655
434
  {
656
- displayName: 'Instagram Share to Feed',
435
+ displayName: 'Instagram Share to Feed (Video)',
657
436
  name: 'instagramShareToFeed',
658
437
  type: 'boolean',
659
438
  default: true,
660
- description: 'Whether to share the Instagram video (Reel/Story) to feed',
439
+ description: 'Whether to share Instagram video (Reel/Story) to feed. Only for Upload Video.',
661
440
  displayOptions: {
662
441
  show: {
663
442
  operation: ['uploadVideo'],
664
443
  platform: ['instagram']
665
444
  },
666
445
  },
667
- routing: {
668
- send: {
669
- type: 'body',
670
- property: 'share_to_feed',
671
- }
672
- }
673
446
  },
674
447
  {
675
- displayName: 'Instagram Collaborators',
448
+ displayName: 'Instagram Collaborators (Video)',
676
449
  name: 'instagramCollaborators',
677
450
  type: 'string',
678
451
  default: '',
679
- description: 'Comma-separated list of collaborator usernames for Instagram video',
452
+ description: 'Comma-separated collaborator usernames for Instagram video. Sent as a string. Only for Upload Video.',
680
453
  displayOptions: {
681
454
  show: {
682
455
  operation: ['uploadVideo'],
683
456
  platform: ['instagram']
684
457
  },
685
458
  },
686
- routing: {
687
- send: {
688
- type: 'body',
689
- property: 'collaborators',
690
- }
691
- }
692
459
  },
693
460
  {
694
- displayName: 'Instagram Cover URL',
461
+ displayName: 'Instagram Cover URL (Video)',
695
462
  name: 'instagramCoverUrl',
696
463
  type: 'string',
697
464
  default: '',
698
- description: 'URL for custom video cover on Instagram',
465
+ description: 'URL for custom video cover on Instagram. Only for Upload Video.',
699
466
  displayOptions: {
700
467
  show: {
701
468
  operation: ['uploadVideo'],
702
469
  platform: ['instagram']
703
470
  },
704
471
  },
705
- routing: {
706
- send: {
707
- type: 'body',
708
- property: 'cover_url',
709
- }
710
- }
711
472
  },
712
473
  {
713
- displayName: 'Instagram Audio Name',
474
+ displayName: 'Instagram Audio Name (Video)',
714
475
  name: 'instagramAudioName',
715
476
  type: 'string',
716
477
  default: '',
717
- description: 'Name of the audio track for Instagram video',
478
+ description: 'Name of the audio track for Instagram video. Only for Upload Video.',
718
479
  displayOptions: {
719
480
  show: {
720
481
  operation: ['uploadVideo'],
721
482
  platform: ['instagram']
722
483
  },
723
484
  },
724
- routing: {
725
- send: {
726
- type: 'body',
727
- property: 'audio_name',
728
- }
729
- }
730
485
  },
731
486
  {
732
- displayName: 'Instagram User Tags',
487
+ displayName: 'Instagram User Tags (Video)',
733
488
  name: 'instagramUserTags',
734
489
  type: 'string',
735
490
  default: '',
736
- description: 'Comma-separated list of user tags for Instagram video',
491
+ description: 'Comma-separated user tags for Instagram video. Sent as a string. Only for Upload Video.',
737
492
  displayOptions: {
738
493
  show: {
739
494
  operation: ['uploadVideo'],
740
495
  platform: ['instagram']
741
496
  },
742
497
  },
743
- routing: {
744
- send: {
745
- type: 'body',
746
- property: 'user_tags',
747
- }
748
- }
749
498
  },
750
499
  {
751
- displayName: 'Instagram Location ID',
500
+ displayName: 'Instagram Location ID (Video)',
752
501
  name: 'instagramLocationId',
753
502
  type: 'string',
754
503
  default: '',
755
- description: 'Instagram location ID for the video',
504
+ description: 'Instagram location ID for the video. Only for Upload Video.',
756
505
  displayOptions: {
757
506
  show: {
758
507
  operation: ['uploadVideo'],
759
508
  platform: ['instagram']
760
509
  },
761
510
  },
762
- routing: {
763
- send: {
764
- type: 'body',
765
- property: 'location_id',
766
- }
767
- }
768
511
  },
769
512
  {
770
- displayName: 'Instagram Thumb Offset',
513
+ displayName: 'Instagram Thumb Offset (Video)',
771
514
  name: 'instagramThumbOffset',
772
515
  type: 'string',
773
516
  default: '',
774
- description: 'Timestamp offset for video thumbnail on Instagram',
517
+ description: 'Timestamp offset for video thumbnail on Instagram. Only for Upload Video.',
775
518
  displayOptions: {
776
519
  show: {
777
520
  operation: ['uploadVideo'],
778
521
  platform: ['instagram']
779
522
  },
780
523
  },
781
- routing: {
782
- send: {
783
- type: 'body',
784
- property: 'thumb_offset',
785
- }
786
- }
787
524
  },
788
525
  {
789
- displayName: 'YouTube Description',
526
+ displayName: 'YouTube Video Description',
790
527
  name: 'youtubeDescription',
791
528
  type: 'string',
792
529
  default: '',
793
- description: 'Description of the video for YouTube. If not provided, title is used.',
530
+ description: 'Description of the video for YouTube. If not provided, Title is used. Only for Upload Video.',
794
531
  displayOptions: {
795
532
  show: {
796
533
  operation: ['uploadVideo'],
797
534
  platform: ['youtube']
798
535
  },
799
536
  },
800
- routing: {
801
- send: {
802
- type: 'body',
803
- property: 'description',
804
- }
805
- }
806
537
  },
807
538
  {
808
539
  displayName: 'YouTube Tags',
809
540
  name: 'youtubeTags',
810
541
  type: 'string',
811
542
  default: '',
812
- description: 'Comma-separated list of tags for YouTube video. These will be sent as an array.',
543
+ description: 'Comma-separated list of tags for YouTube video. Will be sent as an array. Only for Upload Video.',
813
544
  displayOptions: {
814
545
  show: {
815
546
  operation: ['uploadVideo'],
816
547
  platform: ['youtube']
817
548
  },
818
549
  },
819
- routing: {
820
- send: {
821
- type: 'body',
822
- property: 'tags',
823
- value: '={{ $value ? $value.split(",").map(tag => tag.trim()) : [] }}',
824
- }
825
- }
826
550
  },
827
551
  {
828
552
  displayName: 'YouTube Category ID',
829
553
  name: 'youtubeCategoryId',
830
554
  type: 'string',
831
555
  default: '22',
832
- description: 'Video category for YouTube',
556
+ description: 'Video category ID for YouTube (e.g., 22 for People & Blogs). Only for Upload Video.',
833
557
  displayOptions: {
834
558
  show: {
835
559
  operation: ['uploadVideo'],
836
560
  platform: ['youtube']
837
561
  },
838
562
  },
839
- routing: {
840
- send: {
841
- type: 'body',
842
- property: 'categoryId',
843
- }
844
- }
845
563
  },
846
564
  {
847
565
  displayName: 'YouTube Privacy Status',
@@ -853,38 +571,26 @@ class UploadPost {
853
571
  { name: 'Private', value: 'private' },
854
572
  ],
855
573
  default: 'public',
856
- description: 'Privacy setting for YouTube video',
574
+ description: 'Privacy setting for YouTube video (public, unlisted, private). Only for Upload Video.',
857
575
  displayOptions: {
858
576
  show: {
859
577
  operation: ['uploadVideo'],
860
578
  platform: ['youtube']
861
579
  },
862
580
  },
863
- routing: {
864
- send: {
865
- type: 'body',
866
- property: 'privacyStatus',
867
- }
868
- }
869
581
  },
870
582
  {
871
583
  displayName: 'YouTube Embeddable',
872
584
  name: 'youtubeEmbeddable',
873
585
  type: 'boolean',
874
586
  default: true,
875
- description: 'Whether the YouTube video is embeddable',
587
+ description: 'Whether the YouTube video is embeddable. Only for Upload Video.',
876
588
  displayOptions: {
877
589
  show: {
878
590
  operation: ['uploadVideo'],
879
591
  platform: ['youtube']
880
592
  },
881
593
  },
882
- routing: {
883
- send: {
884
- type: 'body',
885
- property: 'embeddable',
886
- }
887
- }
888
594
  },
889
595
  {
890
596
  displayName: 'YouTube License',
@@ -895,99 +601,68 @@ class UploadPost {
895
601
  { name: 'Creative Commons - Attribution', value: 'creativeCommon' },
896
602
  ],
897
603
  default: 'youtube',
898
- description: 'Video license for YouTube',
604
+ description: 'Video license for YouTube (youtube, creativeCommon). Only for Upload Video.',
899
605
  displayOptions: {
900
606
  show: {
901
607
  operation: ['uploadVideo'],
902
608
  platform: ['youtube']
903
609
  },
904
610
  },
905
- routing: {
906
- send: {
907
- type: 'body',
908
- property: 'license',
909
- }
910
- }
911
611
  },
912
612
  {
913
613
  displayName: 'YouTube Public Stats Viewable',
914
614
  name: 'youtubePublicStatsViewable',
915
615
  type: 'boolean',
916
616
  default: true,
917
- description: 'Whether public stats are viewable for the YouTube video',
617
+ description: 'Whether public stats are viewable for the YouTube video. Only for Upload Video.',
918
618
  displayOptions: {
919
619
  show: {
920
620
  operation: ['uploadVideo'],
921
621
  platform: ['youtube']
922
622
  },
923
623
  },
924
- routing: {
925
- send: {
926
- type: 'body',
927
- property: 'publicStatsViewable',
928
- }
929
- }
930
624
  },
931
625
  {
932
626
  displayName: 'YouTube Made For Kids',
933
627
  name: 'youtubeMadeForKids',
934
628
  type: 'boolean',
935
629
  default: false,
936
- description: 'Whether the YouTube video is made for kids',
630
+ description: 'Whether the YouTube video is made for kids. Only for Upload Video.',
937
631
  displayOptions: {
938
632
  show: {
939
633
  operation: ['uploadVideo'],
940
634
  platform: ['youtube']
941
635
  },
942
636
  },
943
- routing: {
944
- send: {
945
- type: 'body',
946
- property: 'madeForKids',
947
- }
948
- }
949
637
  },
950
638
  {
951
- displayName: 'Threads Description',
639
+ displayName: 'Threads Video Description',
952
640
  name: 'threadsDescription',
953
641
  type: 'string',
954
642
  default: '',
955
- description: 'The user generated commentary for the post on Threads. If not provided, title is used.',
643
+ description: 'User commentary for Threads video. If not provided, Title is used. Not for Photos/Text.',
956
644
  displayOptions: {
957
645
  show: {
958
- operation: ['uploadVideo', 'uploadText'],
646
+ operation: ['uploadVideo'],
959
647
  platform: ['threads']
960
648
  },
961
649
  },
962
- routing: {
963
- send: {
964
- type: 'body',
965
- property: 'description',
966
- }
967
- }
968
650
  },
969
651
  {
970
- displayName: 'X Tagged User IDs',
652
+ displayName: 'X Tagged User IDs (Video/Text)',
971
653
  name: 'xTaggedUserIds',
972
654
  type: 'string',
973
655
  default: '',
974
- description: 'Comma-separated list of user IDs to tag for X (Twitter) video/text. These will be sent as an array.',
656
+ description: 'Comma-separated list of user IDs to tag for X (Twitter). Not for Photos.',
975
657
  displayOptions: {
976
658
  show: {
977
659
  operation: ['uploadVideo', 'uploadText'],
978
660
  platform: ['x']
979
661
  },
980
662
  },
981
- routing: {
982
- send: {
983
- type: 'body',
984
- property: 'tagged_user_ids',
985
- value: '={{ $value ? $value.split(",").map(id => id.trim()) : [] }}',
986
- }
987
- }
988
663
  },
989
664
  {
990
- displayName: 'X Reply Settings',
665
+ displayName: 'X Reply Settings (Video/Text)',
991
666
  name: 'xReplySettings',
992
667
  type: 'options',
993
668
  options: [
@@ -996,96 +671,65 @@ class UploadPost {
996
671
  { name: 'Everyone', value: 'everyone' },
997
672
  ],
998
673
  default: 'following',
999
- description: 'Who can reply to the X (Twitter) video/text post',
674
+ description: 'Who can reply to the post on X (Twitter) (following, mentionedUsers, everyone). Not for Photos.',
1000
675
  displayOptions: {
1001
676
  show: {
1002
677
  operation: ['uploadVideo', 'uploadText'],
1003
678
  platform: ['x']
1004
679
  },
1005
680
  },
1006
- routing: {
1007
- send: {
1008
- type: 'body',
1009
- property: 'reply_settings',
1010
- }
1011
- }
1012
681
  },
1013
682
  {
1014
683
  displayName: 'X Nullcast (Video)',
1015
684
  name: 'xNullcastVideo',
1016
685
  type: 'boolean',
1017
686
  default: false,
1018
- description: 'Whether to publish X (Twitter) video without broadcasting',
687
+ description: 'Whether to publish X (Twitter) video without broadcasting. Not for Text/Photos.',
1019
688
  displayOptions: {
1020
689
  show: {
1021
690
  operation: ['uploadVideo'],
1022
691
  platform: ['x']
1023
692
  },
1024
693
  },
1025
- routing: {
1026
- send: {
1027
- type: 'body',
1028
- property: 'nullcast',
1029
- }
1030
- }
1031
694
  },
1032
695
  {
1033
696
  displayName: 'X Place ID (Video)',
1034
697
  name: 'xPlaceIdVideo',
1035
698
  type: 'string',
1036
699
  default: '',
1037
- description: 'Location place ID for X (Twitter) video',
700
+ description: 'Location place ID for X (Twitter) video. Not for Text/Photos.',
1038
701
  displayOptions: {
1039
702
  show: {
1040
703
  operation: ['uploadVideo'],
1041
704
  platform: ['x']
1042
705
  },
1043
706
  },
1044
- routing: {
1045
- send: {
1046
- type: 'body',
1047
- property: 'place_id',
1048
- }
1049
- }
1050
707
  },
1051
708
  {
1052
709
  displayName: 'X Poll Duration (Minutes, Video)',
1053
710
  name: 'xPollDurationVideo',
1054
711
  type: 'number',
1055
712
  default: 1440,
1056
- description: 'Poll duration in minutes for X (Twitter) video post. Requires Poll Options.',
713
+ description: 'Poll duration in minutes for X (Twitter) video post (requires Poll Options). Not for Text/Photos.',
1057
714
  displayOptions: {
1058
715
  show: {
1059
716
  operation: ['uploadVideo'],
1060
717
  platform: ['x']
1061
718
  },
1062
719
  },
1063
- routing: {
1064
- send: {
1065
- type: 'body',
1066
- property: 'poll_duration',
1067
- }
1068
- }
1069
720
  },
1070
721
  {
1071
722
  displayName: 'X Poll Options (Video)',
1072
723
  name: 'xPollOptionsVideo',
1073
724
  type: 'string',
1074
725
  default: '',
1075
- description: 'Comma-separated list of poll options for X (Twitter) video post. These will be sent as an array.',
726
+ description: 'Comma-separated list of poll options for X (Twitter) video post. Will be sent as an array. Not for Text/Photos.',
1076
727
  displayOptions: {
1077
728
  show: {
1078
729
  operation: ['uploadVideo'],
1079
730
  platform: ['x']
1080
731
  },
1081
732
  },
1082
- routing: {
1083
- send: {
1084
- type: 'body',
1085
- property: 'poll_options',
1086
- value: '={{ $value ? $value.split(",").map(opt => opt.trim()) : [] }}',
1087
- }
1088
- }
1089
733
  },
1090
734
  {
1091
735
  displayName: 'X Poll Reply Settings (Video)',
@@ -1097,106 +741,342 @@ class UploadPost {
1097
741
  { name: 'Everyone', value: 'everyone' },
1098
742
  ],
1099
743
  default: 'following',
1100
- description: 'Who can reply to the poll in X (Twitter) video post',
744
+ description: 'Who can reply to the poll in X (Twitter) video post (following, mentionedUsers, everyone). Not for Text/Photos.',
1101
745
  displayOptions: {
1102
746
  show: {
1103
747
  operation: ['uploadVideo'],
1104
748
  platform: ['x']
1105
749
  },
1106
750
  },
1107
- routing: {
1108
- send: {
1109
- type: 'body',
1110
- property: 'poll_reply_settings',
1111
- }
1112
- }
1113
751
  },
1114
752
  {
1115
753
  displayName: 'X Post URL (Text)',
1116
754
  name: 'xPostUrlText',
1117
755
  type: 'string',
1118
756
  default: '',
1119
- description: 'URL to attach to the X (Twitter) text post',
757
+ description: 'URL to attach to the X (Twitter) text post. Only for Upload Text.',
1120
758
  displayOptions: {
1121
759
  show: {
1122
760
  operation: ['uploadText'],
1123
761
  platform: ['x']
1124
762
  },
1125
763
  },
1126
- routing: {
1127
- send: {
1128
- type: 'body',
1129
- property: 'post_url',
1130
- }
1131
- }
1132
764
  },
1133
765
  ],
1134
766
  };
1135
767
  }
1136
768
  async execute() {
769
+ var _a, _b;
1137
770
  const items = this.getInputData();
1138
771
  const returnData = [];
1139
- const length = items.length;
1140
- const baseApiUrl = 'https://api.upload-post.com/api';
1141
- const nodeDescription = this.description;
1142
- for (let i = 0; i < length; i++) {
1143
- try {
1144
- const credentials = await this.getCredentials('uploadPostApi', i);
1145
- if (!credentials || !credentials.apiKey) {
1146
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'API key is missing from UploadPostApi credentials.', { itemIndex: i });
772
+ for (let i = 0; i < items.length; i++) {
773
+ const operation = this.getNodeParameter('operation', i);
774
+ const user = this.getNodeParameter('user', i);
775
+ let platforms = this.getNodeParameter('platform', i);
776
+ const title = this.getNodeParameter('title', i);
777
+ let endpoint = '';
778
+ const formData = {};
779
+ formData.user = user;
780
+ formData.title = title;
781
+ switch (operation) {
782
+ case 'uploadPhotos':
783
+ endpoint = '/upload_photos';
784
+ const photoCaption = this.getNodeParameter('caption', i);
785
+ let photosInput = this.getNodeParameter('photos', i, []);
786
+ let photosToProcess;
787
+ if (typeof photosInput === 'string') {
788
+ photosToProcess = photosInput.split(',').map(item => item.trim()).filter(item => item !== '');
789
+ }
790
+ else {
791
+ photosToProcess = photosInput.filter(item => typeof item === 'string' && item.trim() !== '');
792
+ }
793
+ const allowedPhotoPlatforms = ['tiktok', 'instagram', 'linkedin', 'facebook', 'x', 'threads'];
794
+ platforms = platforms.filter(p => allowedPhotoPlatforms.includes(p));
795
+ formData['platform[]'] = platforms;
796
+ if (photosToProcess.length > 0) {
797
+ const photoArray = [];
798
+ for (const photoItem of photosToProcess) {
799
+ if (typeof photoItem === 'string' && photoItem) {
800
+ if (photoItem.toLowerCase().startsWith('http://') || photoItem.toLowerCase().startsWith('https://')) {
801
+ photoArray.push(photoItem);
802
+ }
803
+ else {
804
+ const binaryPropertyName = photoItem;
805
+ try {
806
+ const binaryBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
807
+ const binaryFileDetails = items[i].binary[binaryPropertyName];
808
+ photoArray.push({
809
+ value: binaryBuffer,
810
+ options: {
811
+ filename: (_a = binaryFileDetails.fileName) !== null && _a !== void 0 ? _a : binaryPropertyName,
812
+ contentType: binaryFileDetails.mimeType,
813
+ },
814
+ });
815
+ }
816
+ catch (error) {
817
+ this.logger.warn(`[UploadPost Node] Could not find binary data for property '${binaryPropertyName}' in item ${i}. Error: ${error.message}`);
818
+ }
819
+ }
820
+ }
821
+ }
822
+ if (photoArray.length > 0) {
823
+ formData['photos[]'] = photoArray;
824
+ }
825
+ }
826
+ if (photoCaption)
827
+ formData.caption = photoCaption;
828
+ break;
829
+ case 'uploadVideo':
830
+ endpoint = '/upload';
831
+ const videoInput = this.getNodeParameter('video', i);
832
+ const allowedVideoPlatforms = ['tiktok', 'instagram', 'linkedin', 'youtube', 'facebook', 'x', 'threads'];
833
+ platforms = platforms.filter(p => allowedVideoPlatforms.includes(p));
834
+ formData['platform[]'] = platforms;
835
+ if (videoInput) {
836
+ if (videoInput.toLowerCase().startsWith('http://') || videoInput.toLowerCase().startsWith('https://')) {
837
+ formData.video = videoInput;
838
+ }
839
+ else {
840
+ const binaryPropertyName = videoInput;
841
+ try {
842
+ const binaryBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
843
+ const binaryFileDetails = items[i].binary[binaryPropertyName];
844
+ formData.video = {
845
+ value: binaryBuffer,
846
+ options: {
847
+ filename: (_b = binaryFileDetails.fileName) !== null && _b !== void 0 ? _b : binaryPropertyName,
848
+ contentType: binaryFileDetails.mimeType,
849
+ },
850
+ };
851
+ }
852
+ catch (error) {
853
+ this.logger.warn(`[UploadPost Node] Could not find binary data for video property '${binaryPropertyName}' in item ${i}. Error: ${error.message}`);
854
+ }
855
+ }
856
+ }
857
+ break;
858
+ case 'uploadText':
859
+ endpoint = '/upload_text';
860
+ const allowedTextPlatforms = ['x', 'linkedin', 'facebook', 'threads'];
861
+ platforms = platforms.filter(p => allowedTextPlatforms.includes(p));
862
+ formData['platform[]'] = platforms;
863
+ break;
864
+ }
865
+ if (platforms.includes('linkedin')) {
866
+ const targetLinkedinPageId = this.getNodeParameter('targetLinkedinPageId', i);
867
+ if (targetLinkedinPageId)
868
+ formData.target_linkedin_page_id = targetLinkedinPageId;
869
+ if (operation === 'uploadPhotos') {
870
+ const linkedinVisibility = this.getNodeParameter('linkedinVisibility', i);
871
+ if (linkedinVisibility === 'PUBLIC') {
872
+ formData.visibility = 'PUBLIC';
873
+ }
1147
874
  }
1148
- const apiKey = credentials.apiKey;
1149
- const authorizationHeader = `Apikey ${apiKey}`;
1150
- const operation = this.getNodeParameter('operation', i);
1151
- const operationProperty = nodeDescription.properties.find((prop) => prop.name === 'operation');
1152
- const operationOptions = operationProperty === null || operationProperty === void 0 ? void 0 : operationProperty.options;
1153
- const operationConfig = operationOptions === null || operationOptions === void 0 ? void 0 : operationOptions.find(opt => opt.value === operation);
1154
- if (!operationConfig || !operationConfig.routing || !operationConfig.routing.request) {
1155
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Routing information not found for operation: ${operation}`, { itemIndex: i });
875
+ else if (operation === 'uploadVideo') {
876
+ const linkedinVisibility = this.getNodeParameter('linkedinVisibility', i);
877
+ const linkedinDescription = this.getNodeParameter('linkedinDescription', i);
878
+ formData.visibility = linkedinVisibility;
879
+ if (linkedinDescription)
880
+ formData.description = linkedinDescription;
1156
881
  }
1157
- const requestDetails = operationConfig.routing.request;
1158
- const relativeUrl = requestDetails.url;
1159
- const httpMethod = requestDetails.method;
1160
- if (!relativeUrl || !httpMethod) {
1161
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Incomplete routing details (URL or Method missing) for operation: ${operation}`, { itemIndex: i });
882
+ }
883
+ if (platforms.includes('facebook')) {
884
+ const facebookPageId = this.getNodeParameter('facebookPageId', i);
885
+ formData.facebook_page_id = facebookPageId;
886
+ if (operation === 'uploadVideo') {
887
+ const facebookVideoDescription = this.getNodeParameter('facebookVideoDescription', i);
888
+ const facebookVideoState = this.getNodeParameter('facebookVideoState', i);
889
+ if (facebookVideoDescription)
890
+ formData.description = facebookVideoDescription;
891
+ if (facebookVideoState)
892
+ formData.video_state = facebookVideoState;
1162
893
  }
1163
- let fullUrl;
1164
- if (baseApiUrl.endsWith('/') && relativeUrl.startsWith('/')) {
1165
- fullUrl = baseApiUrl + relativeUrl.substring(1);
894
+ }
895
+ if (platforms.includes('tiktok')) {
896
+ if (operation === 'uploadPhotos') {
897
+ const tiktokAutoAddMusic = this.getNodeParameter('tiktokAutoAddMusic', i);
898
+ const tiktokDisableComment = this.getNodeParameter('tiktokDisableComment', i);
899
+ const tiktokBrandedContentPhoto = this.getNodeParameter('tiktokBrandedContentPhoto', i);
900
+ const tiktokDiscloseCommercialPhoto = this.getNodeParameter('tiktokDiscloseCommercialPhoto', i);
901
+ const tiktokPhotoCoverIndex = this.getNodeParameter('tiktokPhotoCoverIndex', i);
902
+ const tiktokPhotoDescription = this.getNodeParameter('tiktokPhotoDescription', i);
903
+ if (tiktokAutoAddMusic !== undefined)
904
+ formData.auto_add_music = String(tiktokAutoAddMusic);
905
+ if (tiktokDisableComment !== undefined)
906
+ formData.disable_comment = String(tiktokDisableComment);
907
+ if (tiktokBrandedContentPhoto !== undefined)
908
+ formData.branded_content = String(tiktokBrandedContentPhoto);
909
+ if (tiktokDiscloseCommercialPhoto !== undefined)
910
+ formData.disclose_commercial = String(tiktokDiscloseCommercialPhoto);
911
+ if (tiktokPhotoCoverIndex !== undefined)
912
+ formData.photo_cover_index = tiktokPhotoCoverIndex;
913
+ if (tiktokPhotoDescription)
914
+ formData.description = tiktokPhotoDescription;
1166
915
  }
1167
- else if (!baseApiUrl.endsWith('/') && !relativeUrl.startsWith('/')) {
1168
- fullUrl = `${baseApiUrl}/${relativeUrl}`;
916
+ else if (operation === 'uploadVideo') {
917
+ const tiktokPrivacyLevel = this.getNodeParameter('tiktokPrivacyLevel', i);
918
+ const tiktokDisableDuet = this.getNodeParameter('tiktokDisableDuet', i);
919
+ const tiktokDisableComment = this.getNodeParameter('tiktokDisableComment', i);
920
+ const tiktokDisableStitch = this.getNodeParameter('tiktokDisableStitch', i);
921
+ const tiktokCoverTimestamp = this.getNodeParameter('tiktokCoverTimestamp', i);
922
+ const tiktokBrandContentToggle = this.getNodeParameter('tiktokBrandContentToggle', i);
923
+ const tiktokBrandOrganic = this.getNodeParameter('tiktokBrandOrganic', i);
924
+ const tiktokBrandedContentVideo = this.getNodeParameter('tiktokBrandedContentVideo', i);
925
+ const tiktokBrandOrganicToggle = this.getNodeParameter('tiktokBrandOrganicToggle', i);
926
+ const tiktokIsAigc = this.getNodeParameter('tiktokIsAigc', i);
927
+ if (tiktokPrivacyLevel)
928
+ formData.privacy_level = tiktokPrivacyLevel;
929
+ if (tiktokDisableDuet !== undefined)
930
+ formData.disable_duet = String(tiktokDisableDuet);
931
+ if (tiktokDisableComment !== undefined)
932
+ formData.disable_comment = String(tiktokDisableComment);
933
+ if (tiktokDisableStitch !== undefined)
934
+ formData.disable_stitch = String(tiktokDisableStitch);
935
+ if (tiktokCoverTimestamp !== undefined)
936
+ formData.cover_timestamp = tiktokCoverTimestamp;
937
+ if (tiktokBrandContentToggle !== undefined)
938
+ formData.brand_content_toggle = String(tiktokBrandContentToggle);
939
+ if (tiktokBrandOrganic !== undefined)
940
+ formData.brand_organic = String(tiktokBrandOrganic);
941
+ if (tiktokBrandedContentVideo !== undefined)
942
+ formData.branded_content = String(tiktokBrandedContentVideo);
943
+ if (tiktokBrandOrganicToggle !== undefined)
944
+ formData.brand_organic_toggle = String(tiktokBrandOrganicToggle);
945
+ if (tiktokIsAigc !== undefined)
946
+ formData.is_aigc = String(tiktokIsAigc);
1169
947
  }
1170
- else {
1171
- fullUrl = baseApiUrl + relativeUrl;
948
+ }
949
+ if (platforms.includes('instagram')) {
950
+ const instagramMediaTypeInput = this.getNodeParameter('instagramMediaType', i);
951
+ let finalInstagramMediaType = instagramMediaTypeInput;
952
+ if (operation === 'uploadPhotos') {
953
+ if (!instagramMediaTypeInput || !['IMAGE', 'STORIES'].includes(instagramMediaTypeInput)) {
954
+ finalInstagramMediaType = 'IMAGE';
955
+ }
1172
956
  }
1173
- const requestOptions = {
1174
- method: httpMethod,
1175
- uri: fullUrl,
1176
- headers: {
1177
- 'Accept': 'application/json',
1178
- 'Authorization': authorizationHeader,
1179
- },
1180
- json: true,
1181
- };
1182
- if (httpMethod === 'POST' || httpMethod === 'PUT' || httpMethod === 'PATCH') {
1183
- requestOptions.headers['Content-Type'] = 'application/json';
957
+ else if (operation === 'uploadVideo') {
958
+ if (!instagramMediaTypeInput || !['REELS', 'STORIES'].includes(instagramMediaTypeInput)) {
959
+ finalInstagramMediaType = 'REELS';
960
+ }
961
+ }
962
+ if (finalInstagramMediaType)
963
+ formData.media_type = finalInstagramMediaType;
964
+ if (operation === 'uploadVideo') {
965
+ const instagramShareToFeed = this.getNodeParameter('instagramShareToFeed', i);
966
+ const instagramCollaborators = this.getNodeParameter('instagramCollaborators', i);
967
+ const instagramCoverUrl = this.getNodeParameter('instagramCoverUrl', i);
968
+ const instagramAudioName = this.getNodeParameter('instagramAudioName', i);
969
+ const instagramUserTags = this.getNodeParameter('instagramUserTags', i);
970
+ const instagramLocationId = this.getNodeParameter('instagramLocationId', i);
971
+ const instagramThumbOffset = this.getNodeParameter('instagramThumbOffset', i);
972
+ if (instagramShareToFeed !== undefined)
973
+ formData.share_to_feed = String(instagramShareToFeed);
974
+ if (instagramCollaborators)
975
+ formData.collaborators = instagramCollaborators;
976
+ if (instagramCoverUrl)
977
+ formData.cover_url = instagramCoverUrl;
978
+ if (instagramAudioName)
979
+ formData.audio_name = instagramAudioName;
980
+ if (instagramUserTags)
981
+ formData.user_tags = instagramUserTags;
982
+ if (instagramLocationId)
983
+ formData.location_id = instagramLocationId;
984
+ if (instagramThumbOffset)
985
+ formData.thumb_offset = instagramThumbOffset;
1184
986
  }
1185
- this.logger.debug(`[UploadPost Node] Executing direct request: ${httpMethod} ${fullUrl} with API Key auth.`);
1186
- const responseData = await this.helpers.request.call(this, requestOptions);
1187
- returnData.push({ json: responseData, pairedItem: i });
1188
987
  }
1189
- catch (error) {
1190
- if (this.continueOnFail()) {
1191
- returnData.push({ json: { error: error.message }, pairedItem: i });
1192
- continue;
988
+ if (platforms.includes('youtube') && operation === 'uploadVideo') {
989
+ const youtubeDescription = this.getNodeParameter('youtubeDescription', i);
990
+ const youtubeTagsRaw = this.getNodeParameter('youtubeTags', i);
991
+ const youtubeCategoryId = this.getNodeParameter('youtubeCategoryId', i);
992
+ const youtubePrivacyStatus = this.getNodeParameter('youtubePrivacyStatus', i);
993
+ const youtubeEmbeddable = this.getNodeParameter('youtubeEmbeddable', i);
994
+ const youtubeLicense = this.getNodeParameter('youtubeLicense', i);
995
+ const youtubePublicStatsViewable = this.getNodeParameter('youtubePublicStatsViewable', i);
996
+ const youtubeMadeForKids = this.getNodeParameter('youtubeMadeForKids', i);
997
+ if (youtubeDescription)
998
+ formData.description = youtubeDescription;
999
+ if (youtubeTagsRaw)
1000
+ formData.tags = youtubeTagsRaw.split(',').map(tag => tag.trim());
1001
+ if (youtubeCategoryId)
1002
+ formData.categoryId = youtubeCategoryId;
1003
+ if (youtubePrivacyStatus)
1004
+ formData.privacyStatus = youtubePrivacyStatus;
1005
+ if (youtubeEmbeddable !== undefined)
1006
+ formData.embeddable = String(youtubeEmbeddable);
1007
+ if (youtubeLicense)
1008
+ formData.license = youtubeLicense;
1009
+ if (youtubePublicStatsViewable !== undefined)
1010
+ formData.publicStatsViewable = String(youtubePublicStatsViewable);
1011
+ if (youtubeMadeForKids !== undefined)
1012
+ formData.madeForKids = String(youtubeMadeForKids);
1013
+ }
1014
+ if (platforms.includes('threads')) {
1015
+ if (operation === 'uploadVideo') {
1016
+ const threadsDescription = this.getNodeParameter('threadsDescription', i);
1017
+ if (threadsDescription)
1018
+ formData.description = threadsDescription;
1193
1019
  }
1194
- if (error.context) {
1195
- error.context.itemIndex = i;
1196
- throw error;
1020
+ }
1021
+ if (platforms.includes('x')) {
1022
+ if (operation === 'uploadText') {
1023
+ const xPostUrlText = this.getNodeParameter('xPostUrlText', i);
1024
+ if (xPostUrlText)
1025
+ formData.post_url = xPostUrlText;
1026
+ const xTaggedUserIdsText = this.getNodeParameter('xTaggedUserIds', i);
1027
+ const xReplySettingsText = this.getNodeParameter('xReplySettings', i);
1028
+ if (xTaggedUserIdsText)
1029
+ formData.tagged_user_ids = xTaggedUserIdsText.split(',').map(id => id.trim());
1030
+ if (xReplySettingsText)
1031
+ formData.reply_settings = xReplySettingsText;
1032
+ delete formData.nullcast;
1033
+ delete formData.place_id;
1034
+ delete formData.poll_duration;
1035
+ delete formData.poll_options;
1036
+ delete formData.poll_reply_settings;
1037
+ }
1038
+ else if (operation === 'uploadVideo') {
1039
+ const xTaggedUserIds = this.getNodeParameter('xTaggedUserIds', i);
1040
+ const xReplySettings = this.getNodeParameter('xReplySettings', i);
1041
+ const xNullcastVideo = this.getNodeParameter('xNullcastVideo', i);
1042
+ const xPlaceIdVideo = this.getNodeParameter('xPlaceIdVideo', i);
1043
+ const xPollDurationVideo = this.getNodeParameter('xPollDurationVideo', i);
1044
+ const xPollOptionsVideoRaw = this.getNodeParameter('xPollOptionsVideo', i);
1045
+ const xPollReplySettingsVideo = this.getNodeParameter('xPollReplySettingsVideo', i);
1046
+ if (xTaggedUserIds)
1047
+ formData.tagged_user_ids = xTaggedUserIds.split(',').map(id => id.trim());
1048
+ if (xReplySettings)
1049
+ formData.reply_settings = xReplySettings;
1050
+ if (xNullcastVideo !== undefined)
1051
+ formData.nullcast = String(xNullcastVideo);
1052
+ if (xPlaceIdVideo)
1053
+ formData.place_id = xPlaceIdVideo;
1054
+ if (xPollDurationVideo !== undefined)
1055
+ formData.poll_duration = xPollDurationVideo;
1056
+ if (xPollOptionsVideoRaw)
1057
+ formData.poll_options = xPollOptionsVideoRaw.split(',').map(opt => opt.trim());
1058
+ if (xPollReplySettingsVideo)
1059
+ formData.poll_reply_settings = xPollReplySettingsVideo;
1197
1060
  }
1198
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
1199
1061
  }
1062
+ const credentials = await this.getCredentials('uploadPostApi');
1063
+ const apiKey = credentials.apiKey;
1064
+ const options = {
1065
+ uri: `https://api.upload-post.com/api${endpoint}`,
1066
+ method: 'POST',
1067
+ headers: {
1068
+ 'Authorization': `Apikey ${apiKey}`,
1069
+ },
1070
+ formData,
1071
+ json: true,
1072
+ };
1073
+ const responseData = await this.helpers.request(options);
1074
+ returnData.push({
1075
+ json: responseData,
1076
+ pairedItem: {
1077
+ item: i,
1078
+ },
1079
+ });
1200
1080
  }
1201
1081
  return [returnData];
1202
1082
  }