Skip to content

Commit 0d024b2

Browse files
update from master
2 parents 7543e09 + 4125959 commit 0d024b2

File tree

7 files changed

+303
-15
lines changed

7 files changed

+303
-15
lines changed

.travis.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
language: node_js
2+
sudo: false # causes tests to be run in Travis CI's newer, faster build infrastructure
23
node_js:
34
- "0.10"
5+
- "0.12"
6+
- "stable"
47
script:
58
- npm test
69
after_success:
7-
- npm run coveralls
10+
- npm run coveralls

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ language_translation.translate({
252252
console.log(JSON.stringify(translation, null, 2));
253253
});
254254

255-
language_identification.identify({
255+
language_translation.identify({
256256
text: 'The language translation service takes text input and identifies the language used.' },
257257
function (err, language) {
258258
if (err)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "watson-developer-cloud",
3-
"version": "0.9.30",
3+
"version": "0.10.1",
44
"description": "Nodejs Client Wrapper to use the IBM Watson and Services",
55
"main": "./lib/index",
66
"repository": {

services/alchemy_vision/v1.js

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var extend = require('extend');
2020
var requestFactory = require('../../lib/requestwrapper');
2121
var endpoints = require('../../lib/alchemy_endpoints.json');
2222
var helper = require('../../lib/helper');
23+
var isStream = require('isstream');
2324
var pick = require('object.pick');
2425
var omit = require('object.omit');
2526
var fs = require('fs');
@@ -39,7 +40,7 @@ function errorFormatter(cb) {
3940
}, null);
4041
}
4142
};
42-
};
43+
}
4344

