n8n-nodes-upload-post 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -35
- package/dist/nodes/UploadPost/UploadPost.node.d.ts +2 -0
- package/dist/nodes/UploadPost/UploadPost.node.js +655 -304
- package/dist/nodes/UploadPost/UploadPost.node.js.map +1 -1
- package/dist/package.json +4 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UploadPost = void 0;
|
|
4
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const MANUAL_USER_VALUE = '__manual_user__';
|
|
6
|
+
const MANUAL_FACEBOOK_VALUE = '__manual_facebook__';
|
|
7
|
+
const MANUAL_LINKEDIN_VALUE = '__manual_linkedin__';
|
|
8
|
+
const MANUAL_PINTEREST_VALUE = '__manual_pinterest__';
|
|
5
9
|
class UploadPost {
|
|
6
10
|
constructor() {
|
|
7
11
|
this.description = {
|
|
@@ -81,12 +85,14 @@ class UploadPost {
|
|
|
81
85
|
displayOptions: { show: { resource: ['users'] } },
|
|
82
86
|
},
|
|
83
87
|
{
|
|
84
|
-
displayName: 'User Identifier',
|
|
88
|
+
displayName: 'User Identifier Name or ID',
|
|
85
89
|
name: 'user',
|
|
86
|
-
type: '
|
|
90
|
+
type: 'options',
|
|
91
|
+
noDataExpression: true,
|
|
87
92
|
required: true,
|
|
88
93
|
default: '',
|
|
89
|
-
description: '
|
|
94
|
+
description: 'Choose from your created profiles, or specify a profile name using an <a href="https://docs.n8n.io/code/expressions/">expression</a>. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
|
95
|
+
typeOptions: { loadOptionsMethod: 'getUserProfiles' },
|
|
90
96
|
displayOptions: {
|
|
91
97
|
show: {
|
|
92
98
|
resource: ['uploads', 'users'],
|
|
@@ -95,22 +101,28 @@ class UploadPost {
|
|
|
95
101
|
},
|
|
96
102
|
},
|
|
97
103
|
{
|
|
98
|
-
displayName: '
|
|
104
|
+
displayName: 'User Identifier (Manual Entry)',
|
|
105
|
+
name: 'userManual',
|
|
106
|
+
type: 'string',
|
|
107
|
+
required: true,
|
|
108
|
+
default: '',
|
|
109
|
+
description: 'Provide a profile name or ID when it does not appear in the list',
|
|
110
|
+
displayOptions: {
|
|
111
|
+
show: {
|
|
112
|
+
resource: ['uploads', 'users'],
|
|
113
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText', 'generateJwt'],
|
|
114
|
+
user: [MANUAL_USER_VALUE]
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
displayName: 'Platform Names or IDs',
|
|
99
120
|
name: 'platform',
|
|
100
121
|
type: 'multiOptions',
|
|
101
122
|
required: true,
|
|
102
|
-
|
|
103
|
-
{ name: 'Facebook', value: 'facebook' },
|
|
104
|
-
{ name: 'Instagram', value: 'instagram' },
|
|
105
|
-
{ name: 'LinkedIn', value: 'linkedin' },
|
|
106
|
-
{ name: 'Pinterest', value: 'pinterest' },
|
|
107
|
-
{ name: 'Threads', value: 'threads' },
|
|
108
|
-
{ name: 'TikTok', value: 'tiktok' },
|
|
109
|
-
{ name: 'X (Twitter)', value: 'x' },
|
|
110
|
-
{ name: 'YouTube', value: 'youtube' },
|
|
111
|
-
],
|
|
123
|
+
typeOptions: { loadOptionsMethod: 'getPlatforms' },
|
|
112
124
|
default: [],
|
|
113
|
-
description: '
|
|
125
|
+
description: 'Choose from the list, or specify IDs using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
114
126
|
displayOptions: { show: { resource: ['uploads'], operation: ['uploadPhotos', 'uploadVideo', 'uploadText'] } },
|
|
115
127
|
},
|
|
116
128
|
{
|
|
@@ -179,44 +191,32 @@ class UploadPost {
|
|
|
179
191
|
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo', 'uploadText'], platform: ['pinterest'] } },
|
|
180
192
|
},
|
|
181
193
|
{
|
|
182
|
-
displayName: '
|
|
183
|
-
name: '
|
|
194
|
+
displayName: 'Threads Title (Override)',
|
|
195
|
+
name: 'threadsTitle',
|
|
184
196
|
type: 'string',
|
|
185
|
-
required: true,
|
|
186
197
|
default: '',
|
|
187
|
-
description: '
|
|
188
|
-
displayOptions: {
|
|
189
|
-
show: {
|
|
190
|
-
operation: ['uploadPhotos'],
|
|
191
|
-
},
|
|
192
|
-
},
|
|
198
|
+
description: 'Optional override for Threads title',
|
|
199
|
+
displayOptions: { show: { operation: ['uploadText'], platform: ['threads'] } },
|
|
193
200
|
},
|
|
194
201
|
{
|
|
195
202
|
displayName: 'Description (Optional)',
|
|
196
203
|
name: 'description',
|
|
197
204
|
type: 'string',
|
|
198
205
|
default: '',
|
|
199
|
-
description: '
|
|
206
|
+
description: 'Optional extended description used for LinkedIn commentary, Facebook description/message, YouTube video description, Pinterest description, and TikTok photo captions. Other platforms ignore it. When empty we fall back to the main title where a description is required. Platform-specific overrides below take precedence.',
|
|
200
207
|
displayOptions: {
|
|
201
208
|
show: {
|
|
202
|
-
operation: ['uploadPhotos', 'uploadVideo']
|
|
209
|
+
operation: ['uploadPhotos', 'uploadVideo'],
|
|
210
|
+
platform: ['linkedin', 'facebook', 'youtube', 'pinterest', 'tiktok']
|
|
203
211
|
}
|
|
204
212
|
},
|
|
205
213
|
},
|
|
206
|
-
{
|
|
207
|
-
displayName: 'Instagram Description (Override)',
|
|
208
|
-
name: 'instagramDescription',
|
|
209
|
-
type: 'string',
|
|
210
|
-
default: '',
|
|
211
|
-
description: 'Optional description override for Instagram',
|
|
212
|
-
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo'], platform: ['instagram'] } },
|
|
213
|
-
},
|
|
214
214
|
{
|
|
215
215
|
displayName: 'Facebook Description (Override)',
|
|
216
216
|
name: 'facebookDescription',
|
|
217
217
|
type: 'string',
|
|
218
218
|
default: '',
|
|
219
|
-
description: '
|
|
219
|
+
description: 'Override for Facebook description/message when supported (Reels/feed, albums). Falls back to the main title when empty.',
|
|
220
220
|
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo'], platform: ['facebook'] } },
|
|
221
221
|
},
|
|
222
222
|
{
|
|
@@ -224,31 +224,23 @@ class UploadPost {
|
|
|
224
224
|
name: 'tiktokDescription',
|
|
225
225
|
type: 'string',
|
|
226
226
|
default: '',
|
|
227
|
-
description: '
|
|
228
|
-
displayOptions: { show: { operation: ['uploadPhotos'
|
|
227
|
+
description: 'Override for TikTok photo post description. Video uploads ignore this value.',
|
|
228
|
+
displayOptions: { show: { operation: ['uploadPhotos'], platform: ['tiktok'] } },
|
|
229
229
|
},
|
|
230
230
|
{
|
|
231
231
|
displayName: 'LinkedIn Description (Override)',
|
|
232
232
|
name: 'linkedinDescription',
|
|
233
233
|
type: 'string',
|
|
234
234
|
default: '',
|
|
235
|
-
description: '
|
|
235
|
+
description: 'Override for LinkedIn post commentary. When empty we repeat the main title.',
|
|
236
236
|
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo'], platform: ['linkedin'] } },
|
|
237
237
|
},
|
|
238
|
-
{
|
|
239
|
-
displayName: 'X Description (Override)',
|
|
240
|
-
name: 'xDescription',
|
|
241
|
-
type: 'string',
|
|
242
|
-
default: '',
|
|
243
|
-
description: 'Optional description override for X',
|
|
244
|
-
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo'], platform: ['x'] } },
|
|
245
|
-
},
|
|
246
238
|
{
|
|
247
239
|
displayName: 'YouTube Description (Override)',
|
|
248
240
|
name: 'youtubeDescription',
|
|
249
241
|
type: 'string',
|
|
250
242
|
default: '',
|
|
251
|
-
description: '
|
|
243
|
+
description: 'Override for YouTube video description. When empty we default to the main title.',
|
|
252
244
|
displayOptions: { show: { operation: ['uploadVideo'], platform: ['youtube'] } },
|
|
253
245
|
},
|
|
254
246
|
{
|
|
@@ -256,16 +248,21 @@ class UploadPost {
|
|
|
256
248
|
name: 'pinterestDescription',
|
|
257
249
|
type: 'string',
|
|
258
250
|
default: '',
|
|
259
|
-
description: '
|
|
251
|
+
description: 'Override for Pinterest pin description (and alt text fallback). When empty we re-use the main title.',
|
|
260
252
|
displayOptions: { show: { operation: ['uploadPhotos', 'uploadVideo'], platform: ['pinterest'] } },
|
|
261
253
|
},
|
|
262
254
|
{
|
|
263
|
-
displayName: '
|
|
264
|
-
name: '
|
|
255
|
+
displayName: 'Photos (Files or URLs)',
|
|
256
|
+
name: 'photos',
|
|
265
257
|
type: 'string',
|
|
258
|
+
required: true,
|
|
266
259
|
default: '',
|
|
267
|
-
description: '
|
|
268
|
-
displayOptions: {
|
|
260
|
+
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.',
|
|
261
|
+
displayOptions: {
|
|
262
|
+
show: {
|
|
263
|
+
operation: ['uploadPhotos'],
|
|
264
|
+
},
|
|
265
|
+
},
|
|
269
266
|
},
|
|
270
267
|
{
|
|
271
268
|
displayName: 'Video (File or URL)',
|
|
@@ -304,7 +301,7 @@ class UploadPost {
|
|
|
304
301
|
displayName: 'Wait for Completion',
|
|
305
302
|
name: 'waitForCompletion',
|
|
306
303
|
type: 'boolean',
|
|
307
|
-
default:
|
|
304
|
+
default: true,
|
|
308
305
|
description: 'Whether to perform best-effort sleeping between status checks within this node. Not guaranteed to finish; for reliable long polling use a separate Wait node plus Get Upload Status.',
|
|
309
306
|
displayOptions: {
|
|
310
307
|
show: {
|
|
@@ -510,9 +507,10 @@ class UploadPost {
|
|
|
510
507
|
displayName: 'Target LinkedIn Page Name or ID',
|
|
511
508
|
name: 'targetLinkedinPageId',
|
|
512
509
|
type: 'options',
|
|
510
|
+
noDataExpression: true,
|
|
513
511
|
default: '',
|
|
514
512
|
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
515
|
-
typeOptions: { loadOptionsMethod: 'getLinkedinPages' },
|
|
513
|
+
typeOptions: { loadOptionsMethod: 'getLinkedinPages', loadOptionsDependsOn: ['user'] },
|
|
516
514
|
displayOptions: {
|
|
517
515
|
show: {
|
|
518
516
|
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
@@ -520,6 +518,21 @@ class UploadPost {
|
|
|
520
518
|
}
|
|
521
519
|
},
|
|
522
520
|
},
|
|
521
|
+
{
|
|
522
|
+
displayName: 'LinkedIn Page Name or ID (Manual Entry)',
|
|
523
|
+
name: 'targetLinkedinPageIdManual',
|
|
524
|
+
type: 'string',
|
|
525
|
+
required: true,
|
|
526
|
+
default: '',
|
|
527
|
+
description: 'Provide the LinkedIn page identifier when it does not appear in the list',
|
|
528
|
+
displayOptions: {
|
|
529
|
+
show: {
|
|
530
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
531
|
+
platform: ['linkedin'],
|
|
532
|
+
targetLinkedinPageId: [MANUAL_LINKEDIN_VALUE]
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
},
|
|
523
536
|
{
|
|
524
537
|
displayName: 'LinkedIn Video Description',
|
|
525
538
|
name: 'linkedinDescription',
|
|
@@ -537,10 +550,11 @@ class UploadPost {
|
|
|
537
550
|
displayName: 'Facebook Page Name or ID',
|
|
538
551
|
name: 'facebookPageId',
|
|
539
552
|
type: 'options',
|
|
553
|
+
noDataExpression: true,
|
|
540
554
|
required: true,
|
|
541
555
|
default: '',
|
|
542
556
|
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
543
|
-
typeOptions: { loadOptionsMethod: 'getFacebookPages' },
|
|
557
|
+
typeOptions: { loadOptionsMethod: 'getFacebookPages', loadOptionsDependsOn: ['user'] },
|
|
544
558
|
displayOptions: {
|
|
545
559
|
show: {
|
|
546
560
|
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
@@ -548,6 +562,21 @@ class UploadPost {
|
|
|
548
562
|
}
|
|
549
563
|
},
|
|
550
564
|
},
|
|
565
|
+
{
|
|
566
|
+
displayName: 'Facebook Page Name or ID (Manual Entry)',
|
|
567
|
+
name: 'facebookPageIdManual',
|
|
568
|
+
type: 'string',
|
|
569
|
+
required: true,
|
|
570
|
+
default: '',
|
|
571
|
+
description: 'Provide the Facebook page identifier when it does not appear in the list',
|
|
572
|
+
displayOptions: {
|
|
573
|
+
show: {
|
|
574
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
575
|
+
platform: ['facebook'],
|
|
576
|
+
facebookPageId: [MANUAL_FACEBOOK_VALUE]
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
},
|
|
551
580
|
{
|
|
552
581
|
displayName: 'Facebook Link (Text)',
|
|
553
582
|
name: 'facebookLink',
|
|
@@ -581,10 +610,9 @@ class UploadPost {
|
|
|
581
610
|
options: [
|
|
582
611
|
{ name: 'Published', value: 'PUBLISHED' },
|
|
583
612
|
{ name: 'Draft', value: 'DRAFT' },
|
|
584
|
-
{ name: 'Scheduled', value: 'SCHEDULED' },
|
|
585
613
|
],
|
|
586
614
|
default: 'PUBLISHED',
|
|
587
|
-
description: 'State for Facebook Video (DRAFT
|
|
615
|
+
description: 'State for Facebook Video (DRAFT or PUBLISHED). Use Scheduled Date field for scheduling.',
|
|
588
616
|
displayOptions: {
|
|
589
617
|
show: {
|
|
590
618
|
operation: ['uploadVideo'],
|
|
@@ -636,11 +664,12 @@ class UploadPost {
|
|
|
636
664
|
},
|
|
637
665
|
},
|
|
638
666
|
{
|
|
639
|
-
displayName: 'TikTok
|
|
640
|
-
name: '
|
|
641
|
-
type: '
|
|
642
|
-
default:
|
|
643
|
-
|
|
667
|
+
displayName: 'TikTok Photo Cover Index',
|
|
668
|
+
name: 'tiktokPhotoCoverIndex',
|
|
669
|
+
type: 'number',
|
|
670
|
+
default: 0,
|
|
671
|
+
typeOptions: { minValue: 0 },
|
|
672
|
+
description: 'Index (0-based) of photo to use as cover for TikTok photo post. Only for Upload Photos.',
|
|
644
673
|
displayOptions: {
|
|
645
674
|
show: {
|
|
646
675
|
operation: ['uploadPhotos'],
|
|
@@ -649,11 +678,11 @@ class UploadPost {
|
|
|
649
678
|
},
|
|
650
679
|
},
|
|
651
680
|
{
|
|
652
|
-
displayName: 'TikTok
|
|
653
|
-
name: '
|
|
654
|
-
type: '
|
|
655
|
-
default:
|
|
656
|
-
description: '
|
|
681
|
+
displayName: 'TikTok Photo Description',
|
|
682
|
+
name: 'tiktokPhotoDescription',
|
|
683
|
+
type: 'string',
|
|
684
|
+
default: '',
|
|
685
|
+
description: 'Description for TikTok photo post. If not provided, Title is used. Only for Upload Photos.',
|
|
657
686
|
displayOptions: {
|
|
658
687
|
show: {
|
|
659
688
|
operation: ['uploadPhotos'],
|
|
@@ -662,12 +691,11 @@ class UploadPost {
|
|
|
662
691
|
},
|
|
663
692
|
},
|
|
664
693
|
{
|
|
665
|
-
displayName: 'TikTok
|
|
666
|
-
name: '
|
|
667
|
-
type: '
|
|
668
|
-
default:
|
|
669
|
-
|
|
670
|
-
description: 'Index (0-based) of photo to use as cover for TikTok photo post. Only for Upload Photos.',
|
|
694
|
+
displayName: 'TikTok Brand Content Toggle (Photo)',
|
|
695
|
+
name: 'brand_content_toggle',
|
|
696
|
+
type: 'boolean',
|
|
697
|
+
default: false,
|
|
698
|
+
description: 'Whether to set as true for paid partnerships that promote third-party brands',
|
|
671
699
|
displayOptions: {
|
|
672
700
|
show: {
|
|
673
701
|
operation: ['uploadPhotos'],
|
|
@@ -676,11 +704,11 @@ class UploadPost {
|
|
|
676
704
|
},
|
|
677
705
|
},
|
|
678
706
|
{
|
|
679
|
-
displayName: 'TikTok Photo
|
|
680
|
-
name: '
|
|
681
|
-
type: '
|
|
682
|
-
default:
|
|
683
|
-
description: '
|
|
707
|
+
displayName: 'TikTok Brand Organic Toggle (Photo)',
|
|
708
|
+
name: 'brand_organic_toggle',
|
|
709
|
+
type: 'boolean',
|
|
710
|
+
default: false,
|
|
711
|
+
description: 'Whether to set as true when promoting the creator\'s own business',
|
|
684
712
|
displayOptions: {
|
|
685
713
|
show: {
|
|
686
714
|
operation: ['uploadPhotos'],
|
|
@@ -748,36 +776,10 @@ class UploadPost {
|
|
|
748
776
|
},
|
|
749
777
|
{
|
|
750
778
|
displayName: 'TikTok Brand Content Toggle (Video)',
|
|
751
|
-
name: '
|
|
752
|
-
type: 'boolean',
|
|
753
|
-
default: false,
|
|
754
|
-
description: 'Whether to enable branded content for TikTok video. Only for Upload Video.',
|
|
755
|
-
displayOptions: {
|
|
756
|
-
show: {
|
|
757
|
-
operation: ['uploadVideo'],
|
|
758
|
-
platform: ['tiktok']
|
|
759
|
-
},
|
|
760
|
-
},
|
|
761
|
-
},
|
|
762
|
-
{
|
|
763
|
-
displayName: 'TikTok Brand Organic (Video)',
|
|
764
|
-
name: 'tiktokBrandOrganic',
|
|
779
|
+
name: 'brand_content_toggle',
|
|
765
780
|
type: 'boolean',
|
|
766
781
|
default: false,
|
|
767
|
-
description: 'Whether to enable
|
|
768
|
-
displayOptions: {
|
|
769
|
-
show: {
|
|
770
|
-
operation: ['uploadVideo'],
|
|
771
|
-
platform: ['tiktok']
|
|
772
|
-
},
|
|
773
|
-
},
|
|
774
|
-
},
|
|
775
|
-
{
|
|
776
|
-
displayName: 'TikTok Branded Content (Video)',
|
|
777
|
-
name: 'tiktokBrandedContentVideo',
|
|
778
|
-
type: 'boolean',
|
|
779
|
-
default: false,
|
|
780
|
-
description: 'Whether to enable branded content with disclosure for TikTok video. Only for Upload Video.',
|
|
782
|
+
description: 'Whether to enable brand content toggle for paid partnerships that promote third-party brands',
|
|
781
783
|
displayOptions: {
|
|
782
784
|
show: {
|
|
783
785
|
operation: ['uploadVideo'],
|
|
@@ -787,10 +789,10 @@ class UploadPost {
|
|
|
787
789
|
},
|
|
788
790
|
{
|
|
789
791
|
displayName: 'TikTok Brand Organic Toggle (Video)',
|
|
790
|
-
name: '
|
|
792
|
+
name: 'brand_organic_toggle',
|
|
791
793
|
type: 'boolean',
|
|
792
794
|
default: false,
|
|
793
|
-
description: 'Whether to enable organic
|
|
795
|
+
description: 'Whether to enable brand organic toggle when promoting the creator\'s own business',
|
|
794
796
|
displayOptions: {
|
|
795
797
|
show: {
|
|
796
798
|
operation: ['uploadVideo'],
|
|
@@ -938,17 +940,29 @@ class UploadPost {
|
|
|
938
940
|
},
|
|
939
941
|
},
|
|
940
942
|
{
|
|
941
|
-
displayName: '
|
|
942
|
-
name: '
|
|
943
|
+
displayName: 'Threads Long Text as Single Post',
|
|
944
|
+
name: 'threadsLongTextAsPost',
|
|
945
|
+
type: 'boolean',
|
|
946
|
+
default: false,
|
|
947
|
+
description: 'Whether long text is published as a single post. If false (default), a thread is created if the text exceeds 500 characters.',
|
|
948
|
+
displayOptions: { show: { operation: ['uploadText'], platform: ['threads'] } },
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
displayName: 'Reddit Subreddit',
|
|
952
|
+
name: 'redditSubreddit',
|
|
943
953
|
type: 'string',
|
|
954
|
+
required: true,
|
|
944
955
|
default: '',
|
|
945
|
-
description: '
|
|
946
|
-
displayOptions: {
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
956
|
+
description: 'Destination subreddit, without r/ (e.g., python)',
|
|
957
|
+
displayOptions: { show: { operation: ['uploadText'] } },
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
displayName: 'Reddit Flair ID',
|
|
961
|
+
name: 'redditFlairId',
|
|
962
|
+
type: 'string',
|
|
963
|
+
default: '',
|
|
964
|
+
description: 'ID of the flair template to apply to the post',
|
|
965
|
+
displayOptions: { show: { operation: ['uploadText'], platform: ['reddit'] } },
|
|
952
966
|
},
|
|
953
967
|
{
|
|
954
968
|
displayName: 'YouTube Tags',
|
|
@@ -1063,20 +1077,142 @@ class UploadPost {
|
|
|
1063
1077
|
},
|
|
1064
1078
|
},
|
|
1065
1079
|
},
|
|
1080
|
+
{
|
|
1081
|
+
displayName: 'YouTube Self Declared Made For Kids',
|
|
1082
|
+
name: 'youtubeSelfDeclaredMadeForKids',
|
|
1083
|
+
type: 'boolean',
|
|
1084
|
+
default: false,
|
|
1085
|
+
description: 'Whether this is an explicit declaration for children content (COPPA compliance). Only for Upload Video.',
|
|
1086
|
+
displayOptions: {
|
|
1087
|
+
show: {
|
|
1088
|
+
operation: ['uploadVideo'],
|
|
1089
|
+
platform: ['youtube']
|
|
1090
|
+
},
|
|
1091
|
+
},
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
displayName: 'YouTube Contains Synthetic Media',
|
|
1095
|
+
name: 'youtubeContainsSyntheticMedia',
|
|
1096
|
+
type: 'boolean',
|
|
1097
|
+
default: false,
|
|
1098
|
+
description: 'Whether this is a declaration for AI/synthetic content transparency. Only for Upload Video.',
|
|
1099
|
+
displayOptions: {
|
|
1100
|
+
show: {
|
|
1101
|
+
operation: ['uploadVideo'],
|
|
1102
|
+
platform: ['youtube']
|
|
1103
|
+
},
|
|
1104
|
+
},
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
displayName: 'YouTube Default Language',
|
|
1108
|
+
name: 'youtubeDefaultLanguage',
|
|
1109
|
+
type: 'string',
|
|
1110
|
+
default: '',
|
|
1111
|
+
description: 'Title/description language (BCP-47 codes like "es", "en"). Only for Upload Video.',
|
|
1112
|
+
displayOptions: {
|
|
1113
|
+
show: {
|
|
1114
|
+
operation: ['uploadVideo'],
|
|
1115
|
+
platform: ['youtube']
|
|
1116
|
+
},
|
|
1117
|
+
},
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
displayName: 'YouTube Default Audio Language',
|
|
1121
|
+
name: 'youtubeDefaultAudioLanguage',
|
|
1122
|
+
type: 'string',
|
|
1123
|
+
default: '',
|
|
1124
|
+
description: 'Video audio language (BCP-47 codes like "es-ES", "en-US"). Only for Upload Video.',
|
|
1125
|
+
displayOptions: {
|
|
1126
|
+
show: {
|
|
1127
|
+
operation: ['uploadVideo'],
|
|
1128
|
+
platform: ['youtube']
|
|
1129
|
+
},
|
|
1130
|
+
},
|
|
1131
|
+
},
|
|
1132
|
+
{
|
|
1133
|
+
displayName: 'YouTube Allowed Countries',
|
|
1134
|
+
name: 'youtubeAllowedCountries',
|
|
1135
|
+
type: 'string',
|
|
1136
|
+
default: '',
|
|
1137
|
+
description: 'Comma-separated country codes for allowed regions (ISO 3166-1 alpha-2). Cannot be used with blocked countries. Only for Upload Video.',
|
|
1138
|
+
displayOptions: {
|
|
1139
|
+
show: {
|
|
1140
|
+
operation: ['uploadVideo'],
|
|
1141
|
+
platform: ['youtube']
|
|
1142
|
+
},
|
|
1143
|
+
},
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
displayName: 'YouTube Blocked Countries',
|
|
1147
|
+
name: 'youtubeBlockedCountries',
|
|
1148
|
+
type: 'string',
|
|
1149
|
+
default: '',
|
|
1150
|
+
description: 'Comma-separated country codes for blocked regions (ISO 3166-1 alpha-2). Cannot be used with allowed countries. Only for Upload Video.',
|
|
1151
|
+
displayOptions: {
|
|
1152
|
+
show: {
|
|
1153
|
+
operation: ['uploadVideo'],
|
|
1154
|
+
platform: ['youtube']
|
|
1155
|
+
},
|
|
1156
|
+
},
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
displayName: 'YouTube Has Paid Product Placement',
|
|
1160
|
+
name: 'youtubeHasPaidProductPlacement',
|
|
1161
|
+
type: 'boolean',
|
|
1162
|
+
default: false,
|
|
1163
|
+
description: 'Whether this is a declaration for paid product placements (FTC compliance). Only for Upload Video.',
|
|
1164
|
+
displayOptions: {
|
|
1165
|
+
show: {
|
|
1166
|
+
operation: ['uploadVideo'],
|
|
1167
|
+
platform: ['youtube']
|
|
1168
|
+
},
|
|
1169
|
+
},
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
displayName: 'YouTube Recording Date',
|
|
1173
|
+
name: 'youtubeRecordingDate',
|
|
1174
|
+
type: 'dateTime',
|
|
1175
|
+
default: '',
|
|
1176
|
+
description: 'Recording timestamp (ISO 8601 format). Only for Upload Video.',
|
|
1177
|
+
displayOptions: {
|
|
1178
|
+
show: {
|
|
1179
|
+
operation: ['uploadVideo'],
|
|
1180
|
+
platform: ['youtube']
|
|
1181
|
+
},
|
|
1182
|
+
},
|
|
1183
|
+
},
|
|
1066
1184
|
{
|
|
1067
1185
|
displayName: 'Pinterest Board Name or ID',
|
|
1068
1186
|
name: 'pinterestBoardId',
|
|
1069
1187
|
type: 'options',
|
|
1188
|
+
noDataExpression: true,
|
|
1070
1189
|
default: '',
|
|
1071
1190
|
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
|
1072
|
-
typeOptions: { loadOptionsMethod: 'getPinterestBoards' },
|
|
1191
|
+
typeOptions: { loadOptionsMethod: 'getPinterestBoards', loadOptionsDependsOn: ['user'] },
|
|
1073
1192
|
displayOptions: {
|
|
1074
1193
|
show: {
|
|
1075
1194
|
resource: ['uploads'],
|
|
1195
|
+
operation: ['uploadPhotos', 'uploadVideo'],
|
|
1076
1196
|
platform: ['pinterest']
|
|
1077
1197
|
},
|
|
1078
1198
|
},
|
|
1079
1199
|
},
|
|
1200
|
+
{
|
|
1201
|
+
displayName: 'Pinterest Board Name or ID (Manual Entry)',
|
|
1202
|
+
name: 'pinterestBoardIdManual',
|
|
1203
|
+
type: 'string',
|
|
1204
|
+
required: true,
|
|
1205
|
+
default: '',
|
|
1206
|
+
description: 'Provide the Pinterest board identifier when it does not appear in the list',
|
|
1207
|
+
displayOptions: {
|
|
1208
|
+
show: {
|
|
1209
|
+
resource: ['uploads'],
|
|
1210
|
+
operation: ['uploadPhotos', 'uploadVideo'],
|
|
1211
|
+
platform: ['pinterest'],
|
|
1212
|
+
pinterestBoardId: [MANUAL_PINTEREST_VALUE]
|
|
1213
|
+
},
|
|
1214
|
+
},
|
|
1215
|
+
},
|
|
1080
1216
|
{
|
|
1081
1217
|
displayName: 'Pinterest Link (Photo/Video)',
|
|
1082
1218
|
name: 'pinterestLink',
|
|
@@ -1149,58 +1285,47 @@ class UploadPost {
|
|
|
1149
1285
|
},
|
|
1150
1286
|
},
|
|
1151
1287
|
{
|
|
1152
|
-
displayName: '
|
|
1153
|
-
name: 'threadsDescription',
|
|
1154
|
-
type: 'string',
|
|
1155
|
-
default: '',
|
|
1156
|
-
description: 'User commentary for Threads video. If not provided, Title is used. Not for Photos/Text.',
|
|
1157
|
-
displayOptions: {
|
|
1158
|
-
show: {
|
|
1159
|
-
operation: ['uploadVideo'],
|
|
1160
|
-
platform: ['threads']
|
|
1161
|
-
},
|
|
1162
|
-
},
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
displayName: 'X Tagged User IDs (Video/Text)',
|
|
1288
|
+
displayName: 'X Tagged User IDs',
|
|
1166
1289
|
name: 'xTaggedUserIds',
|
|
1167
1290
|
type: 'string',
|
|
1168
1291
|
default: '',
|
|
1169
|
-
description: 'Comma-separated list of user IDs to tag for X (Twitter)
|
|
1292
|
+
description: 'Comma-separated list of user IDs to tag for X (Twitter)',
|
|
1170
1293
|
displayOptions: {
|
|
1171
1294
|
show: {
|
|
1172
|
-
operation: ['
|
|
1295
|
+
operation: ['uploadPhotos', 'uploadVideo'],
|
|
1173
1296
|
platform: ['x']
|
|
1174
1297
|
},
|
|
1175
1298
|
},
|
|
1176
1299
|
},
|
|
1177
1300
|
{
|
|
1178
|
-
displayName: 'X Reply Settings
|
|
1301
|
+
displayName: 'X Reply Settings',
|
|
1179
1302
|
name: 'xReplySettings',
|
|
1180
1303
|
type: 'options',
|
|
1181
1304
|
options: [
|
|
1305
|
+
{ name: 'Everyone', value: 'everyone' },
|
|
1182
1306
|
{ name: 'Following', value: 'following' },
|
|
1183
1307
|
{ name: 'Mentioned Users', value: 'mentionedUsers' },
|
|
1184
|
-
{ name: '
|
|
1308
|
+
{ name: 'Subscribers', value: 'subscribers' },
|
|
1309
|
+
{ name: 'Verified', value: 'verified' },
|
|
1185
1310
|
],
|
|
1186
|
-
default: '
|
|
1187
|
-
description: 'Who can reply to the post on X (Twitter)
|
|
1311
|
+
default: 'everyone',
|
|
1312
|
+
description: 'Who can reply to the post on X (Twitter)',
|
|
1188
1313
|
displayOptions: {
|
|
1189
1314
|
show: {
|
|
1190
|
-
operation: ['uploadVideo', 'uploadText'],
|
|
1315
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1191
1316
|
platform: ['x']
|
|
1192
1317
|
},
|
|
1193
1318
|
},
|
|
1194
1319
|
},
|
|
1195
1320
|
{
|
|
1196
|
-
displayName: 'X Nullcast
|
|
1321
|
+
displayName: 'X Nullcast',
|
|
1197
1322
|
name: 'xNullcastVideo',
|
|
1198
1323
|
type: 'boolean',
|
|
1199
1324
|
default: false,
|
|
1200
|
-
description: 'Whether to publish X (Twitter)
|
|
1325
|
+
description: 'Whether to publish X (Twitter) post without broadcasting (promoted-only posts)',
|
|
1201
1326
|
displayOptions: {
|
|
1202
1327
|
show: {
|
|
1203
|
-
operation: ['uploadVideo'],
|
|
1328
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1204
1329
|
platform: ['x']
|
|
1205
1330
|
},
|
|
1206
1331
|
},
|
|
@@ -1219,47 +1344,48 @@ class UploadPost {
|
|
|
1219
1344
|
},
|
|
1220
1345
|
},
|
|
1221
1346
|
{
|
|
1222
|
-
displayName: 'X Poll Duration (Minutes
|
|
1223
|
-
name: '
|
|
1347
|
+
displayName: 'X Poll Duration (Minutes)',
|
|
1348
|
+
name: 'xPollDuration',
|
|
1224
1349
|
type: 'number',
|
|
1225
1350
|
default: 1440,
|
|
1226
|
-
description: 'Poll duration in minutes for X (Twitter)
|
|
1351
|
+
description: 'Poll duration in minutes for X (Twitter) post (requires Poll Options)',
|
|
1227
1352
|
displayOptions: {
|
|
1228
1353
|
show: {
|
|
1229
|
-
operation: ['
|
|
1354
|
+
operation: ['uploadText'],
|
|
1230
1355
|
platform: ['x']
|
|
1231
|
-
}
|
|
1356
|
+
}
|
|
1232
1357
|
},
|
|
1233
1358
|
},
|
|
1234
1359
|
{
|
|
1235
|
-
displayName: 'X Poll Options
|
|
1236
|
-
name: '
|
|
1360
|
+
displayName: 'X Poll Options',
|
|
1361
|
+
name: 'xPollOptions',
|
|
1237
1362
|
type: 'string',
|
|
1238
1363
|
default: '',
|
|
1239
|
-
description: 'Comma-separated list of poll options for X (Twitter)
|
|
1364
|
+
description: 'Comma-separated list of poll options for X (Twitter) post',
|
|
1240
1365
|
displayOptions: {
|
|
1241
1366
|
show: {
|
|
1242
|
-
operation: ['
|
|
1367
|
+
operation: ['uploadText'],
|
|
1243
1368
|
platform: ['x']
|
|
1244
|
-
}
|
|
1369
|
+
}
|
|
1245
1370
|
},
|
|
1246
1371
|
},
|
|
1247
1372
|
{
|
|
1248
|
-
displayName: 'X Poll Reply Settings
|
|
1249
|
-
name: '
|
|
1373
|
+
displayName: 'X Poll Reply Settings',
|
|
1374
|
+
name: 'xPollReplySettings',
|
|
1250
1375
|
type: 'options',
|
|
1251
1376
|
options: [
|
|
1252
1377
|
{ name: 'Following', value: 'following' },
|
|
1253
1378
|
{ name: 'Mentioned Users', value: 'mentionedUsers' },
|
|
1254
1379
|
{ name: 'Everyone', value: 'everyone' },
|
|
1380
|
+
{ name: 'Subscribers', value: 'subscribers' },
|
|
1255
1381
|
],
|
|
1256
1382
|
default: 'following',
|
|
1257
|
-
description: 'Who can reply to the poll in X (Twitter)
|
|
1383
|
+
description: 'Who can reply to the poll in X (Twitter) post',
|
|
1258
1384
|
displayOptions: {
|
|
1259
1385
|
show: {
|
|
1260
|
-
operation: ['
|
|
1386
|
+
operation: ['uploadText'],
|
|
1261
1387
|
platform: ['x']
|
|
1262
|
-
}
|
|
1388
|
+
}
|
|
1263
1389
|
},
|
|
1264
1390
|
},
|
|
1265
1391
|
{
|
|
@@ -1276,111 +1402,257 @@ class UploadPost {
|
|
|
1276
1402
|
},
|
|
1277
1403
|
},
|
|
1278
1404
|
{
|
|
1279
|
-
displayName: 'X
|
|
1280
|
-
name: '
|
|
1405
|
+
displayName: 'X Quote Tweet ID',
|
|
1406
|
+
name: 'xQuoteTweetId',
|
|
1407
|
+
type: 'string',
|
|
1408
|
+
default: '',
|
|
1409
|
+
description: 'ID of the tweet to quote in a quote tweet',
|
|
1410
|
+
displayOptions: {
|
|
1411
|
+
show: {
|
|
1412
|
+
operation: ['uploadText'],
|
|
1413
|
+
platform: ['x']
|
|
1414
|
+
}
|
|
1415
|
+
},
|
|
1416
|
+
},
|
|
1417
|
+
{
|
|
1418
|
+
displayName: 'X Geo Place ID',
|
|
1419
|
+
name: 'xGeoPlaceId',
|
|
1420
|
+
type: 'string',
|
|
1421
|
+
default: '',
|
|
1422
|
+
description: 'Geographic place ID to add location to the tweet',
|
|
1423
|
+
displayOptions: {
|
|
1424
|
+
show: {
|
|
1425
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1426
|
+
platform: ['x']
|
|
1427
|
+
},
|
|
1428
|
+
},
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
displayName: 'X For Super Followers Only',
|
|
1432
|
+
name: 'xForSuperFollowersOnly',
|
|
1281
1433
|
type: 'boolean',
|
|
1282
1434
|
default: false,
|
|
1283
|
-
description: 'Whether
|
|
1435
|
+
description: 'Whether the tweet is exclusive for super followers',
|
|
1284
1436
|
displayOptions: {
|
|
1285
1437
|
show: {
|
|
1286
|
-
operation: ['uploadVideo', 'uploadText'],
|
|
1438
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1287
1439
|
platform: ['x']
|
|
1288
1440
|
},
|
|
1289
1441
|
},
|
|
1290
1442
|
},
|
|
1291
1443
|
{
|
|
1292
|
-
displayName: '
|
|
1293
|
-
name: '
|
|
1444
|
+
displayName: 'X Community ID',
|
|
1445
|
+
name: 'xCommunityId',
|
|
1294
1446
|
type: 'string',
|
|
1295
1447
|
default: '',
|
|
1296
|
-
description: '
|
|
1448
|
+
description: 'Community ID for posting in specific communities',
|
|
1297
1449
|
displayOptions: {
|
|
1298
1450
|
show: {
|
|
1299
|
-
operation: ['uploadPhotos', 'uploadVideo']
|
|
1300
|
-
|
|
1451
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1452
|
+
platform: ['x']
|
|
1453
|
+
},
|
|
1301
1454
|
},
|
|
1302
1455
|
},
|
|
1303
1456
|
{
|
|
1304
|
-
displayName: '
|
|
1305
|
-
name: '
|
|
1306
|
-
type: '
|
|
1307
|
-
default:
|
|
1308
|
-
description: '
|
|
1309
|
-
displayOptions: {
|
|
1457
|
+
displayName: 'X Share with Followers',
|
|
1458
|
+
name: 'xShareWithFollowers',
|
|
1459
|
+
type: 'boolean',
|
|
1460
|
+
default: false,
|
|
1461
|
+
description: 'Whether to share community post with followers',
|
|
1462
|
+
displayOptions: {
|
|
1463
|
+
show: {
|
|
1464
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1465
|
+
platform: ['x']
|
|
1466
|
+
},
|
|
1467
|
+
},
|
|
1310
1468
|
},
|
|
1311
1469
|
{
|
|
1312
|
-
displayName: '
|
|
1313
|
-
name: '
|
|
1470
|
+
displayName: 'X Direct Message Deep Link',
|
|
1471
|
+
name: 'xDirectMessageDeepLink',
|
|
1314
1472
|
type: 'string',
|
|
1315
1473
|
default: '',
|
|
1316
|
-
description: '
|
|
1317
|
-
displayOptions: {
|
|
1474
|
+
description: 'Link to take the conversation from public timeline to private Direct Message',
|
|
1475
|
+
displayOptions: {
|
|
1476
|
+
show: {
|
|
1477
|
+
operation: ['uploadPhotos', 'uploadVideo', 'uploadText'],
|
|
1478
|
+
platform: ['x']
|
|
1479
|
+
}
|
|
1480
|
+
},
|
|
1318
1481
|
},
|
|
1319
1482
|
{
|
|
1320
|
-
displayName: '
|
|
1321
|
-
name: '
|
|
1483
|
+
displayName: 'X Card URI',
|
|
1484
|
+
name: 'xCardUri',
|
|
1322
1485
|
type: 'string',
|
|
1323
1486
|
default: '',
|
|
1324
|
-
description: '
|
|
1325
|
-
displayOptions: {
|
|
1487
|
+
description: 'URI of card (for Twitter Cards/ads/promoted content)',
|
|
1488
|
+
displayOptions: {
|
|
1489
|
+
show: {
|
|
1490
|
+
operation: ['uploadText'],
|
|
1491
|
+
platform: ['x']
|
|
1492
|
+
}
|
|
1493
|
+
},
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
displayName: 'X Long Text as Single Post',
|
|
1497
|
+
name: 'xLongTextAsPost',
|
|
1498
|
+
type: 'boolean',
|
|
1499
|
+
default: false,
|
|
1500
|
+
description: 'Whether to post long text as a single post instead of splitting into a thread (if supported)',
|
|
1501
|
+
displayOptions: {
|
|
1502
|
+
show: {
|
|
1503
|
+
operation: ['uploadVideo', 'uploadText'],
|
|
1504
|
+
platform: ['x']
|
|
1505
|
+
},
|
|
1506
|
+
},
|
|
1326
1507
|
},
|
|
1327
1508
|
],
|
|
1328
1509
|
};
|
|
1329
1510
|
this.methods = {
|
|
1330
1511
|
loadOptions: {
|
|
1331
|
-
async
|
|
1332
|
-
const
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1512
|
+
async getPlatforms() {
|
|
1513
|
+
const operation = this.getCurrentNodeParameter('operation');
|
|
1514
|
+
const allPlatforms = [
|
|
1515
|
+
{ name: 'Facebook', value: 'facebook' },
|
|
1516
|
+
{ name: 'Instagram', value: 'instagram' },
|
|
1517
|
+
{ name: 'LinkedIn', value: 'linkedin' },
|
|
1518
|
+
{ name: 'Pinterest', value: 'pinterest' },
|
|
1519
|
+
{ name: 'Reddit', value: 'reddit' },
|
|
1520
|
+
{ name: 'Threads', value: 'threads' },
|
|
1521
|
+
{ name: 'TikTok', value: 'tiktok' },
|
|
1522
|
+
{ name: 'X (Twitter)', value: 'x' },
|
|
1523
|
+
{ name: 'YouTube', value: 'youtube' },
|
|
1524
|
+
];
|
|
1525
|
+
const platformSupport = {
|
|
1526
|
+
uploadPhotos: ['facebook', 'instagram', 'linkedin', 'pinterest', 'threads', 'tiktok', 'x'],
|
|
1527
|
+
uploadVideo: ['facebook', 'instagram', 'linkedin', 'pinterest', 'threads', 'tiktok', 'x', 'youtube'],
|
|
1528
|
+
uploadText: ['facebook', 'linkedin', 'reddit', 'threads', 'x'],
|
|
1344
1529
|
};
|
|
1345
|
-
const
|
|
1346
|
-
|
|
1347
|
-
|
|
1530
|
+
const supportedPlatforms = platformSupport[operation] || [];
|
|
1531
|
+
return allPlatforms.filter(platform => supportedPlatforms.includes(platform.value));
|
|
1532
|
+
},
|
|
1533
|
+
async getFacebookPages() {
|
|
1534
|
+
try {
|
|
1535
|
+
const credentials = await this.getCredentials('uploadPostApi');
|
|
1536
|
+
const apiKey = credentials.apiKey;
|
|
1537
|
+
const profile = this.getCurrentNodeParameter('user') || '';
|
|
1538
|
+
const qs = {};
|
|
1539
|
+
if (profile)
|
|
1540
|
+
qs.profile = profile;
|
|
1541
|
+
const options = {
|
|
1542
|
+
uri: 'https://api.upload-post.com/api/uploadposts/facebook/pages',
|
|
1543
|
+
method: 'GET',
|
|
1544
|
+
headers: { Authorization: `ApiKey ${apiKey}` },
|
|
1545
|
+
qs,
|
|
1546
|
+
json: true,
|
|
1547
|
+
};
|
|
1548
|
+
const resp = await this.helpers.request(options);
|
|
1549
|
+
const pages = (resp && (resp.pages || resp.data || []));
|
|
1550
|
+
const pageOptions = (pages || []).map(p => ({ name: p.name ? `${p.name} (${p.id})` : p.id, value: p.id }));
|
|
1551
|
+
return [
|
|
1552
|
+
{ name: 'Manual entry...', value: MANUAL_FACEBOOK_VALUE },
|
|
1553
|
+
...pageOptions
|
|
1554
|
+
];
|
|
1555
|
+
}
|
|
1556
|
+
catch (error) {
|
|
1557
|
+
return [
|
|
1558
|
+
{ name: 'Manual entry...', value: MANUAL_FACEBOOK_VALUE }
|
|
1559
|
+
];
|
|
1560
|
+
}
|
|
1348
1561
|
},
|
|
1349
1562
|
async getLinkedinPages() {
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1563
|
+
try {
|
|
1564
|
+
const credentials = await this.getCredentials('uploadPostApi');
|
|
1565
|
+
const apiKey = credentials.apiKey;
|
|
1566
|
+
const profile = this.getCurrentNodeParameter('user') || '';
|
|
1567
|
+
const qs = {};
|
|
1568
|
+
if (profile)
|
|
1569
|
+
qs.profile = profile;
|
|
1570
|
+
const options = {
|
|
1571
|
+
uri: 'https://api.upload-post.com/api/uploadposts/linkedin/pages',
|
|
1572
|
+
method: 'GET',
|
|
1573
|
+
headers: { Authorization: `ApiKey ${apiKey}` },
|
|
1574
|
+
qs,
|
|
1575
|
+
json: true,
|
|
1576
|
+
};
|
|
1577
|
+
const resp = await this.helpers.request(options);
|
|
1578
|
+
const pages = (resp && (resp.pages || resp.data || []));
|
|
1579
|
+
const pageOptions = (pages || []).map(p => ({ name: p.name ? `${p.name} (${p.id})` : p.id, value: p.id }));
|
|
1580
|
+
return [
|
|
1581
|
+
{ name: 'Manual entry...', value: MANUAL_LINKEDIN_VALUE },
|
|
1582
|
+
{ name: 'Me (Personal Profile)', value: 'me' },
|
|
1583
|
+
...pageOptions
|
|
1584
|
+
];
|
|
1585
|
+
}
|
|
1586
|
+
catch (error) {
|
|
1587
|
+
return [
|
|
1588
|
+
{ name: 'Manual entry...', value: MANUAL_LINKEDIN_VALUE },
|
|
1589
|
+
{ name: 'Me (Personal Profile)', value: 'me' }
|
|
1590
|
+
];
|
|
1591
|
+
}
|
|
1366
1592
|
},
|
|
1367
1593
|
async getPinterestBoards() {
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1594
|
+
try {
|
|
1595
|
+
const credentials = await this.getCredentials('uploadPostApi');
|
|
1596
|
+
const apiKey = credentials.apiKey;
|
|
1597
|
+
const profile = this.getCurrentNodeParameter('user') || '';
|
|
1598
|
+
const qs = {};
|
|
1599
|
+
if (profile)
|
|
1600
|
+
qs.profile = profile;
|
|
1601
|
+
const options = {
|
|
1602
|
+
uri: 'https://api.upload-post.com/api/uploadposts/pinterest/boards',
|
|
1603
|
+
method: 'GET',
|
|
1604
|
+
headers: { Authorization: `ApiKey ${apiKey}` },
|
|
1605
|
+
qs,
|
|
1606
|
+
json: true,
|
|
1607
|
+
};
|
|
1608
|
+
const resp = await this.helpers.request(options);
|
|
1609
|
+
const boards = (resp && (resp.boards || resp.data || []));
|
|
1610
|
+
const boardOptions = (boards || []).map(b => ({ name: b.name ? `${b.name} (${b.id})` : b.id, value: b.id }));
|
|
1611
|
+
return [
|
|
1612
|
+
{ name: 'Manual entry...', value: MANUAL_PINTEREST_VALUE },
|
|
1613
|
+
...boardOptions
|
|
1614
|
+
];
|
|
1615
|
+
}
|
|
1616
|
+
catch (error) {
|
|
1617
|
+
return [
|
|
1618
|
+
{ name: 'Manual entry...', value: MANUAL_PINTEREST_VALUE }
|
|
1619
|
+
];
|
|
1620
|
+
}
|
|
1621
|
+
},
|
|
1622
|
+
async getUserProfiles() {
|
|
1623
|
+
try {
|
|
1624
|
+
const credentials = await this.getCredentials('uploadPostApi');
|
|
1625
|
+
const apiKey = credentials.apiKey;
|
|
1626
|
+
const options = {
|
|
1627
|
+
uri: 'https://api.upload-post.com/api/uploadposts/users',
|
|
1628
|
+
method: 'GET',
|
|
1629
|
+
headers: { Authorization: `ApiKey ${apiKey}` },
|
|
1630
|
+
json: true,
|
|
1631
|
+
};
|
|
1632
|
+
const resp = await this.helpers.request(options);
|
|
1633
|
+
const profiles = (resp && resp.profiles);
|
|
1634
|
+
const profileOptions = (profiles || []).map(profile => {
|
|
1635
|
+
const connectedPlatforms = Object.keys(profile.social_accounts || {})
|
|
1636
|
+
.filter(platform => profile.social_accounts[platform] && typeof profile.social_accounts[platform] === 'object')
|
|
1637
|
+
.join(', ');
|
|
1638
|
+
const displayName = connectedPlatforms
|
|
1639
|
+
? `${profile.username} (${connectedPlatforms})`
|
|
1640
|
+
: profile.username;
|
|
1641
|
+
return {
|
|
1642
|
+
name: displayName,
|
|
1643
|
+
value: profile.username
|
|
1644
|
+
};
|
|
1645
|
+
});
|
|
1646
|
+
return [
|
|
1647
|
+
{ name: 'Manual entry...', value: MANUAL_USER_VALUE },
|
|
1648
|
+
...profileOptions
|
|
1649
|
+
];
|
|
1650
|
+
}
|
|
1651
|
+
catch (error) {
|
|
1652
|
+
return [
|
|
1653
|
+
{ name: 'Manual entry...', value: MANUAL_USER_VALUE }
|
|
1654
|
+
];
|
|
1655
|
+
}
|
|
1384
1656
|
},
|
|
1385
1657
|
},
|
|
1386
1658
|
};
|
|
@@ -1393,7 +1665,13 @@ class UploadPost {
|
|
|
1393
1665
|
const operation = this.getNodeParameter('operation', i);
|
|
1394
1666
|
const isUploadOperation = ['uploadPhotos', 'uploadVideo', 'uploadText'].includes(operation);
|
|
1395
1667
|
const needsUser = isUploadOperation || operation === 'generateJwt';
|
|
1396
|
-
const
|
|
1668
|
+
const userSelection = needsUser ? this.getNodeParameter('user', i) : '';
|
|
1669
|
+
const userManualValue = needsUser && userSelection === MANUAL_USER_VALUE
|
|
1670
|
+
? this.getNodeParameter('userManual', i)
|
|
1671
|
+
: '';
|
|
1672
|
+
const user = needsUser
|
|
1673
|
+
? (userSelection === MANUAL_USER_VALUE ? userManualValue : userSelection)
|
|
1674
|
+
: '';
|
|
1397
1675
|
let platforms = isUploadOperation ? this.getNodeParameter('platform', i) : [];
|
|
1398
1676
|
const title = isUploadOperation ? this.getNodeParameter('title', i) : '';
|
|
1399
1677
|
let endpoint = '';
|
|
@@ -1478,8 +1756,10 @@ class UploadPost {
|
|
|
1478
1756
|
}
|
|
1479
1757
|
if (isUploadOperation) {
|
|
1480
1758
|
const genericDescription = this.getNodeParameter('description', i, '');
|
|
1481
|
-
|
|
1759
|
+
const descriptionPlatforms = new Set(['linkedin', 'facebook', 'youtube', 'pinterest', 'tiktok']);
|
|
1760
|
+
if (genericDescription && platforms.some(p => descriptionPlatforms.has(p))) {
|
|
1482
1761
|
formData.description = genericDescription;
|
|
1762
|
+
}
|
|
1483
1763
|
try {
|
|
1484
1764
|
if (platforms.includes('linkedin')) {
|
|
1485
1765
|
const linkedinDescription = this.getNodeParameter('linkedinDescription', i, '');
|
|
@@ -1496,14 +1776,6 @@ class UploadPost {
|
|
|
1496
1776
|
}
|
|
1497
1777
|
}
|
|
1498
1778
|
catch { }
|
|
1499
|
-
try {
|
|
1500
|
-
if (platforms.includes('threads')) {
|
|
1501
|
-
const threadsDescription = this.getNodeParameter('threadsDescription', i, '');
|
|
1502
|
-
if (threadsDescription)
|
|
1503
|
-
formData.threads_description = threadsDescription;
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
catch { }
|
|
1507
1779
|
try {
|
|
1508
1780
|
if (platforms.includes('facebook')) {
|
|
1509
1781
|
const facebookDescription = this.getNodeParameter('facebookDescription', i, '');
|
|
@@ -1512,14 +1784,6 @@ class UploadPost {
|
|
|
1512
1784
|
}
|
|
1513
1785
|
}
|
|
1514
1786
|
catch { }
|
|
1515
|
-
try {
|
|
1516
|
-
if (platforms.includes('instagram')) {
|
|
1517
|
-
const instagramDescription = this.getNodeParameter('instagramDescription', i, '');
|
|
1518
|
-
if (instagramDescription)
|
|
1519
|
-
formData.instagram_description = instagramDescription;
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
catch { }
|
|
1523
1787
|
try {
|
|
1524
1788
|
if (platforms.includes('tiktok')) {
|
|
1525
1789
|
const tiktokDescription = this.getNodeParameter('tiktokDescription', i, '');
|
|
@@ -1528,14 +1792,6 @@ class UploadPost {
|
|
|
1528
1792
|
}
|
|
1529
1793
|
}
|
|
1530
1794
|
catch { }
|
|
1531
|
-
try {
|
|
1532
|
-
if (platforms.includes('x')) {
|
|
1533
|
-
const xDescription = this.getNodeParameter('xDescription', i, '');
|
|
1534
|
-
if (xDescription)
|
|
1535
|
-
formData.x_description = xDescription;
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
catch { }
|
|
1539
1795
|
try {
|
|
1540
1796
|
if (platforms.includes('pinterest')) {
|
|
1541
1797
|
const pinterestDescription = this.getNodeParameter('pinterestDescription', i, '');
|
|
@@ -1621,7 +1877,7 @@ class UploadPost {
|
|
|
1621
1877
|
break;
|
|
1622
1878
|
case 'uploadText':
|
|
1623
1879
|
endpoint = '/upload_text';
|
|
1624
|
-
const allowedTextPlatforms = ['x', 'linkedin', 'facebook', 'threads'];
|
|
1880
|
+
const allowedTextPlatforms = ['x', 'linkedin', 'facebook', 'threads', 'reddit'];
|
|
1625
1881
|
platforms = platforms.filter(p => allowedTextPlatforms.includes(p));
|
|
1626
1882
|
formData['platform[]'] = platforms;
|
|
1627
1883
|
break;
|
|
@@ -1713,7 +1969,11 @@ class UploadPost {
|
|
|
1713
1969
|
break;
|
|
1714
1970
|
}
|
|
1715
1971
|
if (isUploadOperation && platforms.includes('pinterest')) {
|
|
1716
|
-
const
|
|
1972
|
+
const pinterestSelection = this.getNodeParameter('pinterestBoardId', i);
|
|
1973
|
+
const pinterestManual = pinterestSelection === MANUAL_PINTEREST_VALUE
|
|
1974
|
+
? this.getNodeParameter('pinterestBoardIdManual', i)
|
|
1975
|
+
: '';
|
|
1976
|
+
const pinterestBoardId = pinterestSelection === MANUAL_PINTEREST_VALUE ? pinterestManual : pinterestSelection;
|
|
1717
1977
|
if (pinterestBoardId)
|
|
1718
1978
|
formData.pinterest_board_id = pinterestBoardId;
|
|
1719
1979
|
const pinterestLink = this.getNodeParameter('pinterestLink', i);
|
|
@@ -1742,8 +2002,12 @@ class UploadPost {
|
|
|
1742
2002
|
}
|
|
1743
2003
|
}
|
|
1744
2004
|
if (isUploadOperation && platforms.includes('linkedin')) {
|
|
1745
|
-
const
|
|
1746
|
-
|
|
2005
|
+
const targetLinkedinSelection = this.getNodeParameter('targetLinkedinPageId', i);
|
|
2006
|
+
const targetLinkedinManual = targetLinkedinSelection === MANUAL_LINKEDIN_VALUE
|
|
2007
|
+
? this.getNodeParameter('targetLinkedinPageIdManual', i)
|
|
2008
|
+
: '';
|
|
2009
|
+
const targetLinkedinPageId = targetLinkedinSelection === MANUAL_LINKEDIN_VALUE ? targetLinkedinManual : targetLinkedinSelection;
|
|
2010
|
+
if (targetLinkedinPageId && targetLinkedinPageId !== 'me') {
|
|
1747
2011
|
const match = targetLinkedinPageId.match(/(\d+)$/);
|
|
1748
2012
|
if (match) {
|
|
1749
2013
|
formData.target_linkedin_page_id = match[1];
|
|
@@ -1764,7 +2028,11 @@ class UploadPost {
|
|
|
1764
2028
|
}
|
|
1765
2029
|
}
|
|
1766
2030
|
if (isUploadOperation && platforms.includes('facebook')) {
|
|
1767
|
-
const
|
|
2031
|
+
const facebookPageSelection = this.getNodeParameter('facebookPageId', i);
|
|
2032
|
+
const facebookPageManual = facebookPageSelection === MANUAL_FACEBOOK_VALUE
|
|
2033
|
+
? this.getNodeParameter('facebookPageIdManual', i)
|
|
2034
|
+
: '';
|
|
2035
|
+
const facebookPageId = facebookPageSelection === MANUAL_FACEBOOK_VALUE ? facebookPageManual : facebookPageSelection;
|
|
1768
2036
|
formData.facebook_page_id = facebookPageId;
|
|
1769
2037
|
if (operation === 'uploadVideo') {
|
|
1770
2038
|
const facebookVideoState = this.getNodeParameter('facebookVideoState', i);
|
|
@@ -1780,25 +2048,25 @@ class UploadPost {
|
|
|
1780
2048
|
else if (operation === 'uploadText') {
|
|
1781
2049
|
const facebookLink = this.getNodeParameter('facebookLink', i);
|
|
1782
2050
|
if (facebookLink)
|
|
1783
|
-
formData.
|
|
2051
|
+
formData.facebook_link_url = facebookLink;
|
|
1784
2052
|
}
|
|
1785
2053
|
}
|
|
1786
2054
|
if (isUploadOperation && platforms.includes('tiktok')) {
|
|
1787
2055
|
if (operation === 'uploadPhotos') {
|
|
1788
2056
|
const tiktokAutoAddMusic = this.getNodeParameter('tiktokAutoAddMusic', i);
|
|
1789
2057
|
const tiktokDisableComment = this.getNodeParameter('tiktokDisableComment', i);
|
|
1790
|
-
const
|
|
1791
|
-
const
|
|
2058
|
+
const brandContentToggle = this.getNodeParameter('brand_content_toggle', i);
|
|
2059
|
+
const brandOrganicToggle = this.getNodeParameter('brand_organic_toggle', i);
|
|
1792
2060
|
const tiktokPhotoCoverIndex = this.getNodeParameter('tiktokPhotoCoverIndex', i);
|
|
1793
2061
|
const tiktokPhotoDescription = this.getNodeParameter('tiktokPhotoDescription', i);
|
|
1794
2062
|
if (tiktokAutoAddMusic !== undefined)
|
|
1795
2063
|
formData.auto_add_music = String(tiktokAutoAddMusic);
|
|
1796
2064
|
if (tiktokDisableComment !== undefined)
|
|
1797
2065
|
formData.disable_comment = String(tiktokDisableComment);
|
|
1798
|
-
if (
|
|
1799
|
-
formData.
|
|
1800
|
-
if (
|
|
1801
|
-
formData.
|
|
2066
|
+
if (brandContentToggle !== undefined)
|
|
2067
|
+
formData.brand_content_toggle = String(brandContentToggle);
|
|
2068
|
+
if (brandOrganicToggle !== undefined)
|
|
2069
|
+
formData.brand_organic_toggle = String(brandOrganicToggle);
|
|
1802
2070
|
if (tiktokPhotoCoverIndex !== undefined)
|
|
1803
2071
|
formData.photo_cover_index = tiktokPhotoCoverIndex;
|
|
1804
2072
|
if (tiktokPhotoDescription && formData.description === undefined)
|
|
@@ -1810,10 +2078,8 @@ class UploadPost {
|
|
|
1810
2078
|
const tiktokDisableComment = this.getNodeParameter('tiktokDisableComment', i);
|
|
1811
2079
|
const tiktokDisableStitch = this.getNodeParameter('tiktokDisableStitch', i);
|
|
1812
2080
|
const tiktokCoverTimestamp = this.getNodeParameter('tiktokCoverTimestamp', i);
|
|
1813
|
-
const
|
|
1814
|
-
const
|
|
1815
|
-
const tiktokBrandedContentVideo = this.getNodeParameter('tiktokBrandedContentVideo', i);
|
|
1816
|
-
const tiktokBrandOrganicToggle = this.getNodeParameter('tiktokBrandOrganicToggle', i);
|
|
2081
|
+
const brandContentToggle = this.getNodeParameter('brand_content_toggle', i);
|
|
2082
|
+
const brandOrganicToggle = this.getNodeParameter('brand_organic_toggle', i);
|
|
1817
2083
|
const tiktokIsAigc = this.getNodeParameter('tiktokIsAigc', i);
|
|
1818
2084
|
const tiktokPostMode = this.getNodeParameter('tiktokPostMode', i);
|
|
1819
2085
|
if (tiktokPrivacyLevel)
|
|
@@ -1826,14 +2092,10 @@ class UploadPost {
|
|
|
1826
2092
|
formData.disable_stitch = String(tiktokDisableStitch);
|
|
1827
2093
|
if (tiktokCoverTimestamp !== undefined)
|
|
1828
2094
|
formData.cover_timestamp = tiktokCoverTimestamp;
|
|
1829
|
-
if (
|
|
1830
|
-
formData.brand_content_toggle = String(
|
|
1831
|
-
if (
|
|
1832
|
-
formData.
|
|
1833
|
-
if (tiktokBrandedContentVideo !== undefined)
|
|
1834
|
-
formData.branded_content = String(tiktokBrandedContentVideo);
|
|
1835
|
-
if (tiktokBrandOrganicToggle !== undefined)
|
|
1836
|
-
formData.brand_organic_toggle = String(tiktokBrandOrganicToggle);
|
|
2095
|
+
if (brandContentToggle !== undefined)
|
|
2096
|
+
formData.brand_content_toggle = String(brandContentToggle);
|
|
2097
|
+
if (brandOrganicToggle !== undefined)
|
|
2098
|
+
formData.brand_organic_toggle = String(brandOrganicToggle);
|
|
1837
2099
|
if (tiktokIsAigc !== undefined)
|
|
1838
2100
|
formData.is_aigc = String(tiktokIsAigc);
|
|
1839
2101
|
if (tiktokPostMode)
|
|
@@ -1889,7 +2151,7 @@ class UploadPost {
|
|
|
1889
2151
|
const youtubeMadeForKids = this.getNodeParameter('youtubeMadeForKids', i);
|
|
1890
2152
|
const youtubeThumbnail = this.getNodeParameter('youtubeThumbnail', i);
|
|
1891
2153
|
if (youtubeTagsRaw)
|
|
1892
|
-
formData
|
|
2154
|
+
formData['tags[]'] = youtubeTagsRaw.split(',').map(tag => tag.trim());
|
|
1893
2155
|
if (youtubeCategoryId)
|
|
1894
2156
|
formData.categoryId = youtubeCategoryId;
|
|
1895
2157
|
if (youtubePrivacyStatus)
|
|
@@ -1924,18 +2186,96 @@ class UploadPost {
|
|
|
1924
2186
|
}
|
|
1925
2187
|
}
|
|
1926
2188
|
}
|
|
2189
|
+
const youtubeSelfDeclaredMadeForKids = this.getNodeParameter('youtubeSelfDeclaredMadeForKids', i);
|
|
2190
|
+
const youtubeContainsSyntheticMedia = this.getNodeParameter('youtubeContainsSyntheticMedia', i);
|
|
2191
|
+
const youtubeDefaultLanguage = this.getNodeParameter('youtubeDefaultLanguage', i);
|
|
2192
|
+
const youtubeDefaultAudioLanguage = this.getNodeParameter('youtubeDefaultAudioLanguage', i);
|
|
2193
|
+
const youtubeAllowedCountries = this.getNodeParameter('youtubeAllowedCountries', i);
|
|
2194
|
+
const youtubeBlockedCountries = this.getNodeParameter('youtubeBlockedCountries', i);
|
|
2195
|
+
const youtubeHasPaidProductPlacement = this.getNodeParameter('youtubeHasPaidProductPlacement', i);
|
|
2196
|
+
const youtubeRecordingDate = this.getNodeParameter('youtubeRecordingDate', i);
|
|
2197
|
+
if (youtubeSelfDeclaredMadeForKids !== undefined)
|
|
2198
|
+
formData.selfDeclaredMadeForKids = String(youtubeSelfDeclaredMadeForKids);
|
|
2199
|
+
if (youtubeContainsSyntheticMedia !== undefined)
|
|
2200
|
+
formData.containsSyntheticMedia = String(youtubeContainsSyntheticMedia);
|
|
2201
|
+
if (youtubeDefaultLanguage)
|
|
2202
|
+
formData.defaultLanguage = youtubeDefaultLanguage;
|
|
2203
|
+
if (youtubeDefaultAudioLanguage)
|
|
2204
|
+
formData.defaultAudioLanguage = youtubeDefaultAudioLanguage;
|
|
2205
|
+
if (youtubeAllowedCountries)
|
|
2206
|
+
formData.allowedCountries = youtubeAllowedCountries;
|
|
2207
|
+
if (youtubeBlockedCountries)
|
|
2208
|
+
formData.blockedCountries = youtubeBlockedCountries;
|
|
2209
|
+
if (youtubeHasPaidProductPlacement !== undefined)
|
|
2210
|
+
formData.hasPaidProductPlacement = String(youtubeHasPaidProductPlacement);
|
|
2211
|
+
if (youtubeRecordingDate)
|
|
2212
|
+
formData.recordingDate = youtubeRecordingDate;
|
|
1927
2213
|
}
|
|
1928
2214
|
if (isUploadOperation && platforms.includes('x')) {
|
|
2215
|
+
const xQuoteTweetId = this.getNodeParameter('xQuoteTweetId', i, '');
|
|
2216
|
+
const xGeoPlaceId = this.getNodeParameter('xGeoPlaceId', i, '');
|
|
2217
|
+
const xForSuperFollowersOnly = this.getNodeParameter('xForSuperFollowersOnly', i, false);
|
|
2218
|
+
const xCommunityId = this.getNodeParameter('xCommunityId', i, '');
|
|
2219
|
+
const xShareWithFollowers = this.getNodeParameter('xShareWithFollowers', i, false);
|
|
2220
|
+
const xDirectMessageDeepLink = this.getNodeParameter('xDirectMessageDeepLink', i, '');
|
|
2221
|
+
const xCardUri = this.getNodeParameter('xCardUri', i, '');
|
|
2222
|
+
if (xQuoteTweetId)
|
|
2223
|
+
formData.quote_tweet_id = xQuoteTweetId;
|
|
2224
|
+
if (xGeoPlaceId)
|
|
2225
|
+
formData.geo_place_id = xGeoPlaceId;
|
|
2226
|
+
if (xForSuperFollowersOnly)
|
|
2227
|
+
formData.for_super_followers_only = String(xForSuperFollowersOnly);
|
|
2228
|
+
if (xCommunityId)
|
|
2229
|
+
formData.community_id = xCommunityId;
|
|
2230
|
+
if (xShareWithFollowers)
|
|
2231
|
+
formData.share_with_followers = String(xShareWithFollowers);
|
|
2232
|
+
if (xDirectMessageDeepLink)
|
|
2233
|
+
formData.direct_message_deep_link = xDirectMessageDeepLink;
|
|
2234
|
+
if (xCardUri)
|
|
2235
|
+
formData.card_uri = xCardUri;
|
|
1929
2236
|
if (operation === 'uploadText') {
|
|
1930
2237
|
const xPostUrlText = this.getNodeParameter('xPostUrlText', i);
|
|
1931
2238
|
if (xPostUrlText)
|
|
1932
2239
|
formData.post_url = xPostUrlText;
|
|
1933
|
-
const xTaggedUserIdsText = this.getNodeParameter('xTaggedUserIds', i);
|
|
1934
2240
|
const xReplySettingsText = this.getNodeParameter('xReplySettings', i);
|
|
1935
|
-
if (
|
|
1936
|
-
formData.tagged_user_ids = xTaggedUserIdsText.split(',').map(id => id.trim());
|
|
1937
|
-
if (xReplySettingsText)
|
|
2241
|
+
if (xReplySettingsText && xReplySettingsText !== 'everyone')
|
|
1938
2242
|
formData.reply_settings = xReplySettingsText;
|
|
2243
|
+
const xPollDuration = this.getNodeParameter('xPollDuration', i, 1440);
|
|
2244
|
+
const xPollOptionsRaw = this.getNodeParameter('xPollOptions', i, '');
|
|
2245
|
+
const xPollReplySettings = this.getNodeParameter('xPollReplySettings', i, 'following');
|
|
2246
|
+
const xCardUri = this.getNodeParameter('xCardUri', i, '');
|
|
2247
|
+
const xQuoteTweetId = this.getNodeParameter('xQuoteTweetId', i, '');
|
|
2248
|
+
const xDirectMessageDeepLink = this.getNodeParameter('xDirectMessageDeepLink', i, '');
|
|
2249
|
+
const hasPollOptions = xPollOptionsRaw && xPollOptionsRaw.trim();
|
|
2250
|
+
const hasCardUri = xCardUri && xCardUri.trim();
|
|
2251
|
+
const hasQuoteTweetId = xQuoteTweetId && xQuoteTweetId.trim();
|
|
2252
|
+
const hasDirectMessageDeepLink = xDirectMessageDeepLink && xDirectMessageDeepLink.trim();
|
|
2253
|
+
if (hasPollOptions && (hasCardUri || hasQuoteTweetId || hasDirectMessageDeepLink)) {
|
|
2254
|
+
const conflictingFields = [];
|
|
2255
|
+
if (hasCardUri)
|
|
2256
|
+
conflictingFields.push('X Card URI');
|
|
2257
|
+
if (hasQuoteTweetId)
|
|
2258
|
+
conflictingFields.push('X Quote Tweet ID');
|
|
2259
|
+
if (hasDirectMessageDeepLink)
|
|
2260
|
+
conflictingFields.push('X Direct Message Deep Link');
|
|
2261
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `X Poll Options cannot be used with: ${conflictingFields.join(', ')}. These fields are mutually exclusive.`);
|
|
2262
|
+
}
|
|
2263
|
+
if (hasPollOptions) {
|
|
2264
|
+
const pollOptions = xPollOptionsRaw.split(',').map(opt => opt.trim()).filter(opt => opt.length > 0);
|
|
2265
|
+
if (pollOptions.length < 2 || pollOptions.length > 4) {
|
|
2266
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `X Poll Options must contain between 2 and 4 non-empty options. Found: ${pollOptions.length}`);
|
|
2267
|
+
}
|
|
2268
|
+
const invalidOptions = pollOptions.filter(opt => opt.length > 25);
|
|
2269
|
+
if (invalidOptions.length > 0) {
|
|
2270
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `X Poll Options cannot exceed 25 characters each. Invalid options: ${invalidOptions.join(', ')}`);
|
|
2271
|
+
}
|
|
2272
|
+
if (xPollDuration < 5 || xPollDuration > 10080) {
|
|
2273
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `X Poll Duration must be between 5 and 10080 minutes (5 minutes to 7 days). Provided: ${xPollDuration}`);
|
|
2274
|
+
}
|
|
2275
|
+
formData['poll_options[]'] = pollOptions;
|
|
2276
|
+
formData.poll_duration = xPollDuration;
|
|
2277
|
+
formData.poll_reply_settings = xPollReplySettings;
|
|
2278
|
+
}
|
|
1939
2279
|
try {
|
|
1940
2280
|
const xLongTextAsPostText = this.getNodeParameter('xLongTextAsPost', i, false);
|
|
1941
2281
|
if (xLongTextAsPostText)
|
|
@@ -1944,35 +2284,44 @@ class UploadPost {
|
|
|
1944
2284
|
catch { }
|
|
1945
2285
|
delete formData.nullcast;
|
|
1946
2286
|
delete formData.place_id;
|
|
1947
|
-
delete formData.poll_duration;
|
|
1948
|
-
delete formData.poll_options;
|
|
1949
|
-
delete formData.poll_reply_settings;
|
|
1950
2287
|
}
|
|
1951
|
-
else if (operation === 'uploadVideo') {
|
|
2288
|
+
else if (operation === 'uploadVideo' || operation === 'uploadPhotos') {
|
|
1952
2289
|
const xTaggedUserIds = this.getNodeParameter('xTaggedUserIds', i);
|
|
1953
2290
|
const xReplySettings = this.getNodeParameter('xReplySettings', i);
|
|
1954
2291
|
const xNullcastVideo = this.getNodeParameter('xNullcastVideo', i);
|
|
1955
|
-
const xPlaceIdVideo = this.getNodeParameter('xPlaceIdVideo', i);
|
|
1956
|
-
const xPollDurationVideo = this.getNodeParameter('xPollDurationVideo', i);
|
|
1957
|
-
const xPollOptionsVideoRaw = this.getNodeParameter('xPollOptionsVideo', i);
|
|
1958
|
-
const xPollReplySettingsVideo = this.getNodeParameter('xPollReplySettingsVideo', i);
|
|
1959
|
-
const xLongTextAsPost = this.getNodeParameter('xLongTextAsPost', i, false);
|
|
1960
2292
|
if (xTaggedUserIds)
|
|
1961
|
-
formData
|
|
1962
|
-
if (xReplySettings)
|
|
2293
|
+
formData['tagged_user_ids[]'] = xTaggedUserIds.split(',').map(id => id.trim());
|
|
2294
|
+
if (xReplySettings && xReplySettings !== 'everyone')
|
|
1963
2295
|
formData.reply_settings = xReplySettings;
|
|
1964
2296
|
if (xNullcastVideo !== undefined)
|
|
1965
2297
|
formData.nullcast = String(xNullcastVideo);
|
|
1966
|
-
if (
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2298
|
+
if (operation === 'uploadVideo') {
|
|
2299
|
+
try {
|
|
2300
|
+
const xLongTextAsPost = this.getNodeParameter('xLongTextAsPost', i, false);
|
|
2301
|
+
if (xLongTextAsPost)
|
|
2302
|
+
formData.x_long_text_as_post = String(xLongTextAsPost);
|
|
2303
|
+
}
|
|
2304
|
+
catch { }
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
if (isUploadOperation && platforms.includes('threads')) {
|
|
2309
|
+
if (operation === 'uploadText') {
|
|
2310
|
+
const threadsTitle = this.getNodeParameter('threadsTitle', i, '');
|
|
2311
|
+
if (threadsTitle)
|
|
2312
|
+
formData.threads_title = threadsTitle;
|
|
2313
|
+
const threadsLongTextAsPost = this.getNodeParameter('threadsLongTextAsPost', i, false);
|
|
2314
|
+
if (threadsLongTextAsPost)
|
|
2315
|
+
formData.threads_long_text_as_post = String(threadsLongTextAsPost);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
if (isUploadOperation && platforms.includes('reddit')) {
|
|
2319
|
+
if (operation === 'uploadText') {
|
|
2320
|
+
const redditSubreddit = this.getNodeParameter('redditSubreddit', i);
|
|
2321
|
+
formData.subreddit = redditSubreddit;
|
|
2322
|
+
const redditFlairId = this.getNodeParameter('redditFlairId', i, '');
|
|
2323
|
+
if (redditFlairId)
|
|
2324
|
+
formData.flair_id = redditFlairId;
|
|
1976
2325
|
}
|
|
1977
2326
|
}
|
|
1978
2327
|
const credentials = await this.getCredentials('uploadPostApi');
|
|
@@ -2006,6 +2355,8 @@ class UploadPost {
|
|
|
2006
2355
|
options.qs = qs;
|
|
2007
2356
|
}
|
|
2008
2357
|
}
|
|
2358
|
+
this.logger.info(`Operation: ${operation}, Is Upload Operation: ${isUploadOperation}`);
|
|
2359
|
+
this.logger.info('Complete Form Data being sent (JSON): ' + JSON.stringify(formData, null, 2));
|
|
2009
2360
|
const responseData = await this.helpers.request(options);
|
|
2010
2361
|
const shouldConsiderPolling = operation === 'uploadPhotos' || operation === 'uploadVideo' || operation === 'uploadText';
|
|
2011
2362
|
const waitForCompletion = shouldConsiderPolling ? this.getNodeParameter('waitForCompletion', i, false) : false;
|