diff --git a/packages/nodes-base/nodes/Signl4/GenericFunctions.ts b/packages/nodes-base/nodes/Signl4/GenericFunctions.ts index 5281ae8c25ede..62f53823c76e8 100644 --- a/packages/nodes-base/nodes/Signl4/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Signl4/GenericFunctions.ts @@ -9,26 +9,33 @@ import { import { OptionsWithUri, } from 'request'; - + /** * Make an API request to SIGNL4 * * @param {IHookFunctions | IExecuteFunctions} this - * @param {object} message + * @param {string} method + * @param {string} contentType + * @param {string} body + * @param {object} query + * @param {string} teamSecret + * @param {object} options * @returns {Promise} + * */ -export async function SIGNL4ApiRequest(this: IExecuteFunctions, method: string, resource: string, body: any = {}, query: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any +export async function SIGNL4ApiRequest(this: IExecuteFunctions, method: string, contentType: string, body: string, query: IDataObject = {}, teamSecret?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any let options: OptionsWithUri = { headers: { 'Accept': '*/*', + 'Content-Type': contentType }, method, body, qs: query, - uri: uri || ``, - json: true, + uri: "https://connect.signl4.com/webhook/" + teamSecret, + json: false, }; if (!Object.keys(body).length) { @@ -40,7 +47,7 @@ export async function SIGNL4ApiRequest(this: IExecuteFunctions, method: string, options = Object.assign({}, options, option); try { - return await this.helpers.request!(options); + return JSON.parse(await this.helpers.request!(options)); } catch (error) { if (error.response && error.response.body && error.response.body.details) { diff --git a/packages/nodes-base/nodes/Signl4/Signl4.node.json b/packages/nodes-base/nodes/Signl4/Signl4.node.json index e6e06e864fcad..8337da9d3017e 100644 --- a/packages/nodes-base/nodes/Signl4/Signl4.node.json +++ b/packages/nodes-base/nodes/Signl4/Signl4.node.json @@ -1,7 +1,7 @@ { "node": "n8n-nodes-base.signl4", - "nodeVersion": "1.0", - "codexVersion": "1.0", + "nodeVersion": "1.1", + "codexVersion": "1.1", "categories": [ "Communication", "Development" diff --git a/packages/nodes-base/nodes/Signl4/Signl4.node.ts b/packages/nodes-base/nodes/Signl4/Signl4.node.ts index 2b8defc44095e..56d73c8a86404 100644 --- a/packages/nodes-base/nodes/Signl4/Signl4.node.ts +++ b/packages/nodes-base/nodes/Signl4/Signl4.node.ts @@ -265,36 +265,71 @@ export class Signl4 implements INodeType { if (operation === 'send') { const message = this.getNodeParameter('message', i) as string; const additionalFields = this.getNodeParameter('additionalFields',i) as IDataObject; + + let data = ""; - const data: IDataObject = { - message, - }; + // Message + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"message\"\r\n\r\n"; + data += message + "\r\n"; - if (additionalFields.alertingScenario) { - data['X-S4-AlertingScenario'] = additionalFields.alertingScenario as string; - } - if (additionalFields.externalId) { - data['X-S4-ExternalID'] = additionalFields.externalId as string; + // Title + if (additionalFields.title) { + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"title\"\r\n\r\n"; + data += additionalFields.title as string + "\r\n"; } - if (additionalFields.filtering) { - data['X-S4-Filtering'] = (additionalFields.filtering as boolean).toString(); + + // X-S4-Service + if (additionalFields.service) { + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-Service\"\r\n\r\n"; + data += additionalFields.service as string + "\r\n"; } + + // X-S4-Location if (additionalFields.locationFieldsUi) { const locationUi = (additionalFields.locationFieldsUi as IDataObject).locationFieldsValues as IDataObject; if (locationUi) { - data['X-S4-Location'] = `${locationUi.latitude},${locationUi.longitude}`; + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-Location\"\r\n\r\n"; + data += `${locationUi.latitude},${locationUi.longitude}` + "\r\n"; } } - if (additionalFields.service) { - data['X-S4-Service'] = additionalFields.service as string; + + // X-S4-AlertingScenario + if (additionalFields.alertingScenario) { + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-AlertingScenario\"\r\n\r\n"; + data += additionalFields.alertingScenario as string + "\r\n"; } - data['X-S4-Status'] = 'new'; - if (additionalFields.title) { - data['title'] = additionalFields.title as string; + + // X-S4-Filtering + if (additionalFields.filtering) { + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-Filtering\"\r\n\r\n"; + data += (additionalFields.filtering as boolean).toString() + "\r\n"; } - const attachments = additionalFields.attachmentsUi as IDataObject; + // X-S4-ExternalID + if (additionalFields.externalId) { + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-ExternalID\"\r\n\r\n"; + data += additionalFields.externalId as string + "\r\n"; + } + + // Status + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-Status\"\r\n\r\n"; + data += "new\r\n"; + // Source System + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"X-S4-SourceSystem\"\r\n\r\n"; + data += "n8n\r\n"; + + // Attachments + const attachments = additionalFields.attachmentsUi as IDataObject; if (attachments) { if (attachments.attachmentsBinary && items[i].binary) { @@ -304,38 +339,39 @@ export class Signl4 implements INodeType { if (binaryProperty) { - const supportedFileExtension = ['png', 'jpg', 'txt']; + const supportedFileExtension = ['png', 'jpg', 'bmp', 'gif', 'mp3', 'wav']; if (!supportedFileExtension.includes(binaryProperty.fileExtension as string)) { throw new Error(`Invalid extension, just ${supportedFileExtension.join(',')} are supported}`); } - data['file'] = { - value: Buffer.from(binaryProperty.data, BINARY_ENCODING), - options: { - filename: binaryProperty.fileName, - contentType: binaryProperty.mimeType, - }, - }; + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513\r\n"; + data += "Content-Disposition: form-data; name=\"" + binaryProperty.fileName + "\"; filename=\"" + binaryProperty.fileName + "\"\r\n"; + data += "Content-Type: " + binaryProperty.mimeType + "\r\n"; + data += "Content-Transfer-Encoding: base64\r\n\r\n"; + + data += Buffer.from(binaryProperty.data, 'base64').toString('base64') + "\r\n"; } else { throw new Error(`Binary property ${propertyName} does not exist on input`); } } } + + data += "------Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513--\r\n"; const credentials = this.getCredentials('signl4Api'); - const endpoint = `https://connect.signl4.com/webhook/${credentials?.teamSecret}`; + const teamSecret = credentials?.teamSecret as string; responseData = await SIGNL4ApiRequest.call( this, 'POST', - '', + 'multipart/form-data; boundary=----Boundary-cc2050af-c42f-4cda-a0c3-ede7eaa89513', data, {}, - endpoint, + teamSecret, {}, ); } @@ -347,18 +383,21 @@ export class Signl4 implements INodeType { data['X-S4-ExternalID'] = this.getNodeParameter('externalId', i) as string; data['X-S4-Status'] = 'resolved'; + + // Source system + data['X-S4-SourceSystem'] = 'n8n'; const credentials = this.getCredentials('signl4Api'); - const endpoint = `https://connect.signl4.com/webhook/${credentials?.teamSecret}`; + const teamSecret = credentials?.teamSecret as string; responseData = await SIGNL4ApiRequest.call( this, 'POST', - '', - data, + 'application/json', + JSON.stringify(data), {}, - endpoint, + teamSecret, {}, ); }