n8n-nodes-eranol 0.2.4 → 0.2.6

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,4 +1,5 @@
1
- import { type INodeType, type INodeTypeDescription } from 'n8n-workflow';
1
+ import { type IExecuteFunctions, type INodeExecutionData, type INodeType, type INodeTypeDescription } from 'n8n-workflow';
2
2
  export declare class Eranol implements INodeType {
3
3
  description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
4
5
  }
@@ -9,6 +9,233 @@ const compose_1 = require("./resources/compose");
9
9
  const job_1 = require("./resources/job");
10
10
  const image_1 = require("./resources/image");
11
11
  const notify_1 = require("./resources/notify");
12
+ const BASE_URL = 'https://eranol.com/api/v1';
13
+ const OPERATION_MAP = {
14
+ // video
15
+ addIntro: { method: 'POST', url: '/ffmpeg/video/add-intro' },
16
+ addOutro: { method: 'POST', url: '/ffmpeg/video/add-outro' },
17
+ caption: { method: 'POST', url: '/ffmpeg/video/caption' },
18
+ extractAudio: { method: 'POST', url: '/ffmpeg/video/extract/audio' },
19
+ extractImages: { method: 'POST', url: '/ffmpeg/video/extract/images' },
20
+ generateGif: { method: 'POST', url: '/ffmpeg/video/extract/gif' },
21
+ overlay: { method: 'POST', url: '/ffmpeg/video/overlay' },
22
+ progressBar: { method: 'POST', url: '/ffmpeg/video/progress-bar' },
23
+ reframe: { method: 'POST', url: '/ffmpeg/video/reframe' },
24
+ thumbnail: { method: 'POST', url: '/ffmpeg/video/thumbnail' },
25
+ trim: { method: 'POST', url: '/ffmpeg/video/trim' },
26
+ watermark: { method: 'POST', url: '/ffmpeg/video/watermark' },
27
+ // audio
28
+ denoise: { method: 'POST', url: '/ffmpeg/audio/denoise' },
29
+ highlights: { method: 'POST', url: '/ffmpeg/audio/highlights' },
30
+ removeSilence: { method: 'POST', url: '/ffmpeg/audio/remove-silence' },
31
+ // convert
32
+ audioToMp3: { method: 'POST', url: '/ffmpeg/convert/audio/to/mp3' },
33
+ audioToWav: { method: 'POST', url: '/ffmpeg/convert/audio/to/wav' },
34
+ imageToJpg: { method: 'POST', url: '/ffmpeg/convert/image/to/jpg' },
35
+ imageToWebp: { method: 'POST', url: '/ffmpeg/convert/image/to/webp' },
36
+ videoToMp4: { method: 'POST', url: '/ffmpeg/convert/video/to/mp4' },
37
+ videoToWebm: { method: 'POST', url: '/ffmpeg/convert/video/to/webm' },
38
+ // compose
39
+ concat: { method: 'POST', url: '/ffmpeg/video/concat' },
40
+ composeVideo: { method: 'POST', url: '/ffmpeg/video/compose' },
41
+ merge: { method: 'POST', url: '/ffmpeg/merge' },
42
+ // image
43
+ generateImage: { method: 'POST', url: '/image' },
44
+ // notify
45
+ sendEmail: { method: 'POST', url: '/notifications/email' },
46
+ };
47
+ function buildBody(operation, p) {
48
+ var _a, _b, _c, _d;
49
+ const additional = p('additionalFields', {});
50
+ switch (operation) {
51
+ // ── video ──────────────────────────────────────────────────────────
52
+ case 'trim':
53
+ return { url: p('url'), start_sec: p('startSec'), end_sec: p('endSec') };
54
+ case 'addIntro':
55
+ return { url: p('url'), intro_url: p('introUrl') };
56
+ case 'addOutro':
57
+ return { url: p('url'), outro_url: p('outroUrl') };
58
+ case 'caption': {
59
+ const body = { url: p('url') };
60
+ if (additional.fontColor !== undefined)
61
+ body.font_color = additional.fontColor;
62
+ if (additional.fontSize !== undefined)
63
+ body.font_size = additional.fontSize;
64
+ if (additional.maxSegmentDuration !== undefined)
65
+ body.max_segment_duration = additional.maxSegmentDuration;
66
+ if (additional.maxWordsPerLine !== undefined)
67
+ body.max_words_per_line = additional.maxWordsPerLine;
68
+ if (additional.outlineColor !== undefined)
69
+ body.outline_color = additional.outlineColor;
70
+ if (additional.outlineWidth !== undefined)
71
+ body.outline_width = additional.outlineWidth;
72
+ if (additional.position !== undefined)
73
+ body.position = additional.position;
74
+ return body;
75
+ }
76
+ case 'extractAudio': {
77
+ const body = { url: p('url') };
78
+ if (additional.mono !== undefined)
79
+ body.mono = additional.mono;
80
+ return body;
81
+ }
82
+ case 'extractImages': {
83
+ const body = { url: p('url'), start_sec: p('startSec'), end_sec: p('endSec') };
84
+ if (additional.fps !== undefined)
85
+ body.fps = additional.fps;
86
+ return body;
87
+ }
88
+ case 'generateGif': {
89
+ const body = { url: p('url'), start_sec: p('startSec'), end_sec: p('endSec') };
90
+ if (additional.fps !== undefined)
91
+ body.fps = additional.fps;
92
+ if (additional.width !== undefined)
93
+ body.width = additional.width;
94
+ return body;
95
+ }
96
+ case 'overlay': {
97
+ const raw = p('overlays', { overlayValues: [] });
98
+ return { url: p('url'), overlays: (_a = raw.overlayValues) !== null && _a !== void 0 ? _a : [] };
99
+ }
100
+ case 'progressBar': {
101
+ const body = { url: p('url') };
102
+ if (additional.color !== undefined)
103
+ body.color = additional.color;
104
+ if (additional.height !== undefined)
105
+ body.height = additional.height;
106
+ if (additional.opacity !== undefined)
107
+ body.opacity = additional.opacity;
108
+ if (additional.position !== undefined)
109
+ body.position = additional.position;
110
+ if (additional.style !== undefined)
111
+ body.style = additional.style;
112
+ return body;
113
+ }
114
+ case 'reframe': {
115
+ const body = { url: p('url'), width: p('width'), height: p('height') };
116
+ if (additional.bgColor !== undefined)
117
+ body.bg_color = additional.bgColor;
118
+ return body;
119
+ }
120
+ case 'thumbnail': {
121
+ const body = { url: p('url') };
122
+ if (additional.bgColor !== undefined)
123
+ body.bg_color = additional.bgColor;
124
+ if (additional.fontColor !== undefined)
125
+ body.font_color = additional.fontColor;
126
+ if (additional.fontSize !== undefined)
127
+ body.font_size = additional.fontSize;
128
+ if (additional.height !== undefined)
129
+ body.height = additional.height;
130
+ if (additional.position !== undefined)
131
+ body.position = additional.position;
132
+ if (additional.text !== undefined)
133
+ body.text = additional.text;
134
+ if (additional.timeSec !== undefined)
135
+ body.time_sec = additional.timeSec;
136
+ if (additional.width !== undefined)
137
+ body.width = additional.width;
138
+ return body;
139
+ }
140
+ case 'watermark': {
141
+ const body = { url: p('url'), watermark_url: p('watermarkUrl') };
142
+ if (additional.position !== undefined)
143
+ body.position = additional.position;
144
+ if (additional.scale !== undefined)
145
+ body.scale = additional.scale;
146
+ if (additional.opacity !== undefined)
147
+ body.opacity = additional.opacity;
148
+ if (additional.margin !== undefined)
149
+ body.margin = additional.margin;
150
+ return body;
151
+ }
152
+ // ── audio ──────────────────────────────────────────────────────────
153
+ case 'denoise': {
154
+ const body = { url: p('url') };
155
+ if (additional.method !== undefined)
156
+ body.method = additional.method;
157
+ if (additional.noiseReduction !== undefined)
158
+ body.noise_reduction = additional.noiseReduction;
159
+ return body;
160
+ }
161
+ case 'highlights': {
162
+ const body = { url: p('url') };
163
+ if (additional.topN !== undefined)
164
+ body.top_n = additional.topN;
165
+ if (additional.clipDuration !== undefined)
166
+ body.clip_duration = additional.clipDuration;
167
+ return body;
168
+ }
169
+ case 'removeSilence': {
170
+ const body = { url: p('url') };
171
+ if (additional.silenceThreshDb !== undefined)
172
+ body.silence_thresh_db = additional.silenceThreshDb;
173
+ if (additional.minSilenceDuration !== undefined)
174
+ body.min_silence_duration = additional.minSilenceDuration;
175
+ if (additional.padding !== undefined)
176
+ body.padding = additional.padding;
177
+ return body;
178
+ }
179
+ // ── convert ────────────────────────────────────────────────────────
180
+ case 'audioToMp3':
181
+ case 'audioToWav':
182
+ case 'imageToJpg':
183
+ case 'imageToWebp':
184
+ case 'videoToMp4':
185
+ case 'videoToWebm':
186
+ return { url: p('url') };
187
+ // ── compose ────────────────────────────────────────────────────────
188
+ case 'concat': {
189
+ const raw = p('clips', { clipValues: [] });
190
+ return { clips: (_b = raw.clipValues) !== null && _b !== void 0 ? _b : [] };
191
+ }
192
+ case 'composeVideo': {
193
+ const raw = p('overlays', { overlayValues: [] });
194
+ return { main_video_url: p('mainVideoUrl'), overlays: (_c = raw.overlayValues) !== null && _c !== void 0 ? _c : [] };
195
+ }
196
+ case 'merge': {
197
+ const raw = p('images', { imageValues: [] });
198
+ const body = { images: (_d = raw.imageValues) !== null && _d !== void 0 ? _d : [], audio_url: p('audioUrl') };
199
+ if (additional.audioMode !== undefined)
200
+ body.audio_mode = additional.audioMode;
201
+ if (additional.bgAudioUrl !== undefined)
202
+ body.bg_audio_url = additional.bgAudioUrl;
203
+ if (additional.bgAudioVolume !== undefined)
204
+ body.bg_audio_volume = additional.bgAudioVolume;
205
+ if (additional.fadeSecs !== undefined)
206
+ body.fade_secs = additional.fadeSecs;
207
+ if (additional.fit !== undefined)
208
+ body.fit = additional.fit;
209
+ if (additional.fps !== undefined)
210
+ body.fps = additional.fps;
211
+ if (additional.height !== undefined)
212
+ body.height = additional.height;
213
+ if (additional.transition !== undefined)
214
+ body.transition = additional.transition;
215
+ if (additional.width !== undefined)
216
+ body.width = additional.width;
217
+ return body;
218
+ }
219
+ // ── image ──────────────────────────────────────────────────────────
220
+ case 'generateImage': {
221
+ const body = { prompt: p('prompt') };
222
+ if (additional.height !== undefined)
223
+ body.height = additional.height;
224
+ if (additional.negativePrompt !== undefined)
225
+ body.negative_prompt = additional.negativePrompt;
226
+ if (additional.seed !== undefined)
227
+ body.seed = additional.seed;
228
+ if (additional.width !== undefined)
229
+ body.width = additional.width;
230
+ return body;
231
+ }
232
+ // ── notify ─────────────────────────────────────────────────────────
233
+ case 'sendEmail':
234
+ return { to: p('to'), subject: p('subject'), message: p('message') };
235
+ default:
236
+ return {};
237
+ }
238
+ }
12
239
  class Eranol {
13
240
  constructor() {
14
241
  this.description = {
@@ -30,13 +257,6 @@ class Eranol {
30
257
  required: true,
31
258
  },
32
259
  ],
33
- requestDefaults: {
34
- baseURL: 'https://eranol.com/api/v1',
35
- headers: {
36
- Accept: 'application/json',
37
- 'Content-Type': 'application/json',
38
- },
39
- },
40
260
  properties: [
41
261
  {
42
262
  displayName: 'Resource',
@@ -86,5 +306,87 @@ class Eranol {
86
306
  usableAsTool: true,
87
307
  };
88
308
  }
309
+ async execute() {
310
+ const request = this.helpers.httpRequestWithAuthentication.bind(this);
311
+ const items = this.getInputData();
312
+ const returnData = [];
313
+ for (let i = 0; i < items.length; i++) {
314
+ const resource = this.getNodeParameter('resource', i);
315
+ const operation = this.getNodeParameter('operation', i);
316
+ const useJsonBody = this.getNodeParameter('useJsonBody', i, false);
317
+ const p = (name, fallback) => {
318
+ try {
319
+ return this.getNodeParameter(name, i);
320
+ }
321
+ catch {
322
+ return fallback;
323
+ }
324
+ };
325
+ let responseData;
326
+ // ── GET/DELETE operations (no body) ────────────────────────────
327
+ if (resource === 'job') {
328
+ const jobId = operation !== 'verify' ? p('jobId') : '';
329
+ if (operation === 'getStatus') {
330
+ responseData = await request('eranolApi', {
331
+ method: 'GET',
332
+ url: `${BASE_URL}/ffmpeg/status/${jobId}`,
333
+ headers: { Accept: 'application/json' },
334
+ });
335
+ }
336
+ else if (operation === 'getResult') {
337
+ responseData = await request('eranolApi', {
338
+ method: 'GET',
339
+ url: `${BASE_URL}/ffmpeg/result/${jobId}`,
340
+ headers: { Accept: 'application/json' },
341
+ });
342
+ }
343
+ else if (operation === 'deleteJob') {
344
+ responseData = await request('eranolApi', {
345
+ method: 'DELETE',
346
+ url: `${BASE_URL}/ffmpeg/jobs/${jobId}`,
347
+ headers: { Accept: 'application/json' },
348
+ });
349
+ }
350
+ else if (operation === 'verify') {
351
+ responseData = await request('eranolApi', {
352
+ method: 'GET',
353
+ url: `${BASE_URL}/verify`,
354
+ headers: { Accept: 'application/json' },
355
+ });
356
+ }
357
+ }
358
+ else if (resource === 'image' && operation === 'imageStatus') {
359
+ const jobId = p('jobId');
360
+ responseData = await request('eranolApi', {
361
+ method: 'GET',
362
+ url: `${BASE_URL}/image/status/${jobId}`,
363
+ headers: { Accept: 'application/json' },
364
+ });
365
+ }
366
+ else {
367
+ // ── POST operations ────────────────────────────────────────
368
+ const route = OPERATION_MAP[operation];
369
+ if (!route) {
370
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
371
+ }
372
+ const body = useJsonBody
373
+ ? JSON.parse(p('jsonBody', '{}'))
374
+ : buildBody(operation, p);
375
+ responseData = await request('eranolApi', {
376
+ method: route.method,
377
+ url: `${BASE_URL}${route.url}`,
378
+ headers: {
379
+ Accept: 'application/json',
380
+ 'Content-Type': 'application/json',
381
+ },
382
+ body,
383
+ json: true,
384
+ });
385
+ }
386
+ const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
387
+ returnData.push(...executionData);
388
+ }
389
+ return [returnData];
390
+ }
89
391
  }
90
392
  exports.Eranol = Eranol;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-eranol",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "n8n community node for Eranol FFmpeg media processing API",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/harshalone/n8n-nodes-eranol",