n8n-nodes-tareno 1.1.0 → 1.2.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.
@@ -4,6 +4,7 @@ export declare class Tareno implements INodeType {
4
4
  methods: {
5
5
  loadOptions: {
6
6
  getAccounts(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
+ getPinterestBoards(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
8
  };
8
9
  };
9
10
  execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
@@ -35,6 +35,11 @@ class Tareno {
35
35
  value: 'post',
36
36
  description: 'Create and manage social media posts',
37
37
  },
38
+ {
39
+ name: 'Media Library',
40
+ value: 'media',
41
+ description: 'Send content to Tareno Media Library',
42
+ },
38
43
  {
39
44
  name: 'Account',
40
45
  value: 'account',
@@ -94,6 +99,41 @@ class Tareno {
94
99
  default: '',
95
100
  description: 'Select a connected social media account',
96
101
  },
102
+ // Format Selection for Instagram/Facebook
103
+ {
104
+ displayName: 'Format',
105
+ name: 'format',
106
+ type: 'options',
107
+ displayOptions: {
108
+ show: {
109
+ resource: ['post'],
110
+ },
111
+ },
112
+ options: [
113
+ { name: 'Feed Post', value: 'post' },
114
+ { name: 'Story', value: 'story' },
115
+ { name: 'Reel', value: 'reel' },
116
+ ],
117
+ default: 'post',
118
+ description: 'Content format (applies to Instagram/Facebook)',
119
+ },
120
+ // Pinterest Board Selection
121
+ {
122
+ displayName: 'Pinterest Board',
123
+ name: 'pinterestBoard',
124
+ type: 'options',
125
+ typeOptions: {
126
+ loadOptionsMethod: 'getPinterestBoards',
127
+ loadOptionsDependsOn: ['accountId'],
128
+ },
129
+ displayOptions: {
130
+ show: {
131
+ resource: ['post'],
132
+ },
133
+ },
134
+ default: '',
135
+ description: 'Select a Pinterest board (only for Pinterest accounts)',
136
+ },
97
137
  // Post Text
98
138
  {
99
139
  displayName: 'Text/Caption',
@@ -169,13 +209,6 @@ class Tareno {
169
209
  default: '',
170
210
  description: 'Description for YouTube videos',
171
211
  },
172
- {
173
- displayName: 'Pinterest Board',
174
- name: 'pinterestBoard',
175
- type: 'string',
176
- default: '',
177
- description: 'Pinterest board name or ID',
178
- },
179
212
  {
180
213
  displayName: 'Pinterest Link',
181
214
  name: 'pinterestLink',
@@ -186,6 +219,56 @@ class Tareno {
186
219
  ],
187
220
  },
188
221
  // ========================
222
+ // MEDIA LIBRARY OPERATIONS
223
+ // ========================
224
+ {
225
+ displayName: 'Operation',
226
+ name: 'operation',
227
+ type: 'options',
228
+ noDataExpression: true,
229
+ displayOptions: {
230
+ show: {
231
+ resource: ['media'],
232
+ },
233
+ },
234
+ options: [
235
+ {
236
+ name: 'Upload',
237
+ value: 'upload',
238
+ description: 'Upload media to Tareno library',
239
+ action: 'Upload to media library',
240
+ },
241
+ ],
242
+ default: 'upload',
243
+ },
244
+ // Media URL for library
245
+ {
246
+ displayName: 'Media URL',
247
+ name: 'mediaUrl',
248
+ type: 'string',
249
+ required: true,
250
+ displayOptions: {
251
+ show: {
252
+ resource: ['media'],
253
+ },
254
+ },
255
+ default: '',
256
+ description: 'URL of the media to upload to your library',
257
+ },
258
+ // Media name for library
259
+ {
260
+ displayName: 'File Name',
261
+ name: 'fileName',
262
+ type: 'string',
263
+ displayOptions: {
264
+ show: {
265
+ resource: ['media'],
266
+ },
267
+ },
268
+ default: '',
269
+ description: 'Optional name for the file',
270
+ },
271
+ // ========================
189
272
  // ACCOUNT OPERATIONS
190
273
  // ========================
191
274
  {
@@ -249,11 +332,15 @@ class Tareno {
249
332
  json: true,
250
333
  });
251
334
  if (response.accounts && Array.isArray(response.accounts)) {
252
- return response.accounts.map((account) => ({
253
- name: `${account.platform.charAt(0).toUpperCase() + account.platform.slice(1)} - ${account.username || account.displayName || 'Unknown'}`,
254
- value: account.id,
255
- description: `Platform: ${account.platform}`,
256
- }));
335
+ return response.accounts.map((account) => {
336
+ const platformName = account.platform.charAt(0).toUpperCase() + account.platform.slice(1);
337
+ const displayName = account.username || account.displayName || 'Unknown';
338
+ return {
339
+ name: `${platformName} - ${displayName}`,
340
+ value: account.id,
341
+ description: `Platform: ${account.platform}`,
342
+ };
343
+ });
257
344
  }
258
345
  return [];
259
346
  }
@@ -267,6 +354,35 @@ class Tareno {
267
354
  ];
268
355
  }
269
356
  },
357
+ // Dynamically load Pinterest boards
358
+ async getPinterestBoards() {
359
+ const credentials = await this.getCredentials('tarenoApi');
360
+ const baseUrl = credentials.baseUrl || 'https://tareno.co';
361
+ const accountId = this.getNodeParameter('accountId', '');
362
+ if (!accountId) {
363
+ return [{ name: 'Select an account first', value: '' }];
364
+ }
365
+ try {
366
+ const response = await this.helpers.httpRequest({
367
+ method: 'GET',
368
+ url: `${baseUrl}/api/external/pinterest/boards?accountId=${accountId}`,
369
+ headers: {
370
+ 'X-Tareno-API-Key': credentials.apiKey,
371
+ },
372
+ json: true,
373
+ });
374
+ if (response.boards && Array.isArray(response.boards)) {
375
+ return response.boards.map((board) => ({
376
+ name: board.name,
377
+ value: board.id,
378
+ }));
379
+ }
380
+ return [{ name: 'No boards found (or not a Pinterest account)', value: '' }];
381
+ }
382
+ catch (error) {
383
+ return [{ name: 'Not a Pinterest account', value: '' }];
384
+ }
385
+ },
270
386
  },
271
387
  };
