11/**
2- * Copyright 2013,2015 IBM Corp.
2+ * Copyright 2013,2015, 2016 IBM Corp.
33 *
44 * Licensed under the Apache License, Version 2.0 (the 'License');
55 * you may not use this file except in compliance with the License.
1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 **/
16+
17+
18+ // AlchemyAPI Text Analysis functions supported by this node
1619var FEATURES = {
1720 'page-image' : 'image' ,
1821 'image-kw' : 'imageKeywords' ,
@@ -25,77 +28,114 @@ var FEATURES = {
2528 'concept' : 'concepts' ,
2629 'relation' : 'relations' ,
2730 'pub-date' : 'publicationDate' ,
28- 'doc-sentiment' : 'docSentiment'
31+ 'doc-sentiment' : 'docSentiment' ,
32+ 'doc-emotion' : 'docEmotions'
2933} ;
3034
3135module . exports = function ( RED ) {
32- var cfenv = require ( 'cfenv' ) ,
33- AlchemyAPI = require ( 'alchemy-api' ) ;
3436
35- var services = cfenv . getAppEnv ( ) . services ,
36- service ;
37+ var cfenv = require ( 'cfenv' ) ;
38+ var watson = require ( 'watson-developer-cloud' ) ;
39+
40+ // Require the Cloud Foundry Module to pull credentials from bound service
41+ // If they are found then the api key is stored in the variable s_apikey.
42+ //
43+ // This separation between s_apikey and apikey is to allow
44+ // the end user to modify the key redentials when the service is not bound.
45+ // Otherwise, once set apikey is never reset, resulting in a frustrated
46+ // user who, when he errenously enters bad credentials, can't figure out why
47+ // the edited ones are not being taken.
48+
49+ var services = cfenv . getAppEnv ( ) . services ;
50+ var service ;
3751
38- var apikey ;
52+ var apikey , s_apikey ;
3953
4054 var service = cfenv . getAppEnv ( ) . getServiceCreds ( / a l c h e m y / i) ;
4155
4256 if ( service ) {
43- apikey = service . apikey ;
57+ s_apikey = service . apikey ;
4458 }
4559
4660 RED . httpAdmin . get ( '/alchemy-feature-extract/vcap' , function ( req , res ) {
4761 res . json ( service ? { bound_service : true } : null ) ;
4862 } ) ;
4963
64+
65+ // This is the Alchemy Data Node
66+
5067 function AlchemyFeatureExtractNode ( config ) {
5168 RED . nodes . createNode ( this , config ) ;
5269 var node = this ;
5370
5471 this . on ( 'input' , function ( msg ) {
5572 if ( ! msg . payload ) {
73+ this . status ( { fill :'red' , shape :'ring' , text :'missing payload' } ) ;
5674 var message = 'Missing property: msg.payload' ;
5775 node . error ( message , msg ) ;
5876 return ;
5977 }
6078
61- apikey = apikey || this . credentials . apikey ;
79+ // If it is present the newly provided user entered key takes precedence over the existing one.
80+ apikey = s_apikey || this . credentials . apikey ;
81+ this . status ( { } ) ;
6282
6383 if ( ! apikey ) {
84+ this . status ( { fill :'red' , shape :'ring' , text :'missing credentials' } ) ;
6485 var message = 'Missing Alchemy API service credentials' ;
6586 node . error ( message , msg ) ;
6687 return ;
6788 }
6889
69- var alchemy = new AlchemyAPI ( apikey ) ;
90+ var alchemy_language = watson . alchemy_language ( { api_key : apikey } ) ;
91+
92+ // Check which features have been requested.
7093
7194 var enabled_features = Object . keys ( FEATURES ) . filter ( function ( feature ) {
7295 return config [ feature ]
7396 } ) ;
7497
98+
7599 if ( ! enabled_features . length ) {
100+ this . status ( { fill :'red' , shape :'ring' , text :'no features selected' } ) ;
76101 var message = 'AlchemyAPI node must have at least one selected feature.' ;
77102 node . error ( message , msg ) ;
78103 return ;
79104 }
80105
81- alchemy . combined ( msg . payload , enabled_features , msg . alchemy_options || { } , function ( err , response ) {
82- if ( err || response . status === 'ERROR' ) {
83- var message = 'Alchemy API request error: ' + ( err ? err : response . statusInfo ) ;
84- node . error ( message , msg ) ;
85- return ;
86- }
106+ // The watson node-SDK expects the features as a single string.
107+ var extract = "" ; //doc-sentiment";
108+ enabled_features . forEach ( function ( entry ) { extract += ( ',' + entry ) } )
109+
110+ //console.log("Will be looking for ", extract)
87111
88- msg . features = { } ;
89- Object . keys ( FEATURES ) . forEach ( function ( feature ) {
90- var answer_feature = FEATURES [ feature ] ;
91- msg . features [ feature ] = response [ answer_feature ] ;
92- } ) ;
112+ var params = { text : msg . payload , extract : extract } ;
113+
114+ alchemy_language . combined ( params , function ( err , response ) {
115+ if ( err || response . status === 'ERROR' ) {
116+ node . status ( { fill :'red' , shape :'ring' , text :'call to alchmeyapi language service failed' } ) ;
117+ console . log ( 'Error:' , msg , err ) ;
118+ node . error ( err , msg ) ;
119+ }
120+ else {
121+ msg . features = { } ;
122+ //msg.features['all'] = response;
123+
124+ Object . keys ( FEATURES ) . forEach ( function ( feature ) {
125+ var answer_feature = FEATURES [ feature ] ;
126+
127+ msg . features [ feature ] = response [ answer_feature ] || { } ;
128+ } ) ;
129+
130+ node . send ( msg ) ;
131+ }
132+ } ) ;
93133
94- node . send ( msg )
95- } )
96134 } ) ;
97135 }
98136
137+
138+ //Register the node as alchemy-feature-extract to nodeRED
99139 RED . nodes . registerType ( 'alchemy-feature-extract' , AlchemyFeatureExtractNode , {
100140 credentials : {
101141 apikey : { type :"password" }
0 commit comments