n8n-nodes-sendit 1.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,176 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.SendIt = void 0;
4
- // Base URL for SendIt API
5
- const SENDIT_API_BASE_URL = 'https://sendit.infiniteappsai.com/api/v1';
37
+ const n8n_workflow_1 = require("n8n-workflow");
38
+ const SENDIT_API_ORIGIN = 'https://sendit.infiniteappsai.com';
39
+ const SENDIT_API_BASE_URL = `${SENDIT_API_ORIGIN}/api/v1`;
40
+ const PLATFORM_OPTIONS = [
41
+ { name: 'X (Twitter)', value: 'x' },
42
+ { name: 'LinkedIn', value: 'linkedin' },
43
+ { name: 'LinkedIn Page', value: 'linkedin-page' },
44
+ { name: 'Facebook', value: 'facebook' },
45
+ { name: 'Instagram', value: 'instagram' },
46
+ { name: 'Instagram Standalone', value: 'instagram-standalone' },
47
+ { name: 'Threads', value: 'threads' },
48
+ { name: 'Bluesky', value: 'bluesky' },
49
+ { name: 'Mastodon', value: 'mastodon' },
50
+ { name: 'Warpcast', value: 'warpcast' },
51
+ { name: 'Nostr', value: 'nostr' },
52
+ { name: 'VK', value: 'vk' },
53
+ { name: 'YouTube', value: 'youtube' },
54
+ { name: 'TikTok', value: 'tiktok' },
55
+ { name: 'Reddit', value: 'reddit' },
56
+ { name: 'Lemmy', value: 'lemmy' },
57
+ { name: 'Discord', value: 'discord' },
58
+ { name: 'Slack', value: 'slack' },
59
+ { name: 'Telegram', value: 'telegram' },
60
+ { name: 'Pinterest', value: 'pinterest' },
61
+ { name: 'Dribbble', value: 'dribbble' },
62
+ { name: 'Medium', value: 'medium' },
63
+ { name: 'DEV.to', value: 'devto' },
64
+ { name: 'Hashnode', value: 'hashnode' },
65
+ { name: 'WordPress', value: 'wordpress' },
66
+ { name: 'Google My Business', value: 'gmb' },
67
+ { name: 'Listmonk', value: 'listmonk' },
68
+ { name: 'Skool', value: 'skool' },
69
+ { name: 'Whop', value: 'whop' },
70
+ { name: 'Kick', value: 'kick' },
71
+ { name: 'Twitch', value: 'twitch' },
72
+ { name: 'Product Hunt', value: 'producthunt' },
73
+ ];
74
+ function getOptionalString(value) {
75
+ if (typeof value !== 'string') {
76
+ return undefined;
77
+ }
78
+ const trimmed = value.trim();
79
+ return trimmed.length > 0 ? trimmed : undefined;
80
+ }
81
+ function buildOptionalHeaders(teamId, idempotencyKey) {
82
+ const headers = {};
83
+ if (teamId) {
84
+ headers['X-Team-ID'] = teamId;
85
+ }
86
+ if (idempotencyKey) {
87
+ headers['Idempotency-Key'] = idempotencyKey;
88
+ }
89
+ return headers;
90
+ }
91
+ function parseCsvList(value) {
92
+ if (!value) {
93
+ return undefined;
94
+ }
95
+ const parsed = value
96
+ .split(',')
97
+ .map((entry) => entry.trim())
98
+ .filter((entry) => entry.length > 0);
99
+ return parsed.length > 0 ? parsed : undefined;
100
+ }
101
+ function maybeArray(value) {
102
+ if (Array.isArray(value)) {
103
+ const normalized = value
104
+ .map((item) => (typeof item === 'string' ? item.trim() : String(item)))
105
+ .filter((item) => item.length > 0);
106
+ return normalized.length > 0 ? normalized : undefined;
107
+ }
108
+ if (typeof value === 'string') {
109
+ return parseCsvList(value);
110
+ }
111
+ return undefined;
112
+ }
113
+ function parseJsonInput(value, label) {
114
+ if (!value || value.trim().length === 0) {
115
+ return undefined;
116
+ }
117
+ try {
118
+ return JSON.parse(value);
119
+ }
120
+ catch {
121
+ throw new Error(`${label} must be valid JSON`);
122
+ }
123
+ }
124
+ function normalizeResponse(response) {
125
+ if (response === null || response === undefined) {
126
+ return {};
127
+ }
128
+ if (Buffer.isBuffer(response)) {
129
+ return {
130
+ dataBase64: response.toString('base64'),
131
+ byteLength: response.length,
132
+ };
133
+ }
134
+ if (typeof response === 'string') {
135
+ return { data: response };
136
+ }
137
+ if (typeof response !== 'object') {
138
+ return { data: response };
139
+ }
140
+ return response;
141
+ }
142
+ async function requestV1(context, request, optionalHeaders) {
143
+ var _a;
144
+ const requestHeaders = (_a = request.headers) !== null && _a !== void 0 ? _a : {};
145
+ const headers = {
146
+ ...requestHeaders,
147
+ ...optionalHeaders,
148
+ };
149
+ return context.helpers.httpRequestWithAuthentication.call(context, 'sendItApi', {
150
+ baseURL: SENDIT_API_BASE_URL,
151
+ ...request,
152
+ headers: Object.keys(headers).length > 0 ? headers : undefined,
153
+ });
154
+ }
155
+ async function requestAbsolute(context, request, optionalHeaders) {
156
+ var _a;
157
+ const requestHeaders = (_a = request.headers) !== null && _a !== void 0 ? _a : {};
158
+ const headers = {
159
+ ...requestHeaders,
160
+ ...optionalHeaders,
161
+ };
162
+ return context.helpers.httpRequestWithAuthentication.call(context, 'sendItApi', {
163
+ baseURL: SENDIT_API_ORIGIN,
164
+ ...request,
165
+ headers: Object.keys(headers).length > 0 ? headers : undefined,
166
+ });
167
+ }
168
+ function assertObject(value, message) {
169
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
170
+ throw new Error(message);
171
+ }
172
+ return value;
173
+ }
6
174
  class SendIt {
7
175
  constructor() {
8
176
  this.description = {
@@ -12,7 +180,7 @@ class SendIt {
12
180
  group: ['transform'],
13
181
  version: 1,
14
182
  subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
15
- description: 'Multi-platform social media publishing',
183
+ description: 'Multi-platform social media publishing with AI content generation',
16
184
  defaults: {
17
185
  name: 'SendIt',
18
186
  },
@@ -38,193 +206,326 @@ class SendIt {
38
206
  type: 'options',
39
207
  noDataExpression: true,
40
208
  options: [
41
- {
42
- name: 'Post',
43
- value: 'post',
44
- },
45
- {
46
- name: 'Scheduled Post',
47
- value: 'scheduledPost',
48
- },
49
- {
50
- name: 'Account',
51
- value: 'account',
52
- },
53
- {
54
- name: 'Validation',
55
- value: 'validation',
56
- },
57
- {
58
- name: 'Analytics',
59
- value: 'analytics',
60
- },
209
+ { name: 'Post', value: 'post' },
210
+ { name: 'AI', value: 'ai' },
211
+ { name: 'Media', value: 'media' },
212
+ { name: 'Scheduled Post', value: 'scheduledPost' },
213
+ { name: 'Account', value: 'account' },
214
+ { name: 'Validation', value: 'validation' },
215
+ { name: 'Analytics', value: 'analytics' },
216
+ { name: 'Brand Voice', value: 'brandVoice' },
217
+ { name: 'Campaign', value: 'campaign' },
218
+ { name: 'Inbox', value: 'inbox' },
219
+ { name: 'Listening', value: 'listening' },
220
+ { name: 'AI Media', value: 'aiMedia' },
221
+ { name: 'Meta', value: 'meta' },
222
+ { name: 'Content Score', value: 'contentScore' },
223
+ { name: 'Library', value: 'library' },
224
+ { name: 'Approvals', value: 'approvals' },
225
+ { name: 'Bulk Schedule', value: 'bulkSchedule' },
226
+ { name: 'Connect', value: 'connect' },
227
+ { name: 'Webhooks', value: 'webhooks' },
228
+ { name: 'Advanced', value: 'advanced' },
61
229
  ],
62
230
  default: 'post',
63
231
  },
64
- // Post operations
232
+ {
233
+ displayName: 'Team ID',
234
+ name: 'teamId',
235
+ type: 'string',
236
+ default: '',
237
+ description: 'Optional team scope. Sent as X-Team-ID header when provided',
238
+ },
239
+ {
240
+ displayName: 'Idempotency Key',
241
+ name: 'idempotencyKey',
242
+ type: 'string',
243
+ default: '',
244
+ description: 'Optional idempotency key. Sent as Idempotency-Key header when provided',
245
+ },
246
+ // ===== Operations by resource =====
65
247
  {
66
248
  displayName: 'Operation',
67
249
  name: 'operation',
68
250
  type: 'options',
69
251
  noDataExpression: true,
70
- displayOptions: {
71
- show: {
72
- resource: ['post'],
73
- },
74
- },
252
+ displayOptions: { show: { resource: ['post'] } },
75
253
  options: [
76
- {
77
- name: 'Publish',
78
- value: 'publish',
79
- description: 'Publish content to social media platforms immediately',
80
- action: 'Publish a post',
81
- },
254
+ { name: 'Publish', value: 'publish', description: 'Publish content to social media platforms immediately', action: 'Publish a post' },
255
+ { name: 'Publish with AI', value: 'publishAi', description: 'Generate content with AI and publish to platforms', action: 'Publish with AI-generated content' },
82
256
  ],
83
257
  default: 'publish',
84
258
  },
85
- // Scheduled Post operations
86
259
  {
87
260
  displayName: 'Operation',
88
261
  name: 'operation',
89
262
  type: 'options',
90
263
  noDataExpression: true,
91
- displayOptions: {
92
- show: {
93
- resource: ['scheduledPost'],
94
- },
95
- },
264
+ displayOptions: { show: { resource: ['ai'] } },
96
265
  options: [
97
- {
98
- name: 'Create',
99
- value: 'create',
100
- description: 'Schedule a post for future publishing',
101
- action: 'Schedule a post',
102
- },
103
- {
104
- name: 'Get All',
105
- value: 'getAll',
106
- description: 'Get all scheduled posts',
107
- action: 'Get all scheduled posts',
108
- },
109
- {
110
- name: 'Delete',
111
- value: 'delete',
112
- description: 'Cancel a scheduled post',
113
- action: 'Cancel a scheduled post',
114
- },
115
- {
116
- name: 'Trigger Now',
117
- value: 'trigger',
118
- description: 'Publish a scheduled post immediately',
119
- action: 'Trigger scheduled post now',
120
- },
266
+ { name: 'Generate Content', value: 'generate', description: 'Generate platform-specific content from media or prompt', action: 'Generate AI content' },
121
267
  ],
122
- default: 'create',
268
+ default: 'generate',
123
269
  },
124
- // Account operations
125
270
  {
126
271
  displayName: 'Operation',
127
272
  name: 'operation',
128
273
  type: 'options',
129
274
  noDataExpression: true,
130
- displayOptions: {
131
- show: {
132
- resource: ['account'],
133
- },
134
- },
275
+ displayOptions: { show: { resource: ['media'] } },
135
276
  options: [
136
- {
137
- name: 'Get All',
138
- value: 'getAll',
139
- description: 'Get all connected accounts',
140
- action: 'Get all accounts',
141
- },
277
+ { name: 'Upload', value: 'upload', description: 'Upload media file to get a URL', action: 'Upload media' },
142
278
  ],
143
- default: 'getAll',
279
+ default: 'upload',
144
280
  },
145
- // Validation operations
146
281
  {
147
282
  displayName: 'Operation',
148
283
  name: 'operation',
149
284
  type: 'options',
150
285
  noDataExpression: true,
151
- displayOptions: {
152
- show: {
153
- resource: ['validation'],
154
- },
155
- },
286
+ displayOptions: { show: { resource: ['scheduledPost'] } },
156
287
  options: [
157
- {
158
- name: 'Validate',
159
- value: 'validate',
160
- description: 'Validate content before publishing',
161
- action: 'Validate content',
162
- },
288
+ { name: 'Create', value: 'create', description: 'Schedule a post for future publishing', action: 'Schedule a post' },
289
+ { name: 'Get All', value: 'getAll', description: 'Get all scheduled posts', action: 'Get all scheduled posts' },
290
+ { name: 'Delete', value: 'delete', description: 'Cancel a scheduled post', action: 'Cancel a scheduled post' },
291
+ { name: 'Trigger Now', value: 'trigger', description: 'Publish a scheduled post immediately', action: 'Trigger scheduled post now' },
163
292
  ],
293
+ default: 'create',
294
+ },
295
+ {
296
+ displayName: 'Operation',
297
+ name: 'operation',
298
+ type: 'options',
299
+ noDataExpression: true,
300
+ displayOptions: { show: { resource: ['account'] } },
301
+ options: [{ name: 'Get All', value: 'getAll', description: 'Get all connected accounts', action: 'Get all accounts' }],
302
+ default: 'getAll',
303
+ },
304
+ {
305
+ displayName: 'Operation',
306
+ name: 'operation',
307
+ type: 'options',
308
+ noDataExpression: true,
309
+ displayOptions: { show: { resource: ['validation'] } },
310
+ options: [{ name: 'Validate', value: 'validate', description: 'Validate content before publishing', action: 'Validate content' }],
164
311
  default: 'validate',
165
312
  },
166
- // Analytics operations
167
313
  {
168
314
  displayName: 'Operation',
169
315
  name: 'operation',
170
316
  type: 'options',
171
317
  noDataExpression: true,
172
- displayOptions: {
173
- show: {
174
- resource: ['analytics'],
175
- },
176
- },
318
+ displayOptions: { show: { resource: ['analytics'] } },
319
+ options: [{ name: 'Get Analytics', value: 'getAnalytics', description: 'Get engagement analytics for posts on a platform', action: 'Get analytics for a platform' }],
320
+ default: 'getAnalytics',
321
+ },
322
+ {
323
+ displayName: 'Operation',
324
+ name: 'operation',
325
+ type: 'options',
326
+ noDataExpression: true,
327
+ displayOptions: { show: { resource: ['brandVoice'] } },
177
328
  options: [
178
- {
179
- name: 'Get Analytics',
180
- value: 'getAnalytics',
181
- description: 'Get engagement analytics for posts on a platform',
182
- action: 'Get analytics for a platform',
183
- },
329
+ { name: 'Create', value: 'create', description: 'Create a new brand voice profile', action: 'Create a brand voice' },
330
+ { name: 'List', value: 'list', description: 'List all brand voice profiles', action: 'List brand voices' },
184
331
  ],
185
- default: 'getAnalytics',
332
+ default: 'create',
333
+ },
334
+ {
335
+ displayName: 'Operation',
336
+ name: 'operation',
337
+ type: 'options',
338
+ noDataExpression: true,
339
+ displayOptions: { show: { resource: ['campaign'] } },
340
+ options: [
341
+ { name: 'Plan', value: 'plan', description: 'Create a new campaign with AI-planned posts', action: 'Plan a campaign' },
342
+ { name: 'List', value: 'list', description: 'List all campaigns', action: 'List campaigns' },
343
+ { name: 'Schedule', value: 'schedule', description: 'Schedule all posts in a campaign', action: 'Schedule a campaign' },
344
+ ],
345
+ default: 'plan',
346
+ },
347
+ {
348
+ displayName: 'Operation',
349
+ name: 'operation',
350
+ type: 'options',
351
+ noDataExpression: true,
352
+ displayOptions: { show: { resource: ['inbox'] } },
353
+ options: [
354
+ { name: 'List', value: 'list', description: 'List inbox threads', action: 'List inbox threads' },
355
+ { name: 'Reply', value: 'reply', description: 'Reply to an inbox thread', action: 'Reply to a thread' },
356
+ { name: 'Get Thread', value: 'getThread', description: 'Get a single inbox thread with messages', action: 'Get an inbox thread' },
357
+ { name: 'Update Status', value: 'updateStatus', description: 'Update thread status', action: 'Update inbox thread status' },
358
+ ],
359
+ default: 'list',
360
+ },
361
+ {
362
+ displayName: 'Operation',
363
+ name: 'operation',
364
+ type: 'options',
365
+ noDataExpression: true,
366
+ displayOptions: { show: { resource: ['listening'] } },
367
+ options: [
368
+ { name: 'Refresh', value: 'refresh', description: 'Trigger a social listening refresh', action: 'Refresh social listening data' },
369
+ { name: 'List Keywords', value: 'listKeywords', description: 'List tracked listening keywords', action: 'List listening keywords' },
370
+ { name: 'Create Keyword', value: 'createKeyword', description: 'Create a listening keyword', action: 'Create listening keyword' },
371
+ { name: 'Get Keyword', value: 'getKeyword', description: 'Get listening keyword by ID', action: 'Get listening keyword' },
372
+ { name: 'Update Keyword', value: 'updateKeyword', description: 'Update listening keyword', action: 'Update listening keyword' },
373
+ { name: 'Delete Keyword', value: 'deleteKeyword', description: 'Delete listening keyword', action: 'Delete listening keyword' },
374
+ { name: 'List Mentions', value: 'listMentions', description: 'List mentions', action: 'List listening mentions' },
375
+ { name: 'Get Mention', value: 'getMention', description: 'Get mention by ID', action: 'Get listening mention' },
376
+ { name: 'Mark Mentions Read', value: 'markMentionsRead', description: 'Mark mentions as read', action: 'Mark listening mentions as read' },
377
+ { name: 'Archive Mentions', value: 'archiveMentions', description: 'Archive mentions', action: 'Archive listening mentions' },
378
+ { name: 'List Alerts', value: 'listAlerts', description: 'List listening alerts', action: 'List listening alerts' },
379
+ { name: 'Mark Alerts Read', value: 'markAlertsRead', description: 'Mark alerts as read', action: 'Mark listening alerts as read' },
380
+ { name: 'Dismiss Alerts', value: 'dismissAlerts', description: 'Dismiss alerts', action: 'Dismiss listening alerts' },
381
+ { name: 'Get Summary', value: 'getSummary', description: 'Get listening summary', action: 'Get listening summary' },
382
+ ],
383
+ default: 'refresh',
384
+ },
385
+ {
386
+ displayName: 'Operation',
387
+ name: 'operation',
388
+ type: 'options',
389
+ noDataExpression: true,
390
+ displayOptions: { show: { resource: ['aiMedia'] } },
391
+ options: [
392
+ { name: 'Create', value: 'create', description: 'Generate AI media (image or video)', action: 'Create AI media' },
393
+ { name: 'Get Status', value: 'getStatus', description: 'Get the status of an AI media generation job', action: 'Get AI media status' },
394
+ ],
395
+ default: 'create',
396
+ },
397
+ {
398
+ displayName: 'Operation',
399
+ name: 'operation',
400
+ type: 'options',
401
+ noDataExpression: true,
402
+ displayOptions: { show: { resource: ['meta'] } },
403
+ options: [
404
+ { name: 'Get Capabilities', value: 'getCapabilities', action: 'Get capabilities' },
405
+ { name: 'Get Requirements', value: 'getRequirements', action: 'Get platform requirements' },
406
+ { name: 'Get Platform Settings Schema', value: 'getPlatformSettingsSchema', action: 'Get platform settings schema' },
407
+ { name: 'Get Best Times', value: 'getBestTimes', action: 'Get best times to post' },
408
+ { name: 'Get Webhook Events Catalog', value: 'getWebhookEventsCatalog', action: 'Get webhook events catalog' },
409
+ { name: 'Get Webhook Triggers', value: 'getWebhookTriggers', action: 'Get webhook triggers' },
410
+ ],
411
+ default: 'getCapabilities',
412
+ },
413
+ {
414
+ displayName: 'Operation',
415
+ name: 'operation',
416
+ type: 'options',
417
+ noDataExpression: true,
418
+ displayOptions: { show: { resource: ['contentScore'] } },
419
+ options: [{ name: 'Score', value: 'score', action: 'Score content quality' }],
420
+ default: 'score',
421
+ },
422
+ {
423
+ displayName: 'Operation',
424
+ name: 'operation',
425
+ type: 'options',
426
+ noDataExpression: true,
427
+ displayOptions: { show: { resource: ['library'] } },
428
+ options: [
429
+ { name: 'List', value: 'list', action: 'List library items' },
430
+ { name: 'Create', value: 'create', action: 'Create library item' },
431
+ { name: 'Get', value: 'get', action: 'Get library item' },
432
+ { name: 'Update', value: 'update', action: 'Update library item' },
433
+ { name: 'Delete', value: 'delete', action: 'Delete library item' },
434
+ { name: 'List Categories', value: 'listCategories', action: 'List library categories' },
435
+ { name: 'List Tags', value: 'listTags', action: 'List library tags' },
436
+ ],
437
+ default: 'list',
438
+ },
439
+ {
440
+ displayName: 'Operation',
441
+ name: 'operation',
442
+ type: 'options',
443
+ noDataExpression: true,
444
+ displayOptions: { show: { resource: ['approvals'] } },
445
+ options: [
446
+ { name: 'List', value: 'list', action: 'List approvals' },
447
+ { name: 'Approve', value: 'approve', action: 'Approve post' },
448
+ { name: 'Reject', value: 'reject', action: 'Reject post' },
449
+ ],
450
+ default: 'list',
451
+ },
452
+ {
453
+ displayName: 'Operation',
454
+ name: 'operation',
455
+ type: 'options',
456
+ noDataExpression: true,
457
+ displayOptions: { show: { resource: ['bulkSchedule'] } },
458
+ options: [
459
+ { name: 'List Imports', value: 'listImports', action: 'List bulk imports' },
460
+ { name: 'Get Import', value: 'getImport', action: 'Get bulk import' },
461
+ { name: 'Validate CSV', value: 'validateCsv', action: 'Validate CSV payload' },
462
+ { name: 'Import CSV', value: 'importCsv', action: 'Import CSV payload' },
463
+ { name: 'Download Template', value: 'downloadTemplate', action: 'Download bulk schedule template' },
464
+ ],
465
+ default: 'listImports',
466
+ },
467
+ {
468
+ displayName: 'Operation',
469
+ name: 'operation',
470
+ type: 'options',
471
+ noDataExpression: true,
472
+ displayOptions: { show: { resource: ['connect'] } },
473
+ options: [
474
+ { name: 'Get Connect Action', value: 'getConnectAction', action: 'Get connect action for platform' },
475
+ { name: 'Connect Token', value: 'connectToken', action: 'Connect with token credentials' },
476
+ { name: 'Connect Webhook', value: 'connectWebhook', action: 'Connect with webhook credentials' },
477
+ ],
478
+ default: 'getConnectAction',
479
+ },
480
+ {
481
+ displayName: 'Operation',
482
+ name: 'operation',
483
+ type: 'options',
484
+ noDataExpression: true,
485
+ displayOptions: { show: { resource: ['webhooks'] } },
486
+ options: [{ name: 'Test Webhook', value: 'testWebhook', action: 'Send a test webhook delivery' }],
487
+ default: 'testWebhook',
488
+ },
489
+ {
490
+ displayName: 'Operation',
491
+ name: 'operation',
492
+ type: 'options',
493
+ noDataExpression: true,
494
+ displayOptions: { show: { resource: ['advanced'] } },
495
+ options: [{ name: 'API Request', value: 'apiRequest', action: 'Run advanced API request' }],
496
+ default: 'apiRequest',
186
497
  },
187
- // Platforms field
498
+ // ===== Existing publish / schedule fields =====
188
499
  {
189
500
  displayName: 'Platforms',
190
501
  name: 'platforms',
191
502
  type: 'multiOptions',
192
- options: [
193
- { name: 'LinkedIn', value: 'linkedin' },
194
- { name: 'Instagram', value: 'instagram' },
195
- { name: 'Threads', value: 'threads' },
196
- { name: 'TikTok', value: 'tiktok' },
197
- { name: 'X (Twitter)', value: 'x' },
198
- ],
503
+ options: PLATFORM_OPTIONS,
199
504
  default: [],
200
505
  required: true,
201
506
  displayOptions: {
202
507
  show: {
203
- resource: ['post', 'scheduledPost', 'validation'],
204
- operation: ['publish', 'create', 'validate'],
508
+ resource: ['post', 'scheduledPost', 'validation', 'ai', 'contentScore'],
509
+ operation: ['publish', 'publishAi', 'create', 'validate', 'generate', 'score'],
205
510
  },
206
511
  },
207
512
  description: 'Select platforms to publish to',
208
513
  },
209
- // Text content
210
514
  {
211
515
  displayName: 'Text',
212
516
  name: 'text',
213
517
  type: 'string',
214
- typeOptions: {
215
- rows: 4,
216
- },
518
+ typeOptions: { rows: 4 },
217
519
  default: '',
218
520
  required: true,
219
521
  displayOptions: {
220
522
  show: {
221
- resource: ['post', 'scheduledPost', 'validation'],
222
- operation: ['publish', 'create', 'validate'],
523
+ resource: ['post', 'scheduledPost', 'validation', 'contentScore'],
524
+ operation: ['publish', 'create', 'validate', 'score'],
223
525
  },
224
526
  },
225
527
  description: 'The text content of your post',
226
528
  },
227
- // Media URL
228
529
  {
229
530
  displayName: 'Media URL',
230
531
  name: 'mediaUrl',
@@ -232,99 +533,105 @@ class SendIt {
232
533
  default: '',
233
534
  displayOptions: {
234
535
  show: {
235
- resource: ['post', 'scheduledPost', 'validation'],
236
- operation: ['publish', 'create', 'validate'],
536
+ resource: ['post', 'scheduledPost', 'validation', 'ai', 'contentScore'],
537
+ operation: ['publish', 'publishAi', 'create', 'validate', 'generate', 'score'],
237
538
  },
238
539
  },
239
- description: 'URL to an image or video (required for Instagram and TikTok)',
540
+ description: 'URL to an image or video (required for some platforms)',
240
541
  },
241
- // Scheduled Time
242
542
  {
243
- displayName: 'Scheduled Time',
244
- name: 'scheduledTime',
245
- type: 'dateTime',
543
+ displayName: 'Input Mode',
544
+ name: 'mediaInputMode',
545
+ type: 'options',
546
+ options: [
547
+ { name: 'Binary Data', value: 'binary' },
548
+ { name: 'File Path', value: 'filePath' },
549
+ ],
550
+ default: 'binary',
551
+ displayOptions: { show: { resource: ['media'], operation: ['upload'] } },
552
+ description: 'How to provide the media file',
553
+ },
554
+ {
555
+ displayName: 'Binary Property',
556
+ name: 'binaryPropertyName',
557
+ type: 'string',
558
+ default: 'data',
559
+ displayOptions: {
560
+ show: {
561
+ resource: ['media'],
562
+ operation: ['upload'],
563
+ mediaInputMode: ['binary'],
564
+ },
565
+ },
566
+ description: 'Name of the binary property containing the file',
567
+ },
568
+ {
569
+ displayName: 'File Path',
570
+ name: 'filePath',
571
+ type: 'string',
246
572
  default: '',
247
- required: true,
248
573
  displayOptions: {
249
574
  show: {
250
- resource: ['scheduledPost'],
251
- operation: ['create'],
575
+ resource: ['media'],
576
+ operation: ['upload'],
577
+ mediaInputMode: ['filePath'],
252
578
  },
253
579
  },
580
+ description: 'Absolute path to the media file',
581
+ },
582
+ {
583
+ displayName: 'Prompt',
584
+ name: 'aiPrompt',
585
+ type: 'string',
586
+ typeOptions: { rows: 3 },
587
+ default: '',
588
+ displayOptions: { show: { resource: ['post', 'ai'], operation: ['publishAi', 'generate'] } },
589
+ description: 'Additional context or instructions for AI content generation',
590
+ },
591
+ {
592
+ displayName: 'Scheduled Time',
593
+ name: 'scheduledTime',
594
+ type: 'dateTime',
595
+ default: '',
596
+ required: true,
597
+ displayOptions: { show: { resource: ['scheduledPost'], operation: ['create'] } },
254
598
  description: 'When to publish the post',
255
599
  },
256
- // Schedule ID
257
600
  {
258
601
  displayName: 'Schedule ID',
259
602
  name: 'scheduleId',
260
603
  type: 'string',
261
604
  default: '',
262
605
  required: true,
263
- displayOptions: {
264
- show: {
265
- resource: ['scheduledPost'],
266
- operation: ['delete', 'trigger'],
267
- },
268
- },
606
+ displayOptions: { show: { resource: ['scheduledPost'], operation: ['delete', 'trigger'] } },
269
607
  description: 'The ID of the scheduled post',
270
608
  },
271
- // Platform filter
272
609
  {
273
610
  displayName: 'Platform Filter',
274
611
  name: 'platformFilter',
275
612
  type: 'options',
276
- options: [
277
- { name: 'All Platforms', value: '' },
278
- { name: 'LinkedIn', value: 'linkedin' },
279
- { name: 'Instagram', value: 'instagram' },
280
- { name: 'Threads', value: 'threads' },
281
- { name: 'TikTok', value: 'tiktok' },
282
- { name: 'X (Twitter)', value: 'x' },
283
- ],
613
+ options: [{ name: 'All Platforms', value: '' }, ...PLATFORM_OPTIONS],
284
614
  default: '',
285
- displayOptions: {
286
- show: {
287
- resource: ['scheduledPost'],
288
- operation: ['getAll'],
289
- },
290
- },
615
+ displayOptions: { show: { resource: ['scheduledPost'], operation: ['getAll'] } },
291
616
  description: 'Filter scheduled posts by platform',
292
617
  },
293
- // Analytics platform selector
294
618
  {
295
619
  displayName: 'Platform',
296
620
  name: 'analyticsPlatform',
297
621
  type: 'options',
298
- options: [
299
- { name: 'LinkedIn', value: 'linkedin' },
300
- { name: 'Instagram', value: 'instagram' },
301
- { name: 'Threads', value: 'threads' },
302
- { name: 'TikTok', value: 'tiktok' },
303
- { name: 'X (Twitter)', value: 'x' },
304
- ],
622
+ options: PLATFORM_OPTIONS,
305
623
  default: 'linkedin',
306
624
  required: true,
307
- displayOptions: {
308
- show: {
309
- resource: ['analytics'],
310
- operation: ['getAnalytics'],
311
- },
312
- },
625
+ displayOptions: { show: { resource: ['analytics'], operation: ['getAnalytics'] } },
313
626
  description: 'The platform to get analytics for',
314
627
  },
315
- // Additional options
316
628
  {
317
629
  displayName: 'Additional Options',
318
630
  name: 'additionalOptions',
319
631
  type: 'collection',
320
632
  placeholder: 'Add Option',
321
633
  default: {},
322
- displayOptions: {
323
- show: {
324
- resource: ['post', 'validation'],
325
- operation: ['publish', 'validate'],
326
- },
327
- },
634
+ displayOptions: { show: { resource: ['post', 'validation'], operation: ['publish', 'validate'] } },
328
635
  options: [
329
636
  {
330
637
  displayName: 'Media URLs (for carousel)',
@@ -345,43 +652,1144 @@ class SendIt {
345
652
  default: 'auto',
346
653
  description: 'Specify the media type',
347
654
  },
348
- ],
349
- },
350
- ],
351
- };
352
- }
353
- async execute() {
354
- const items = this.getInputData();
355
- const returnData = [];
356
- const resource = this.getNodeParameter('resource', 0);
655
+ {
656
+ displayName: 'Facebook Mode',
657
+ name: 'facebookMode',
658
+ type: 'options',
659
+ options: [
660
+ { name: 'Auto (try Reels first)', value: 'auto' },
661
+ { name: 'Reel', value: 'reel' },
662
+ { name: 'Feed Video', value: 'feed' },
663
+ ],
664
+ default: 'auto',
665
+ description: 'How to publish videos to Facebook',
666
+ },
667
+ {
668
+ displayName: 'YouTube Mode',
669
+ name: 'youtubeMode',
670
+ type: 'options',
671
+ options: [
672
+ { name: 'Auto', value: 'auto' },
673
+ { name: 'Short', value: 'short' },
674
+ { name: 'Standard Video', value: 'standard' },
675
+ ],
676
+ default: 'auto',
677
+ description: 'How to publish videos to YouTube',
678
+ },
679
+ {
680
+ displayName: 'Pinterest Board ID',
681
+ name: 'pinterestBoardId',
682
+ type: 'string',
683
+ default: '',
684
+ description: 'Pinterest board ID to pin to',
685
+ },
686
+ ],
687
+ },
688
+ {
689
+ displayName: 'AI Options',
690
+ name: 'aiOptions',
691
+ type: 'collection',
692
+ placeholder: 'Add Option',
693
+ default: {},
694
+ displayOptions: { show: { resource: ['post', 'ai'], operation: ['publishAi', 'generate'] } },
695
+ options: [
696
+ {
697
+ displayName: 'Hashtags',
698
+ name: 'hashtags',
699
+ type: 'options',
700
+ options: [
701
+ { name: 'Platform Default', value: 'platform_auto' },
702
+ { name: 'On (include hashtags)', value: 'on' },
703
+ { name: 'Off (no hashtags)', value: 'off' },
704
+ ],
705
+ default: 'platform_auto',
706
+ description: 'Hashtag generation mode',
707
+ },
708
+ {
709
+ displayName: 'Tone',
710
+ name: 'tone',
711
+ type: 'options',
712
+ options: [
713
+ { name: 'Professional', value: 'professional' },
714
+ { name: 'Casual', value: 'casual' },
715
+ { name: 'Energetic', value: 'energetic' },
716
+ { name: 'Informative', value: 'informative' },
717
+ ],
718
+ default: 'professional',
719
+ description: 'Content tone',
720
+ },
721
+ {
722
+ displayName: 'Style',
723
+ name: 'style',
724
+ type: 'options',
725
+ options: [
726
+ { name: 'Storytelling', value: 'storytelling' },
727
+ { name: 'Promotional', value: 'promotional' },
728
+ { name: 'Educational', value: 'educational' },
729
+ { name: 'Entertaining', value: 'entertaining' },
730
+ ],
731
+ default: 'promotional',
732
+ description: 'Content style',
733
+ },
734
+ {
735
+ displayName: 'Call To Action',
736
+ name: 'callToAction',
737
+ type: 'string',
738
+ default: '',
739
+ description: 'Call-to-action to include in content',
740
+ },
741
+ {
742
+ displayName: 'Strict AI',
743
+ name: 'strictAi',
744
+ type: 'boolean',
745
+ default: false,
746
+ description: 'Fail if AI generation fails (otherwise use fallback templates)',
747
+ },
748
+ {
749
+ displayName: 'Facebook Mode',
750
+ name: 'facebookMode',
751
+ type: 'options',
752
+ options: [
753
+ { name: 'Auto (try Reels first)', value: 'auto' },
754
+ { name: 'Reel', value: 'reel' },
755
+ { name: 'Feed Video', value: 'feed' },
756
+ ],
757
+ default: 'auto',
758
+ description: 'How to publish videos to Facebook',
759
+ },
760
+ {
761
+ displayName: 'YouTube Mode',
762
+ name: 'youtubeMode',
763
+ type: 'options',
764
+ options: [
765
+ { name: 'Auto', value: 'auto' },
766
+ { name: 'Short', value: 'short' },
767
+ { name: 'Standard Video', value: 'standard' },
768
+ ],
769
+ default: 'auto',
770
+ description: 'How to publish videos to YouTube',
771
+ },
772
+ ],
773
+ },
774
+ // ===== Existing brand voice / campaign / inbox / listening / ai media fields =====
775
+ {
776
+ displayName: 'Name',
777
+ name: 'brandVoiceName',
778
+ type: 'string',
779
+ default: '',
780
+ required: true,
781
+ displayOptions: { show: { resource: ['brandVoice'], operation: ['create'] } },
782
+ description: 'Name for the brand voice profile',
783
+ },
784
+ {
785
+ displayName: 'Description',
786
+ name: 'brandVoiceDescription',
787
+ type: 'string',
788
+ typeOptions: { rows: 3 },
789
+ default: '',
790
+ displayOptions: { show: { resource: ['brandVoice'], operation: ['create'] } },
791
+ description: 'Description of the brand voice',
792
+ },
793
+ {
794
+ displayName: 'Tone',
795
+ name: 'brandVoiceTone',
796
+ type: 'string',
797
+ default: '',
798
+ displayOptions: { show: { resource: ['brandVoice'], operation: ['create'] } },
799
+ description: 'Tone of voice (e.g. professional, casual, witty)',
800
+ },
801
+ {
802
+ displayName: 'Vocabulary',
803
+ name: 'brandVoiceVocabulary',
804
+ type: 'string',
805
+ default: '',
806
+ displayOptions: { show: { resource: ['brandVoice'], operation: ['create'] } },
807
+ description: 'Comma-separated preferred vocabulary words',
808
+ },
809
+ {
810
+ displayName: 'Banned Words',
811
+ name: 'brandVoiceBannedWords',
812
+ type: 'string',
813
+ default: '',
814
+ displayOptions: { show: { resource: ['brandVoice'], operation: ['create'] } },
815
+ description: 'Comma-separated words to avoid',
816
+ },
817
+ {
818
+ displayName: 'Is Default',
819
+ name: 'brandVoiceIsDefault',
820
+ type: 'boolean',
821
+ default: false,
822
+ displayOptions: { show: { resource: ['brandVoice'], operation: ['create'] } },
823
+ description: 'Whether this is the default brand voice',
824
+ },
825
+ {
826
+ displayName: 'Objective',
827
+ name: 'campaignObjective',
828
+ type: 'string',
829
+ typeOptions: { rows: 3 },
830
+ default: '',
831
+ displayOptions: { show: { resource: ['campaign'], operation: ['plan'] } },
832
+ description: 'Optional high-level objective to include in the campaign brief',
833
+ },
834
+ {
835
+ displayName: 'Platforms',
836
+ name: 'campaignPlatforms',
837
+ type: 'multiOptions',
838
+ options: PLATFORM_OPTIONS,
839
+ default: [],
840
+ required: true,
841
+ displayOptions: { show: { resource: ['campaign'], operation: ['plan'] } },
842
+ description: 'Target platforms for the campaign',
843
+ },
844
+ {
845
+ displayName: 'Brief',
846
+ name: 'campaignBrief',
847
+ type: 'string',
848
+ typeOptions: { rows: 4 },
849
+ default: '',
850
+ required: true,
851
+ displayOptions: { show: { resource: ['campaign'], operation: ['plan'] } },
852
+ description: 'Detailed campaign brief (required by API)',
853
+ },
854
+ {
855
+ displayName: 'Post Count',
856
+ name: 'campaignPostCount',
857
+ type: 'number',
858
+ default: 5,
859
+ displayOptions: { show: { resource: ['campaign'], operation: ['plan'] } },
860
+ description: 'Number of posts to generate in the campaign',
861
+ },
862
+ {
863
+ displayName: 'Start Date',
864
+ name: 'campaignStartDate',
865
+ type: 'dateTime',
866
+ default: '',
867
+ displayOptions: { show: { resource: ['campaign'], operation: ['plan'] } },
868
+ description: 'Optional campaign start date/time (ISO 8601)',
869
+ },
870
+ {
871
+ displayName: 'End Date',
872
+ name: 'campaignEndDate',
873
+ type: 'dateTime',
874
+ default: '',
875
+ displayOptions: { show: { resource: ['campaign'], operation: ['plan'] } },
876
+ description: 'Optional campaign end date/time (ISO 8601)',
877
+ },
878
+ {
879
+ displayName: 'Campaign ID',
880
+ name: 'campaignId',
881
+ type: 'string',
882
+ default: '',
883
+ required: true,
884
+ displayOptions: { show: { resource: ['campaign'], operation: ['schedule'] } },
885
+ description: 'The ID of the campaign to schedule',
886
+ },
887
+ {
888
+ displayName: 'Platform Filter',
889
+ name: 'inboxPlatformFilter',
890
+ type: 'options',
891
+ options: [{ name: 'All Platforms', value: '' }, ...PLATFORM_OPTIONS],
892
+ default: '',
893
+ displayOptions: { show: { resource: ['inbox'], operation: ['list'] } },
894
+ description: 'Optional platform filter for inbox threads',
895
+ },
896
+ {
897
+ displayName: 'Status Filter',
898
+ name: 'inboxStatusFilter',
899
+ type: 'options',
900
+ options: [
901
+ { name: 'All Statuses', value: '' },
902
+ { name: 'Open', value: 'open' },
903
+ { name: 'Replied', value: 'replied' },
904
+ { name: 'Closed', value: 'closed' },
905
+ { name: 'Archived', value: 'archived' },
906
+ ],
907
+ default: '',
908
+ displayOptions: { show: { resource: ['inbox'], operation: ['list'] } },
909
+ description: 'Optional status filter for inbox threads',
910
+ },
911
+ {
912
+ displayName: 'Limit',
913
+ name: 'inboxLimit',
914
+ type: 'number',
915
+ typeOptions: { minValue: 1, maxValue: 50 },
916
+ default: 20,
917
+ displayOptions: { show: { resource: ['inbox'], operation: ['list'] } },
918
+ description: 'Maximum number of threads to return (1-50)',
919
+ },
920
+ {
921
+ displayName: 'Thread ID',
922
+ name: 'inboxThreadId',
923
+ type: 'string',
924
+ default: '',
925
+ required: true,
926
+ displayOptions: {
927
+ show: {
928
+ resource: ['inbox'],
929
+ operation: ['reply', 'getThread', 'updateStatus'],
930
+ },
931
+ },
932
+ description: 'The ID of the inbox thread',
933
+ },
934
+ {
935
+ displayName: 'Message',
936
+ name: 'inboxMessage',
937
+ type: 'string',
938
+ typeOptions: { rows: 3 },
939
+ default: '',
940
+ required: true,
941
+ displayOptions: { show: { resource: ['inbox'], operation: ['reply'] } },
942
+ description: 'The reply message content',
943
+ },
944
+ {
945
+ displayName: 'Thread Status',
946
+ name: 'inboxThreadStatus',
947
+ type: 'options',
948
+ options: [
949
+ { name: 'Open', value: 'open' },
950
+ { name: 'Replied', value: 'replied' },
951
+ { name: 'Closed', value: 'closed' },
952
+ { name: 'Archived', value: 'archived' },
953
+ ],
954
+ default: 'open',
955
+ required: true,
956
+ displayOptions: { show: { resource: ['inbox'], operation: ['updateStatus'] } },
957
+ description: 'Updated status for thread',
958
+ },
959
+ {
960
+ displayName: 'Platforms',
961
+ name: 'listeningPlatforms',
962
+ type: 'multiOptions',
963
+ options: PLATFORM_OPTIONS,
964
+ default: [],
965
+ displayOptions: {
966
+ show: {
967
+ resource: ['listening'],
968
+ operation: ['refresh', 'createKeyword', 'updateKeyword'],
969
+ },
970
+ },
971
+ description: 'Platforms for listening operation',
972
+ },
973
+ {
974
+ displayName: 'Keyword IDs',
975
+ name: 'listeningKeywordIds',
976
+ type: 'string',
977
+ default: '',
978
+ displayOptions: {
979
+ show: {
980
+ resource: ['listening'],
981
+ operation: ['refresh'],
982
+ },
983
+ },
984
+ description: 'Comma-separated keyword IDs to refresh',
985
+ },
986
+ {
987
+ displayName: 'Keyword ID',
988
+ name: 'listeningKeywordId',
989
+ type: 'string',
990
+ default: '',
991
+ required: true,
992
+ displayOptions: {
993
+ show: {
994
+ resource: ['listening'],
995
+ operation: ['getKeyword', 'updateKeyword', 'deleteKeyword'],
996
+ },
997
+ },
998
+ description: 'Listening keyword ID',
999
+ },
1000
+ {
1001
+ displayName: 'Keyword',
1002
+ name: 'listeningKeyword',
1003
+ type: 'string',
1004
+ default: '',
1005
+ required: true,
1006
+ displayOptions: {
1007
+ show: {
1008
+ resource: ['listening'],
1009
+ operation: ['createKeyword'],
1010
+ },
1011
+ },
1012
+ description: 'Keyword text to monitor',
1013
+ },
1014
+ {
1015
+ displayName: 'Keyword Type',
1016
+ name: 'listeningKeywordType',
1017
+ type: 'options',
1018
+ options: [
1019
+ { name: 'Brand', value: 'brand' },
1020
+ { name: 'Competitor', value: 'competitor' },
1021
+ { name: 'Product', value: 'product' },
1022
+ { name: 'Hashtag', value: 'hashtag' },
1023
+ { name: 'Custom', value: 'custom' },
1024
+ ],
1025
+ default: 'brand',
1026
+ displayOptions: {
1027
+ show: {
1028
+ resource: ['listening'],
1029
+ operation: ['createKeyword', 'updateKeyword', 'listKeywords'],
1030
+ },
1031
+ },
1032
+ description: 'Listening keyword type',
1033
+ },
1034
+ {
1035
+ displayName: 'Active Only',
1036
+ name: 'listeningActiveOnly',
1037
+ type: 'boolean',
1038
+ default: true,
1039
+ displayOptions: { show: { resource: ['listening'], operation: ['listKeywords'] } },
1040
+ description: 'Only include active keywords',
1041
+ },
1042
+ {
1043
+ displayName: 'Notify Email',
1044
+ name: 'listeningNotifyEmail',
1045
+ type: 'boolean',
1046
+ default: false,
1047
+ displayOptions: { show: { resource: ['listening'], operation: ['createKeyword', 'updateKeyword'] } },
1048
+ description: 'Enable email notifications',
1049
+ },
1050
+ {
1051
+ displayName: 'Notify Webhook',
1052
+ name: 'listeningNotifyWebhook',
1053
+ type: 'boolean',
1054
+ default: false,
1055
+ displayOptions: { show: { resource: ['listening'], operation: ['createKeyword', 'updateKeyword'] } },
1056
+ description: 'Enable webhook notifications',
1057
+ },
1058
+ {
1059
+ displayName: 'Webhook URL',
1060
+ name: 'listeningWebhookUrl',
1061
+ type: 'string',
1062
+ default: '',
1063
+ displayOptions: { show: { resource: ['listening'], operation: ['createKeyword', 'updateKeyword'] } },
1064
+ description: 'Webhook URL for notifications',
1065
+ },
1066
+ {
1067
+ displayName: 'Sentiment Filter',
1068
+ name: 'listeningSentimentFilter',
1069
+ type: 'options',
1070
+ options: [
1071
+ { name: 'Any', value: '' },
1072
+ { name: 'Positive', value: 'positive' },
1073
+ { name: 'Neutral', value: 'neutral' },
1074
+ { name: 'Negative', value: 'negative' },
1075
+ ],
1076
+ default: '',
1077
+ displayOptions: {
1078
+ show: {
1079
+ resource: ['listening'],
1080
+ operation: ['createKeyword', 'updateKeyword', 'listMentions'],
1081
+ },
1082
+ },
1083
+ description: 'Sentiment filter',
1084
+ },
1085
+ {
1086
+ displayName: 'Mention ID',
1087
+ name: 'listeningMentionId',
1088
+ type: 'string',
1089
+ default: '',
1090
+ required: true,
1091
+ displayOptions: { show: { resource: ['listening'], operation: ['getMention'] } },
1092
+ description: 'Mention ID',
1093
+ },
1094
+ {
1095
+ displayName: 'Mention IDs',
1096
+ name: 'listeningMentionIds',
1097
+ type: 'string',
1098
+ default: '',
1099
+ required: true,
1100
+ displayOptions: { show: { resource: ['listening'], operation: ['markMentionsRead', 'archiveMentions'] } },
1101
+ description: 'Comma-separated mention IDs',
1102
+ },
1103
+ {
1104
+ displayName: 'Alerts Unread Only',
1105
+ name: 'listeningAlertsUnreadOnly',
1106
+ type: 'boolean',
1107
+ default: false,
1108
+ displayOptions: { show: { resource: ['listening'], operation: ['listAlerts'] } },
1109
+ description: 'Only include unread alerts',
1110
+ },
1111
+ {
1112
+ displayName: 'Alert Priority',
1113
+ name: 'listeningAlertPriority',
1114
+ type: 'options',
1115
+ options: [
1116
+ { name: 'Any', value: '' },
1117
+ { name: 'Low', value: 'low' },
1118
+ { name: 'Medium', value: 'medium' },
1119
+ { name: 'High', value: 'high' },
1120
+ { name: 'Critical', value: 'critical' },
1121
+ ],
1122
+ default: '',
1123
+ displayOptions: { show: { resource: ['listening'], operation: ['listAlerts'] } },
1124
+ description: 'Alert priority filter',
1125
+ },
1126
+ {
1127
+ displayName: 'Listening Limit',
1128
+ name: 'listeningLimit',
1129
+ type: 'number',
1130
+ default: 50,
1131
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions', 'listAlerts'] } },
1132
+ description: 'Max records to return',
1133
+ },
1134
+ {
1135
+ displayName: 'Listening Offset',
1136
+ name: 'listeningOffset',
1137
+ type: 'number',
1138
+ default: 0,
1139
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions'] } },
1140
+ description: 'Offset for pagination',
1141
+ },
1142
+ {
1143
+ displayName: 'Mention Platform',
1144
+ name: 'listeningMentionPlatform',
1145
+ type: 'options',
1146
+ options: [{ name: 'Any', value: '' }, ...PLATFORM_OPTIONS],
1147
+ default: '',
1148
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions'] } },
1149
+ description: 'Platform filter for mentions',
1150
+ },
1151
+ {
1152
+ displayName: 'Mention Keyword ID',
1153
+ name: 'listeningMentionKeywordId',
1154
+ type: 'string',
1155
+ default: '',
1156
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions'] } },
1157
+ description: 'Filter mentions by keyword ID',
1158
+ },
1159
+ {
1160
+ displayName: 'Mentions Is Read',
1161
+ name: 'listeningIsRead',
1162
+ type: 'options',
1163
+ options: [
1164
+ { name: 'Any', value: '' },
1165
+ { name: 'Read', value: 'true' },
1166
+ { name: 'Unread', value: 'false' },
1167
+ ],
1168
+ default: '',
1169
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions'] } },
1170
+ description: 'Read state filter',
1171
+ },
1172
+ {
1173
+ displayName: 'Mentions Is Archived',
1174
+ name: 'listeningIsArchived',
1175
+ type: 'options',
1176
+ options: [
1177
+ { name: 'Any', value: '' },
1178
+ { name: 'Archived', value: 'true' },
1179
+ { name: 'Active', value: 'false' },
1180
+ ],
1181
+ default: '',
1182
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions'] } },
1183
+ description: 'Archived state filter',
1184
+ },
1185
+ {
1186
+ displayName: 'Mentions Since',
1187
+ name: 'listeningSince',
1188
+ type: 'dateTime',
1189
+ default: '',
1190
+ displayOptions: { show: { resource: ['listening'], operation: ['listMentions'] } },
1191
+ description: 'Only mentions since this timestamp',
1192
+ },
1193
+ {
1194
+ displayName: 'Alert IDs',
1195
+ name: 'listeningAlertIds',
1196
+ type: 'string',
1197
+ default: '',
1198
+ required: true,
1199
+ displayOptions: { show: { resource: ['listening'], operation: ['markAlertsRead', 'dismissAlerts'] } },
1200
+ description: 'Comma-separated alert IDs',
1201
+ },
1202
+ {
1203
+ displayName: 'Provider',
1204
+ name: 'aiMediaProvider',
1205
+ type: 'options',
1206
+ options: [
1207
+ { name: 'Sora', value: 'sora' },
1208
+ { name: 'Runway', value: 'runway' },
1209
+ { name: 'Pika', value: 'pika' },
1210
+ { name: 'Adobe Express', value: 'adobe-express' },
1211
+ ],
1212
+ default: 'sora',
1213
+ required: true,
1214
+ displayOptions: { show: { resource: ['aiMedia'], operation: ['create'] } },
1215
+ description: 'AI media generation provider',
1216
+ },
1217
+ {
1218
+ displayName: 'Prompt',
1219
+ name: 'aiMediaPrompt',
1220
+ type: 'string',
1221
+ typeOptions: { rows: 3 },
1222
+ default: '',
1223
+ required: true,
1224
+ displayOptions: { show: { resource: ['aiMedia'], operation: ['create'] } },
1225
+ description: 'Prompt describing the media to generate',
1226
+ },
1227
+ {
1228
+ displayName: 'Media Type',
1229
+ name: 'aiMediaType',
1230
+ type: 'options',
1231
+ options: [
1232
+ { name: 'Image', value: 'image' },
1233
+ { name: 'Video', value: 'video' },
1234
+ ],
1235
+ default: 'image',
1236
+ displayOptions: { show: { resource: ['aiMedia'], operation: ['create'] } },
1237
+ description: 'Type of media to generate',
1238
+ },
1239
+ {
1240
+ displayName: 'Style Preset',
1241
+ name: 'aiMediaStylePreset',
1242
+ type: 'string',
1243
+ default: '',
1244
+ displayOptions: { show: { resource: ['aiMedia'], operation: ['create'] } },
1245
+ description: 'Optional style preset for generation',
1246
+ },
1247
+ {
1248
+ displayName: 'Job ID',
1249
+ name: 'aiMediaJobId',
1250
+ type: 'string',
1251
+ default: '',
1252
+ required: true,
1253
+ displayOptions: { show: { resource: ['aiMedia'], operation: ['getStatus'] } },
1254
+ description: 'The ID of the AI media generation job',
1255
+ },
1256
+ // ===== New Meta fields =====
1257
+ {
1258
+ displayName: 'Platform',
1259
+ name: 'metaPlatform',
1260
+ type: 'options',
1261
+ options: PLATFORM_OPTIONS,
1262
+ default: 'linkedin',
1263
+ required: true,
1264
+ displayOptions: {
1265
+ show: {
1266
+ resource: ['meta'],
1267
+ operation: ['getRequirements', 'getPlatformSettingsSchema', 'getBestTimes'],
1268
+ },
1269
+ },
1270
+ description: 'Platform for this meta operation',
1271
+ },
1272
+ {
1273
+ displayName: 'Best Times Limit',
1274
+ name: 'metaBestTimesLimit',
1275
+ type: 'number',
1276
+ default: 5,
1277
+ displayOptions: {
1278
+ show: {
1279
+ resource: ['meta'],
1280
+ operation: ['getBestTimes'],
1281
+ },
1282
+ },
1283
+ description: 'Maximum best-time recommendations to return',
1284
+ },
1285
+ // ===== Content score fields =====
1286
+ {
1287
+ displayName: 'Score Media URLs',
1288
+ name: 'scoreMediaUrls',
1289
+ type: 'string',
1290
+ default: '',
1291
+ displayOptions: { show: { resource: ['contentScore'], operation: ['score'] } },
1292
+ description: 'Comma-separated media URLs for scoring',
1293
+ },
1294
+ {
1295
+ displayName: 'Score Scheduled Time',
1296
+ name: 'scoreScheduledTime',
1297
+ type: 'dateTime',
1298
+ default: '',
1299
+ displayOptions: { show: { resource: ['contentScore'], operation: ['score'] } },
1300
+ description: 'Optional scheduled time for score context',
1301
+ },
1302
+ // ===== Library fields =====
1303
+ {
1304
+ displayName: 'Library Item ID',
1305
+ name: 'libraryItemId',
1306
+ type: 'string',
1307
+ default: '',
1308
+ required: true,
1309
+ displayOptions: {
1310
+ show: {
1311
+ resource: ['library'],
1312
+ operation: ['get', 'update', 'delete'],
1313
+ },
1314
+ },
1315
+ description: 'Library item ID',
1316
+ },
1317
+ {
1318
+ displayName: 'Title',
1319
+ name: 'libraryTitle',
1320
+ type: 'string',
1321
+ default: '',
1322
+ required: true,
1323
+ displayOptions: {
1324
+ show: {
1325
+ resource: ['library'],
1326
+ operation: ['create', 'update'],
1327
+ },
1328
+ },
1329
+ description: 'Library item title',
1330
+ },
1331
+ {
1332
+ displayName: 'Body Text',
1333
+ name: 'libraryText',
1334
+ type: 'string',
1335
+ typeOptions: { rows: 4 },
1336
+ default: '',
1337
+ required: true,
1338
+ displayOptions: {
1339
+ show: {
1340
+ resource: ['library'],
1341
+ operation: ['create', 'update'],
1342
+ },
1343
+ },
1344
+ description: 'Library item text body',
1345
+ },
1346
+ {
1347
+ displayName: 'Library Type',
1348
+ name: 'libraryType',
1349
+ type: 'options',
1350
+ options: [
1351
+ { name: 'Draft', value: 'draft' },
1352
+ { name: 'Template', value: 'template' },
1353
+ { name: 'Evergreen', value: 'evergreen' },
1354
+ ],
1355
+ default: 'draft',
1356
+ displayOptions: {
1357
+ show: {
1358
+ resource: ['library'],
1359
+ operation: ['list', 'create', 'update'],
1360
+ },
1361
+ },
1362
+ description: 'Library content type',
1363
+ },
1364
+ {
1365
+ displayName: 'Category',
1366
+ name: 'libraryCategory',
1367
+ type: 'string',
1368
+ default: '',
1369
+ displayOptions: {
1370
+ show: {
1371
+ resource: ['library'],
1372
+ operation: ['list', 'create', 'update'],
1373
+ },
1374
+ },
1375
+ description: 'Library category',
1376
+ },
1377
+ {
1378
+ displayName: 'Tags',
1379
+ name: 'libraryTags',
1380
+ type: 'string',
1381
+ default: '',
1382
+ displayOptions: {
1383
+ show: {
1384
+ resource: ['library'],
1385
+ operation: ['list', 'create', 'update'],
1386
+ },
1387
+ },
1388
+ description: 'Comma-separated tags',
1389
+ },
1390
+ {
1391
+ displayName: 'Target Platforms',
1392
+ name: 'libraryTargetPlatforms',
1393
+ type: 'multiOptions',
1394
+ options: PLATFORM_OPTIONS,
1395
+ default: [],
1396
+ displayOptions: {
1397
+ show: {
1398
+ resource: ['library'],
1399
+ operation: ['list', 'create', 'update'],
1400
+ },
1401
+ },
1402
+ description: 'Target platforms for this library item',
1403
+ },
1404
+ {
1405
+ displayName: 'Search',
1406
+ name: 'librarySearch',
1407
+ type: 'string',
1408
+ default: '',
1409
+ displayOptions: { show: { resource: ['library'], operation: ['list'] } },
1410
+ description: 'Search text',
1411
+ },
1412
+ {
1413
+ displayName: 'Limit',
1414
+ name: 'libraryLimit',
1415
+ type: 'number',
1416
+ default: 50,
1417
+ displayOptions: { show: { resource: ['library'], operation: ['list'] } },
1418
+ description: 'Maximum number of library items to return',
1419
+ },
1420
+ {
1421
+ displayName: 'Offset',
1422
+ name: 'libraryOffset',
1423
+ type: 'number',
1424
+ default: 0,
1425
+ displayOptions: { show: { resource: ['library'], operation: ['list'] } },
1426
+ description: 'Offset for pagination',
1427
+ },
1428
+ {
1429
+ displayName: 'Evergreen Enabled',
1430
+ name: 'libraryEvergreenEnabled',
1431
+ type: 'boolean',
1432
+ default: false,
1433
+ displayOptions: {
1434
+ show: {
1435
+ resource: ['library'],
1436
+ operation: ['create', 'update'],
1437
+ },
1438
+ },
1439
+ description: 'Enable evergreen republishing',
1440
+ },
1441
+ {
1442
+ displayName: 'Evergreen Interval Days',
1443
+ name: 'libraryEvergreenIntervalDays',
1444
+ type: 'number',
1445
+ default: 0,
1446
+ displayOptions: {
1447
+ show: {
1448
+ resource: ['library'],
1449
+ operation: ['create', 'update'],
1450
+ },
1451
+ },
1452
+ description: 'Optional evergreen interval days',
1453
+ },
1454
+ {
1455
+ displayName: 'Evergreen Max Publishes',
1456
+ name: 'libraryEvergreenMaxPublishes',
1457
+ type: 'number',
1458
+ default: 0,
1459
+ displayOptions: {
1460
+ show: {
1461
+ resource: ['library'],
1462
+ operation: ['create', 'update'],
1463
+ },
1464
+ },
1465
+ description: 'Optional max evergreen publish count',
1466
+ },
1467
+ // ===== Approvals fields =====
1468
+ {
1469
+ displayName: 'Approval Post ID',
1470
+ name: 'approvalPostId',
1471
+ type: 'string',
1472
+ default: '',
1473
+ required: true,
1474
+ displayOptions: {
1475
+ show: {
1476
+ resource: ['approvals'],
1477
+ operation: ['approve', 'reject'],
1478
+ },
1479
+ },
1480
+ description: 'Scheduled post ID in approvals queue',
1481
+ },
1482
+ {
1483
+ displayName: 'Approval Comment',
1484
+ name: 'approvalComment',
1485
+ type: 'string',
1486
+ default: '',
1487
+ displayOptions: {
1488
+ show: {
1489
+ resource: ['approvals'],
1490
+ operation: ['approve'],
1491
+ },
1492
+ },
1493
+ description: 'Optional approval comment',
1494
+ },
1495
+ {
1496
+ displayName: 'Rejection Reason',
1497
+ name: 'approvalReason',
1498
+ type: 'string',
1499
+ default: '',
1500
+ required: true,
1501
+ displayOptions: {
1502
+ show: {
1503
+ resource: ['approvals'],
1504
+ operation: ['reject'],
1505
+ },
1506
+ },
1507
+ description: 'Required rejection reason',
1508
+ },
1509
+ // ===== Bulk schedule fields =====
1510
+ {
1511
+ displayName: 'Import ID',
1512
+ name: 'bulkImportId',
1513
+ type: 'string',
1514
+ default: '',
1515
+ required: true,
1516
+ displayOptions: { show: { resource: ['bulkSchedule'], operation: ['getImport'] } },
1517
+ description: 'Bulk import ID',
1518
+ },
1519
+ {
1520
+ displayName: 'CSV Content',
1521
+ name: 'bulkCsvContent',
1522
+ type: 'string',
1523
+ typeOptions: { rows: 6 },
1524
+ default: '',
1525
+ required: true,
1526
+ displayOptions: {
1527
+ show: {
1528
+ resource: ['bulkSchedule'],
1529
+ operation: ['validateCsv', 'importCsv'],
1530
+ },
1531
+ },
1532
+ description: 'Raw CSV string payload',
1533
+ },
1534
+ {
1535
+ displayName: 'Filename',
1536
+ name: 'bulkFilename',
1537
+ type: 'string',
1538
+ default: 'upload.csv',
1539
+ displayOptions: {
1540
+ show: {
1541
+ resource: ['bulkSchedule'],
1542
+ operation: ['validateCsv', 'importCsv'],
1543
+ },
1544
+ },
1545
+ description: 'CSV filename for import metadata',
1546
+ },
1547
+ {
1548
+ displayName: 'Skip Errors',
1549
+ name: 'bulkSkipErrors',
1550
+ type: 'boolean',
1551
+ default: false,
1552
+ displayOptions: { show: { resource: ['bulkSchedule'], operation: ['importCsv'] } },
1553
+ description: 'Continue import even if some rows fail validation',
1554
+ },
1555
+ // ===== Connect fields =====
1556
+ {
1557
+ displayName: 'Connect Platform',
1558
+ name: 'connectPlatform',
1559
+ type: 'options',
1560
+ options: PLATFORM_OPTIONS,
1561
+ default: 'linkedin',
1562
+ required: true,
1563
+ displayOptions: { show: { resource: ['connect'], operation: ['getConnectAction', 'connectToken', 'connectWebhook'] } },
1564
+ description: 'Platform to connect',
1565
+ },
1566
+ {
1567
+ displayName: 'Credentials JSON',
1568
+ name: 'connectCredentialsJson',
1569
+ type: 'string',
1570
+ typeOptions: { rows: 6 },
1571
+ default: '',
1572
+ required: true,
1573
+ displayOptions: { show: { resource: ['connect'], operation: ['connectToken'] } },
1574
+ description: 'JSON object of token/custom credentials',
1575
+ },
1576
+ {
1577
+ displayName: 'Webhook URL',
1578
+ name: 'connectWebhookUrl',
1579
+ type: 'string',
1580
+ default: '',
1581
+ required: true,
1582
+ displayOptions: { show: { resource: ['connect'], operation: ['connectWebhook'] } },
1583
+ description: 'Webhook URL for webhook-based platform connections',
1584
+ },
1585
+ {
1586
+ displayName: 'Metadata JSON',
1587
+ name: 'connectMetadataJson',
1588
+ type: 'string',
1589
+ typeOptions: { rows: 4 },
1590
+ default: '',
1591
+ displayOptions: { show: { resource: ['connect'], operation: ['connectWebhook'] } },
1592
+ description: 'Optional JSON metadata object',
1593
+ },
1594
+ // ===== Webhook helper fields =====
1595
+ {
1596
+ displayName: 'Webhook ID',
1597
+ name: 'webhookId',
1598
+ type: 'string',
1599
+ default: '',
1600
+ required: true,
1601
+ displayOptions: { show: { resource: ['webhooks'], operation: ['testWebhook'] } },
1602
+ description: 'Webhook subscription ID to test',
1603
+ },
1604
+ // ===== Advanced fields =====
1605
+ {
1606
+ displayName: 'Method',
1607
+ name: 'advancedMethod',
1608
+ type: 'options',
1609
+ options: [
1610
+ { name: 'GET', value: 'GET' },
1611
+ { name: 'POST', value: 'POST' },
1612
+ { name: 'PATCH', value: 'PATCH' },
1613
+ { name: 'PUT', value: 'PUT' },
1614
+ { name: 'DELETE', value: 'DELETE' },
1615
+ ],
1616
+ default: 'GET',
1617
+ required: true,
1618
+ displayOptions: { show: { resource: ['advanced'], operation: ['apiRequest'] } },
1619
+ description: 'HTTP method for advanced request',
1620
+ },
1621
+ {
1622
+ displayName: 'Path',
1623
+ name: 'advancedPath',
1624
+ type: 'string',
1625
+ default: '/api/v1/capabilities',
1626
+ required: true,
1627
+ displayOptions: { show: { resource: ['advanced'], operation: ['apiRequest'] } },
1628
+ description: 'Absolute API path starting with /api/v1/ or /api/v2/',
1629
+ },
1630
+ {
1631
+ displayName: 'Query JSON',
1632
+ name: 'advancedQueryJson',
1633
+ type: 'string',
1634
+ typeOptions: { rows: 4 },
1635
+ default: '',
1636
+ displayOptions: { show: { resource: ['advanced'], operation: ['apiRequest'] } },
1637
+ description: 'Optional JSON object for query string params',
1638
+ },
1639
+ {
1640
+ displayName: 'Body JSON',
1641
+ name: 'advancedBodyJson',
1642
+ type: 'string',
1643
+ typeOptions: { rows: 6 },
1644
+ default: '',
1645
+ displayOptions: { show: { resource: ['advanced'], operation: ['apiRequest'] } },
1646
+ description: 'Optional JSON payload for request body',
1647
+ },
1648
+ {
1649
+ displayName: 'Response Mode',
1650
+ name: 'advancedResponseMode',
1651
+ type: 'options',
1652
+ options: [
1653
+ { name: 'JSON', value: 'json' },
1654
+ { name: 'Text', value: 'text' },
1655
+ { name: 'Binary', value: 'binary' },
1656
+ ],
1657
+ default: 'json',
1658
+ displayOptions: { show: { resource: ['advanced'], operation: ['apiRequest'] } },
1659
+ description: 'How to decode the response payload',
1660
+ },
1661
+ {
1662
+ displayName: 'Request Timeout (ms)',
1663
+ name: 'requestTimeoutMs',
1664
+ type: 'number',
1665
+ default: 30000,
1666
+ description: 'Optional timeout. Applied by advanced API request operation',
1667
+ },
1668
+ ],
1669
+ };
1670
+ }
1671
+ async execute() {
1672
+ var _a, _b, _c, _d;
1673
+ const items = this.getInputData();
1674
+ const returnData = [];
1675
+ const resource = this.getNodeParameter('resource', 0);
357
1676
  const operation = this.getNodeParameter('operation', 0);
358
1677
  for (let i = 0; i < items.length; i++) {
359
1678
  try {
360
- let response;
1679
+ const teamId = getOptionalString(this.getNodeParameter('teamId', i));
1680
+ const idempotencyKey = getOptionalString(this.getNodeParameter('idempotencyKey', i));
1681
+ const optionalHeaders = buildOptionalHeaders(teamId, idempotencyKey);
1682
+ let response = {};
361
1683
  if (resource === 'post') {
362
1684
  if (operation === 'publish') {
363
1685
  const platforms = this.getNodeParameter('platforms', i);
364
1686
  const text = this.getNodeParameter('text', i);
365
1687
  const mediaUrl = this.getNodeParameter('mediaUrl', i);
366
1688
  const additionalOptions = this.getNodeParameter('additionalOptions', i);
1689
+ response = await requestV1(this, {
1690
+ method: 'POST',
1691
+ url: '/publish',
1692
+ body: {
1693
+ platforms,
1694
+ content: {
1695
+ text,
1696
+ mediaUrl: mediaUrl || undefined,
1697
+ mediaUrls: maybeArray(additionalOptions.mediaUrls),
1698
+ mediaType: additionalOptions.mediaType || 'auto',
1699
+ facebookMode: additionalOptions.facebookMode,
1700
+ youtubeMode: additionalOptions.youtubeMode,
1701
+ pinterestBoardId: additionalOptions.pinterestBoardId,
1702
+ },
1703
+ },
1704
+ json: true,
1705
+ }, optionalHeaders);
1706
+ }
1707
+ else if (operation === 'publishAi') {
1708
+ const platforms = this.getNodeParameter('platforms', i);
1709
+ const mediaUrl = this.getNodeParameter('mediaUrl', i);
1710
+ const prompt = this.getNodeParameter('aiPrompt', i);
1711
+ const aiOptions = this.getNodeParameter('aiOptions', i);
367
1712
  const body = {
368
1713
  platforms,
369
- content: {
370
- text,
371
- mediaUrl: mediaUrl || undefined,
372
- mediaUrls: additionalOptions.mediaUrls
373
- ? additionalOptions.mediaUrls.split(',').map((u) => u.trim())
374
- : undefined,
375
- mediaType: additionalOptions.mediaType || 'auto',
376
- },
1714
+ mediaUrl: mediaUrl || undefined,
1715
+ prompt: prompt || undefined,
1716
+ hashtags: aiOptions.hashtags || 'platform_auto',
1717
+ strictAi: aiOptions.strictAi || false,
1718
+ facebookMode: aiOptions.facebookMode,
1719
+ youtubeMode: aiOptions.youtubeMode,
377
1720
  };
378
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1721
+ if (aiOptions.tone || aiOptions.style || aiOptions.callToAction) {
1722
+ body.generation = {
1723
+ tone: aiOptions.tone,
1724
+ style: aiOptions.style,
1725
+ callToAction: aiOptions.callToAction,
1726
+ };
1727
+ }
1728
+ response = await requestV1(this, {
379
1729
  method: 'POST',
380
- baseURL: SENDIT_API_BASE_URL,
381
- url: '/publish',
1730
+ url: '/publish-ai',
1731
+ body,
1732
+ json: true,
1733
+ }, optionalHeaders);
1734
+ }
1735
+ }
1736
+ else if (resource === 'ai') {
1737
+ if (operation === 'generate') {
1738
+ const platforms = this.getNodeParameter('platforms', i);
1739
+ const mediaUrl = this.getNodeParameter('mediaUrl', i);
1740
+ const prompt = this.getNodeParameter('aiPrompt', i);
1741
+ const aiOptions = this.getNodeParameter('aiOptions', i);
1742
+ const body = {
1743
+ platforms,
1744
+ mediaUrl: mediaUrl || undefined,
1745
+ prompt: prompt || undefined,
1746
+ hashtags: aiOptions.hashtags || 'platform_auto',
1747
+ strictAi: aiOptions.strictAi || false,
1748
+ };
1749
+ if (aiOptions.tone || aiOptions.style || aiOptions.callToAction) {
1750
+ body.generation = {
1751
+ tone: aiOptions.tone,
1752
+ style: aiOptions.style,
1753
+ callToAction: aiOptions.callToAction,
1754
+ };
1755
+ }
1756
+ response = await requestV1(this, {
1757
+ method: 'POST',
1758
+ url: '/ai/generate-content',
382
1759
  body,
383
1760
  json: true,
384
- });
1761
+ }, optionalHeaders);
1762
+ }
1763
+ }
1764
+ else if (resource === 'media') {
1765
+ if (operation === 'upload') {
1766
+ const inputMode = this.getNodeParameter('mediaInputMode', i);
1767
+ if (inputMode === 'binary') {
1768
+ const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
1769
+ const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
1770
+ const buffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
1771
+ const formData = new FormData();
1772
+ formData.append('file', new Blob([buffer]), binaryData.fileName || 'upload');
1773
+ response = await requestV1(this, {
1774
+ method: 'POST',
1775
+ url: '/media/upload',
1776
+ body: formData,
1777
+ }, optionalHeaders);
1778
+ }
1779
+ else {
1780
+ const filePath = this.getNodeParameter('filePath', i);
1781
+ const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
1782
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
1783
+ const fileBuffer = await fs.readFile(filePath);
1784
+ const fileName = path.basename(filePath);
1785
+ const formData = new FormData();
1786
+ formData.append('file', new Blob([fileBuffer]), fileName);
1787
+ response = await requestV1(this, {
1788
+ method: 'POST',
1789
+ url: '/media/upload',
1790
+ body: formData,
1791
+ }, optionalHeaders);
1792
+ }
385
1793
  }
386
1794
  }
387
1795
  else if (resource === 'scheduledPost') {
@@ -390,9 +1798,8 @@ class SendIt {
390
1798
  const text = this.getNodeParameter('text', i);
391
1799
  const mediaUrl = this.getNodeParameter('mediaUrl', i);
392
1800
  const scheduledTime = this.getNodeParameter('scheduledTime', i);
393
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1801
+ response = await requestV1(this, {
394
1802
  method: 'POST',
395
- baseURL: SENDIT_API_BASE_URL,
396
1803
  url: '/schedule',
397
1804
  body: {
398
1805
  platforms,
@@ -403,7 +1810,7 @@ class SendIt {
403
1810
  scheduledTime,
404
1811
  },
405
1812
  json: true,
406
- });
1813
+ }, optionalHeaders);
407
1814
  }
408
1815
  else if (operation === 'getAll') {
409
1816
  const platformFilter = this.getNodeParameter('platformFilter', i);
@@ -411,37 +1818,33 @@ class SendIt {
411
1818
  if (platformFilter) {
412
1819
  qs.platform = platformFilter;
413
1820
  }
414
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1821
+ response = await requestV1(this, {
415
1822
  method: 'GET',
416
- baseURL: SENDIT_API_BASE_URL,
417
1823
  url: '/scheduled',
418
1824
  qs,
419
- });
1825
+ }, optionalHeaders);
420
1826
  }
