n8n-nodes-converthub 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +156 -0
- package/dist/credentials/ConverthubApi.credentials.d.ts +10 -0
- package/dist/credentials/ConverthubApi.credentials.js +38 -0
- package/dist/credentials/ConverthubApi.credentials.js.map +1 -0
- package/dist/credentials/converthub.dark.svg +5 -0
- package/dist/credentials/converthub.svg +5 -0
- package/dist/nodes/Converthub/Converthub.node.d.ts +5 -0
- package/dist/nodes/Converthub/Converthub.node.js +412 -0
- package/dist/nodes/Converthub/Converthub.node.js.map +1 -0
- package/dist/nodes/Converthub/Converthub.node.json +18 -0
- package/dist/nodes/Converthub/converthub.dark.svg +5 -0
- package/dist/nodes/Converthub/converthub.svg +5 -0
- package/dist/nodes/Converthub/resources/account/index.d.ts +4 -0
- package/dist/nodes/Converthub/resources/account/index.js +28 -0
- package/dist/nodes/Converthub/resources/account/index.js.map +1 -0
- package/dist/nodes/Converthub/resources/conversion/index.d.ts +4 -0
- package/dist/nodes/Converthub/resources/conversion/index.js +359 -0
- package/dist/nodes/Converthub/resources/conversion/index.js.map +1 -0
- package/dist/nodes/Converthub/resources/formats/index.d.ts +4 -0
- package/dist/nodes/Converthub/resources/formats/index.js +89 -0
- package/dist/nodes/Converthub/resources/formats/index.js.map +1 -0
- package/dist/package.json +65 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +65 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ConvertHub
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# n8n-nodes-converthub
|
|
2
|
+
|
|
3
|
+
This is an n8n community node that lets you use [ConvertHub](https://converthub.com) in your n8n workflows.
|
|
4
|
+
|
|
5
|
+
ConvertHub is a powerful file conversion API that supports 800+ format conversion pairs across images, documents, audio, video, and more.
|
|
6
|
+
|
|
7
|
+
[n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/sustainable-use-license/) workflow automation platform.
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Operations](#operations)
|
|
11
|
+
- [Credentials](#credentials)
|
|
12
|
+
- [Compatibility](#compatibility)
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
- [Resources](#resources)
|
|
15
|
+
- [Version history](#version-history)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
|
|
20
|
+
|
|
21
|
+
use the Community Nodes menu in n8n:
|
|
22
|
+
|
|
23
|
+
1. Go to **Settings** > **Community Nodes**
|
|
24
|
+
2. Click **Install**
|
|
25
|
+
3. Enter `n8n-nodes-converthub` in the **Enter npm package name** field
|
|
26
|
+
4. Click **Install**
|
|
27
|
+
|
|
28
|
+
## Operations
|
|
29
|
+
|
|
30
|
+
This node supports the following operations:
|
|
31
|
+
|
|
32
|
+
### Conversion Resource
|
|
33
|
+
- **Convert File** - Convert a file from one format to another (supports binary data)
|
|
34
|
+
- **Convert from URL** - Convert a file by providing its URL
|
|
35
|
+
|
|
36
|
+
### Formats Resource
|
|
37
|
+
- **Get All Supported Formats** - Get a list of all supported file formats grouped by type
|
|
38
|
+
- **Get Format Conversions** - Get available conversions for a specific format
|
|
39
|
+
- **Check Conversion Support** - Check if a specific conversion is supported
|
|
40
|
+
- **Get All Supported Conversions** - Get all supported formats with conversion mappings
|
|
41
|
+
|
|
42
|
+
### Account Resource
|
|
43
|
+
- **Get Account Details** - Get account information including credits, plan details, and file size limits
|
|
44
|
+
|
|
45
|
+
## Credentials
|
|
46
|
+
|
|
47
|
+
To use this node, you need a ConvertHub API key:
|
|
48
|
+
|
|
49
|
+
1. Sign up for a developer account at [ConvertHub API Signup](https://converthub.com/api/signup)
|
|
50
|
+
2. Navigate to your dashboard
|
|
51
|
+
3. Generate a new API key in the API Keys section
|
|
52
|
+
4. Copy your API key
|
|
53
|
+
|
|
54
|
+
### Setting up credentials in n8n:
|
|
55
|
+
|
|
56
|
+
1. In n8n, go to **Credentials** > **New**
|
|
57
|
+
2. Search for "ConvertHub API"
|
|
58
|
+
3. Enter your API key in the **API Key** field
|
|
59
|
+
4. Click **Save**
|
|
60
|
+
|
|
61
|
+
**Note:** All API requests require authentication. Keep your API key secure and never expose it in client-side code.
|
|
62
|
+
|
|
63
|
+
## Compatibility
|
|
64
|
+
|
|
65
|
+
- Minimum n8n version: 1.0.0
|
|
66
|
+
- Tested against n8n version: 1.117.3
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
### Example 1: Convert an Image
|
|
71
|
+
|
|
72
|
+
This example shows how to convert a PNG image to JPG:
|
|
73
|
+
|
|
74
|
+
1. Use an **HTTP Request** node or **Read Binary File** node to get your source file
|
|
75
|
+
2. Add the **ConvertHub** node
|
|
76
|
+
3. Select **Conversion** as the resource
|
|
77
|
+
4. Select **Convert File** as the operation
|
|
78
|
+
5. Set **Binary Property** to `data` (or your binary property name)
|
|
79
|
+
6. Set **Target Format** to `jpg`
|
|
80
|
+
7. Optionally, add quality settings in **Additional Fields**
|
|
81
|
+
8. Execute the workflow
|
|
82
|
+
9.
|
|
83
|
+
### Example 2: Convert from URL
|
|
84
|
+
|
|
85
|
+
1. Add a **ConvertHub** node
|
|
86
|
+
2. Select **Conversion** as the resource
|
|
87
|
+
3. Select **Convert from URL** as the operation
|
|
88
|
+
4. Enter the file URL (e.g., `https://example.com/document.pdf`)
|
|
89
|
+
5. Set **Target Format** to `docx`
|
|
90
|
+
6. Execute the workflow
|
|
91
|
+
|
|
92
|
+
### Example 3: Check Supported Formats
|
|
93
|
+
|
|
94
|
+
1. Add a **ConvertHub** node
|
|
95
|
+
2. Select **Formats** as the resource
|
|
96
|
+
3. Select **Get All Supported Formats** as the operation
|
|
97
|
+
4. Execute to see all supported format groups
|
|
98
|
+
|
|
99
|
+
### Example 4: Check Account Credits
|
|
100
|
+
|
|
101
|
+
1. Add a **ConvertHub** node
|
|
102
|
+
2. Select **Account** as the resource
|
|
103
|
+
3. Select **Get Account Details** as the operation
|
|
104
|
+
4. Execute to see your remaining credits and plan details
|
|
105
|
+
|
|
106
|
+
### Conversion Options
|
|
107
|
+
|
|
108
|
+
The **Convert File** and **Convert from URL** operations support these optional parameters:
|
|
109
|
+
|
|
110
|
+
- **Output Filename** - Custom name for the output file
|
|
111
|
+
- **Webhook URL** - URL to receive webhook notification when conversion completes
|
|
112
|
+
- **Quality** - Quality setting (1-100) for lossy formats like JPEG, MP3
|
|
113
|
+
- **Resolution** - Resolution for image/video conversions (e.g., "1920x1080")
|
|
114
|
+
- **Bitrate** - Bitrate for audio/video conversions (e.g., "320k")
|
|
115
|
+
- **Sample Rate** - Sample rate for audio conversions (e.g., 44100)
|
|
116
|
+
- **Metadata** - Custom key-value pairs for tracking purposes
|
|
117
|
+
|
|
118
|
+
## API Limits
|
|
119
|
+
|
|
120
|
+
- **File Size Limit**: 50MB for direct upload
|
|
121
|
+
- **Rate Limits**: Varies by plan (see API documentation)
|
|
122
|
+
- **File Retention**: Converted files are available for 24 hours
|
|
123
|
+
- **Credits**: Each conversion consumes 1 credit
|
|
124
|
+
|
|
125
|
+
## Resources
|
|
126
|
+
|
|
127
|
+
* [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
|
|
128
|
+
* [ConvertHub API Documentation](https://converthub.com/api/docs)
|
|
129
|
+
* [ConvertHub Website](https://converthub.com/api)
|
|
130
|
+
* [GitHub Repository](https://github.com/converthub-api/n8n-nodes-converthub)
|
|
131
|
+
|
|
132
|
+
## Version history
|
|
133
|
+
|
|
134
|
+
### 0.1.0 (Current)
|
|
135
|
+
|
|
136
|
+
- Initial release
|
|
137
|
+
- Support for file conversion (direct upload and URL-based)
|
|
138
|
+
- Support for job management (status, cancel, delete)
|
|
139
|
+
- Support for format discovery endpoints
|
|
140
|
+
- Support for account information endpoint
|
|
141
|
+
- Support for 800+ format conversion pairs
|
|
142
|
+
- Full API v2 coverage
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
[MIT](LICENSE.md)
|
|
147
|
+
|
|
148
|
+
## Support
|
|
149
|
+
|
|
150
|
+
For issues and questions:
|
|
151
|
+
- Email: support@converthub.com
|
|
152
|
+
- GitHub Issues: [Report an issue](https://github.com/converthub-api/n8n-nodes-converthub/issues)
|
|
153
|
+
|
|
154
|
+
## Contributing
|
|
155
|
+
|
|
156
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties, Icon } from 'n8n-workflow';
|
|
2
|
+
export declare class ConverthubApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
icon: Icon;
|
|
7
|
+
properties: INodeProperties[];
|
|
8
|
+
authenticate: IAuthenticateGeneric;
|
|
9
|
+
test: ICredentialTestRequest;
|
|
10
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConverthubApi = void 0;
|
|
4
|
+
class ConverthubApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'converthubApi';
|
|
7
|
+
this.displayName = 'Converthub API';
|
|
8
|
+
this.documentationUrl = 'https://github.com/converthub-api/n8n-nodes-converthub#credentials';
|
|
9
|
+
this.icon = 'file:converthub.svg';
|
|
10
|
+
this.properties = [
|
|
11
|
+
{
|
|
12
|
+
displayName: 'API Key',
|
|
13
|
+
name: 'apiKey',
|
|
14
|
+
type: 'string',
|
|
15
|
+
typeOptions: { password: true },
|
|
16
|
+
required: true,
|
|
17
|
+
default: '',
|
|
18
|
+
description: 'The API key for ConvertHub API. Get your API key from https://converthub.com/api/signup',
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
this.authenticate = {
|
|
22
|
+
type: 'generic',
|
|
23
|
+
properties: {
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: '=Bearer {{$credentials.apiKey}}',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
this.test = {
|
|
30
|
+
request: {
|
|
31
|
+
baseURL: 'https://api.converthub.com',
|
|
32
|
+
url: '/v2/account',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.ConverthubApi = ConverthubApi;
|
|
38
|
+
//# sourceMappingURL=ConverthubApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConverthubApi.credentials.js","sourceRoot":"","sources":["../../credentials/ConverthubApi.credentials.ts"],"names":[],"mappings":";;;AAQA,MAAa,aAAa;IAA1B;QACC,SAAI,GAAG,eAAe,CAAC;QAEvB,gBAAW,GAAG,gBAAgB,CAAC;QAG/B,qBAAgB,GAAG,oEAAoE,CAAC;QAExF,SAAI,GAAS,qBAAqB,CAAC;QAEnC,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,yFAAyF;aACtG;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,iCAAiC;iBAChD;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,4BAA4B;gBACrC,GAAG,EAAE,aAAa;aAClB;SACD,CAAC;IACH,CAAC;CAAA;AArCD,sCAqCC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type IExecuteFunctions, type INodeExecutionData, type INodeType, type INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare class Converthub implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Converthub = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const conversion_1 = require("./resources/conversion");
|
|
6
|
+
const formats_1 = require("./resources/formats");
|
|
7
|
+
const account_1 = require("./resources/account");
|
|
8
|
+
class Converthub {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.description = {
|
|
11
|
+
displayName: 'ConvertHub',
|
|
12
|
+
name: 'converthub',
|
|
13
|
+
icon: 'file:converthub.svg',
|
|
14
|
+
group: ['transform'],
|
|
15
|
+
version: 1,
|
|
16
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
17
|
+
description: 'Convert files between 800+ formats using ConvertHub API',
|
|
18
|
+
defaults: {
|
|
19
|
+
name: 'ConvertHub',
|
|
20
|
+
},
|
|
21
|
+
usableAsTool: true,
|
|
22
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
23
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
24
|
+
credentials: [{ name: 'converthubApi', required: true }],
|
|
25
|
+
requestDefaults: {
|
|
26
|
+
baseURL: 'https://api.converthub.com/v2',
|
|
27
|
+
headers: {
|
|
28
|
+
Accept: 'application/json',
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
properties: [
|
|
33
|
+
{
|
|
34
|
+
displayName: 'Resource',
|
|
35
|
+
name: 'resource',
|
|
36
|
+
type: 'options',
|
|
37
|
+
noDataExpression: true,
|
|
38
|
+
options: [
|
|
39
|
+
{
|
|
40
|
+
name: 'Conversion',
|
|
41
|
+
value: 'conversion',
|
|
42
|
+
description: 'Convert files between formats',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'Format',
|
|
46
|
+
value: 'formats',
|
|
47
|
+
description: 'Get information about supported formats',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'Account',
|
|
51
|
+
value: 'account',
|
|
52
|
+
description: 'Get account information',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
default: 'conversion',
|
|
56
|
+
},
|
|
57
|
+
...conversion_1.conversionDescription,
|
|
58
|
+
...formats_1.formatsDescription,
|
|
59
|
+
...account_1.accountDescription,
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async execute() {
|
|
64
|
+
var _a;
|
|
65
|
+
const items = this.getInputData();
|
|
66
|
+
const returnData = [];
|
|
67
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
68
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
69
|
+
const pollForCompletion = async (jobId, downloadFile = true, binaryPropertyName = 'data', itemIndex = 0, expectedFilename) => {
|
|
70
|
+
var _a;
|
|
71
|
+
const maxAttempts = 150;
|
|
72
|
+
let attempts = 0;
|
|
73
|
+
while (attempts < maxAttempts) {
|
|
74
|
+
try {
|
|
75
|
+
const statusResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
76
|
+
method: 'GET',
|
|
77
|
+
url: `https://api.converthub.com/v2/jobs/${jobId}`,
|
|
78
|
+
json: true,
|
|
79
|
+
});
|
|
80
|
+
const success = statusResponse.success;
|
|
81
|
+
const status = statusResponse.status;
|
|
82
|
+
if (status === 'completed' && success === true) {
|
|
83
|
+
const downloadResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
84
|
+
method: 'GET',
|
|
85
|
+
url: `https://api.converthub.com/v2/jobs/${jobId}/download`,
|
|
86
|
+
json: true,
|
|
87
|
+
});
|
|
88
|
+
const downloadUrl = downloadResponse.download_url;
|
|
89
|
+
const result = {
|
|
90
|
+
json: {
|
|
91
|
+
...statusResponse,
|
|
92
|
+
download_url: downloadUrl,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
if (downloadFile && downloadUrl) {
|
|
96
|
+
const fileBuffer = await this.helpers.httpRequest({
|
|
97
|
+
method: 'GET',
|
|
98
|
+
url: downloadUrl,
|
|
99
|
+
encoding: 'arraybuffer',
|
|
100
|
+
});
|
|
101
|
+
const outputFilename = expectedFilename ||
|
|
102
|
+
statusResponse.output_filename ||
|
|
103
|
+
downloadUrl.split('/').pop() ||
|
|
104
|
+
'converted-file';
|
|
105
|
+
result.binary = {
|
|
106
|
+
[binaryPropertyName]: await this.helpers.prepareBinaryData(Buffer.from(fileBuffer), outputFilename),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
if (success === false) {
|
|
112
|
+
const errorObj = statusResponse.error;
|
|
113
|
+
let errorMessage = 'Unknown error';
|
|
114
|
+
if (errorObj && typeof errorObj === 'object') {
|
|
115
|
+
const errMsg = errorObj.message;
|
|
116
|
+
if (errMsg && typeof errMsg === 'string') {
|
|
117
|
+
errorMessage = errMsg;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (typeof errorObj === 'string') {
|
|
121
|
+
errorMessage = errorObj;
|
|
122
|
+
}
|
|
123
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
if ((_a = error.response) === null || _a === void 0 ? void 0 : _a.body) {
|
|
128
|
+
const errorBody = error.response.body;
|
|
129
|
+
const errorMessage = errorBody.error || errorBody.message || errorBody.errors || 'Unknown error';
|
|
130
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Conversion failed: ${errorMessage}`);
|
|
131
|
+
}
|
|
132
|
+
if (error.message && error.message.includes('Conversion failed')) {
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
await (0, n8n_workflow_1.sleep)(2000);
|
|
137
|
+
attempts++;
|
|
138
|
+
}
|
|
139
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Conversion timed out after 5 minutes');
|
|
140
|
+
};
|
|
141
|
+
for (let i = 0; i < items.length; i++) {
|
|
142
|
+
try {
|
|
143
|
+
if (resource === 'conversion') {
|
|
144
|
+
if (operation === 'convertFile') {
|
|
145
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
146
|
+
const targetFormat = this.getNodeParameter('targetFormat', i);
|
|
147
|
+
const options = this.getNodeParameter('options', i, {});
|
|
148
|
+
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
149
|
+
const outputBinaryPropertyName = options.binaryPropertyName || 'data';
|
|
150
|
+
const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
|
|
151
|
+
const dataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
152
|
+
const FormData = require('form-data');
|
|
153
|
+
const formDataPayload = new FormData();
|
|
154
|
+
formDataPayload.append('file', dataBuffer, {
|
|
155
|
+
filename: binaryData.fileName || 'file',
|
|
156
|
+
contentType: binaryData.mimeType || 'application/octet-stream',
|
|
157
|
+
});
|
|
158
|
+
formDataPayload.append('target_format', targetFormat);
|
|
159
|
+
let outputFilename = additionalFields.output_filename;
|
|
160
|
+
if (!outputFilename && binaryData.fileName) {
|
|
161
|
+
const baseName = binaryData.fileName.replace(/\.[^/.]+$/, '');
|
|
162
|
+
outputFilename = `${baseName}.${targetFormat}`;
|
|
163
|
+
}
|
|
164
|
+
if (outputFilename) {
|
|
165
|
+
formDataPayload.append('output_filename', outputFilename);
|
|
166
|
+
}
|
|
167
|
+
if (additionalFields.webhook_url) {
|
|
168
|
+
formDataPayload.append('webhook_url', additionalFields.webhook_url);
|
|
169
|
+
}
|
|
170
|
+
if (additionalFields.quality) {
|
|
171
|
+
formDataPayload.append('options[quality]', additionalFields.quality);
|
|
172
|
+
}
|
|
173
|
+
if (additionalFields.resolution) {
|
|
174
|
+
formDataPayload.append('options[resolution]', additionalFields.resolution);
|
|
175
|
+
}
|
|
176
|
+
if (additionalFields.bitrate) {
|
|
177
|
+
formDataPayload.append('options[bitrate]', additionalFields.bitrate);
|
|
178
|
+
}
|
|
179
|
+
if (additionalFields.sample_rate) {
|
|
180
|
+
formDataPayload.append('options[sample_rate]', additionalFields.sample_rate);
|
|
181
|
+
}
|
|
182
|
+
if (additionalFields.metadata) {
|
|
183
|
+
const metadataValues = additionalFields.metadata
|
|
184
|
+
.metadataValues;
|
|
185
|
+
if (metadataValues) {
|
|
186
|
+
for (const item of metadataValues) {
|
|
187
|
+
formDataPayload.append(`metadata[${item.key}]`, item.value);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
let response;
|
|
192
|
+
try {
|
|
193
|
+
response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
194
|
+
method: 'POST',
|
|
195
|
+
url: 'https://api.converthub.com/v2/convert',
|
|
196
|
+
body: formDataPayload,
|
|
197
|
+
headers: {
|
|
198
|
+
...formDataPayload.getHeaders(),
|
|
199
|
+
},
|
|
200
|
+
skipSslCertificateValidation: false,
|
|
201
|
+
ignoreHttpStatusErrors: true,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to connect to API: ${error.message}`);
|
|
206
|
+
}
|
|
207
|
+
const success = response.success;
|
|
208
|
+
if (success === false) {
|
|
209
|
+
const errorObj = response.error;
|
|
210
|
+
let errorMessage = 'Conversion request failed';
|
|
211
|
+
if (errorObj && typeof errorObj === 'object') {
|
|
212
|
+
errorMessage = errorObj.message;
|
|
213
|
+
}
|
|
214
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex: i });
|
|
215
|
+
}
|
|
216
|
+
const jobId = response.job_id;
|
|
217
|
+
const completedResponse = await pollForCompletion(jobId, true, outputBinaryPropertyName, i, outputFilename);
|
|
218
|
+
returnData.push(completedResponse);
|
|
219
|
+
}
|
|
220
|
+
else if (operation === 'convertUrl') {
|
|
221
|
+
const fileUrl = this.getNodeParameter('fileUrl', i);
|
|
222
|
+
const targetFormat = this.getNodeParameter('targetFormat', i);
|
|
223
|
+
const options = this.getNodeParameter('options', i, {});
|
|
224
|
+
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
225
|
+
const outputBinaryPropertyName = options.binaryPropertyName || 'data';
|
|
226
|
+
const body = {
|
|
227
|
+
file_url: fileUrl,
|
|
228
|
+
target_format: targetFormat,
|
|
229
|
+
};
|
|
230
|
+
let outputFilename = additionalFields.output_filename;
|
|
231
|
+
if (!outputFilename) {
|
|
232
|
+
try {
|
|
233
|
+
const urlPath = new URL(fileUrl).pathname;
|
|
234
|
+
const urlFilename = urlPath.split('/').pop() || 'file';
|
|
235
|
+
const baseName = urlFilename.replace(/\.[^/.]+$/, '');
|
|
236
|
+
outputFilename = `${baseName}.${targetFormat}`;
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
outputFilename = `converted.${targetFormat}`;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (outputFilename) {
|
|
243
|
+
body.output_filename = outputFilename;
|
|
244
|
+
}
|
|
245
|
+
if (additionalFields.webhook_url) {
|
|
246
|
+
body.webhook_url = additionalFields.webhook_url;
|
|
247
|
+
}
|
|
248
|
+
const conversionOptions = {};
|
|
249
|
+
if (additionalFields.quality)
|
|
250
|
+
conversionOptions.quality = additionalFields.quality;
|
|
251
|
+
if (additionalFields.resolution)
|
|
252
|
+
conversionOptions.resolution = additionalFields.resolution;
|
|
253
|
+
if (additionalFields.bitrate)
|
|
254
|
+
conversionOptions.bitrate = additionalFields.bitrate;
|
|
255
|
+
if (additionalFields.sample_rate)
|
|
256
|
+
conversionOptions.sample_rate = additionalFields.sample_rate;
|
|
257
|
+
if (Object.keys(conversionOptions).length > 0) {
|
|
258
|
+
body.options = conversionOptions;
|
|
259
|
+
}
|
|
260
|
+
if (additionalFields.metadata) {
|
|
261
|
+
const metadata = {};
|
|
262
|
+
const metadataValues = additionalFields.metadata
|
|
263
|
+
.metadataValues;
|
|
264
|
+
if (metadataValues) {
|
|
265
|
+
for (const item of metadataValues) {
|
|
266
|
+
metadata[item.key] = item.value;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (Object.keys(metadata).length > 0) {
|
|
270
|
+
body.metadata = metadata;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
let response;
|
|
274
|
+
try {
|
|
275
|
+
response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
276
|
+
method: 'POST',
|
|
277
|
+
url: 'https://api.converthub.com/v2/convert-url',
|
|
278
|
+
body,
|
|
279
|
+
json: true,
|
|
280
|
+
ignoreHttpStatusErrors: true,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to connect to API: ${error.message}`);
|
|
285
|
+
}
|
|
286
|
+
const success = response.success;
|
|
287
|
+
if (success === false) {
|
|
288
|
+
const errorObj = response.error;
|
|
289
|
+
let errorMessage = 'Conversion request failed';
|
|
290
|
+
if (errorObj && typeof errorObj === 'object') {
|
|
291
|
+
errorMessage = errorObj.message;
|
|
292
|
+
}
|
|
293
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex: i });
|
|
294
|
+
}
|
|
295
|
+
const jobId = response.job_id;
|
|
296
|
+
const completedResponse = await pollForCompletion(jobId, true, outputBinaryPropertyName, i, outputFilename);
|
|
297
|
+
returnData.push(completedResponse);
|
|
298
|
+
}
|
|
299
|
+
else if (operation === 'getStatus') {
|
|
300
|
+
const jobId = this.getNodeParameter('jobId', i);
|
|
301
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
302
|
+
method: 'GET',
|
|
303
|
+
url: `https://api.converthub.com/v2/jobs/${jobId}`,
|
|
304
|
+
json: true,
|
|
305
|
+
});
|
|
306
|
+
returnData.push({ json: response });
|
|
307
|
+
}
|
|
308
|
+
else if (operation === 'getDownloadUrl') {
|
|
309
|
+
const jobId = this.getNodeParameter('jobId', i);
|
|
310
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
311
|
+
method: 'GET',
|
|
312
|
+
url: `https://api.converthub.com/v2/jobs/${jobId}/download`,
|
|
313
|
+
json: true,
|
|
314
|
+
});
|
|
315
|
+
returnData.push({ json: response });
|
|
316
|
+
}
|
|
317
|
+
else if (operation === 'cancelJob') {
|
|
318
|
+
const jobId = this.getNodeParameter('jobId', i);
|
|
319
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
320
|
+
method: 'DELETE',
|
|
321
|
+
url: `https://api.converthub.com/v2/jobs/${jobId}`,
|
|
322
|
+
json: true,
|
|
323
|
+
});
|
|
324
|
+
returnData.push({ json: response });
|
|
325
|
+
}
|
|
326
|
+
else if (operation === 'deleteConversion') {
|
|
327
|
+
const jobId = this.getNodeParameter('jobId', i);
|
|
328
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
329
|
+
method: 'DELETE',
|
|
330
|
+
url: `https://api.converthub.com/v2/jobs/${jobId}/destroy`,
|
|
331
|
+
json: true,
|
|
332
|
+
});
|
|
333
|
+
returnData.push({ json: response });
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
else if (resource === 'formats') {
|
|
337
|
+
if (operation === 'getAllFormats') {
|
|
338
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
339
|
+
method: 'GET',
|
|
340
|
+
url: 'https://api.converthub.com/v2/formats',
|
|
341
|
+
json: true,
|
|
342
|
+
});
|
|
343
|
+
returnData.push({ json: response });
|
|
344
|
+
}
|
|
345
|
+
else if (operation === 'getFormatConversions') {
|
|
346
|
+
const format = this.getNodeParameter('format', i);
|
|
347
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
348
|
+
method: 'GET',
|
|
349
|
+
url: `https://api.converthub.com/v2/formats/${format}/conversions`,
|
|
350
|
+
json: true,
|
|
351
|
+
});
|
|
352
|
+
returnData.push({ json: response });
|
|
353
|
+
}
|
|
354
|
+
else if (operation === 'checkConversionSupport') {
|
|
355
|
+
const sourceFormat = this.getNodeParameter('sourceFormat', i);
|
|
356
|
+
const targetFormat = this.getNodeParameter('targetFormat', i);
|
|
357
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
358
|
+
method: 'GET',
|
|
359
|
+
url: `https://api.converthub.com/v2/formats/${sourceFormat}/to/${targetFormat}`,
|
|
360
|
+
json: true,
|
|
361
|
+
});
|
|
362
|
+
returnData.push({ json: response });
|
|
363
|
+
}
|
|
364
|
+
else if (operation === 'getAllConversions') {
|
|
365
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
366
|
+
method: 'GET',
|
|
367
|
+
url: 'https://api.converthub.com/v2/formats/supported-conversions',
|
|
368
|
+
json: true,
|
|
369
|
+
});
|
|
370
|
+
returnData.push({ json: response });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else if (resource === 'account') {
|
|
374
|
+
if (operation === 'getDetails') {
|
|
375
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'converthubApi', {
|
|
376
|
+
method: 'GET',
|
|
377
|
+
url: 'https://api.converthub.com/v2/account',
|
|
378
|
+
json: true,
|
|
379
|
+
});
|
|
380
|
+
returnData.push({ json: response });
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
let errorMessage = error.message;
|
|
386
|
+
if ((_a = error.response) === null || _a === void 0 ? void 0 : _a.body) {
|
|
387
|
+
const errorBody = error.response.body;
|
|
388
|
+
if (errorBody.error && typeof errorBody.error === 'object' && errorBody.error.message) {
|
|
389
|
+
errorMessage = errorBody.error.message;
|
|
390
|
+
}
|
|
391
|
+
else if (typeof errorBody.error === 'string') {
|
|
392
|
+
errorMessage = errorBody.error;
|
|
393
|
+
}
|
|
394
|
+
else if (errorBody.message) {
|
|
395
|
+
errorMessage = errorBody.message;
|
|
396
|
+
}
|
|
397
|
+
else if (errorBody.errors) {
|
|
398
|
+
errorMessage = JSON.stringify(errorBody.errors);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (this.continueOnFail()) {
|
|
402
|
+
returnData.push({ json: { error: errorMessage }, pairedItem: { item: i } });
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return [returnData];
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
exports.Converthub = Converthub;
|
|
412
|
+
//# sourceMappingURL=Converthub.node.js.map
|