272
388
  }
@@ -285,11 +401,11 @@ class Tareno {
285
401
  // ========================
286
402
  if (resource === 'post') {
287
403
  const accountId = this.getNodeParameter('accountId', i);
404
+ const format = this.getNodeParameter('format', i);
405
+ const pinterestBoard = this.getNodeParameter('pinterestBoard', i);
288
406
  const text = this.getNodeParameter('text', i);
289
407
  const mediaUrlsRaw = this.getNodeParameter('mediaUrls', i);
290
408
  const additionalOptions = this.getNodeParameter('additionalOptions', i);
291
- // We need to get the platform from the account
292
- // For now, we'll include it in the API call and let the backend figure it out
293
409
  const mediaUrls = mediaUrlsRaw
294
410
  ? mediaUrlsRaw.split(',').map(url => url.trim()).filter(Boolean)
295
411
  : [];
@@ -297,16 +413,20 @@ class Tareno {
297
413
  accountId,
298
414
  text,
299
415
  mediaUrls,
416
+ metadata: {
417
+ format,
418
+ ...additionalOptions,
419
+ },
300
420
  };
421
+ // Add Pinterest board if selected
422
+ if (pinterestBoard) {
423
+ body.metadata.pinterestBoard = pinterestBoard;
424
+ }
301
425
  // Add schedule time if scheduling
302
426
  if (operation === 'schedule') {
303
427
  const scheduledAt = this.getNodeParameter('scheduledAt', i);
304
428
  body.scheduledAt = scheduledAt;
305
429
  }
306
- // Add metadata for platform-specific options
307
- if (Object.keys(additionalOptions).length > 0) {
308
- body.metadata = additionalOptions;
309
- }
310
430
  responseData = await this.helpers.httpRequest({
311
431
  method: 'POST',
312
432
  url: `${baseUrl}/api/external/publish`,
@@ -319,6 +439,26 @@ class Tareno {
319
439
  });
320
440
  }
321
441
  // ========================
442
+ // MEDIA LIBRARY RESOURCE
443
+ // ========================
444
+ if (resource === 'media' && operation === 'upload') {
445
+ const mediaUrl = this.getNodeParameter('mediaUrl', i);
446
+ const fileName = this.getNodeParameter('fileName', i);
447
+ responseData = await this.helpers.httpRequest({
448
+ method: 'POST',
449
+ url: `${baseUrl}/api/external/media`,
450
+ headers: {
451
+ 'Content-Type': 'application/json',
452
+ 'X-Tareno-API-Key': credentials.apiKey,
453
+ },
454
+ body: {
455
+ mediaUrl,
456
+ fileName: fileName || undefined,
457
+ },
458
+ json: true,
459
+ });
460
+ }
461
+ // ========================
322
462
  // ACCOUNT RESOURCE
323
463
  // ========================
324
464
  if (resource === 'account' && operation === 'getAll') {
@@ -1,12 +1,15 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="none">
2
2
  <defs>
3
- <linearGradient id="tarenoGrad" x1="0%" y1="0%" x2="100%" y2="100%">
3
+ <linearGradient id="tarenoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
4
  <stop offset="0%" style="stop-color:#10B981"/>
5
- <stop offset="100%" style="stop-color:#059669"/>
5
+ <stop offset="50%" style="stop-color:#059669"/>
6
+ <stop offset="100%" style="stop-color:#047857"/>
6
7
  </linearGradient>
7
8
  </defs>
8
- <rect width="100" height="100" rx="22" fill="url(#tarenoGrad)"/>
9
- <path d="M25 30 L50 20 L75 30 L75 45 L50 55 L25 45 Z" fill="white" opacity="0.9"/>
10
- <path d="M25 50 L50 60 L75 50 L75 65 L50 75 L25 65 Z" fill="white" opacity="0.7"/>
11
- <path d="M50 20 L50 75" stroke="white" stroke-width="3" opacity="0.3"/>
9
+ <!-- Background -->
10
+ <rect width="100" height="100" rx="20" fill="url(#tarenoGradient)"/>
11
+ <!-- T letter stylized -->
12
+ <path d="M25 25 H75 V35 H55 V75 H45 V35 H25 Z" fill="white"/>
13
+ <!-- Decorative check/arrow -->
14
+ <path d="M60 55 L70 65 L85 45" stroke="white" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.9"/>
12
15
  </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tareno",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "N8N community nodes for Tareno - Social Media Management Platform",
5
5
  "license": "MIT",
6
6
  "homepage": "https://tareno.co",