From 896e64f8d2dafa0181520452df019efddd39d48b Mon Sep 17 00:00:00 2001 From: d3no Date: Wed, 12 Feb 2020 15:52:36 +0800 Subject: [PATCH] Commit Mocean node --- .../nodes/Mocean/GenericFunctions.ts | 68 +++++ .../nodes-base/nodes/Mocean/Mocean.node.ts | 233 ++++++++++++++++++ .../nodes/Mocean/MoceanApi.credentials.ts | 27 ++ packages/nodes-base/nodes/Mocean/logo.png | Bin 0 -> 1833 bytes 4 files changed, 328 insertions(+) create mode 100644 packages/nodes-base/nodes/Mocean/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Mocean/Mocean.node.ts create mode 100644 packages/nodes-base/nodes/Mocean/MoceanApi.credentials.ts create mode 100644 packages/nodes-base/nodes/Mocean/logo.png diff --git a/packages/nodes-base/nodes/Mocean/GenericFunctions.ts b/packages/nodes-base/nodes/Mocean/GenericFunctions.ts new file mode 100644 index 0000000000..4dfdf415e4 --- /dev/null +++ b/packages/nodes-base/nodes/Mocean/GenericFunctions.ts @@ -0,0 +1,68 @@ +import { + IExecuteFunctions, + IHookFunctions, +} from 'n8n-core'; + +import { + IDataObject, +} from 'n8n-workflow'; + +/** + * Make an API request to Twilio + * + * @param {IHookFunctions} this + * @param {string} method + * @param {string} url + * @param {object} body + * @returns {Promise} + */ +export async function moceanApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('moceanApi'); + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + if (query === undefined) { + query = {}; + } + + if (method === 'POST') { + body['mocean-api-key'] = credentials['mocean-api-key']; + body['mocean-api-secret'] = credentials['mocean-api-secret']; + body['mocean-resp-format'] = 'JSON'; + } else if(method === 'GET') { + query['mocean-api-key'] = credentials['mocean-api-key']; + query['mocean-api-secret'] = credentials['mocean-api-secret']; + query['mocean-resp-format'] = 'JSON'; + } + console.log(body); + const options = { + method, + form: body, + qs: query, + uri: `https://rest.moceanapi.com${endpoint}`, + json: true + }; + + try { + return await this.helpers.request(options); + } catch (error) { + if (error.statusCode === 401) { + // Return a clear error + throw new Error('Authentication fail.'); + } + + if (error.response && error.response.body && error.response.body.message) { + // Try to return the error prettier + let errorMessage = `Twilio error response [${error.statusCode}]: ${error.response.body.message}`; + if (error.response.body.more_info) { + errorMessage = `errorMessage (${error.response.body.more_info})`; + } + + throw new Error(errorMessage); + } + + // If that data does not exist for some reason return the actual error + throw error; + } +} \ No newline at end of file diff --git a/packages/nodes-base/nodes/Mocean/Mocean.node.ts b/packages/nodes-base/nodes/Mocean/Mocean.node.ts new file mode 100644 index 0000000000..33a2b1fd91 --- /dev/null +++ b/packages/nodes-base/nodes/Mocean/Mocean.node.ts @@ -0,0 +1,233 @@ +import { IExecuteFunctions } from 'n8n-core'; +import { + IDataObject, + INodeExecutionData, + INodeType, + INodeTypeDescription, +} from 'n8n-workflow'; + +import {moceanApiRequest} from './GenericFunctions'; + + +export class Mocean implements INodeType { + description: INodeTypeDescription = { + displayName: 'Mocean', + name: 'mocean', + icon: 'file:logo.png', + group: ['transform'], + version: 1, + description: 'This is the official node created from Mocean', + defaults: { + name: 'Mocean', + color: '#772244', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: "moceanApi", + required: true + } + ], + properties: [ + // Node properties which the user gets displayed and + // can change on the node. + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options:[ + { + name: "SMS", + value: "sms" + }, + { + name: "Voice", + value: "voice" + } + ], + default: 'sms', + }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'sms', + 'voice' + ], + }, + }, + options: [ + { + name: 'Send', + value: 'send', + description: 'Send SMS/Voice message', + }, + ], + default: 'send', + description: 'The operation to perform.', + }, + { + displayName: 'From', + name: 'from', + type: 'string', + default: '', + placeholder: 'Sender Number', + required: true, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + 'voice', + ], + }, + }, + description: 'The number to which to send the message', + }, + + { + displayName: 'To', + name: 'to', + type: 'string', + default: '', + placeholder: 'Receipient number', + required: true, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + 'voice', + ], + }, + }, + description: 'The number from which to send the message', + }, + + { + displayName: 'Language', + name: 'language', + type: 'options', + options:[ + { + name: "English (United States)", + value: "en-US" + }, + { + name: "English (United Kingdom)", + value: "en-GB" + }, + { + name: "Chinese Mandarin (China", + value: "cmn-CN" + }, + { + name: "Japanese (Japan)", + value: "ja-JP" + }, + { + name: "Korean (Korea)", + value: "ko-KR" + } + ], + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'voice', + ], + }, + }, + default: 'en-US', + }, + + { + displayName: 'Message', + name: 'message', + type: 'string', + default: '', + placeholder: '', + required: true, + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + 'voice', + ], + }, + }, + description: 'The message to send', + }, + ], + + }; + + + async execute(this: IExecuteFunctions): Promise { + + const items = this.getInputData(); + let item: INodeExecutionData; + let returnData: IDataObject[] = []; + + let endpoint: string; + let operation: string; + let requesetMethod: string; + let resource: string; + let text: string; + // For Post + let body: IDataObject; + // For Query string + let qs: IDataObject; + + + for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { + body = {}; + qs = {}; + + resource = this.getNodeParameter('resource', itemIndex, '') as string; + operation = this.getNodeParameter('operation',itemIndex,'') as string; + text = this.getNodeParameter('message', itemIndex, '') as string; + requesetMethod = 'POST'; + body['mocean-from'] = this.getNodeParameter('from', itemIndex, '') as string; + body['mocean-to'] = this.getNodeParameter('to', itemIndex, '') as string; + + + if (resource === 'voice') { + let language: string = this.getNodeParameter("language",itemIndex) as string; + let command:any = [{"action": "say", "language": `${language}`, "text": `${text}`}]; + + body['mocean-command'] = JSON.stringify(command); + endpoint = '/rest/2/voice/dial'; + } else if(resource === 'sms') { + body['mocean-text'] = text; + endpoint = '/rest/2/sms'; + } else { + throw new Error(`Unknown resource ${resource}`); + } + + if (operation === "send") { + const responseData = await moceanApiRequest.call(this,requesetMethod,endpoint,body,qs); + returnData.push(responseData as IDataObject); + } else { + throw new Error(`Unknown operation ${operation}`); + } + + + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/Mocean/MoceanApi.credentials.ts b/packages/nodes-base/nodes/Mocean/MoceanApi.credentials.ts new file mode 100644 index 0000000000..fb46b2d224 --- /dev/null +++ b/packages/nodes-base/nodes/Mocean/MoceanApi.credentials.ts @@ -0,0 +1,27 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + + +export class MoceanApi implements ICredentialType { + name = 'moceanApi'; + displayName = 'Mocean Api'; + properties = [ + // The credentials to get from user and save encrypted. + // Properties can be defined exactly in the same way + // as node properties. + { + displayName: 'API Key', + name: 'mocean-api-key', + type: 'string' as NodePropertyTypes, + default: '', + }, + { + displayName: 'API Secret', + name: 'mocean-api-secret', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Mocean/logo.png b/packages/nodes-base/nodes/Mocean/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5368d5f0b4c05e4dd27ad11560c880b384f60248 GIT binary patch literal 1833 zcmV+^2iEwBP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn z4jTXf0AG4kSaechcOY9y8Ey_$*C@9KL%gjmT zQUC*E6D|`=6HB8+0|NsK0|+oQFfcX*l14zbIaDao00o$so23DvxmmKADTvPn08hFV zXd5lqi~s-zLrFwIRA@u(T4`)lRTTba=}e)EP?jRQfwt0u(t>P3p|Y6@f}#k${lA%fZW`q022taliM^$vru-eC~dI}E~lhe25HFbL}% z24TI!Agp&7g!K-Cu-@^|5jM?Ulj~iuIS)3g88NNGaeB>Q-;#!)ft$EyL3OnYD`s@Z zq#@C2e(CoGn6oYy6_+a1d+_sdPex+v+}?<5+d!KmF5alZl%+X1bmmVuYTYoI09Ty{ zQ7yuezfODB#=XT@^4(dSyIcYPzXhtQTv$A%E2a+<2 zTLC66IfB)@is1Elv2uD3OdJxW=Jy`Ih5_&I0r*VMp)oMmxjjIQ8*UorAYF>T8v#x_SrBD|b{N1j9c%faIC`aN_h$R9=;JZGbjql}=^jN9yWa^&Gj(T76Q@ z`QdbV;FW-y&6t#$<(s9Y*pnX|b?V-1HuGvR!6L78d|Adh&5~ID1MfqFv^Cn;NzPU0 z#>UNza)V&RcW4Z6&RBR4zJcqEI3ymCp?GfAKK1$D@9hSfg~A#fg#2y8;XF1Lj-wnW z#-n`K2o#h2_U#40BX%V9ZG)TpUPt-C(J0Ltja$dZVfLtwY9GOt{l5beaQ>O=S&{b5 z8Q+Qq#e>5lMM^)%FFLH|#b=q<7I>?!gvy=Wie*C5hxM67F!KXSW*osb3+2ZLhueWW zPVD)jpJqrzM%2TC3Gvjc8zq#vWYAki1yFt~r*%^@58^{*4;f~LJB<<)vS7Jnewv6T z3}SeQO-Z#8pJAt+A2ZWV@ao0pIlZ+Bl32B?P`meoDs9;`M3vWCN?%H+o?Z4(>=ZP@ zbaHTy7D_IKr*EjK+@jmck&s|3y2mzVbUm;z%jcODhEvrS_9gWy z?-QaM`7G{7;T6_DgJ5eI3{#i2FeR+HH=>tg-uhF@u88u!TtI*5_o!#vB4uQ(BAlXv z5CAG5szn&4zsmJs3leAijMkA1Kmatt+(@GTN}tv$I-7pEfb^e=)u!W;+M}BF>xX3K z-(gY>N=1-+*R$Of(tW6P(#F4?WK-nlAAD~WDH1bQl2}L(9%taC2}LqMQex%o2|4UD zfw);#gT<4(Fxx=(;Vby|*NfbXf%oCACt~={&=_@}wzH7Zy+CKZn9OchBF%}ONz-cA zJWOR9R@2{_N?viP3YavwL0unZCt;xIn7=_ih&HTu$%^xK4ZMfng!kx}dn11$<|RL& z>~>JP*7`v>d%g?!w<%%%9oslJW(WJQJtQ|w93mVdJsQ@s9;J~C8OpPm0ok8(4W^#y2;os= z@0G4>aJ>>4^ZTgJWi09s+^EDQ9y5{sH^CIo+LX~L4dH{gqGxOq^m>M6sK&PU%l_ESW_fbe^MELiQvaB>9x7Sn^IZYQ>W{Sdlse#H zGn0lUFgxXp<*2CAbzX4-YCCJU<3K)f_RMBHgRtIV5Y{^k!g_~6Snn_h>m3GRy~7}^ZvcM* Xq(*?jdKNqp00000NkvXXu0mjfPl00L literal 0 HcmV?d00001