n8n-nodes-eranol 0.2.3 → 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;
@@ -25,6 +25,7 @@ exports.audioDescription = [
25
25
  request: {
26
26
  method: 'POST',
27
27
  url: '/ffmpeg/audio/denoise',
28
+ headers: { 'Content-Type': 'application/json' },
28
29
  },
29
30
  },
30
31
  },
@@ -37,6 +38,7 @@ exports.audioDescription = [
37
38
  request: {
38
39
  method: 'POST',
39
40
  url: '/ffmpeg/audio/highlights',
41
+ headers: { 'Content-Type': 'application/json' },
40
42
  },
41
43
  },
42
44
  },
@@ -49,6 +51,7 @@ exports.audioDescription = [
49
51
  request: {
50
52
  method: 'POST',
51
53
  url: '/ffmpeg/audio/remove-silence',
54
+ headers: { 'Content-Type': 'application/json' },
52
55
  },
53
56
  },
54
57
  },
@@ -25,6 +25,7 @@ exports.composeDescription = [
25
25
  request: {
26
26
  method: 'POST',
27
27
  url: '/ffmpeg/video/concat',
28
+ headers: { 'Content-Type': 'application/json' },
28
29
  },
29
30
  },
30
31
  },
@@ -37,6 +38,7 @@ exports.composeDescription = [
37
38
  request: {
38
39
  method: 'POST',
39
40
  url: '/ffmpeg/video/compose',
41
+ headers: { 'Content-Type': 'application/json' },
40
42
  },
41
43
  },
42
44
  },
@@ -49,6 +51,7 @@ exports.composeDescription = [
49
51
  request: {
50
52
  method: 'POST',
51
53
  url: '/ffmpeg/merge',
54
+ headers: { 'Content-Type': 'application/json' },
52
55
  },
53
56
  },
54
57
  },
@@ -28,6 +28,7 @@ exports.convertDescription = [
28
28
  request: {
29
29
  method: 'POST',
30
30
  url: '/ffmpeg/convert/audio/to/mp3',
31
+ headers: { 'Content-Type': 'application/json' },
31
32
  },
32
33
  },
33
34
  },
@@ -40,6 +41,7 @@ exports.convertDescription = [
40
41
  request: {
41
42
  method: 'POST',
42
43
  url: '/ffmpeg/convert/audio/to/wav',
44
+ headers: { 'Content-Type': 'application/json' },
43
45
  },
44
46
  },
45
47
  },
@@ -52,6 +54,7 @@ exports.convertDescription = [
52
54
  request: {
53
55
  method: 'POST',
54
56
  url: '/ffmpeg/convert/image/to/jpg',
57
+ headers: { 'Content-Type': 'application/json' },
55
58
  },
56
59
  },
57
60
  },
@@ -64,6 +67,7 @@ exports.convertDescription = [
64
67
  request: {
65
68
  method: 'POST',
66
69
  url: '/ffmpeg/convert/image/to/webp',
70
+ headers: { 'Content-Type': 'application/json' },
67
71
  },
68
72
  },
69
73
  },
@@ -76,6 +80,7 @@ exports.convertDescription = [
76
80
  request: {
77
81
  method: 'POST',
78
82
  url: '/ffmpeg/convert/video/to/mp4',
83
+ headers: { 'Content-Type': 'application/json' },
79
84
  },
80
85
  },
81
86
  },
@@ -88,6 +93,7 @@ exports.convertDescription = [
88
93
  request: {
89
94
  method: 'POST',
90
95
  url: '/ffmpeg/convert/video/to/webm',
96
+ headers: { 'Content-Type': 'application/json' },
91
97
  },
92
98
  },
93
99
  },
@@ -24,6 +24,7 @@ exports.imageDescription = [
24
24
  request: {
25
25
  method: 'POST',
26
26
  url: '/image',
27
+ headers: { 'Content-Type': 'application/json' },
27
28
  },
28
29
  },
