From 812cdaeace137b7d29f85bb50fce1dfa2f47f3f2 Mon Sep 17 00:00:00 2001 From: Beedataco <43684526+Beedataco@users.noreply.github.com> Date: Fri, 11 Feb 2022 08:52:24 -0500 Subject: [PATCH] BeeFlow 1 --- credentials/BeeFlowOmni.credentials.ts | 18 + credentials/ExampleCredentials.credentials.ts | 27 -- nodes/BeeFlowOmni/BeeFlowOmni.node.json | 20 + nodes/BeeFlowOmni/BeeFlowOmni.node.ts | 346 ++++++++++++++++++ nodes/BeeFlowOmni/BeeFlowOmni.png | Bin 0 -> 1188 bytes nodes/BeeFlowOmni/GenericFunctions.ts | 54 +++ nodes/ExampleNode/ExampleNode.node.ts | 57 --- package.json | 16 +- 8 files changed, 446 insertions(+), 92 deletions(-) create mode 100644 credentials/BeeFlowOmni.credentials.ts delete mode 100644 credentials/ExampleCredentials.credentials.ts create mode 100644 nodes/BeeFlowOmni/BeeFlowOmni.node.json create mode 100644 nodes/BeeFlowOmni/BeeFlowOmni.node.ts create mode 100644 nodes/BeeFlowOmni/BeeFlowOmni.png create mode 100644 nodes/BeeFlowOmni/GenericFunctions.ts delete mode 100644 nodes/ExampleNode/ExampleNode.node.ts diff --git a/credentials/BeeFlowOmni.credentials.ts b/credentials/BeeFlowOmni.credentials.ts new file mode 100644 index 0000000..c62af70 --- /dev/null +++ b/credentials/BeeFlowOmni.credentials.ts @@ -0,0 +1,18 @@ +import { + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class BeeFlowOmniKey implements ICredentialType { + name = 'BeeFlowOmniKey'; + displayName = 'BeeFlow Omni API Key'; + documentationUrl = 'BeeFlowOmni'; + properties: INodeProperties[] = [ + { + displayName: 'Authorization', + name: 'apiKey Authorization', + type: 'string', + default: '', + }, + ]; +} diff --git a/credentials/ExampleCredentials.credentials.ts b/credentials/ExampleCredentials.credentials.ts deleted file mode 100644 index 7e84255..0000000 --- a/credentials/ExampleCredentials.credentials.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { - ICredentialType, - NodePropertyTypes, -} from 'n8n-workflow'; - - -export class ExampleCredentials implements ICredentialType { - name = 'exampleCredentials'; - displayName = 'Example Credentials'; - properties = [ - // The credentials to get from user and save encrypted. - // Properties can be defined exactly in the same way - // as node properties. - { - displayName: 'User', - name: 'user', - type: 'string' as NodePropertyTypes, - default: '', - }, - { - displayName: 'Access Token', - name: 'accessToken', - type: 'string' as NodePropertyTypes, - default: '', - }, - ]; -} diff --git a/nodes/BeeFlowOmni/BeeFlowOmni.node.json b/nodes/BeeFlowOmni/BeeFlowOmni.node.json new file mode 100644 index 0000000..9d1a849 --- /dev/null +++ b/nodes/BeeFlowOmni/BeeFlowOmni.node.json @@ -0,0 +1,20 @@ +{ + "node": "n8n-nodes-base.BeeFlowOmni", + "nodeVersion": "1.0", + "codexVersion": "1.0", + "categories": [ + "Communication" + ], + "resources": { + "credentialDocumentation": [ + { + "url": "https://docs.n8n.io/credentials/sms77" + } + ], + "primaryDocumentation": [ + { + "url": "https://docs.n8n.io/nodes/n8n-nodes-base.sms77/" + } + ] + } +} diff --git a/nodes/BeeFlowOmni/BeeFlowOmni.node.ts b/nodes/BeeFlowOmni/BeeFlowOmni.node.ts new file mode 100644 index 0000000..535c809 --- /dev/null +++ b/nodes/BeeFlowOmni/BeeFlowOmni.node.ts @@ -0,0 +1,346 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + INodeExecutionData, + INodeType, + INodeTypeDescription, + NodeOperationError, +} from 'n8n-workflow'; + +import { + BeeFlowOmniRequest, +} from './GenericFunctions'; + +export class BeeFlowOmni implements INodeType { + description: INodeTypeDescription = { + displayName: 'BeeFlowOmni', + name: 'BeeFlowOmni', + icon: 'file:BeeFlowOmni.png', + group: ['transform'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Send SMS and make text-to-speech calls', + defaults: { + name: 'BeeFlowOmni', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'BeeFlowOmniKey', + required: true, + }, + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'SMS', + value: 'sms', + }, + { + name: 'Voice Call', + value: 'voice', + }, + ], + default: 'sms', + description: 'The resource to operate on.', + }, + + // operations + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'sms', + ], + }, + }, + options: [ + { + name: 'Send', + value: 'send', + description: 'Send SMS', + }, + ], + default: 'send', + description: 'The operation to perform', + }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'voice', + ], + }, + }, + options: [ + { + name: 'Send', + value: 'send', + description: 'Converts text to voice and calls a given number', + }, + ], + default: 'send', + description: 'The operation to perform', + }, + { + displayName: 'From', + name: 'from', + type: 'string', + default: '', + placeholder: '+573459876543', + required: false, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + ], + }, + }, + description: 'The caller ID displayed in the receivers display. Max 16 numeric or 11 alphanumeric characters', + }, + { + displayName: 'To', + name: 'to', + type: 'string', + default: '', + placeholder: '+573459876543, MyGroup', + required: true, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + 'voice', + ], + }, + }, + description: 'The number of your recipient(s) separated by comma. Can be regular numbers or contact/groups from BeeFlowOmni', + }, + { + displayName: 'Message', + name: 'message', + type: 'string', + default: '', + required: true, + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + 'voice', + ], + }, + }, + description: 'The message to send. Max. 1520 characters', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Opton', + default: {}, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + ], + }, + }, + options: [ + { + displayName: 'Debug', + name: 'debug', + type: 'boolean', + default: false, + description: 'If enabled, the API returns fake responses like in a sandbox', + }, + { + displayName: 'Delay', + name: 'delay', + type: 'dateTime', + default: '', + description: 'Pick a date for time delayed dispatch', + }, + { + displayName: 'Foreign ID', + name: 'foreign_id', + type: 'string', + default: '', + placeholder: 'MyCustomForeignID', + description: 'Custom foreign ID returned in DLR callbacks', + }, + { + displayName: 'Flash', + name: 'flash', + type: 'boolean', + default: false, + description: 'Send as flash message being displayed directly the receiver\'s display', + }, + { + displayName: 'Label', + name: 'label', + type: 'string', + default: '', + placeholder: 'MyCustomLabel', + description: 'Custom label used to group analytics', + }, + { + displayName: 'No Reload', + name: 'no_reload', + type: 'boolean', + default: false, + description: 'Disable reload lock to allow sending duplicate messages', + }, + { + displayName: 'Performance Tracking', + name: 'performance_tracking', + type: 'boolean', + default: false, + description: 'Enable performance tracking for URLs found in the message text', + }, + { + displayName: 'TTL', + name: 'ttl', + type: 'number', + default: 2880, + typeOptions: { + minValue: 1, + }, + description: 'Custom time to live specifying the validity period of a message in minutes', + }, + ], + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Opton', + default: {}, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'voice', + ], + }, + }, + options: [ + { + displayName: 'Debug', + name: 'debug', + type: 'boolean', + default: false, + description: 'If enabled, the API returns fake responses like in a sandbox', + }, + { + displayName: 'From', + name: 'from', + type: 'string', + default: '', + placeholder: '+4901234567890', + description: 'The caller ID. Please use only verified sender IDs, one of your virtual inbound numbers or one of our shared virtual numbers', + }, + { + displayName: 'XML', + name: 'xml', + type: 'boolean', + default: false, + description: 'Enable if text is of XML format', + }, + ], + }, + ], + }; + + async execute(this: IExecuteFunctions): Promise { + const returnData: IDataObject[] = []; + + for (let i = 0; i < this.getInputData().length; i++) { + const resource = this.getNodeParameter('resource', i); + const operation = this.getNodeParameter('operation', i); + let responseData; + try { + if (resource === 'sms') { + if (operation === 'send') { + const from = this.getNodeParameter('from', i) as string; + const to = this.getNodeParameter('to', i) as string; + const text = this.getNodeParameter('message', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body = { + "messages": [ + { + "from": from, + "destinations": [ + { + "to": to + } + ], + "text": text + } + ] +}; + responseData = await BeeFlowOmniRequest.call(this, 'POST', '/sms/2/text/advanced', body); + } + } + + if (resource === 'voice') { + if (operation === 'send') { + const to = this.getNodeParameter('to', i) as string; + const text = this.getNodeParameter('message', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + const body = { + to, + text, + ...options, + }; + responseData = await BeeFlowOmniRequest.call(this, 'POST', '/voice', body); + } + } + + if (Array.isArray(responseData)) { + returnData.push.apply(returnData, responseData as IDataObject[]); + } else if (responseData !== undefined) { + returnData.push(responseData as IDataObject); + } + + } catch (error) { + if (this.continueOnFail()) { + returnData.push({ error: error.message }); + continue; + } + throw error; + } + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/nodes/BeeFlowOmni/BeeFlowOmni.png b/nodes/BeeFlowOmni/BeeFlowOmni.png new file mode 100644 index 0000000000000000000000000000000000000000..500ba005ae607319db55ee5faf60847d2bc4bf87 GIT binary patch literal 1188 zcmV;V1Y7%wP)b?)N%R!`%B)D8`gF6{P!2ta}3jMrS8Zm*nRN) z_SpC5s_)BX;-Mhcco5WY2-0fh`tRHL>CpD#%k|&4@za#+zA@T^_Wk+i`talV?Vaqy zf#|V&=B{?;t7_w`#&q?C@tOqN%sM_Zpu}t(Vs$M?rWk7IPcB&O9xrzuMi*C^KyB5)Eb} zFz ziRXPq+}S?ht?x1qh6>$7Noi>%oe&`?5M|9o?Hd7J z6+r%ri&cb3+?m@Kl6{P0TTQL5vI2^&=`xWoXiiv{VX(_X$-a`_>$xw7?n)J4=bV-L@j2XOF4Is>fmwlGOUz7Dt_ikvbS)=&iDUWxoK%g+zbQMVog30000} + */ +export async function BeeFlowOmniRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, qs: IDataObject = {}): Promise { // tslint:disable-line:no-any + const credentials = await this.getCredentials('BeeFlowOmniKey'); + if (credentials === undefined) { + throw new NodeOperationError(this.getNode(), 'No credentials got returned!'); + } + + const options: OptionsWithUri = { + headers: { + SentWith: 'n8n', + 'X-Api-Key': credentials.apiKey, + }, + qs, + uri: `https://api2.iatechsas.com/${endpoint}`, + json: true, + method, + }; + + if (Object.keys(body).length) { + options.form = body; + body.json = 1; + } + + const response = await this.helpers.request(options); + + if (response.success !== '100') { + throw new NodeApiError(this.getNode(), response, { message: 'Invalid BeeFlowOmni credentials or API error!' }); + } + + return response; +} diff --git a/nodes/ExampleNode/ExampleNode.node.ts b/nodes/ExampleNode/ExampleNode.node.ts deleted file mode 100644 index df7d60c..0000000 --- a/nodes/ExampleNode/ExampleNode.node.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { IExecuteFunctions } from 'n8n-core'; -import { - INodeExecutionData, - INodeType, - INodeTypeDescription, -} from 'n8n-workflow'; - - -export class ExampleNode implements INodeType { - description: INodeTypeDescription = { - displayName: 'Example Node', - name: 'exampleNode', - group: ['transform'], - version: 1, - description: 'Basic Example Node', - defaults: { - name: 'Example Node', - color: '#772244', - }, - inputs: ['main'], - outputs: ['main'], - properties: [ - // Node properties which the user gets displayed and - // can change on the node. - { - displayName: 'My String', - name: 'myString', - type: 'string', - default: '', - placeholder: 'Placeholder value', - description: 'The description text', - }, - ], - }; - - - async execute(this: IExecuteFunctions): Promise { - - const items = this.getInputData(); - - let item: INodeExecutionData; - let myString: string; - - // Itterates over all input items and add the key "myString" with the - // value the parameter "myString" resolves to. - // (This could be a different value for each item in case it contains an expression) - for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { - myString = this.getNodeParameter('myString', itemIndex, '') as string; - item = items[itemIndex]; - - item.json['myString'] = myString; - } - - return this.prepareOutputData(items); - - } -} diff --git a/package.json b/package.json index 5fe4f72..6eb18fb 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,16 @@ { - "name": "n8n-nodes-starter", + "name": "n8n-nodes", "version": "0.1.0", - "description": "Example starter module for custom n8n nodes.", + "description": "Módulos BEE", "license": "SEE LICENSE IN LICENSE.md", - "homepage": "https://n8n.io", + "homepage": "beedata.co", "author": { - "name": "Jan Oberhauser", - "email": "jan@n8n.io" + "name": "Santiago Pino", + "email": "info@beedata.co" }, "repository": { "type": "git", - "url": "git+https://github.com/n8n-io/n8n-nodes-starter.git" + "url": "git+https://github.com/Beedataco/n8n-nodes.git" }, "main": "index.js", "scripts": { @@ -27,10 +27,10 @@ ], "n8n": { "credentials": [ - "dist/credentials/ExampleCredentials.credentials.js" + "dist/credentials/BeeFlowOmni.credentials.js" ], "nodes": [ - "dist/nodes/ExampleNode/ExampleNode.node.js" + "dist/nodes/BeeFlowOmni/BeeFlowOmni.node.js" ] }, "devDependencies": {