feat(Slack Node): Update to use the new API method for file uploads (#9323)

This commit is contained in:
Jon 2024-05-08 10:40:24 +01:00 committed by GitHub
parent 435272b568
commit 695e762663
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 120 additions and 24 deletions

View file

@ -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);

View file

@ -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 <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
},
{
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 <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
},
{
displayName: 'File Name',
name: 'fileName',

View file

@ -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),

View file

@ -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;