diff --git a/packages/nodes-base/nodes/Slack/Slack.node.ts b/packages/nodes-base/nodes/Slack/Slack.node.ts
index 16ef542f3b..0eac92e536 100644
--- a/packages/nodes-base/nodes/Slack/Slack.node.ts
+++ b/packages/nodes-base/nodes/Slack/Slack.node.ts
@@ -14,13 +14,14 @@ export class Slack extends VersionedNodeType {
group: ['output'],
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Slack API',
- defaultVersion: 2.1,
+ defaultVersion: 2.2,
};
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
1: new SlackV1(baseDescription),
2: new SlackV2(baseDescription),
2.1: new SlackV2(baseDescription),
+ 2.2: new SlackV2(baseDescription),
};
super(nodeVersions, baseDescription);
diff --git a/packages/nodes-base/nodes/Slack/V2/FileDescription.ts b/packages/nodes-base/nodes/Slack/V2/FileDescription.ts
index aecf8e2bfb..07d514ff49 100644
--- a/packages/nodes-base/nodes/Slack/V2/FileDescription.ts
+++ b/packages/nodes-base/nodes/Slack/V2/FileDescription.ts
@@ -47,6 +47,7 @@ export const fileFields: INodeProperties[] = [
show: {
operation: ['upload'],
resource: ['file'],
+ '@version': [2, 2.1],
},
},
description: 'Whether the data to upload should be taken from binary field',
@@ -61,6 +62,7 @@ export const fileFields: INodeProperties[] = [
operation: ['upload'],
resource: ['file'],
binaryData: [false],
+ '@version': [2, 2.1],
},
},
placeholder: '',
@@ -76,6 +78,23 @@ export const fileFields: INodeProperties[] = [
operation: ['upload'],
resource: ['file'],
binaryData: [true],
+ '@version': [2, 2.1],
+ },
+ },
+ placeholder: '',
+ description: 'Name of the binary property which contains the data for the file to be uploaded',
+ },
+ {
+ displayName: 'File Property',
+ name: 'binaryPropertyName',
+ type: 'string',
+ default: 'data',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['upload'],
+ resource: ['file'],
+ '@version': [2.2],
},
},
placeholder: '',
@@ -102,10 +121,31 @@ export const fileFields: INodeProperties[] = [
typeOptions: {
loadOptionsMethod: 'getChannels',
},
+ displayOptions: {
+ show: {
+ '@version': [2, 2.1],
+ },
+ },
default: [],
description:
'The channels to send the file to. Choose from the list, or specify IDs using an expression.',
},
+ {
+ displayName: 'Channel Name or ID',
+ name: 'channelId',
+ type: 'options',
+ typeOptions: {
+ loadOptionsMethod: 'getChannels',
+ },
+ displayOptions: {
+ show: {
+ '@version': [2.2],
+ },
+ },
+ default: [],
+ description:
+ 'The channel to send the file to. Choose from the list, or specify an ID using an expression.',
+ },
{
displayName: 'File Name',
name: 'fileName',
diff --git a/packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts b/packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts
index 7df2ff5d11..2554565239 100644
--- a/packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/Slack/V2/GenericFunctions.ts
@@ -29,7 +29,7 @@ export async function slackApiRequest(
},
body,
qs: query,
- uri: `https://slack.com/api${resource}`,
+ uri: resource.startsWith('https') ? resource : `https://slack.com/api${resource}`,
json: true,
};
options = Object.assign({}, options, option);
@@ -78,6 +78,7 @@ export async function slackApiRequest(
},
);
}
+
throw new NodeOperationError(
this.getNode(),
'Slack error response: ' + JSON.stringify(response.error),
diff --git a/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts b/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts
index 3e9d4133bc..df0ac7b999 100644
--- a/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts
+++ b/packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts
@@ -38,7 +38,7 @@ export class SlackV2 implements INodeType {
constructor(baseDescription: INodeTypeBaseDescription) {
this.description = {
...baseDescription,
- version: [2, 2.1],
+ version: [2, 2.1, 2.2],
defaults: {
name: 'Slack',
},
@@ -1040,11 +1040,13 @@ export class SlackV2 implements INodeType {
if (operation === 'upload') {
const options = this.getNodeParameter('options', i);
const body: IDataObject = {};
+ const fileBody: IDataObject = {};
+
if (options.channelIds) {
body.channels = (options.channelIds as string[]).join(',');
}
- if (options.fileName) {
- body.filename = options.fileName as string;
+ if (options.channelId) {
+ body.channel_id = options.channelId as string;
}
if (options.initialComment) {
body.initial_comment = options.initialComment as string;
@@ -1053,35 +1055,87 @@ export class SlackV2 implements INodeType {
body.thread_ts = options.threadTs as string;
}
if (options.title) {
- body.title = options.title as string;
+ if (nodeVersion <= 2.1) {
+ body.title = options.title as string;
+ }
}
- if (this.getNodeParameter('binaryData', i)) {
+
+ if (this.getNodeParameter('binaryData', i, false) || nodeVersion > 2.1) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
+ let fileSize: number;
let uploadData: Buffer | Readable;
if (binaryData.id) {
uploadData = await this.helpers.getBinaryStream(binaryData.id);
+ const metadata = await this.helpers.getBinaryMetadata(binaryData.id);
+ fileSize = metadata.fileSize;
} else {
uploadData = Buffer.from(binaryData.data, BINARY_ENCODING);
+ fileSize = uploadData.length;
+ }
+
+ if (nodeVersion <= 2.1) {
+ body.file = {
+ value: uploadData,
+ options: {
+ filename: binaryData.fileName,
+ contentType: binaryData.mimeType,
+ },
+ };
+
+ responseData = await slackApiRequest.call(
+ this,
+ 'POST',
+ '/files.upload',
+ {},
+ qs,
+ { 'Content-Type': 'multipart/form-data' },
+ { formData: body },
+ );
+ responseData = responseData.file;
+ } else {
+ fileBody.file = {
+ value: uploadData,
+ options: {
+ filename: binaryData.fileName,
+ contentType: binaryData.mimeType,
+ },
+ };
+
+ const uploadUrl = await slackApiRequest.call(
+ this,
+ 'GET',
+ '/files.getUploadURLExternal',
+ {},
+ {
+ filename: options.fileName ? options.fileName : binaryData.fileName,
+ length: fileSize,
+ },
+ );
+ await slackApiRequest.call(
+ this,
+ 'POST',
+ uploadUrl.upload_url,
+ {},
+ qs,
+ { 'Content-Type': 'multipart/form-data' },
+ { formData: fileBody },
+ );
+ body.files = [
+ {
+ id: uploadUrl.file_id,
+ title: options.title ? options.title : binaryData.fileName,
+ },
+ ];
+ responseData = await slackApiRequest.call(
+ this,
+ 'POST',
+ '/files.completeUploadExternal',
+ body,
+ );
+ responseData = responseData.files;
}
- body.file = {
- value: uploadData,
- options: {
- filename: binaryData.fileName,
- contentType: binaryData.mimeType,
- },
- };
- responseData = await slackApiRequest.call(
- this,
- 'POST',
- '/files.upload',
- {},
- qs,
- { 'Content-Type': 'multipart/form-data' },
- { formData: body },
- );
- responseData = responseData.file;
} else {
const fileContent = this.getNodeParameter('fileContent', i) as string;
body.content = fileContent;