29
30
  },
@@ -23,6 +23,7 @@ exports.notifyDescription = [
23
23
  request: {
24
24
  method: 'POST',
25
25
  url: '/notifications/email',
26
+ headers: { 'Content-Type': 'application/json' },
26
27
  },
27
28
  },
28
29
  },
@@ -34,6 +34,7 @@ exports.videoDescription = [
34
34
  request: {
35
35
  method: 'POST',
36
36
  url: '/ffmpeg/video/add-intro',
37
+ headers: { 'Content-Type': 'application/json' },
37
38
  },
38
39
  },
39
40
  },
@@ -46,6 +47,7 @@ exports.videoDescription = [
46
47
  request: {
47
48
  method: 'POST',
48
49
  url: '/ffmpeg/video/add-outro',
50
+ headers: { 'Content-Type': 'application/json' },
49
51
  },
50
52
  },
51
53
  },
@@ -58,6 +60,7 @@ exports.videoDescription = [
58
60
  request: {
59
61
  method: 'POST',
60
62
  url: '/ffmpeg/video/caption',
63
+ headers: { 'Content-Type': 'application/json' },
61
64
  },
62
65
  },
63
66
  },
@@ -70,6 +73,7 @@ exports.videoDescription = [
70
73
  request: {
71
74
  method: 'POST',
72
75
  url: '/ffmpeg/video/extract/audio',
76
+ headers: { 'Content-Type': 'application/json' },
73
77
  },
74
78
  },
75
79
  },
@@ -82,6 +86,7 @@ exports.videoDescription = [
82
86
  request: {
83
87
  method: 'POST',
84
88
  url: '/ffmpeg/video/extract/images',
89
+ headers: { 'Content-Type': 'application/json' },
85
90
  },
86
91
  },
87
92
  },
@@ -94,6 +99,7 @@ exports.videoDescription = [
94
99
  request: {
95
100
  method: 'POST',
96
101
  url: '/ffmpeg/video/extract/gif',
102
+ headers: { 'Content-Type': 'application/json' },
97
103
  },
98
104
  },
99
105
  },
@@ -106,6 +112,7 @@ exports.videoDescription = [
106
112
  request: {
107
113
  method: 'POST',
108
114
  url: '/ffmpeg/video/overlay',
115
+ headers: { 'Content-Type': 'application/json' },
109
116
  },
110
117
  },
111
118
  },
@@ -118,6 +125,7 @@ exports.videoDescription = [
118
125
  request: {
119
126
  method: 'POST',
120
127
  url: '/ffmpeg/video/progress-bar',
128
+ headers: { 'Content-Type': 'application/json' },
121
129
  },
122
130
  },
123
131
  },
@@ -130,6 +138,7 @@ exports.videoDescription = [
130
138
  request: {
131
139
  method: 'POST',
132
140
  url: '/ffmpeg/video/reframe',
141
+ headers: { 'Content-Type': 'application/json' },
133
142
  },
134
143
  },
135
144
  },
@@ -142,6 +151,7 @@ exports.videoDescription = [
142
151
  request: {
143
152
  method: 'POST',
144
153
  url: '/ffmpeg/video/thumbnail',
154
+ headers: { 'Content-Type': 'application/json' },
145
155
  },
146
156
  },
147
157
  },
@@ -154,6 +164,7 @@ exports.videoDescription = [
154
164
  request: {
155
165
  method: 'POST',
156
166
  url: '/ffmpeg/video/trim',
167
+ headers: { 'Content-Type': 'application/json' },
157
168
  },
158
169
  },
159
170
  },
@@ -166,6 +177,7 @@ exports.videoDescription = [
166
177
  request: {
167
178
  method: 'POST',
168
179
  url: '/ffmpeg/video/watermark',
180
+ headers: { 'Content-Type': 'application/json' },
169
181
  },
170
182
  },
171
183
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-eranol",
3
- "version": "0.2.3",
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",