From 6f7390467d77688ab7163016b26fb445b563ac79 Mon Sep 17 00:00:00 2001 From: chughts Date: Thu, 18 May 2017 10:33:15 +0100 Subject: [PATCH 01/16] Tone Analysis Node was not allowing json as input --- utilities/tone-utils.js | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/utilities/tone-utils.js b/utilities/tone-utils.js index 1c2342ba..8b9f9494 100644 --- a/utilities/tone-utils.js +++ b/utilities/tone-utils.js @@ -17,28 +17,38 @@ function ToneUtils () { } - ToneUtils.prototype = { check: function () { return '"IBM Watson Node-RED Utilities for Tone Analyser'; }, + isJsonString: function(str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + }, + + isJsonObject: function(str) { + if (str instanceof Array || str instanceof Object) { + return true; + } + return false; + }, + // Function that checks the payload and determines // whether it is JSON or a Buffer checkPayload: function(payload) { var message = null; var isBuffer = false; - var hasJSONmethod = (typeof payload.toJSON === 'function') ; + var isJSON = this.isJsonString(payload) || this.isJsonObject(payload); - if (hasJSONmethod === true) { - if (payload.toJSON().type === 'Buffer') { - isBuffer = true; - } - } // Payload (text to be analysed) must be a string (content is either raw string or Buffer) - if (typeof payload !== 'string' && isBuffer !== true) { - message = 'The payload must be either a string or a Buffer'; + if (typeof payload !== 'string' && isJSON !== true) { + message = 'The payload must be either a string or a JSON Buffer'; } return message; @@ -50,7 +60,7 @@ ToneUtils.prototype = { parseToneOption: function(msg, config) { var tones = msg.tones || config.tones; - return (tones === 'all' ? '' : tones); + return (tones === 'all' ? '' : tones); }, // function to parse through the options in preparation @@ -58,17 +68,19 @@ ToneUtils.prototype = { parseOptions: function(msg, config) { var options = { 'text': msg.payload, - 'sentences': msg.sentences || config.sentences, - 'isHTML': msg.contentType || config.contentType + 'sentences': msg.sentences || config.sentences, + 'isHTML': msg.contentType || config.contentType }; + if (this.isJsonObject(msg.payload)) { + options.text = JSON.stringify(msg.payload); + } options.tones = this.parseToneOption(msg, config); return options; } - }; var toneutils = new ToneUtils(); -module.exports = toneutils; \ No newline at end of file +module.exports = toneutils; From 67d1c0e9b40a3e3e3cf37637c484561c7721066f Mon Sep 17 00:00:00 2001 From: chughts Date: Thu, 18 May 2017 10:35:11 +0100 Subject: [PATCH 02/16] Bump Version Number --- README.md | 3 +++ package.json | 2 +- services/language_translator_identify/v2.html | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92c7df9f..95380c2c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Node-RED Watson Nodes for IBM Bluemix CLA assistant +### New in version 0.5.7 +- Fix to Tone Analyzer to allow JSON as input + ### New in version 0.5.6 - User Agent added to following nodes: Conversation, Conversation Workspace Manager, Discovery, Discovery Query Builder, Document Conversion, Language Translator, diff --git a/package.json b/package.json index e5afbaf3..6d8a1f63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-node-watson", - "version": "0.5.6", + "version": "0.5.7", "description": "A collection of Node-RED nodes for IBM Watson services", "dependencies": { "alchemy-api": "^1.3.0", diff --git a/services/language_translator_identify/v2.html b/services/language_translator_identify/v2.html index fbf85eab..61b938e1 100644 --- a/services/language_translator_identify/v2.html +++ b/services/language_translator_identify/v2.html @@ -35,7 +35,7 @@ From 98a7751b225c0b1d03b8d5e3ecbe6843407042b1 Mon Sep 17 00:00:00 2001 From: chughts Date: Thu, 18 May 2017 15:54:01 +0100 Subject: [PATCH 05/16] Node Support for Conversational Tone --- README.md | 1 + services/tone_analyzer/v3.js | 58 +++++++++++++++++++++++++----------- utilities/tone-utils.js | 29 ++++++++++++------ 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 95380c2c..56be746c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Node-RED Watson Nodes for IBM Bluemix ### New in version 0.5.7 - Fix to Tone Analyzer to allow JSON as input +- Enabled Conversation Tone method to Tone Analyzer Node ### New in version 0.5.6 - User Agent added to following nodes: Conversation, Conversation Workspace Manager, diff --git a/services/tone_analyzer/v3.js b/services/tone_analyzer/v3.js index be56b0e6..081a710a 100644 --- a/services/tone_analyzer/v3.js +++ b/services/tone_analyzer/v3.js @@ -84,6 +84,35 @@ module.exports = function (RED) { }; + function invokeService(config, options, settings) { + const tone_analyzer = new ToneAnalyzerV3({ + 'username': settings.username, + 'password': settings.password, + version_date: '2016-05-19', + headers: { + 'User-Agent': pkg.name + '-' + pkg.version + } + }); + + var p = new Promise(function resolver(resolve, reject){ + switch (config['tone-method']) { + case 'generalTone' : + tone_analyzer.tone(options, function (err, response) { + if (err) { + reject(err); + } + resolve(response); + }); + break; + case 'customerEngagementTone' : + reject('customer Engagement Tone not yet implemented in this node'); + break; + } + }); + + return p; + } + // function when the node recieves input inside a flow. // Configuration is first checked before the service is invoked. var processOnInput = function(msg, config, node) { @@ -94,28 +123,21 @@ module.exports = function (RED) { return; } else { - var tone_analyzer = new ToneAnalyzerV3({ - 'username': settings.username, - 'password': settings.password, - version_date: '2016-05-19', - headers: { - 'User-Agent': pkg.name + '-' + pkg.version - } - }); - var options = toneutils.parseOptions(msg, config); node.status({fill:'blue', shape:'dot', text:'requesting'}); - tone_analyzer.tone(options, function (err, response) { - node.status({}) - if (err) { - node.error(err, msg); - } else { - msg.response = response; - } - node.send(msg); - }); + invokeService(config, options, settings) + .then(function(data){ + node.status({}) + node.send(msg); + node.status({}); + }) + .catch(function(err){ + msg.response = err; + node.status({fill:'red', shape:'dot', text: err}); + node.error(err, msg); + }); } }); diff --git a/utilities/tone-utils.js b/utilities/tone-utils.js index 082aa391..662e5926 100644 --- a/utilities/tone-utils.js +++ b/utilities/tone-utils.js @@ -48,7 +48,7 @@ ToneUtils.prototype = { if (typeof payload !== 'string' && isJSON !== true) { message = 'The payload must be either a string, JSON or a Buffer'; } - + return message; }, @@ -64,16 +64,27 @@ ToneUtils.prototype = { // function to parse through the options in preparation // for the sevice call. parseOptions: function(msg, config) { - var options = { - 'text': msg.payload, - 'sentences': msg.sentences || config.sentences, - 'isHTML': msg.contentType || config.contentType - }; - if (this.isJsonObject(msg.payload)) { - options.text = JSON.stringify(msg.payload); + var options = {}; + + switch (config['tone-method']) { + case 'generalTone' : + options.sentences = msg.sentences || config.sentences; + options.isHTML = msg.contentType || config.contentType; + options.tones = this.parseToneOption(msg, config); + options.text = this.isJsonObject(msg.payload) ? + JSON.stringify(msg.payload) : + msg.payload; + break + case 'customerEngagementTone' : + options.utterances = this.isJsonObject(msg.payload) ? + JSON.stringify(msg.payload) : + msg.payload; + if (this.isJsonObject(msg.payload)) { + options.utterances = JSON.stringify(msg.payload); + } + break; } - options.tones = this.parseToneOption(msg, config); return options; } From 93103f95f2b24d98c00d5fb7544d16294bc87a40 Mon Sep 17 00:00:00 2001 From: chughts Date: Thu, 18 May 2017 16:52:33 +0100 Subject: [PATCH 06/16] Node Support for Conversational Tone --- services/tone_analyzer/v3.js | 47 +++++++++++++++--------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/services/tone_analyzer/v3.js b/services/tone_analyzer/v3.js index 081a710a..94bba2d7 100644 --- a/services/tone_analyzer/v3.js +++ b/services/tone_analyzer/v3.js @@ -64,7 +64,7 @@ module.exports = function (RED) { // Function that checks the configuration to make sure that credentials, // payload and options have been provied in the correct format. - var checkConfiguration = function(msg, node, cb) { + var checkConfiguration = function(msg, node) { var message = null; var taSettings = null; @@ -78,8 +78,10 @@ module.exports = function (RED) { message = 'Missing property: msg.payload'; } - if (cb) { - cb(message, taSettings); + if (message) { + return Promise.reject(message); + } else { + return Promise.resolve(taSettings); } }; @@ -116,32 +118,23 @@ module.exports = function (RED) { // function when the node recieves input inside a flow. // Configuration is first checked before the service is invoked. var processOnInput = function(msg, config, node) { - checkConfiguration (msg, node, function(err, settings){ - if (err) { - node.status({fill:'red', shape:'dot', text:err}); - node.error(err, msg); - return; - } else { - + checkConfiguration(msg, node) + .then(function(settings) { var options = toneutils.parseOptions(msg, config); - node.status({fill:'blue', shape:'dot', text:'requesting'}); - - invokeService(config, options, settings) - .then(function(data){ - node.status({}) - node.send(msg); - node.status({}); - }) - .catch(function(err){ - msg.response = err; - node.status({fill:'red', shape:'dot', text: err}); - node.error(err, msg); - }); - } - }); - - }; + return invokeService(config, options, settings); + }) + .then(function(data){ + node.status({}) + node.send(msg); + node.status({}); + }) + .catch(function(err){ + msg.response = err; + node.status({fill:'red', shape:'dot', text: err}); + node.error(err, msg); + }); + } // This is the Tone Analyzer Node. From 86380b639b19830e393deb0e53d22082cb2921d0 Mon Sep 17 00:00:00 2001 From: chughts Date: Thu, 18 May 2017 17:23:55 +0100 Subject: [PATCH 07/16] Node Support for Conversational Tone --- services/tone_analyzer/v3.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/services/tone_analyzer/v3.js b/services/tone_analyzer/v3.js index 94bba2d7..7f586e73 100644 --- a/services/tone_analyzer/v3.js +++ b/services/tone_analyzer/v3.js @@ -85,7 +85,6 @@ module.exports = function (RED) { } }; - function invokeService(config, options, settings) { const tone_analyzer = new ToneAnalyzerV3({ 'username': settings.username, @@ -97,19 +96,21 @@ module.exports = function (RED) { }); var p = new Promise(function resolver(resolve, reject){ + var m = 'tone'; switch (config['tone-method']) { case 'generalTone' : - tone_analyzer.tone(options, function (err, response) { - if (err) { - reject(err); - } - resolve(response); - }); break; case 'customerEngagementTone' : - reject('customer Engagement Tone not yet implemented in this node'); + m = 'tone_chat'; break; } + tone_analyzer[m](options, function (err, response) { + if (err) { + reject(err); + } else { + resolve(response); + } + }); }); return p; @@ -142,13 +143,12 @@ module.exports = function (RED) { RED.nodes.createNode(this, config); var node = this; - // Invoked whenb the node has received an input as part of a flow. + // Invoked when the node has received an input as part of a flow. this.on('input', function (msg) { processOnInput(msg, config, node); }); } - RED.nodes.registerType('watson-tone-analyzer-v3', Node, { credentials: { username: {type:'text'}, From e3baaf0b844916636ba5b63fe4a5efa809d8e8b5 Mon Sep 17 00:00:00 2001 From: chughts Date: Thu, 18 May 2017 18:06:46 +0100 Subject: [PATCH 08/16] Node Support for Conversational Tone --- services/tone_analyzer/v3.html | 2 ++ services/tone_analyzer/v3.js | 7 ++++--- utilities/tone-utils.js | 13 +++++++------ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/services/tone_analyzer/v3.html b/services/tone_analyzer/v3.html index e21760d4..5aa6113d 100644 --- a/services/tone_analyzer/v3.html +++ b/services/tone_analyzer/v3.html @@ -76,6 +76,8 @@ and msg.sentences

Usng the node editor dialog users can filter the results by tone (emotion, language or social) and whether to include sentence-level analysis.

+

When running the Conversational Chat Tone, the input needs to follow the + chat json format for utterences.

For more information about the Tone Analyzer service, read the documentation.

diff --git a/services/tone_analyzer/v3.js b/services/tone_analyzer/v3.js index 7f586e73..11d8b12c 100644 --- a/services/tone_analyzer/v3.js +++ b/services/tone_analyzer/v3.js @@ -19,6 +19,7 @@ module.exports = function (RED) { var pkg = require('../../package.json'), ToneAnalyzerV3 = require('watson-developer-cloud/tone-analyzer/v3'), serviceutils = require('../../utilities/service-utils'), + payloadutils = require('../../utilities/payload-utils'), toneutils = require('../../utilities/tone-utils'), username = '', password = '', sUsername = '', sPassword = '', service = null; @@ -127,13 +128,13 @@ module.exports = function (RED) { }) .then(function(data){ node.status({}) + msg.response = data; node.send(msg); node.status({}); }) .catch(function(err){ - msg.response = err; - node.status({fill:'red', shape:'dot', text: err}); - node.error(err, msg); + payloadutils.reportError(node,msg,err); + node.send(msg); }); } diff --git a/utilities/tone-utils.js b/utilities/tone-utils.js index 662e5926..282f1f7c 100644 --- a/utilities/tone-utils.js +++ b/utilities/tone-utils.js @@ -66,6 +66,10 @@ ToneUtils.prototype = { parseOptions: function(msg, config) { var options = {}; + if (!config['tone-method']) { + config['tone-method'] = 'generalTone'; + } + switch (config['tone-method']) { case 'generalTone' : options.sentences = msg.sentences || config.sentences; @@ -76,12 +80,9 @@ ToneUtils.prototype = { msg.payload; break case 'customerEngagementTone' : - options.utterances = this.isJsonObject(msg.payload) ? - JSON.stringify(msg.payload) : - msg.payload; - if (this.isJsonObject(msg.payload)) { - options.utterances = JSON.stringify(msg.payload); - } + options.utterances = this.isJsonString(msg.payload) ? + JSON.parse(msg.payload) : + msg.payload; break; } From 9207ebc0187c9c7d95fbda6b486cd703600c1395 Mon Sep 17 00:00:00 2001 From: chughts Date: Fri, 19 May 2017 15:37:09 +0100 Subject: [PATCH 09/16] Discovery Node now supports Create Envrionment --- README.md | 1 + services/discovery/discovery-utils.js | 21 ++++++++++++-- services/discovery/v1.html | 42 +++++++++++++++++++++++++-- services/discovery/v1.js | 27 +++++++++++++++++ 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 56be746c..207c322c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Node-RED Watson Nodes for IBM Bluemix ### New in version 0.5.7 - Fix to Tone Analyzer to allow JSON as input - Enabled Conversation Tone method to Tone Analyzer Node +- Discovery Node now supports: Create Environment ### New in version 0.5.6 - User Agent added to following nodes: Conversation, Conversation Workspace Manager, diff --git a/services/discovery/discovery-utils.js b/services/discovery/discovery-utils.js index cf247335..978c9632 100644 --- a/services/discovery/discovery-utils.js +++ b/services/discovery/discovery-utils.js @@ -25,7 +25,7 @@ DiscoveryUtils.prototype = { } else if (msg.discoveryparams && msg.discoveryparams.configurationname) { params.name = msg.discoveryparams.configurationname; } else if (config.configurationname) { - params.name = config.cofigurationname; + params.name = config.configurationname; } return params; }, @@ -51,7 +51,8 @@ DiscoveryUtils.prototype = { params = DiscoveryUtils.prototype.buildParamsForName(msg, config, params); - ['environment_id','collection_id','configuration_id','query'].forEach(function(f) { + ['environment_id','collection_id','configuration_id', + 'query','description','size'].forEach(function(f) { params = DiscoveryUtils.prototype.buildParamsFor(msg, config, params, f); }); @@ -97,6 +98,22 @@ DiscoveryUtils.prototype = { return response; }, + paramNameCheck: function (params) { + var response = ''; + if (!params.name) { + response = 'Missing Name '; + } + return response; + }, + + paramDescriptionCheck: function (params) { + var response = ''; + if (!params.description) { + response = 'Missing Description '; + } + return response; + }, + paramCollectionCheck: function (params) { var response = ''; if (!params.collection_id) { diff --git a/services/discovery/v1.html b/services/discovery/v1.html index 81231f15..6a4fd684 100644 --- a/services/discovery/v1.html +++ b/services/discovery/v1.html @@ -36,7 +36,8 @@
+
+ + +
+
+ + +
@@ -93,9 +103,26 @@

This is the Node for the V1 Watson Discovery service.

The following methods are available:

    +
  • +

    Create New Environment

    +

    For this method the node needs an Environment Name, + Description and Environment Size as input. +

    +

    The name and description can be overridden by specifying + in msg.discoveryparams.environmentname + , msg.discoveryparams.description + and msg.discoveryparams.size +

    +

    Node output :

    +
      +
    • msg.environment : Information about the + newly created envrionment.
    • +
    +
  • +
  • -

    List Existing Envrionments

    -

    For this methong the node does not need any input. If the envrionment name field is left blank +

    List Existing Environments

    +

    For this method the node does not need any input. If the envrionment name field is left blank it will list all envrionments created for the instance of the Discovery service. If the envrionment name is specified, then only the details for the Discovery envrionment with the specified name will be returned. @@ -237,6 +264,8 @@ $('#node-input-filter').parent().hide(); $('#node-input-aggregation').parent().hide(); $('#node-input-return').parent().hide(); + $('#node-input-description').parent().hide(); + $('#node-input-size').parent().hide(); }; disV1.showSelectedFields = function(fields) { @@ -249,6 +278,11 @@ disV1.hideAll(); fields = []; switch (method) { + case 'createEnvrionment': + fields.push('#node-input-environmentname' + + ', #node-input-size' + + ', #node-input-description'); + break; case 'listEnvrionments': fields.push('#node-input-environmentname'); break; @@ -322,6 +356,8 @@ filter: {value: ""}, aggregation: {value: ""}, return: {value: ""}, + description: {value: ""}, + size: {value: 0}, "discovery-method": {value:"listEnvrionments"} }, credentials: { diff --git a/services/discovery/v1.js b/services/discovery/v1.js index d634dd8c..0bac3660 100644 --- a/services/discovery/v1.js +++ b/services/discovery/v1.js @@ -30,6 +30,10 @@ module.exports = function (RED) { function checkParams(method, params){ var response = ''; switch (method) { + case 'createEnvrionment': + response = discoveryutils.paramNameCheck(params) + + discoveryutils.paramDescriptionCheck(params); + break; case 'getEnvironmentDetails': case 'listCollections': response = discoveryutils.paramEnvCheck(params); @@ -50,6 +54,18 @@ module.exports = function (RED) { return response; } + function executeCreateEnvrionment(node, discovery, params, msg) { + discovery.createEnvironment(params, function (err, response) { + node.status({}); + if (err) { + discoveryutils.reportError(node, msg, err.error); + } else { + msg.environment = response.environment ? response.environment : response; + } + node.send(msg); + }); + } + function executeListEnvrionments(node, discovery, params, msg) { discovery.getEnvironments(params, function (err, response) { node.status({}); @@ -134,6 +150,11 @@ module.exports = function (RED) { }); } + function unknownMethod(node, discovery, params, msg) { + discoveryutils.reportError(node, msg, 'Unknown Method'); + node.send(msg); + } + function executeMethod(node, method, params, msg) { var discovery = new DiscoveryV1({ username: username, @@ -145,6 +166,9 @@ module.exports = function (RED) { }); switch (method) { + case 'createEnvrionment': + executeCreateEnvrionment(node, discovery, params, msg); + break; case 'listEnvrionments': executeListEnvrionments(node, discovery, params, msg); break; @@ -166,6 +190,9 @@ module.exports = function (RED) { case 'query': executeQuery(node, discovery, params, msg); break; + default : + unknownMethod(node, discovery, params, msg); + break; } } From e6c58b3ae62d9b8f7200a688358eeed634ae4e20 Mon Sep 17 00:00:00 2001 From: chughts Date: Fri, 19 May 2017 16:27:36 +0100 Subject: [PATCH 10/16] Migrated Discovery Node to use Promises --- services/discovery/v1.js | 224 +++++++++++++++++++++++---------------- 1 file changed, 131 insertions(+), 93 deletions(-) diff --git a/services/discovery/v1.js b/services/discovery/v1.js index 0bac3660..2a51562f 100644 --- a/services/discovery/v1.js +++ b/services/discovery/v1.js @@ -51,112 +51,132 @@ module.exports = function (RED) { discoveryutils.paramConfigurationCheck(params); break; } - return response; + if (response) { + return Promise.reject(response); + } else { + return Promise.resolve(); + } } function executeCreateEnvrionment(node, discovery, params, msg) { - discovery.createEnvironment(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.environment = response.environment ? response.environment : response; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.createEnvironment(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.environment = response.environment ? response.environment : response; + resolve(); + } + }); }); + return p; } function executeListEnvrionments(node, discovery, params, msg) { - discovery.getEnvironments(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.environments = response.environments ? response.environments : []; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.getEnvironments(params, function (err, response) { + console.log('return from getEnvrionments : ', response); + if (err) { + reject(err); + } else { + msg.environments = response.environments ? response.environments : []; + resolve(); + } + }); }); + return p; } function executeEnvrionmentDetails(node, discovery, params, msg) { - discovery.getEnvironment(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.environment_details = response; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.getEnvironment(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.environment_details = response; + resolve(); + } + }); }); + return p; } function executeListCollections(node, discovery, params, msg) { - discovery.getCollections(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.collections = response.collections ? response.collections : []; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.getCollections(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.collections = response.collections ? response.collections : []; + resolve(); + } + }); }); + return p; } function executeGetCollectionDetails(node, discovery, params, msg) { - discovery.getCollection(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.collection_details = response; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.getCollection(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.collection_details = response; + resolve(); + } + }); }); + return p; } function executeListConfigurations(node, discovery, params, msg) { - discovery.getConfigurations(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.configurations = response.configurations ? response.configurations : []; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.getConfigurations(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.configurations = response.configurations ? response.configurations : []; + resolve(); + } + }); }); + return p; } function executeGetConfigurationDetails(node, discovery, params, msg) { - discovery.getConfiguration(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.configuration_details = response; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.getConfiguration(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.configuration_details = response; + resolve(); + } + }); }); + return p; } function executeQuery(node, discovery, params, msg) { - discovery.query(params, function (err, response) { - node.status({}); - if (err) { - discoveryutils.reportError(node, msg, err.error); - } else { - msg.search_results = response; - } - node.send(msg); + var p = new Promise(function resolver(resolve, reject){ + discovery.query(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.search_results = response; + resolve(); + } + }); }); + return p; } function unknownMethod(node, discovery, params, msg) { - discoveryutils.reportError(node, msg, 'Unknown Method'); - node.send(msg); + return Promise.reject('Unable to process as unknown mode has been specified'); } function executeMethod(node, method, params, msg) { - var discovery = new DiscoveryV1({ + const discovery = new DiscoveryV1({ username: username, password: password, version_date: '2017-04-27', @@ -165,38 +185,54 @@ module.exports = function (RED) { } }); + var p = null; + switch (method) { case 'createEnvrionment': - executeCreateEnvrionment(node, discovery, params, msg); + p = executeCreateEnvrionment(node, discovery, params, msg); break; case 'listEnvrionments': - executeListEnvrionments(node, discovery, params, msg); + p = executeListEnvrionments(node, discovery, params, msg); break; case 'getEnvironmentDetails': - executeEnvrionmentDetails(node, discovery, params, msg); + p = executeEnvrionmentDetails(node, discovery, params, msg); break; case 'listCollections': - executeListCollections(node, discovery, params, msg); + p = executeListCollections(node, discovery, params, msg); break; case 'getCollectionDetails': - executeGetCollectionDetails(node, discovery, params, msg); + p = executeGetCollectionDetails(node, discovery, params, msg); break; case 'listConfigurations': - executeListConfigurations(node, discovery, params, msg); + p = executeListConfigurations(node, discovery, params, msg); break; case 'getConfigurationDetails': - executeGetConfigurationDetails(node, discovery, params, msg); + p = executeGetConfigurationDetails(node, discovery, params, msg); break; case 'query': - executeQuery(node, discovery, params, msg); + p = executeQuery(node, discovery, params, msg); break; default : - unknownMethod(node, discovery, params, msg); + p = unknownMethod(node, discovery, params, msg); break; } + return p; + } + function initialCheck(u, p, m) { + var message = ''; + if (!u || !p) { + message = 'Missing Watson Discovery service credentials'; + } else if (!m || '' === m) { + message = 'Required Discovery method has not been specified'; + } + if (message){ + return Promise.reject(message); + } + return Promise.resolve(); } + if (dservice) { sUsername = dservice.username; sPassword = dservice.password; @@ -219,22 +255,24 @@ module.exports = function (RED) { username = sUsername || this.credentials.username; password = sPassword || this.credentials.password; - if (!username || !password) { - message = 'Missing Watson Discovery service credentials'; - } else if (!method || '' === method) { - message = 'Required Discovery method has not been specified'; - } else { - params = discoveryutils.buildParams(msg,config); - message = checkParams(method, params); - } - - if (message) { - discoveryutils.reportError(node,msg,message); - return; - } - - node.status({fill:'blue', shape:'dot', text:'requesting'}); - executeMethod(node, method, params, msg); + node.status({}); + initialCheck(username, password, method) + .then(function(){ + params = discoveryutils.buildParams(msg,config); + return checkParams(method, params); + }) + .then(function(){ + node.status({fill:'blue', shape:'dot', text:'requesting'}); + return executeMethod(node, method, params, msg); + }) + .then(function(){ + node.status({}); + node.send(msg); + }) + .catch(function(err){ + discoveryutils.reportError(node,msg,err); + node.send(msg); + }); }); } From f1dc4a3a9a598e41cb9324e03bf6178018a083d5 Mon Sep 17 00:00:00 2001 From: chughts Date: Fri, 19 May 2017 17:20:57 +0100 Subject: [PATCH 11/16] Shell for Create Configuration Option --- services/discovery/discovery-utils.js | 48 ++++++++++++++++++++++++--- services/discovery/v1.html | 2 ++ services/discovery/v1.js | 26 ++++++++++++++- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/services/discovery/discovery-utils.js b/services/discovery/discovery-utils.js index 978c9632..d8b47ff3 100644 --- a/services/discovery/discovery-utils.js +++ b/services/discovery/discovery-utils.js @@ -30,6 +30,19 @@ DiscoveryUtils.prototype = { return params; }, + buildParamsForPayload: function(msg, config, params) { + var isJSON = DiscoveryUtils.prototype.isJsonString(msg.payload) || + DiscoveryUtils.prototype.isJsonObject(msg.payload); + + // Payload (text to be analysed) must be a string (content is either raw string or Buffer) + if (typeof msg.payload === 'string' || isJSON) { + params.file = DiscoveryUtils.prototype.isJsonObject(msg.payload) ? + JSON.stringify(msg.payload) : + msg.payload; + } + return params; + }, + buildParamsFor: function(msg, config, params, field) { if (msg.discoveryparams && msg.discoveryparams[field]) { params[field] = msg.discoveryparams[field]; @@ -60,6 +73,8 @@ DiscoveryUtils.prototype = { params = DiscoveryUtils.prototype.buildParamsFromConfig(config, params, f); }); + params = DiscoveryUtils.prototype.buildParamsForPayload(msg, config, params); + return params; }, @@ -98,6 +113,14 @@ DiscoveryUtils.prototype = { return response; }, + paramJSONCheck: function (params) { + var response = ''; + if (!params.file) { + response = 'Missing JSON file on payload'; + } + return response; + }, + paramNameCheck: function (params) { var response = ''; if (!params.name) { @@ -177,12 +200,29 @@ DiscoveryUtils.prototype = { return fields; }, - reportError: function (node, msg, message) { - var messageTxt = message.error ? message.error : message; - node.status({fill:'red', shape:'dot', text: messageTxt}); - node.error(message, msg); +// reportError: function (node, msg, message) { +// var messageTxt = message.error ? message.error : message; +// node.status({fill:'red', shape:'dot', text: messageTxt}); +// node.error(message, msg); +// } , + + isJsonString: function(str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + }, + + isJsonObject: function(str) { + if (str instanceof Array || str instanceof Object) { + return true; + } + return false; } + }; var discoveryutils = new DiscoveryUtils(); diff --git a/services/discovery/v1.html b/services/discovery/v1.html index 6a4fd684..c881cfb6 100644 --- a/services/discovery/v1.html +++ b/services/discovery/v1.html @@ -41,6 +41,7 @@ + @@ -286,6 +287,7 @@ case 'listEnvrionments': fields.push('#node-input-environmentname'); break; + case 'createConfiguration': case 'getEnvironmentDetails': case 'listCollections': fields.push('#node-input-environment_id'); diff --git a/services/discovery/v1.js b/services/discovery/v1.js index 2a51562f..110e3318 100644 --- a/services/discovery/v1.js +++ b/services/discovery/v1.js @@ -21,6 +21,7 @@ module.exports = function (RED) { discoveryutils = require('./discovery-utils'), DiscoveryV1 = require('watson-developer-cloud/discovery/v1'), serviceutils = require('../../utilities/service-utils'), + payloadutils = require('../../utilities/payload-utils'), dservice = serviceutils.getServiceCreds(SERVICE_IDENTIFIER), username = null, password = null, @@ -34,6 +35,10 @@ module.exports = function (RED) { response = discoveryutils.paramNameCheck(params) + discoveryutils.paramDescriptionCheck(params); break; + case 'createConfiguration': + response = discoveryutils.paramEnvCheck(params) + + discoveryutils.paramJSONCheck(params); + break; case 'getEnvironmentDetails': case 'listCollections': response = discoveryutils.paramEnvCheck(params); @@ -129,6 +134,21 @@ module.exports = function (RED) { return p; } + function executeCreateConfiguration(node, discovery, params, msg) { + var p = new Promise(function resolver(resolve, reject){ + discovery.createConfiguration(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.configuration = response.configuration ? response.configuration : response; + resolve(); + } + }); + }); + return p; + } + + function executeListConfigurations(node, discovery, params, msg) { var p = new Promise(function resolver(resolve, reject){ discovery.getConfigurations(params, function (err, response) { @@ -203,6 +223,9 @@ module.exports = function (RED) { case 'getCollectionDetails': p = executeGetCollectionDetails(node, discovery, params, msg); break; + case 'createConfiguration': + p = executeCreateConfiguration(node, discovery, params, msg); + break; case 'listConfigurations': p = executeListConfigurations(node, discovery, params, msg); break; @@ -270,7 +293,8 @@ module.exports = function (RED) { node.send(msg); }) .catch(function(err){ - discoveryutils.reportError(node,msg,err); + //discoveryutils.reportError(node,msg,err); + payloadutils.reportError(node,msg,err); node.send(msg); }); }); From 7ab28bd2d29a0f08e681127e2781aabef40337f0 Mon Sep 17 00:00:00 2001 From: chughts Date: Fri, 19 May 2017 18:29:39 +0100 Subject: [PATCH 12/16] Shell for Create Collection Option --- services/discovery/discovery-utils.js | 5 +++++ services/discovery/v1.html | 13 +++++++++++++ services/discovery/v1.js | 28 ++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/services/discovery/discovery-utils.js b/services/discovery/discovery-utils.js index d8b47ff3..166cb17a 100644 --- a/services/discovery/discovery-utils.js +++ b/services/discovery/discovery-utils.js @@ -26,6 +26,10 @@ DiscoveryUtils.prototype = { params.name = msg.discoveryparams.configurationname; } else if (config.configurationname) { params.name = config.configurationname; + } else if (msg.discoveryparams && msg.discoveryparams.collection_name) { + params.name = msg.discoveryparams.collection_name; + } else if (config.collection_name) { + params.name = config.collection_name; } return params; }, @@ -65,6 +69,7 @@ DiscoveryUtils.prototype = { params = DiscoveryUtils.prototype.buildParamsForName(msg, config, params); ['environment_id','collection_id','configuration_id', + 'collection_name', 'query','description','size'].forEach(function(f) { params = DiscoveryUtils.prototype.buildParamsFor(msg, config, params, f); }); diff --git a/services/discovery/v1.html b/services/discovery/v1.html index c881cfb6..83d78909 100644 --- a/services/discovery/v1.html +++ b/services/discovery/v1.html @@ -39,6 +39,7 @@ + @@ -56,6 +57,10 @@ +

    + + +
    @@ -257,6 +262,7 @@ disV1.hideAll = function() { $('#node-input-environmentname').parent().hide(); $('#node-input-environment_id').parent().hide(); + $('#node-input-collection_name').parent().hide(); $('#node-input-collection_id').parent().hide(); $('#node-input-configurationname').parent().hide(); $('#node-input-configuration_id').parent().hide(); @@ -287,6 +293,12 @@ case 'listEnvrionments': fields.push('#node-input-environmentname'); break; + case 'createCollection': + fields.push('#node-input-environment_id' + + ', #node-input-configuration_id' + + ', #node-input-collection_name' + + ', #node-input-description'); + break; case 'createConfiguration': case 'getEnvironmentDetails': case 'listCollections': @@ -353,6 +365,7 @@ collection_id: {value: ""}, configurationname: {value: ""}, configuration_id: {value: ""}, + collection_name: {value: ""}, count: {value: "1"}, query: {value: ""}, filter: {value: ""}, diff --git a/services/discovery/v1.js b/services/discovery/v1.js index 110e3318..09f5d8ea 100644 --- a/services/discovery/v1.js +++ b/services/discovery/v1.js @@ -106,6 +106,30 @@ module.exports = function (RED) { return p; } + function executeCreateCollection(node, discovery, params, msg) { + var p = new Promise(function resolver(resolve, reject){ + + //params.body = {}; + //['name','description','collection_name' + // 'configuration_id'].forEach(function(f) { + // params.body[f] = params[f]; + // //delete params[f]; + //}); + + //console.log('about to create collection with params : ', params); + discovery.createCollection(params, function (err, response) { + if (err) { + reject(err); + } else { + msg.collection = response.collection ? response.collection : response; + resolve(); + } + }); + }); + return p; + } + + function executeListCollections(node, discovery, params, msg) { var p = new Promise(function resolver(resolve, reject){ discovery.getCollections(params, function (err, response) { @@ -148,7 +172,6 @@ module.exports = function (RED) { return p; } - function executeListConfigurations(node, discovery, params, msg) { var p = new Promise(function resolver(resolve, reject){ discovery.getConfigurations(params, function (err, response) { @@ -217,6 +240,9 @@ module.exports = function (RED) { case 'getEnvironmentDetails': p = executeEnvrionmentDetails(node, discovery, params, msg); break; + case 'createCollection': + p = executeCreateCollection(node, discovery, params, msg); + break; case 'listCollections': p = executeListCollections(node, discovery, params, msg); break; From a6cf530db409880af7c35e094fa292cbff4879f9 Mon Sep 17 00:00:00 2001 From: chughts Date: Fri, 19 May 2017 22:19:50 +0100 Subject: [PATCH 13/16] Sometimes this is me --- services/discovery/discovery-utils.js | 21 +++++++++++---------- services/discovery/v1.js | 1 - 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/services/discovery/discovery-utils.js b/services/discovery/discovery-utils.js index 166cb17a..ece62656 100644 --- a/services/discovery/discovery-utils.js +++ b/services/discovery/discovery-utils.js @@ -35,12 +35,12 @@ DiscoveryUtils.prototype = { }, buildParamsForPayload: function(msg, config, params) { - var isJSON = DiscoveryUtils.prototype.isJsonString(msg.payload) || - DiscoveryUtils.prototype.isJsonObject(msg.payload); + var isJSON = this.isJsonString(msg.payload) || + this.isJsonObject(msg.payload); // Payload (text to be analysed) must be a string (content is either raw string or Buffer) if (typeof msg.payload === 'string' || isJSON) { - params.file = DiscoveryUtils.prototype.isJsonObject(msg.payload) ? + params.file = this.isJsonObject(msg.payload) ? JSON.stringify(msg.payload) : msg.payload; } @@ -65,20 +65,21 @@ DiscoveryUtils.prototype = { buildParams: function(msg, config) { var params = {}; + me = this; - params = DiscoveryUtils.prototype.buildParamsForName(msg, config, params); + params = this.buildParamsForName(msg, config, params); ['environment_id','collection_id','configuration_id', 'collection_name', 'query','description','size'].forEach(function(f) { - params = DiscoveryUtils.prototype.buildParamsFor(msg, config, params, f); + params = me.buildParamsFor(msg, config, params, f); }); ['count','filter','aggregation','return'].forEach(function(f) { - params = DiscoveryUtils.prototype.buildParamsFromConfig(config, params, f); + params = me.buildParamsFromConfig(config, params, f); }); - params = DiscoveryUtils.prototype.buildParamsForPayload(msg, config, params); + params = this.buildParamsForPayload(msg, config, params); return params; }, @@ -168,7 +169,7 @@ DiscoveryUtils.prototype = { } if ('object' === typeof d[k]) { - fields = DiscoveryUtils.prototype.buildFieldByStep(d[k], fields, t); + fields = this.buildFieldByStep(d[k], fields, t); } else { switch (k) { case 'text': @@ -195,11 +196,11 @@ DiscoveryUtils.prototype = { if ('results' === k && 'object' === typeof schemaData[k] && 'object' === typeof schemaData[k][0]) { - fields = DiscoveryUtils.prototype.buildFieldByStep(schemaData[k][0], fields, ''); + fields = this.buildFieldByStep(schemaData[k][0], fields, ''); } } if (fields.length) { - fields = fields.filter(DiscoveryUtils.prototype.uniqueFilter); + fields = fields.filter(this.uniqueFilter); } } return fields; diff --git a/services/discovery/v1.js b/services/discovery/v1.js index 09f5d8ea..6137d6da 100644 --- a/services/discovery/v1.js +++ b/services/discovery/v1.js @@ -80,7 +80,6 @@ module.exports = function (RED) { function executeListEnvrionments(node, discovery, params, msg) { var p = new Promise(function resolver(resolve, reject){ discovery.getEnvironments(params, function (err, response) { - console.log('return from getEnvrionments : ', response); if (err) { reject(err); } else { From de5de0aceea8ca1efe518624aff4fc16a82c1c83 Mon Sep 17 00:00:00 2001 From: chughts Date: Sun, 21 May 2017 21:37:53 +0100 Subject: [PATCH 14/16] Implement Discovery Create Collection, Create Configuration --- README.md | 3 ++- package.json | 2 +- services/discovery/v1.html | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 207c322c..261cfd33 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Node-RED Watson Nodes for IBM Bluemix ### New in version 0.5.7 - Fix to Tone Analyzer to allow JSON as input - Enabled Conversation Tone method to Tone Analyzer Node -- Discovery Node now supports: Create Environment +- Discovery Node now supports: Create Environment, Create Configuration, +Create Collection ### New in version 0.5.6 - User Agent added to following nodes: Conversation, Conversation Workspace Manager, diff --git a/package.json b/package.json index 6d8a1f63..aa654ebe 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "temp": "^0.8.3", "qs": "6.x", "image-type": "^2.0.2", - "watson-developer-cloud": "^2.31.1", + "watson-developer-cloud": "^2.31.2", "kuromoji": "^0.0.5", "is-docx": "^0.0.3" }, diff --git a/services/discovery/v1.html b/services/discovery/v1.html index 83d78909..a0689faf 100644 --- a/services/discovery/v1.html +++ b/services/discovery/v1.html @@ -39,10 +39,10 @@ - + - + From 490d57689d3fe879155b326080bb154a8749b115 Mon Sep 17 00:00:00 2001 From: chughts Date: Sun, 21 May 2017 21:52:03 +0100 Subject: [PATCH 15/16] code cleansing --- services/discovery/discovery-utils.js | 8 ++++---- services/tone_analyzer/v3.js | 6 +++--- utilities/tone-utils.js | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/services/discovery/discovery-utils.js b/services/discovery/discovery-utils.js index ece62656..8154396b 100644 --- a/services/discovery/discovery-utils.js +++ b/services/discovery/discovery-utils.js @@ -39,7 +39,7 @@ DiscoveryUtils.prototype = { this.isJsonObject(msg.payload); // Payload (text to be analysed) must be a string (content is either raw string or Buffer) - if (typeof msg.payload === 'string' || isJSON) { + if (typeof msg.payload === 'string' || isJSON) { params.file = this.isJsonObject(msg.payload) ? JSON.stringify(msg.payload) : msg.payload; @@ -64,14 +64,14 @@ DiscoveryUtils.prototype = { }, buildParams: function(msg, config) { - var params = {}; + var params = {}, me = this; params = this.buildParamsForName(msg, config, params); ['environment_id','collection_id','configuration_id', - 'collection_name', - 'query','description','size'].forEach(function(f) { + 'collection_name', + 'query','description','size'].forEach(function(f) { params = me.buildParamsFor(msg, config, params, f); }); diff --git a/services/tone_analyzer/v3.js b/services/tone_analyzer/v3.js index 11d8b12c..134e78cf 100644 --- a/services/tone_analyzer/v3.js +++ b/services/tone_analyzer/v3.js @@ -66,8 +66,8 @@ module.exports = function (RED) { // Function that checks the configuration to make sure that credentials, // payload and options have been provied in the correct format. var checkConfiguration = function(msg, node) { - var message = null; - var taSettings = null; + var message = null, + taSettings = null; taSettings = checkCreds(node.credentials); @@ -136,7 +136,7 @@ module.exports = function (RED) { payloadutils.reportError(node,msg,err); node.send(msg); }); - } + } // This is the Tone Analyzer Node. diff --git a/utilities/tone-utils.js b/utilities/tone-utils.js index 282f1f7c..3f83610d 100644 --- a/utilities/tone-utils.js +++ b/utilities/tone-utils.js @@ -42,10 +42,10 @@ ToneUtils.prototype = { // whether it is JSON or a Buffer checkPayload: function(payload) { var message = null; - var isJSON = this.isJsonString(payload) || this.isJsonObject(payload); + isJSON = this.isJsonString(payload) || this.isJsonObject(payload); // Payload (text to be analysed) must be a string (content is either raw string or Buffer) - if (typeof payload !== 'string' && isJSON !== true) { + if (typeof payload !== 'string' && isJSON !== true) { message = 'The payload must be either a string, JSON or a Buffer'; } @@ -78,7 +78,7 @@ ToneUtils.prototype = { options.text = this.isJsonObject(msg.payload) ? JSON.stringify(msg.payload) : msg.payload; - break + break; case 'customerEngagementTone' : options.utterances = this.isJsonString(msg.payload) ? JSON.parse(msg.payload) : From 9de42505ff367312d5f0dee352bf3d5f04a5045f Mon Sep 17 00:00:00 2001 From: chughts Date: Sun, 21 May 2017 21:57:36 +0100 Subject: [PATCH 16/16] code cleansing --- utilities/tone-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/tone-utils.js b/utilities/tone-utils.js index 3f83610d..7b56205f 100644 --- a/utilities/tone-utils.js +++ b/utilities/tone-utils.js @@ -41,7 +41,7 @@ ToneUtils.prototype = { // Function that checks the payload and determines // whether it is JSON or a Buffer checkPayload: function(payload) { - var message = null; + var message = null, isJSON = this.isJsonString(payload) || this.isJsonObject(payload); // Payload (text to be analysed) must be a string (content is either raw string or Buffer)