From 2d3f02e32c422acbdf268070557b72866d435dd0 Mon Sep 17 00:00:00 2001 From: ricardo Date: Tue, 5 May 2020 13:22:02 -0400 Subject: [PATCH] :zap: added interactive messages (buttons) --- .../nodes/Slack/GenericFunctions.ts | 10 + packages/nodes-base/nodes/Slack/Slack.node.ts | 1219 ++++++++++++++++- 2 files changed, 1211 insertions(+), 18 deletions(-) create mode 100644 packages/nodes-base/nodes/Slack/GenericFunctions.ts diff --git a/packages/nodes-base/nodes/Slack/GenericFunctions.ts b/packages/nodes-base/nodes/Slack/GenericFunctions.ts new file mode 100644 index 0000000000..99b3d726ca --- /dev/null +++ b/packages/nodes-base/nodes/Slack/GenericFunctions.ts @@ -0,0 +1,10 @@ + +export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any + let result; + try { + result = JSON.parse(json!); + } catch (exception) { + result = undefined; + } + return result; +} diff --git a/packages/nodes-base/nodes/Slack/Slack.node.ts b/packages/nodes-base/nodes/Slack/Slack.node.ts index c20f8ba12b..2b5ad83142 100644 --- a/packages/nodes-base/nodes/Slack/Slack.node.ts +++ b/packages/nodes-base/nodes/Slack/Slack.node.ts @@ -1,4 +1,7 @@ -import { IExecuteFunctions } from 'n8n-core'; +import { + IExecuteFunctions, + } from 'n8n-core'; + import { IDataObject, INodeTypeDescription, @@ -6,12 +9,50 @@ import { INodeType, } from 'n8n-workflow'; +import { + validateJSON, +} from './GenericFunctions'; + interface Attachment { fields: { item?: object[]; }; } +interface Text { + type?: string; + text?: string; + emoji?: boolean; + verbatim?: boolean; +} + +interface Confirm { + title?: Text; + text?: Text; + confirm?: Text; + deny?: Text; + style?: string; +} + +interface Element { + type?: string; + text?: Text; + action_id?: string; + url?: string; + value?: string; + style?: string; + confirm?: Confirm; +} + +interface Block { + type?: string; + elements?: Element[]; + block_id?: string; + text?: Text; + fields?: Text[]; + accessory?: Element; +} + export class Slack implements INodeType { description: INodeTypeDescription = { displayName: 'Slack', @@ -262,6 +303,22 @@ export class Slack implements INodeType { }, description: 'Set the bot\'s user name.', }, + { + displayName: 'JSON parameters', + name: 'jsonParameters', + type: 'boolean', + default: false, + displayOptions: { + show: { + operation: [ + 'post' + ], + resource: [ + 'message', + ], + }, + }, + }, { displayName: 'Attachments', name: 'attachments', @@ -278,10 +335,13 @@ export class Slack implements INodeType { resource: [ 'message', ], + jsonParameters: [ + false, + ], }, }, default: {}, // TODO: Remove comment: has to make default array for the main property, check where that happens in UI - description: 'The attachment to add', + description: 'The attachments to add', placeholder: 'Add attachment item', options: [ { @@ -457,6 +517,926 @@ export class Slack implements INodeType { } ], }, + { + displayName: 'Blocks', + name: 'blocksUi', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + multipleValueButtonText: 'Add Block', + }, + displayOptions: { + show: { + operation: [ + 'post' + ], + resource: [ + 'message', + ], + jsonParameters: [ + false, + ], + }, + }, + default: {}, + description: 'The blocks to add', + placeholder: 'Add Block', + options: [ + { + name: 'blocksValues', + displayName: 'Block', + values: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'Actions', + value: 'actions', + }, + { + name: 'Section', + value: 'section', + }, + ], + default: 'actions', + }, + { + displayName: 'Block ID', + name: 'blockId', + type: 'string', + displayOptions: { + show: { + type: [ + 'actions', + ], + }, + }, + default: '', + description: `A string acting as a unique identifier for a block.
+ You can use this block_id when you receive an interaction payload to
+ identify the source of the action. If not specified, a block_id will be generated.
+ Maximum length for this field is 255 characters.`, + }, + { + displayName: 'Elements', + name: 'elementsUi', + placeholder: 'Add Element', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + type: [ + 'actions', + ], + }, + }, + default: {}, + options: [ + { + name: 'elementsValues', + displayName: 'Element', + values: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'Button', + value: 'button', + }, + ], + default: 'button', + description: 'The type of element', + }, + { + displayName: 'Text', + name: 'text', + type: 'string', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + default: '', + description: 'The text for the block.', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format.', + }, + { + displayName: 'Action ID', + name: 'actionId', + type: 'string', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + default: '', + description: `An identifier for this action. You can use this when you receive an interaction
+ payload to identify the source of the action. Should be unique among all other action_ids used
+ elsewhere by your app. `, + }, + { + displayName: 'URL', + name: 'url', + type: 'string', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + default: '', + description: `A URL to load in the user's browser when the button is clicked.
+ Maximum length for this field is 3000 characters. If you're using url, you'll still
+ receive an interaction payload and will need to send an acknowledgement response.`, + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + default: '', + description: 'The value to send along with the interaction payload.', + }, + { + displayName: 'Style', + name: 'style', + type: 'options', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + options: [ + { + name: 'Danger', + value: 'danger', + }, + { + name: 'Default', + value: 'default', + }, + { + name: 'Primary', + value: 'primary', + }, + ], + default: 'default', + description: 'Decorates buttons with alternative visual color schemes.', + }, + { + displayName: 'Confirm', + name: 'confirmUi', + placeholder: 'Add Confirm', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'confirmValue', + displayName: 'Confirm', + values: [ + { + displayName: 'Title', + name: 'titleUi', + placeholder: 'Add Title', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'titleValue', + displayName: 'Title', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'Text of the title.', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: `Defines the dialog's title.`, + }, + { + displayName: 'Text', + name: 'textUi', + placeholder: 'Add Text', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'textValue', + displayName: 'Text', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'The text for the block', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: `Defines the explanatory text that appears in the confirm dialog.`, + }, + { + displayName: 'Confirm', + name: 'confirmTextUi', + placeholder: 'Add Confirm', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'confirmValue', + displayName: 'Confirm', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: `Defines the explanatory text that appears in the confirm dialog.`, + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: 'Defines the text of the button that confirms the action', + }, + { + displayName: 'Deny', + name: 'denyUi', + placeholder: 'Add Deny', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'denyValue', + displayName: 'Deny', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'Defines the text of the button that cancels the action', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: 'Defines the text of the button that cancels the action', + }, + { + displayName: 'Style', + name: 'style', + type: 'options', + options: [ + { + name: 'Danger', + value: 'danger', + }, + { + name: 'Default', + value: 'default', + }, + { + name: 'Primary', + value: 'primary', + }, + ], + default: 'default', + description: 'Defines the color scheme applied to the confirm button.', + }, + ], + }, + ], + description: 'Defines an optional confirmation dialog after the button is clicked.', + }, + ], + }, + ], + }, + { + displayName: 'Block ID', + name: 'blockId', + type: 'string', + displayOptions: { + show: { + type: [ + 'section', + ], + }, + }, + default: '', + description: `A string acting as a unique identifier for a block.
+ You can use this block_id when you receive an interaction payload to
+ identify the source of the action. If not specified, a block_id will be generated.
+ Maximum length for this field is 255 characters.`, + }, + { + displayName: 'Text', + name: 'textUi', + placeholder: 'Add Text', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + displayOptions: { + show: { + type: [ + 'section', + ], + }, + }, + default: {}, + options: [ + { + name: 'textValue', + displayName: 'Text', + values: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'Markdowm', + value: 'mrkwdn', + }, + { + name: 'Plain Text', + value: 'plainText', + }, + ], + default: 'mrkwdn', + description: 'The formatting to use for this text object.', + }, + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'The text for the block. This field accepts any of the standard text formatting markup when type is mrkdwn.', + }, + { + displayName: 'Emoji', + name: 'emoji', + displayOptions: { + show: { + type: [ + 'plainText', + ], + }, + }, + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format. This field is only usable when type is plain_text.', + }, + { + displayName: 'Verbatim', + name: 'verbatim', + displayOptions: { + show: { + type: [ + 'mrkwdn', + ], + }, + }, + type: 'boolean', + default: false, + description: 'When set to false (as is default) URLs will be auto-converted into links, conversation names will be link-ified, and certain mentions will be automatically parsed. ', + }, + ], + }, + ], + description: 'Define the text of the button that cancels the action', + }, + { + displayName: 'Fields', + name: 'fieldsUi', + placeholder: 'Add Fields', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + type: [ + 'section', + ], + }, + }, + default: {}, + options: [ + { + name: 'fieldsValues', + displayName: 'Text', + values: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'Markdowm', + value: 'mrkwdn', + }, + { + name: 'Plain Text', + value: 'plainText', + }, + ], + default: 'mrkwdn', + description: 'The formatting to use for this text object.', + }, + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'The text for the block. This field accepts any of the standard text formatting markup when type is mrkdwn.', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + displayOptions: { + show: { + type: [ + 'plainText', + ], + }, + }, + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format. This field is only usable when type is plain_text.', + }, + { + displayName: 'Verbatim', + name: 'verbatim', + displayOptions: { + show: { + type: [ + 'mrkwdn', + ], + }, + }, + type: 'boolean', + default: false, + description: 'When set to false (as is default) URLs will be auto-converted into links, conversation names will be link-ified, and certain mentions will be automatically parsed. ', + }, + ], + }, + ], + description: `An array of text objects. Any text objects included with
+ fields will be rendered in a compact format that allows for 2 columns of
+ side-by-side text. Maximum number of items is 10.`, + }, + { + displayName: 'Accessory', + name: 'accessoryUi', + placeholder: 'Add Accessory', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + displayOptions: { + show: { + type: [ + 'section', + ], + }, + }, + default: {}, + options: [ + { + name: 'accessoriesValues', + displayName: 'Accessory', + values: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'Button', + value: 'button', + }, + ], + default: 'button', + description: 'The type of element', + }, + { + displayName: 'Text', + name: 'text', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + type: 'string', + default: '', + description: 'The text for the block.', + }, + { + displayName: 'Emoji', + name: 'emoji', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format.', + }, + { + displayName: 'Action ID', + name: 'actionId', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + type: 'string', + default: '', + description: `An identifier for this action. You can use this when you receive an interaction
+ payload to identify the source of the action. Should be unique among all other action_ids used
+ elsewhere by your app. `, + }, + { + displayName: 'URL', + name: 'url', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + type: 'string', + default: '', + description: `A URL to load in the user's browser when the button is clicked.
+ Maximum length for this field is 3000 characters. If you're using url, you'll still
+ receive an interaction payload and will need to send an acknowledgement response.`, + }, + { + displayName: 'Value', + name: 'value', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + type: 'string', + default: '', + description: 'The value to send along with the interaction payload.', + }, + { + displayName: 'Style', + name: 'style', + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + type: 'options', + options: [ + { + name: 'Danger', + value: 'danger', + }, + { + name: 'Default', + value: 'default', + }, + { + name: 'Primary', + value: 'primary', + }, + ], + default: 'default', + description: 'Decorates buttons with alternative visual color schemes.', + }, + { + displayName: 'Confirm', + name: 'confirmUi', + placeholder: 'Add Confirm', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + displayOptions: { + show: { + type: [ + 'button', + ], + }, + }, + default: {}, + options: [ + { + name: 'confirmValue', + displayName: 'Confirm', + values: [ + { + displayName: 'Title', + name: 'titleUi', + placeholder: 'Add Title', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'titleValue', + displayName: 'Title', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'Text of the title.', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: 'Defines an optional confirmation dialog after the button is clicked.', + }, + { + displayName: 'Text', + name: 'textUi', + placeholder: 'Add Text', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'textValue', + displayName: 'Text', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'The text for the block', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: `Defines the explanatory text that appears in the confirm dialog.`, + }, + { + displayName: 'Confirm', + name: 'confirmTextUi', + placeholder: 'Add Confirm', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'confirmValue', + displayName: 'Confirm', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: `Defines the explanatory text that appears in the confirm dialog.`, + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: `Defines the explanatory text that appears in the confirm dialog.`, + }, + { + displayName: 'Deny', + name: 'denyUi', + placeholder: 'Add Deny', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, + }, + default: {}, + options: [ + { + name: 'denyValue', + displayName: 'Deny', + values: [ + { + displayName: 'Text', + name: 'text', + type: 'string', + default: '', + description: 'Define the text of the button that cancels the action', + }, + { + displayName: 'Emoji', + name: 'emoji', + type: 'boolean', + default: false, + description: 'Indicates whether emojis in a text field should be escaped into the colon emoji format', + }, + ], + }, + ], + description: 'Define the text of the button that cancels the action', + }, + { + displayName: 'Style', + name: 'style', + type: 'options', + options: [ + { + name: 'Danger', + value: 'danger', + }, + { + name: 'Default', + value: 'default', + }, + { + name: 'Primary', + value: 'primary', + }, + ], + default: 'default', + description: 'Defines the color scheme applied to the confirm button.', + }, + ], + }, + ], + description: 'Defines an optional confirmation dialog after the button is clicked.', + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + displayName: 'Attachments', + name: 'attachmentsJson', + type: 'json', + default: '', + required: false, + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'message', + ], + operation: [ + 'post', + ], + jsonParameters: [ + true, + ], + }, + }, + description: 'The attachments to add', + }, + { + displayName: 'Blocks', + name: 'blocksJson', + type: 'json', + default: '', + required: false, + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'message', + ], + operation: [ + 'post', + ], + jsonParameters: [ + true, + ], + }, + }, + description: 'The blocks to add', + }, { displayName: 'Other Options', name: 'otherOptions', @@ -562,8 +1542,6 @@ export class Slack implements INodeType { ], }; - - async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); const returnData: IDataObject[] = []; @@ -625,28 +1603,233 @@ export class Slack implements INodeType { body.channel = this.getNodeParameter('channel', i) as string; body.text = this.getNodeParameter('text', i) as string; body.as_user = this.getNodeParameter('as_user', i) as boolean; + const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean; + if (body.as_user === false) { body.username = this.getNodeParameter('username', i) as string; } - const attachments = this.getNodeParameter('attachments', i, []) as unknown as Attachment[]; + if (!jsonParameters) { + const attachments = this.getNodeParameter('attachments', i, []) as unknown as Attachment[]; + const blocksUi = (this.getNodeParameter('blocksUi', i, []) as IDataObject).blocksValues as IDataObject[]; - // The node does save the fields data differently than the API - // expects so fix the data befre we send the request - for (const attachment of attachments) { - if (attachment.fields !== undefined) { - if (attachment.fields.item !== undefined) { - // Move the field-content up - // @ts-ignore - attachment.fields = attachment.fields.item; - } else { - // If it does not have any items set remove it - delete attachment.fields; + + // The node does save the fields data differently than the API + // expects so fix the data befre we send the request + for (const attachment of attachments) { + if (attachment.fields !== undefined) { + if (attachment.fields.item !== undefined) { + // Move the field-content up + // @ts-ignore + attachment.fields = attachment.fields.item; + } else { + // If it does not have any items set remove it + delete attachment.fields; + } } } - } - body['attachments'] = attachments; + body['attachments'] = attachments; + if (blocksUi) { + const blocks: Block[] = []; + for (const blockUi of blocksUi) { + const block: Block = {}; + const elements: Element[] = []; + block.block_id = blockUi.blockId as string; + block.type = blockUi.type as string; + if (block.type === 'actions') { + const elementsUi = (blockUi.elementsUi as IDataObject).elementsValues as IDataObject[]; + if (elementsUi) { + for (const elementUi of elementsUi) { + const element: Element = {}; + if (elementUi.actionId === '') { + throw new Error('Action ID must be set'); + } + if (elementUi.text === '') { + throw new Error('Text must be set'); + } + element.action_id = elementUi.actionId as string; + element.type = elementUi.type as string; + element.text = { + text: elementUi.text as string, + type: 'plain_text', + emoji: elementUi.emoji as boolean, + }; + if (elementUi.url) { + element.url = elementUi.url as string; + } + if (elementUi.value) { + element.value = elementUi.value as string; + } + if (elementUi.style !== 'default') { + element.style = elementUi.style as string; + } + const confirmUi = (elementUi.confirmUi as IDataObject).confirmValue as IDataObject; + if (confirmUi) { + const confirm: Confirm = {}; + const titleUi = (confirmUi.titleUi as IDataObject).titleValue as IDataObject; + const textUi = (confirmUi.textUi as IDataObject).textValue as IDataObject; + const confirmTextUi = (confirmUi.confirmTextUi as IDataObject).confirmValue as IDataObject; + const denyUi = (confirmUi.denyUi as IDataObject).denyValue as IDataObject; + const style = confirmUi.style as string; + if (titleUi) { + confirm.title = { + type: 'plain_text', + text: titleUi.text as string, + emoji: titleUi.emoji as boolean, + }; + } + if (textUi) { + confirm.text = { + type: 'plain_text', + text: textUi.text as string, + emoji: textUi.emoji as boolean, + }; + } + if (confirmTextUi) { + confirm.confirm = { + type: 'plain_text', + text: confirmTextUi.text as string, + emoji: confirmTextUi.emoji as boolean, + }; + } + if (denyUi) { + confirm.deny = { + type: 'plain_text', + text: denyUi.text as string, + emoji: denyUi.emoji as boolean, + }; + } + if (style !== 'default') { + confirm.style = style as string; + } + element.confirm = confirm; + } + elements.push(element); + } + block.elements = elements; + } + } else if (block.type === 'section') { + const textUi = (blockUi.textUi as IDataObject).textValue as IDataObject; + if (textUi) { + const text: Text = {}; + if (textUi.type === 'plainText') { + text.type = 'plain_text'; + text.emoji = textUi.emoji as boolean; + } else { + text.type = 'mrkdwn'; + text.verbatim = textUi.verbatim as boolean; + } + text.text = textUi.text as string; + block.text = text; + } else { + throw new Error('Property text must be defined'); + } + const fieldsUi = (blockUi.fieldsUi as IDataObject).fieldsValues as IDataObject[]; + if (fieldsUi) { + const fields: Text[] = []; + for (const fieldUi of fieldsUi) { + const field: Text = {}; + if (fieldUi.type === 'plainText') { + field.type = 'plain_text'; + field.emoji = fieldUi.emoji as boolean; + } else { + field.type = 'mrkdwn'; + field.verbatim = fieldUi.verbatim as boolean; + } + field.text = fieldUi.text as string; + fields.push(field); + } + // If not fields were added then it's not needed to send the property + if (fields.length > 0) { + block.fields = fields; + } + } + const accessoryUi = (blockUi.accessoryUi as IDataObject).accessoriesValues as IDataObject; + if (accessoryUi) { + const accessory: Element = {}; + if (accessoryUi.type === 'button') { + accessory.type = 'button'; + accessory.text = { + text: accessoryUi.text as string, + type: 'plain_text', + emoji: accessoryUi.emoji as boolean, + }; + if (accessoryUi.url) { + accessory.url = accessoryUi.url as string; + } + if (accessoryUi.value) { + accessory.value = accessoryUi.value as string; + } + if (accessoryUi.style !== 'default') { + accessory.style = accessoryUi.style as string; + } + const confirmUi = (accessoryUi.confirmUi as IDataObject).confirmValue as IDataObject; + if (confirmUi) { + const confirm: Confirm = {}; + const titleUi = (confirmUi.titleUi as IDataObject).titleValue as IDataObject; + const textUi = (confirmUi.textUi as IDataObject).textValue as IDataObject; + const confirmTextUi = (confirmUi.confirmTextUi as IDataObject).confirmValue as IDataObject; + const denyUi = (confirmUi.denyUi as IDataObject).denyValue as IDataObject; + const style = confirmUi.style as string; + if (titleUi) { + confirm.title = { + type: 'plain_text', + text: titleUi.text as string, + emoji: titleUi.emoji as boolean, + }; + } + if (textUi) { + confirm.text = { + type: 'plain_text', + text: textUi.text as string, + emoji: textUi.emoji as boolean, + }; + } + if (confirmTextUi) { + confirm.confirm = { + type: 'plain_text', + text: confirmTextUi.text as string, + emoji: confirmTextUi.emoji as boolean, + }; + } + if (denyUi) { + confirm.deny = { + type: 'plain_text', + text: denyUi.text as string, + emoji: denyUi.emoji as boolean, + }; + } + if (style !== 'default') { + confirm.style = style as string; + } + accessory.confirm = confirm; + } + } + block.accessory = accessory; + } + } + blocks.push(block); + } + body.blocks = blocks; + } + + } else { + const attachmentsJson = this.getNodeParameter('attachmentsJson', i, []) as string; + const blocksJson = this.getNodeParameter('blocksJson', i, []) as string; + if (attachmentsJson !== '' && validateJSON(attachmentsJson) === undefined) { + throw new Error('Attachments it is not a valid json'); + } + if (blocksJson !== '' && validateJSON(blocksJson) === undefined) { + throw new Error('Blocks it is not a valid json'); + } + if (attachmentsJson !== '') { + body.attachments = attachmentsJson; + } + if (blocksJson !== '') { + body.blocks = blocksJson; + } + } // Add all the other options to the request const otherOptions = this.getNodeParameter('otherOptions', i) as IDataObject; Object.assign(body, otherOptions);