421
1827
  else if (operation === 'delete') {
422
1828
  const scheduleId = this.getNodeParameter('scheduleId', i);
423
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1829
+ response = await requestV1(this, {
424
1830
  method: 'DELETE',
425
- baseURL: SENDIT_API_BASE_URL,
426
1831
  url: `/scheduled/${scheduleId}`,
427
- });
1832
+ }, optionalHeaders);
428
1833
  }
429
1834
  else if (operation === 'trigger') {
430
1835
  const scheduleId = this.getNodeParameter('scheduleId', i);
431
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1836
+ response = await requestV1(this, {
432
1837
  method: 'POST',
433
- baseURL: SENDIT_API_BASE_URL,
434
1838
  url: `/scheduled/${scheduleId}/trigger`,
435
- });
1839
+ }, optionalHeaders);
436
1840
  }
437
1841
  }
438
1842
  else if (resource === 'account') {
439
1843
  if (operation === 'getAll') {
440
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1844
+ response = await requestV1(this, {
441
1845
  method: 'GET',
442
- baseURL: SENDIT_API_BASE_URL,
443
1846
  url: '/accounts',
444
- });
1847
+ }, optionalHeaders);
445
1848
  }
446
1849
  }
447
1850
  else if (resource === 'validation') {
@@ -450,41 +1853,698 @@ class SendIt {
450
1853
  const text = this.getNodeParameter('text', i);
451
1854
  const mediaUrl = this.getNodeParameter('mediaUrl', i);
452
1855
  const additionalOptions = this.getNodeParameter('additionalOptions', i);
453
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1856
+ response = await requestV1(this, {
454
1857
  method: 'POST',
455
- baseURL: SENDIT_API_BASE_URL,
456
1858
  url: '/validate',
457
1859
  body: {
458
1860
  platforms,
459
1861
  content: {
460
1862
  text,
461
1863
  mediaUrl: mediaUrl || undefined,
462
- mediaUrls: additionalOptions.mediaUrls
463
- ? additionalOptions.mediaUrls.split(',').map((u) => u.trim())
464
- : undefined,
1864
+ mediaUrls: maybeArray(additionalOptions.mediaUrls),
465
1865
  mediaType: additionalOptions.mediaType || 'auto',
466
1866
  },
467
1867
  },
468
1868
  json: true,
469
- });
1869
+ }, optionalHeaders);
470
1870
  }