4445
function createRequest(method) {
4546
return function(_params, callback ) {
@@ -78,31 +79,81 @@ function AlchemyVision(options) {
7879
}
7980

8081
/**
81-
* Extracts images from a URL.
82+
* Extracts images from a URL or html
8283
*/
83-
AlchemyVision.prototype.imageLinks = createRequest('image_link');
84+
AlchemyVision.prototype.imageLinks = function(_params, callback ) {
85+
var params = _params || {};
86+
var accepted_formats = Object.keys(endpoints['image_link']);
87+
var format = helper.getFormat(params, accepted_formats);
88+
89+
if (format === null) {
90+
callback(new Error('Missing required parameters: ' +
91+
accepted_formats.join(', ') + ' needs to be specified'));
92+
return;
93+
}
94+
95+
var parameters = {
96+
options: {
97+
url: endpoints['image_link'][format],
98+
method: 'POST',
99+
json: true,
100+
qs: extend({outputMode: 'json'}, params) // change default output to json
101+
},
102+
defaultOptions: this._options
103+
};
104+
105+
return requestFactory(parameters, errorFormatter(callback));
106+
};
84107

85108
/**
86109
* Tags image with keywords
87110
*/
88-
AlchemyVision.prototype.imageTags = function(_params, callback) {
111+
AlchemyVision.prototype.imageKeywords = function(_params, callback) {
89112
var params = _params || {};
90-
91-
if (typeof(params.image) !== 'undefined' && typeof(params.image) !== 'string') {
92-
callback(new Error('Invalid arguments: image needs to be a filename or base64 image'));
113+
var accepted_formats = Object.keys(endpoints['image_keywords']);
114+
var format = helper.getFormat(params, accepted_formats);
115+
var image = null;
116+
if (format === null) {
117+
callback(new Error('Missing required parameters: ' +
118+
accepted_formats.join(', ') + ' needs to be specified'));
93119
return;
94120
}
95121

96-
if (typeof(params.image) !== 'string')
97-
params.imagePostMode = 'raw';
98122

99-
return createRequest('image_keywords').call(this, params, callback);
123+
if (typeof(params.image) !== 'undefined') {
124+
// check if image is stream or string
125+
if (typeof(params.image) !== 'string' && !isStream(params.image)) {
126+
callback(new Error('Invalid arguments: image needs to be a stream or base64'));
127+
return;
128+
}
129+
130+
if (isStream(params.image)) {
131+
params.imagePostMode = 'raw';
132+
image = params.image;
133+
delete params.image;
134+
} else {
135+
params.imagePostMode = 'not-raw';
136+
}
137+
}
138+
139+
var parameters = {
140+
options: {
141+
url: endpoints['image_links'][format],
142+
method: 'POST',
143+
json: true,
144+
body: image,
145+
qs: extend({outputMode: 'json'}, params) // change default output to json
146+
},
147+
defaultOptions: this._options
148+
};
149+
150+
return requestFactory(parameters, errorFormatter(callback));
100151
};
101152

102153
/**
103154
* Face detection and Recognition
104155
*/
105-
AlchemyVision.prototype.imageFaces = function(_params, callback) {
156+
AlchemyVision.prototype.recognizeFaces = function(_params, callback) {
106157
var params = _params || {};
107158

108159
if (typeof(params.image) !== 'string')

services/tone_analyzer/v2.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/**
2+
* Copyright 2015 IBM Corp. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
'use strict';
18+
19+
var extend = require('extend');
20+
var requestFactory = require('../../lib/requestwrapper');
21+
22+
function ToneAnalyzer(options) {
23+
// Default URL
24+
var defaultOptions = {
25+
url: 'https://gateway.watsonplatform.net/tone-analyzer-experimental/api'
26+
};
27+
28+
// Replace default options with user provided
29+
this._options = extend(defaultOptions, options);
30+
}
31+
32+
/**
33+
* Main API call. Returns the different tone dimensions of a text.
34+
*
35+
* @param params: An object with a string 'text' element. This is the
36+
* only field used. By this API call
37+
*
38+
* @return upon success, the callback function is called with an object
39+
* containing the different tones (emotion, writing and social), traits
40+
* and the evidence words found in the text.
41+
*
42+
* @see the API docs for a the full documentation.
43+
*
44+
*/
45+
ToneAnalyzer.prototype.tone = function(params, callback) {
46+
if (!params || !params.text){
47+
callback(new Error('Missing required parameters: text'));
48+
return;
49+
}
50+
51+
var parameters = {
52+
options: {
53+
url: '/v2/tone',
54+
method: 'POST',
55+
body: params.text
56+
},
57+
defaultOptions: extend(this._options, {
58+
headers: {
59+
'accept':'application/json',
60+
'content-type': 'text/plain'
61+
}
62+
})
63+
};
64+
65+
return requestFactory(parameters, callback);
66+
};
67+
68+
/**
69+
* Returns related words for a given word (or set of words).
70+
*
71+
* @param params: An object to build the query string. It normally contains
72+
* a property "word", the term to look up.
73+
* Alternatively, one can specify a "context" (part of a phrase) and an
74+
* "index" (of the word to lookup, within "context").
75+
* A 'limit' parameter is also accepted to limit the number of related
76+
* words suggested.
77+
*
78+
* @return upon success, the callback function is called with an object
79+
* containing related words to the ones given. Each word comes with
80+
* the semantic type and the meaning and sense of the root word, and
81+
* a weight associated to a trait. Positive weights would 'level up'
82+
* that particular tone, while negative weights would level it down.
83+
*
84+
* For example, if one wants to sound less "angry" on a message, the
85+
* suggestions with negative correlation with "Anger" (Emotion Tone)
86+
* could be replaced in the txt.
87+
*
88+
* @see the API docs for a the full documentation.
89+
*
90+
*/
91+
ToneAnalyzer.prototype.synonym = function(params, callback) {
92+
var parameters = {
93+
options: {
94+
url: '/v2/synonyms',
95+
method: 'GET',
96+
qs: params,
97+
json: true
98+
},
99+
defaultOptions: extend(this._options, {})
100+
};
101+
102+
return requestFactory(parameters, callback);
103+
};
104+
105+
106+
107+
/**
108+
* Returns the different scorecards implemented by the service.
109+
* This is an array of objects with a "name" and "description" properties.
110+
*
111+
* As a first version, only a "business email" scorecard is implemented.
112+
*
113+
* @see the API docs for a the full documentation.
114+
*
115+
*/
116+
ToneAnalyzer.prototype.scorecards = function(params, callback) {
117+
var parameters = {
118+
options: {
119+
url: '/v2/scorecards',
120+
method: 'GET',
121+
json: true
122+
},
123+
defaultOptions: extend(this._options, {})
124+
};
125+
126+
return requestFactory(parameters, callback);
127+
};
128+
129+
module.exports = ToneAnalyzer;

test/test.tone_analyzer.v1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ var assert = require('assert');
44
var watson = require('../lib/index');
55
var nock = require('nock');
66

7-
describe('tone_analyzer', function() {
7+
describe('tone_analyzer.v1', function() {
88

99
var noop = function() {};
1010

test/test.tone_analyzer.v2.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
'use strict';
2+
3+
var assert = require('assert');
4+
var watson = require('../lib/index');
5+
var nock = require('nock');
6+
var qs = require('qs');
7+
8+
describe('tone_analyzer.v2', function() {
9+
10+
var noop = function() {};
11+
12+
var tone_request = {
13+
text: 'IBM Watson Developer Cloud'
14+
};
15+
var synonym_request = {
16+
'word': 'product'
17+
};
18+
var tone_response = {
19+
tree: {}
20+
};
21+
var synonym_response = [ { headword: 'x' } ];
22+
23+
var tone_path = '/v2/tone',
24+
synonym_path = '/v2/synonyms';
25+
26+
var service = {
27+
username: 'batman',
28+
password: 'bruce-wayne',
29+
url: 'http://ibm.com:86',
30+
version: 'v2'
31+
};
32+
33+
before(function() {
34+
nock.disableNetConnect();
35+
nock(service.url)
36+
.persist()
37+
.post(tone_path, tone_request.text)
38+
.reply(200, tone_response)
39+
.get(synonym_path + '?' + qs.stringify(synonym_request))
40+
.reply(200, synonym_response);
41+
});
42+
43+
after(function() {
44+
nock.cleanAll();
45+
});
46+
47+
var tone_analyzer = watson.tone_analyzer(service);
48+
49+
var missingParameter = function(err) {
50+
assert.ok((err instanceof Error) && /required parameters/.test(err));
51+
};
52+
53+
// Tone API
54+
it('tone API should check no parameters provided', function() {
55+
tone_analyzer.tone({}, missingParameter);
56+
tone_analyzer.tone(null, missingParameter);
57+
tone_analyzer.tone(undefined, missingParameter);
58+
});
59+
60+
it('tone API should generate a valid payload with text', function() {
61+
var req = tone_analyzer.tone(tone_request, noop);
62+
var body = new Buffer(req.body).toString('ascii');
63+
assert.equal(req.uri.href, service.url + tone_path);
64+
assert.equal(body, tone_request.text);
65+
assert.equal(req.method, 'POST');
66+
assert.equal(req.headers['content-type'], 'text/plain');
67+
});
68+
69+
it('tone API should format the response', function(done) {
70+
tone_analyzer.tone(tone_request, function(err, response) {
71+
if (err)
72+
done(err);
73+
else {
74+
assert.equal(JSON.stringify(response), JSON.stringify(tone_response));
75+
done();
76+
}
77+
});
78+
});
79+
80+
// Synonym API
81+
82+
it('synonym API should check no parameters provided', function() {
83+
tone_analyzer.synonym({}, missingParameter);
84+
tone_analyzer.synonym(null, missingParameter);
85+
tone_analyzer.synonym(undefined, missingParameter);
86+
});
87+
88+
it('synonym API should generate a valid payload with content', function() {
89+
var req = tone_analyzer.synonym(synonym_request, noop);
90+
var myquery = qs.stringify(synonym_request);
91+
assert.equal(req.uri.href, service.url + synonym_path + '?' + myquery);
92+
assert.equal(req.uri.query, myquery);
93+
assert.equal(req.method, 'GET');
94+
});
95+
it('synonym API should format the response', function(done) {
96+
tone_analyzer.synonym(synonym_request, function(err, response) {
97+
if (err)
98+
done(err);
99+
else {
100+
assert.equal(JSON.stringify(response), JSON.stringify(synonym_response));
101+
done();
102+
}
103+
});
104+
});
105+
});

0 commit comments

Comments
 (0)