471
1871
  }
472
1872
  else if (resource === 'analytics') {
473
1873
  if (operation === 'getAnalytics') {
474
1874
  const platform = this.getNodeParameter('analyticsPlatform', i);
475
- response = await this.helpers.httpRequestWithAuthentication.call(this, 'sendItApi', {
1875
+ response = await requestV1(this, {
476
1876
  method: 'GET',
477
- baseURL: SENDIT_API_BASE_URL,
478
1877
  url: '/analytics',
479
- qs: {
1878
+ qs: { platform },
1879
+ }, optionalHeaders);
1880
+ }
1881
+ }
1882
+ else if (resource === 'brandVoice') {
1883
+ if (operation === 'create') {
1884
+ const name = this.getNodeParameter('brandVoiceName', i);
1885
+ const description = this.getNodeParameter('brandVoiceDescription', i);
1886
+ const tone = this.getNodeParameter('brandVoiceTone', i);
1887
+ const vocabulary = this.getNodeParameter('brandVoiceVocabulary', i);
1888
+ const bannedWords = this.getNodeParameter('brandVoiceBannedWords', i);
1889
+ const isDefault = this.getNodeParameter('brandVoiceIsDefault', i);
1890
+ const body = {
1891
+ name,
1892
+ description: description || undefined,
1893
+ tone: tone || undefined,
1894
+ vocabulary: maybeArray(vocabulary),
1895
+ bannedWords: maybeArray(bannedWords),
1896
+ isDefault,
1897
+ };
1898
+ response = await requestV1(this, {
1899
+ method: 'POST',
1900
+ url: '/brand-voice',
1901
+ body,
1902
+ json: true,
1903
+ }, optionalHeaders);
1904
+ }
1905
+ else if (operation === 'list') {
1906
+ response = await requestV1(this, {
1907
+ method: 'GET',
1908
+ url: '/brand-voice',
1909
+ }, optionalHeaders);
1910
+ }
1911
+ }
1912
+ else if (resource === 'campaign') {
1913
+ if (operation === 'plan') {
1914
+ const objective = this.getNodeParameter('campaignObjective', i);
1915
+ const platforms = this.getNodeParameter('campaignPlatforms', i);
1916
+ const brief = this.getNodeParameter('campaignBrief', i);
1917
+ const postCount = this.getNodeParameter('campaignPostCount', i);
1918
+ const startDate = this.getNodeParameter('campaignStartDate', i);
1919
+ const endDate = this.getNodeParameter('campaignEndDate', i);
1920
+ const normalizedBrief = brief || objective;
1921
+ response = await requestV1(this, {
1922
+ method: 'POST',
1923
+ url: '/campaigns',
1924
+ body: {
1925
+ brief: normalizedBrief,
1926
+ platforms,
1927
+ postCount: Number.isFinite(postCount) ? postCount : undefined,
1928
+ startDate: startDate || undefined,
1929
+ endDate: endDate || undefined,
1930
+ },
1931
+ json: true,
1932
+ }, optionalHeaders);
1933
+ }
1934
+ else if (operation === 'list') {
1935
+ response = await requestV1(this, {
1936
+ method: 'GET',
1937
+ url: '/campaigns',
1938
+ }, optionalHeaders);
1939
+ }
1940
+ else if (operation === 'schedule') {
1941
+ const campaignId = this.getNodeParameter('campaignId', i);
1942
+ response = await requestV1(this, {
1943
+ method: 'POST',
1944
+ url: `/campaigns/${campaignId}/schedule`,
1945
+ json: true,
1946
+ }, optionalHeaders);
1947
+ }
1948
+ }
1949
+ else if (resource === 'inbox') {
1950
+ if (operation === 'list') {
1951
+ const platformFilter = this.getNodeParameter('inboxPlatformFilter', i);
1952
+ const statusFilter = this.getNodeParameter('inboxStatusFilter', i);
1953
+ const limit = this.getNodeParameter('inboxLimit', i);
1954
+ const qs = { limit };
1955
+ if (platformFilter) {
1956
+ qs.platform = platformFilter;
1957
+ }
1958
+ if (statusFilter) {
1959
+ qs.status = statusFilter;
1960
+ }
1961
+ response = await requestV1(this, {
1962
+ method: 'GET',
1963
+ url: '/inbox',
1964
+ qs,
1965
+ }, optionalHeaders);
1966
+ }
1967
+ else if (operation === 'reply') {
1968
+ const threadId = this.getNodeParameter('inboxThreadId', i);
1969
+ const message = this.getNodeParameter('inboxMessage', i);
1970
+ response = await requestV1(this, {
1971
+ method: 'POST',
1972
+ url: `/inbox/${threadId}/reply`,
1973
+ body: { text: message },
1974
+ json: true,
1975
+ }, optionalHeaders);
1976
+ }
1977
+ else if (operation === 'getThread') {
1978
+ const threadId = this.getNodeParameter('inboxThreadId', i);
1979
+ response = await requestV1(this, {
1980
+ method: 'GET',
1981
+ url: `/inbox/${threadId}`,
1982
+ }, optionalHeaders);
1983
+ }
1984
+ else if (operation === 'updateStatus') {
1985
+ const threadId = this.getNodeParameter('inboxThreadId', i);
1986
+ const status = this.getNodeParameter('inboxThreadStatus', i);
1987
+ response = await requestV1(this, {
1988
+ method: 'POST',
1989
+ url: `/inbox/${threadId}/status`,
1990
+ body: { status },
1991
+ json: true,
1992
+ }, optionalHeaders);
1993
+ }
1994
+ }
1995
+ else if (resource === 'listening') {
1996
+ if (operation === 'refresh') {
1997
+ const platforms = this.getNodeParameter('listeningPlatforms', i);
1998
+ const keywordIdsRaw = this.getNodeParameter('listeningKeywordIds', i);
1999
+ response = await requestV1(this, {
2000
+ method: 'POST',
2001
+ url: '/listening/refresh',
2002
+ body: {
2003
+ platforms,
2004
+ keywordIds: maybeArray(keywordIdsRaw),
2005
+ },
2006
+ json: true,
2007
+ }, optionalHeaders);
2008
+ }
2009
+ else if (operation === 'listKeywords') {
2010
+ const activeOnly = this.getNodeParameter('listeningActiveOnly', i);
2011
+ const keywordType = this.getNodeParameter('listeningKeywordType', i);
2012
+ const qs = {
2013
+ active: activeOnly ? 'true' : 'false',
2014
+ };
2015
+ if (keywordType) {
2016
+ qs.type = keywordType;
2017
+ }
2018
+ response = await requestV1(this, {
2019
+ method: 'GET',
2020
+ url: '/listening/keywords',
2021
+ qs,
2022
+ }, optionalHeaders);
2023
+ }
2024
+ else if (operation === 'createKeyword') {
2025
+ const keyword = this.getNodeParameter('listeningKeyword', i);
2026
+ const type = this.getNodeParameter('listeningKeywordType', i);
2027
+ const platforms = this.getNodeParameter('listeningPlatforms', i);
2028
+ const notifyEmail = this.getNodeParameter('listeningNotifyEmail', i);
2029
+ const notifyWebhook = this.getNodeParameter('listeningNotifyWebhook', i);
2030
+ const webhookUrl = this.getNodeParameter('listeningWebhookUrl', i);
2031
+ const sentimentFilter = this.getNodeParameter('listeningSentimentFilter', i);
2032
+ response = await requestV1(this, {
2033
+ method: 'POST',
2034
+ url: '/listening/keywords',
2035
+ body: {
2036
+ keyword,
2037
+ type,
2038
+ platforms: platforms.length > 0 ? platforms : undefined,
2039
+ notifyEmail,
2040
+ notifyWebhook,
2041
+ webhookUrl: webhookUrl || undefined,
2042
+ sentimentFilter: sentimentFilter || undefined,
2043
+ },
2044
+ json: true,
2045
+ }, optionalHeaders);
2046
+ }
2047
+ else if (operation === 'getKeyword') {
2048
+ const keywordId = this.getNodeParameter('listeningKeywordId', i);
2049
+ response = await requestV1(this, {
2050
+ method: 'GET',
2051
+ url: `/listening/keywords/${keywordId}`,
2052
+ }, optionalHeaders);
2053
+ }
2054
+ else if (operation === 'updateKeyword') {
2055
+ const keywordId = this.getNodeParameter('listeningKeywordId', i);
2056
+ const type = this.getNodeParameter('listeningKeywordType', i);
2057
+ const platforms = this.getNodeParameter('listeningPlatforms', i);
2058
+ const notifyEmail = this.getNodeParameter('listeningNotifyEmail', i);
2059
+ const notifyWebhook = this.getNodeParameter('listeningNotifyWebhook', i);
2060
+ const webhookUrl = this.getNodeParameter('listeningWebhookUrl', i);
2061
+ const sentimentFilter = this.getNodeParameter('listeningSentimentFilter', i);
2062
+ response = await requestV1(this, {
2063
+ method: 'PATCH',
2064
+ url: `/listening/keywords/${keywordId}`,
2065
+ body: {
2066
+ type,
2067
+ platforms: platforms.length > 0 ? platforms : undefined,
2068
+ notifyEmail,
2069
+ notifyWebhook,
2070
+ webhookUrl: webhookUrl || undefined,
2071
+ sentimentFilter: sentimentFilter || undefined,
2072
+ },
2073
+ json: true,
2074
+ }, optionalHeaders);
2075
+ }
2076
+ else if (operation === 'deleteKeyword') {
2077
+ const keywordId = this.getNodeParameter('listeningKeywordId', i);
2078
+ response = await requestV1(this, {
2079
+ method: 'DELETE',
2080
+ url: `/listening/keywords/${keywordId}`,
2081
+ }, optionalHeaders);
2082
+ }
2083
+ else if (operation === 'listMentions') {
2084
+ const keywordId = this.getNodeParameter('listeningMentionKeywordId', i);
2085
+ const platform = this.getNodeParameter('listeningMentionPlatform', i);
2086
+ const sentiment = this.getNodeParameter('listeningSentimentFilter', i);
2087
+ const isRead = this.getNodeParameter('listeningIsRead', i);
2088
+ const isArchived = this.getNodeParameter('listeningIsArchived', i);
2089
+ const since = this.getNodeParameter('listeningSince', i);
2090
+ const limit = this.getNodeParameter('listeningLimit', i);
2091
+ const offset = this.getNodeParameter('listeningOffset', i);
2092
+ const qs = {
2093
+ limit,
2094
+ offset,
2095
+ };
2096
+ if (keywordId)
2097
+ qs.keyword_id = keywordId;
2098
+ if (platform)
2099
+ qs.platform = platform;
2100
+ if (sentiment)
2101
+ qs.sentiment = sentiment;
2102
+ if (isRead)
2103
+ qs.is_read = isRead;
2104
+ if (isArchived)
2105
+ qs.is_archived = isArchived;
2106
+ if (since)
2107
+ qs.since = since;
2108
+ response = await requestV1(this, {
2109
+ method: 'GET',
2110
+ url: '/listening/mentions',
2111
+ qs,
2112
+ }, optionalHeaders);
2113
+ }
2114
+ else if (operation === 'getMention') {
2115
+ const mentionId = this.getNodeParameter('listeningMentionId', i);
2116
+ response = await requestV1(this, {
2117
+ method: 'GET',
2118
+ url: `/listening/mentions/${mentionId}`,
2119
+ }, optionalHeaders);
2120
+ }
2121
+ else if (operation === 'markMentionsRead') {
2122
+ const mentionIds = this.getNodeParameter('listeningMentionIds', i);
2123
+ response = await requestV1(this, {
2124
+ method: 'POST',
2125
+ url: '/listening/mentions/mark-read',
2126
+ body: {
2127
+ ids: (_a = maybeArray(mentionIds)) !== null && _a !== void 0 ? _a : [],
2128
+ },
2129
+ json: true,
2130
+ }, optionalHeaders);
2131
+ }
2132
+ else if (operation === 'archiveMentions') {
2133
+ const mentionIds = this.getNodeParameter('listeningMentionIds', i);
2134
+ response = await requestV1(this, {
2135
+ method: 'POST',
2136
+ url: '/listening/mentions/archive',
2137
+ body: {
2138
+ ids: (_b = maybeArray(mentionIds)) !== null && _b !== void 0 ? _b : [],
2139
+ },
2140
+ json: true,
2141
+ }, optionalHeaders);
2142
+ }
2143
+ else if (operation === 'listAlerts') {
2144
+ const unreadOnly = this.getNodeParameter('listeningAlertsUnreadOnly', i);
2145
+ const priority = this.getNodeParameter('listeningAlertPriority', i);
2146
+ const limit = this.getNodeParameter('listeningLimit', i);
2147
+ const qs = {
2148
+ unread: unreadOnly ? 'true' : 'false',
2149
+ limit,
2150
+ };
2151
+ if (priority) {
2152
+ qs.priority = priority;
2153
+ }
2154
+ response = await requestV1(this, {
2155
+ method: 'GET',
2156
+ url: '/listening/alerts',
2157
+ qs,
2158
+ }, optionalHeaders);
2159
+ }
2160
+ else if (operation === 'markAlertsRead') {
2161
+ const alertIds = this.getNodeParameter('listeningAlertIds', i);
2162
+ response = await requestV1(this, {
2163
+ method: 'POST',
2164
+ url: '/listening/alerts/mark-read',
2165
+ body: {
2166
+ ids: (_c = maybeArray(alertIds)) !== null && _c !== void 0 ? _c : [],
2167
+ },
2168
+ json: true,
2169
+ }, optionalHeaders);
2170
+ }
2171
+ else if (operation === 'dismissAlerts') {
2172
+ const alertIds = this.getNodeParameter('listeningAlertIds', i);
2173
+ response = await requestV1(this, {
2174
+ method: 'POST',
2175
+ url: '/listening/alerts/dismiss',
2176
+ body: {
2177
+ ids: (_d = maybeArray(alertIds)) !== null && _d !== void 0 ? _d : [],
2178
+ },
2179
+ json: true,
2180
+ }, optionalHeaders);
2181
+ }
2182
+ else if (operation === 'getSummary') {
2183
+ response = await requestV1(this, {
2184
+ method: 'GET',
2185
+ url: '/listening/summary',
2186
+ }, optionalHeaders);
2187
+ }
2188
+ }
2189
+ else if (resource === 'aiMedia') {
2190
+ if (operation === 'create') {
2191
+ const provider = this.getNodeParameter('aiMediaProvider', i);
2192
+ const prompt = this.getNodeParameter('aiMediaPrompt', i);
2193
+ const mediaType = this.getNodeParameter('aiMediaType', i);
2194
+ const stylePreset = this.getNodeParameter('aiMediaStylePreset', i);
2195
+ response = await requestV1(this, {
2196
+ method: 'POST',
2197
+ url: '/ai-media',
2198
+ body: {
2199
+ provider,
2200
+ prompt,
2201
+ media_type: mediaType,
2202
+ parameters: stylePreset ? { stylePreset } : {},
2203
+ },
2204
+ json: true,
2205
+ }, optionalHeaders);
2206
+ }
2207
+ else if (operation === 'getStatus') {
2208
+ const jobId = this.getNodeParameter('aiMediaJobId', i);
2209
+ response = await requestV1(this, {
2210
+ method: 'GET',
2211
+ url: `/ai-media/${jobId}`,
2212
+ }, optionalHeaders);
2213
+ }
2214
+ }
2215
+ else if (resource === 'meta') {
2216
+ if (operation === 'getCapabilities') {
2217
+ response = await requestV1(this, { method: 'GET', url: '/capabilities' }, optionalHeaders);
2218
+ }
2219
+ else if (operation === 'getRequirements') {
2220
+ const platform = this.getNodeParameter('metaPlatform', i);
2221
+ response = await requestV1(this, {
2222
+ method: 'GET',
2223
+ url: '/requirements',
2224
+ qs: { platform },
2225
+ }, optionalHeaders);
2226
+ }
2227
+ else if (operation === 'getPlatformSettingsSchema') {
2228
+ const platform = this.getNodeParameter('metaPlatform', i);
2229
+ response = await requestV1(this, {
2230
+ method: 'GET',
2231
+ url: '/platforms/schema',
2232
+ qs: { platform },
2233
+ }, optionalHeaders);
2234
+ }
2235
+ else if (operation === 'getBestTimes') {
2236
+ const platform = this.getNodeParameter('metaPlatform', i);
2237
+ const limit = this.getNodeParameter('metaBestTimesLimit', i);
2238
+ response = await requestV1(this, {
2239
+ method: 'GET',
2240
+ url: '/best-times',
2241
+ qs: { platform, limit },
2242
+ }, optionalHeaders);
2243
+ }
2244
+ else if (operation === 'getWebhookEventsCatalog') {
2245
+ response = await requestV1(this, {
2246
+ method: 'GET',
2247
+ url: '/webhooks/events-catalog',
2248
+ }, optionalHeaders);
2249
+ }
2250
+ else if (operation === 'getWebhookTriggers') {
2251
+ response = await requestV1(this, {
2252
+ method: 'GET',
2253
+ url: '/webhooks/triggers',
2254
+ }, optionalHeaders);
2255
+ }
2256
+ }
2257
+ else if (resource === 'contentScore') {
2258
+ if (operation === 'score') {
2259
+ const platforms = this.getNodeParameter('platforms', i);
2260
+ const text = this.getNodeParameter('text', i);
2261
+ const mediaUrl = this.getNodeParameter('mediaUrl', i);
2262
+ const scoreMediaUrls = this.getNodeParameter('scoreMediaUrls', i);
2263
+ const scoreScheduledTime = this.getNodeParameter('scoreScheduledTime', i);
2264
+ response = await requestV1(this, {
2265
+ method: 'POST',
2266
+ url: '/content-score',
2267
+ body: {
2268
+ platforms,
2269
+ text,
2270
+ mediaUrl: mediaUrl || undefined,
2271
+ mediaUrls: maybeArray(scoreMediaUrls),
2272
+ scheduledTime: scoreScheduledTime || undefined,
2273
+ },
2274
+ json: true,
2275
+ }, optionalHeaders);
2276
+ }
2277
+ }
2278
+ else if (resource === 'library') {
2279
+ if (operation === 'list') {
2280
+ const libraryType = this.getNodeParameter('libraryType', i);
2281
+ const category = this.getNodeParameter('libraryCategory', i);
2282
+ const tags = this.getNodeParameter('libraryTags', i);
2283
+ const targetPlatforms = this.getNodeParameter('libraryTargetPlatforms', i);
2284
+ const search = this.getNodeParameter('librarySearch', i);
2285
+ const limit = this.getNodeParameter('libraryLimit', i);
2286
+ const offset = this.getNodeParameter('libraryOffset', i);
2287
+ const qs = { limit, offset };
2288
+ if (libraryType)
2289
+ qs.type = libraryType;
2290
+ if (category)
2291
+ qs.category = category;
2292
+ if (tags)
2293
+ qs.tags = tags;
2294
+ if (targetPlatforms.length > 0)
2295
+ qs.platform = targetPlatforms[0];
2296
+ if (search)
2297
+ qs.search = search;
2298
+ response = await requestV1(this, {
2299
+ method: 'GET',
2300
+ url: '/library',
2301
+ qs,
2302
+ }, optionalHeaders);
2303
+ }
2304
+ else if (operation === 'create') {
2305
+ const title = this.getNodeParameter('libraryTitle', i);
2306
+ const text = this.getNodeParameter('libraryText', i);
2307
+ const libraryType = this.getNodeParameter('libraryType', i);
2308
+ const category = this.getNodeParameter('libraryCategory', i);
2309
+ const tags = this.getNodeParameter('libraryTags', i);
2310
+ const targetPlatforms = this.getNodeParameter('libraryTargetPlatforms', i);
2311
+ const evergreenEnabled = this.getNodeParameter('libraryEvergreenEnabled', i);
2312
+ const evergreenIntervalDays = this.getNodeParameter('libraryEvergreenIntervalDays', i);
2313
+ const evergreenMaxPublishes = this.getNodeParameter('libraryEvergreenMaxPublishes', i);
2314
+ response = await requestV1(this, {
2315
+ method: 'POST',
2316
+ url: '/library',
2317
+ body: {
2318
+ title,
2319
+ text,
2320
+ type: libraryType,
2321
+ category: category || undefined,
2322
+ tags: maybeArray(tags),
2323
+ targetPlatforms: targetPlatforms.length > 0 ? targetPlatforms : undefined,
2324
+ evergreenEnabled,
2325
+ evergreenIntervalDays: evergreenIntervalDays > 0 ? evergreenIntervalDays : undefined,
2326
+ evergreenMaxPublishes: evergreenMaxPublishes > 0 ? evergreenMaxPublishes : undefined,
2327
+ },
2328
+ json: true,
2329
+ }, optionalHeaders);
2330
+ }
2331
+ else if (operation === 'get') {
2332
+ const itemId = this.getNodeParameter('libraryItemId', i);
2333
+ response = await requestV1(this, {
2334
+ method: 'GET',
2335
+ url: `/library/${itemId}`,
2336
+ }, optionalHeaders);
2337
+ }
2338
+ else if (operation === 'update') {
2339
+ const itemId = this.getNodeParameter('libraryItemId', i);
2340
+ const title = this.getNodeParameter('libraryTitle', i);
2341
+ const text = this.getNodeParameter('libraryText', i);
2342
+ const libraryType = this.getNodeParameter('libraryType', i);
2343
+ const category = this.getNodeParameter('libraryCategory', i);
2344
+ const tags = this.getNodeParameter('libraryTags', i);
2345
+ const targetPlatforms = this.getNodeParameter('libraryTargetPlatforms', i);
2346
+ const evergreenEnabled = this.getNodeParameter('libraryEvergreenEnabled', i);
2347
+ const evergreenIntervalDays = this.getNodeParameter('libraryEvergreenIntervalDays', i);
2348
+ const evergreenMaxPublishes = this.getNodeParameter('libraryEvergreenMaxPublishes', i);
2349
+ response = await requestV1(this, {
2350
+ method: 'PATCH',
2351
+ url: `/library/${itemId}`,
2352
+ body: {
2353
+ title,
2354
+ text,
2355
+ type: libraryType,
2356
+ category: category || undefined,
2357
+ tags: maybeArray(tags),
2358
+ targetPlatforms: targetPlatforms.length > 0 ? targetPlatforms : undefined,
2359
+ evergreenEnabled,
2360
+ evergreenIntervalDays: evergreenIntervalDays > 0 ? evergreenIntervalDays : undefined,
2361
+ evergreenMaxPublishes: evergreenMaxPublishes > 0 ? evergreenMaxPublishes : undefined,
2362
+ },
2363
+ json: true,
2364
+ }, optionalHeaders);
2365
+ }
2366
+ else if (operation === 'delete') {
2367
+ const itemId = this.getNodeParameter('libraryItemId', i);
2368
+ response = await requestV1(this, {
2369
+ method: 'DELETE',
2370
+ url: `/library/${itemId}`,
2371
+ }, optionalHeaders);
2372
+ }
2373
+ else if (operation === 'listCategories') {
2374
+ response = await requestV1(this, {
2375
+ method: 'GET',
2376
+ url: '/library/categories',
2377
+ }, optionalHeaders);
2378
+ }
2379
+ else if (operation === 'listTags') {
2380
+ response = await requestV1(this, {
2381
+ method: 'GET',
2382
+ url: '/library/tags',
2383
+ }, optionalHeaders);
2384
+ }
2385
+ }
2386
+ else if (resource === 'approvals') {
2387
+ if (operation === 'list') {
2388
+ response = await requestV1(this, {
2389
+ method: 'GET',
2390
+ url: '/approvals',
2391
+ }, optionalHeaders);
2392
+ }
2393
+ else if (operation === 'approve') {
2394
+ const postId = this.getNodeParameter('approvalPostId', i);
2395
+ const comment = this.getNodeParameter('approvalComment', i);
2396
+ response = await requestV1(this, {
2397
+ method: 'POST',
2398
+ url: `/approvals/${postId}/approve`,
2399
+ body: {
2400
+ comment: comment || undefined,
2401
+ },
2402
+ json: true,
2403
+ }, optionalHeaders);
2404
+ }
2405
+ else if (operation === 'reject') {
2406
+ const postId = this.getNodeParameter('approvalPostId', i);
2407
+ const reason = this.getNodeParameter('approvalReason', i);
2408
+ response = await requestV1(this, {
2409
+ method: 'POST',
2410
+ url: `/approvals/${postId}/reject`,
2411
+ body: { reason },
2412
+ json: true,
2413
+ }, optionalHeaders);
2414
+ }
2415
+ }
2416
+ else if (resource === 'bulkSchedule') {
2417
+ if (operation === 'listImports') {
2418
+ response = await requestV1(this, {
2419
+ method: 'GET',
2420
+ url: '/bulk-schedule',
2421
+ }, optionalHeaders);
2422
+ }
2423
+ else if (operation === 'getImport') {
2424
+ const importId = this.getNodeParameter('bulkImportId', i);
2425
+ response = await requestV1(this, {
2426
+ method: 'GET',
2427
+ url: `/bulk-schedule/${importId}`,
2428
+ }, optionalHeaders);
2429
+ }
2430
+ else if (operation === 'validateCsv') {
2431
+ const csvContent = this.getNodeParameter('bulkCsvContent', i);
2432
+ const filename = this.getNodeParameter('bulkFilename', i);
2433
+ response = await requestV1(this, {
2434
+ method: 'POST',
2435
+ url: '/bulk-schedule/validate',
2436
+ body: {
2437
+ csvContent,
2438
+ filename,
2439
+ },
2440
+ json: true,
2441
+ }, optionalHeaders);
2442
+ }
2443
+ else if (operation === 'importCsv') {
2444
+ const csvContent = this.getNodeParameter('bulkCsvContent', i);
2445
+ const filename = this.getNodeParameter('bulkFilename', i);
2446
+ const skipErrors = this.getNodeParameter('bulkSkipErrors', i);
2447
+ response = await requestV1(this, {
2448
+ method: 'POST',
2449
+ url: '/bulk-schedule/import',
2450
+ body: {
2451
+ csvContent,
2452
+ filename,
2453
+ skipErrors,
2454
+ },
2455
+ json: true,
2456
+ }, optionalHeaders);
2457
+ }
2458
+ else if (operation === 'downloadTemplate') {
2459
+ response = await requestV1(this, {
2460
+ method: 'GET',
2461
+ url: '/bulk-schedule/template',
2462
+ json: false,
2463
+ }, optionalHeaders);
2464
+ }
2465
+ }
2466
+ else if (resource === 'connect') {
2467
+ if (operation === 'getConnectAction') {
2468
+ const platform = this.getNodeParameter('connectPlatform', i);
2469
+ response = await requestV1(this, {
2470
+ method: 'GET',
2471
+ url: `/connect/${platform}`,
2472
+ }, optionalHeaders);
2473
+ }
2474
+ else if (operation === 'connectToken') {
2475
+ const platform = this.getNodeParameter('connectPlatform', i);
2476
+ const credentialsJson = this.getNodeParameter('connectCredentialsJson', i);
2477
+ const parsed = parseJsonInput(credentialsJson, 'Credentials JSON');
2478
+ const credentials = assertObject(parsed, 'Credentials JSON must parse to an object');
2479
+ response = await requestV1(this, {
2480
+ method: 'POST',
2481
+ url: '/connect/token',
2482
+ body: {
2483
+ platform,
2484
+ credentials,
2485
+ },
2486
+ json: true,
2487
+ }, optionalHeaders);
2488
+ }
2489
+ else if (operation === 'connectWebhook') {
2490
+ const platform = this.getNodeParameter('connectPlatform', i);
2491
+ const webhookUrl = this.getNodeParameter('connectWebhookUrl', i);
2492
+ const metadataJson = this.getNodeParameter('connectMetadataJson', i);
2493
+ const parsedMetadata = parseJsonInput(metadataJson, 'Metadata JSON');
2494
+ const metadata = parsedMetadata ? assertObject(parsedMetadata, 'Metadata JSON must parse to an object') : undefined;
2495
+ response = await requestV1(this, {
2496
+ method: 'POST',
2497
+ url: '/connect/webhook',
2498
+ body: {
480
2499
  platform,
2500
+ webhookUrl,
2501
+ metadata,
481
2502
  },
482
- });
2503
+ json: true,
2504
+ }, optionalHeaders);
2505
+ }
2506
+ }
2507
+ else if (resource === 'webhooks') {
2508
+ if (operation === 'testWebhook') {
2509
+ const webhookId = this.getNodeParameter('webhookId', i);
2510
+ response = await requestV1(this, {
2511
+ method: 'POST',
2512
+ url: `/webhooks/${webhookId}/test`,
2513
+ json: true,
2514
+ }, optionalHeaders);
2515
+ }
2516
+ }
2517
+ else if (resource === 'advanced') {
2518
+ if (operation === 'apiRequest') {
2519
+ const method = this.getNodeParameter('advancedMethod', i);
2520
+ const path = this.getNodeParameter('advancedPath', i);
2521
+ const queryJson = this.getNodeParameter('advancedQueryJson', i);
2522
+ const bodyJson = this.getNodeParameter('advancedBodyJson', i);
2523
+ const responseMode = this.getNodeParameter('advancedResponseMode', i);
2524
+ const requestTimeoutMs = this.getNodeParameter('requestTimeoutMs', i);
2525
+ const normalizedPath = getOptionalString(path);
2526
+ if (!normalizedPath) {
2527
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Path is required for advanced API request');
2528
+ }
2529
+ if (!/^\/api\/v[12]\//.test(normalizedPath)) {
2530
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Advanced path must start with /api/v1/ or /api/v2/');
2531
+ }
2532
+ const parsedQuery = parseJsonInput(queryJson, 'Query JSON');
2533
+ const parsedBody = parseJsonInput(bodyJson, 'Body JSON');
2534
+ const qs = parsedQuery ? assertObject(parsedQuery, 'Query JSON must parse to an object') : undefined;
2535
+ const body = parsedBody === undefined ? undefined : parsedBody;
2536
+ response = await requestAbsolute(this, {
2537
+ method,
2538
+ url: normalizedPath,
2539
+ qs,
2540
+ body,
2541
+ json: responseMode === 'json',
2542
+ encoding: responseMode === 'binary' ? null : undefined,
2543
+ timeout: requestTimeoutMs > 0 ? requestTimeoutMs : undefined,
2544
+ }, optionalHeaders);
483
2545
  }
484
2546
  }
485
- returnData.push({
486
- json: response,
487
- });
2547
+ returnData.push({ json: normalizeResponse(response) });
488
2548
  }
489
2549
  catch (error) {
490
2550
  if (this.continueOnFail()) {