Skip to content

Commit 1f0615f

Browse files
committed
Add ability to lookup using a volume id
1 parent 58bf8d3 commit 1f0615f

File tree

3 files changed

+101
-11
lines changed

3 files changed

+101
-11
lines changed

README.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Search for books matching the specified query.
1818

1919
var books = require('google-books-search');
2020

21-
books.search("Professional JavaScript for Web Developers", function(error, results) {
21+
books.search('Professional JavaScript for Web Developers', function(error, results) {
2222
if ( ! error ) {
2323
console.log(results);
2424
} else {
@@ -65,7 +65,17 @@ Returns an array of JSON objects. For example;
6565

6666
For a description of each value; see the [Google Books API documentaion for volumes](https://developers.google.com/books/docs/v1/reference/volumes).
6767

68-
## Advanced Usage
68+
### .lookup(volumeId, options, callback)
69+
70+
Lookup books by Volume ID.
71+
72+
books.lookup('9KJJYFIss_wC', function(error, result) {
73+
...
74+
});
75+
76+
The options argument accepts an object with a `key` field (your API key).
77+
78+
## Advanced Searches
6979

7080
The search method optionally accepts an options object as the second argument. See below for an overview of the available options.
7181

lib/google-books-search.js

+65-8
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,27 @@ var fields = {
3333

3434

3535
// Base url for Google Books API
36-
var API_BASE_URL = 'https://www.googleapis.com/books/v1/volumes?';
36+
var API_BASE_URL = 'https://www.googleapis.com/books/v1';
3737

3838

3939
/**
4040
* Search Google Books
4141
*
42+
* https://developers.google.com/books/docs/v1/reference/volumes/list
43+
*
4244
* @param {String} query
4345
* @param {object} options
4446
* @param {Function} callback
4547
*/
4648
var search = function(query, options, callback) {
4749

4850
// Make the options object optional
49-
if (!callback || typeof callback != 'function') {
51+
if (!_.isFunction(callback)) {
5052
callback = options;
51-
options = undefined;
53+
options = {};
5254
}
5355

54-
var options = _.extend({}, defaultOptions, options || {});
56+
var options = _.extend({}, defaultOptions, options);
5557

5658
// Validate options
5759
if (!query) {
@@ -85,7 +87,7 @@ var search = function(query, options, callback) {
8587
query.key = options.key;
8688
}
8789

88-
sendRequest(query, function(err, response) {
90+
sendRequest('/volumes', query, function(err, response) {
8991
if (err) {
9092
return callback(err);
9193
}
@@ -104,13 +106,62 @@ var search = function(query, options, callback) {
104106
};
105107

106108

109+
/**
110+
* Retrieves a Volume resource based on ID.
111+
*
112+
* https://developers.google.com/books/docs/v1/reference/volumes/get
113+
*
114+
* @param {String} volumeId
115+
* @param {Function} callback
116+
*/
117+
var lookup = function(volumeId, options, callback) {
118+
119+
var query = {};
120+
121+
// Make the options object optional
122+
if (!_.isFunction(callback)) {
123+
callback = options;
124+
options = {};
125+
}
126+
127+
if (!volumeId) {
128+
return callback(new Error('Volume ID is required'));
129+
}
130+
131+
if (options.key) {
132+
query.key = options.key;
133+
}
134+
135+
sendRequest('/volumes/' + volumeId, query, function(err, response) {
136+
if (err) {
137+
return callback(err);
138+
}
139+
140+
if (!response.id || response.id !== volumeId) {
141+
return callback(null, null);
142+
}
143+
144+
callback(null, parseBook(response), response);
145+
});
146+
};
147+
148+
107149
/**
108150
* Send a Google Books API request
109151
*
110152
* @return {void}
111153
*/
112-
var sendRequest = function(params, callback) {
113-
var url = API_BASE_URL + querystring.stringify(params);
154+
var sendRequest = function(path, params, callback) {
155+
var url = API_BASE_URL;
156+
157+
if (path) {
158+
url += path;
159+
}
160+
161+
if (params) {
162+
url += '?' + querystring.stringify(params);
163+
}
164+
114165
https.get(url, function(response) {
115166
if (response.statusCode !== 200) {
116167
return callback(new Error('Google Books API error. Status Code: ' + response.statusCode));
@@ -125,7 +176,12 @@ var sendRequest = function(params, callback) {
125176
response.on('end', function() {
126177
try {
127178
var data = JSON.parse(body);
128-
callback(null, data);
179+
180+
if (data.error) {
181+
callback(new Error(data.error.message));
182+
} else {
183+
callback(null, data);
184+
}
129185
} catch (e) {
130186
callback(new Error('Invalid response from Google Books API.'));
131187
}
@@ -162,3 +218,4 @@ var parseBook = function(data) {
162218

163219

164220
module.exports.search = search;
221+
module.exports.lookup = lookup;

test/search-test.js

+24-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var mocha = require('mocha');
22
var should = require('should');
33
var books = require('../lib/google-books-search.js');
44

5-
describe('Searching', function() {
5+
describe('Search', function() {
66

77
it('should return a JSON object of books', function(done) {
88
books.search('Guinness World Records', {}, function(error, results) {
@@ -69,3 +69,26 @@ describe('Searching', function() {
6969
});
7070

7171
});
72+
73+
74+
describe('Lookup', function() {
75+
76+
it('should return a JSON object of a volume', function(done) {
77+
books.lookup('9KJJYFIss_wC', function(error, result) {
78+
should.not.exist(error);
79+
result.should.be.an.instanceof(Object);
80+
result.id.should.equal('9KJJYFIss_wC');
81+
result.should.have.property('title');
82+
done();
83+
});
84+
});
85+
86+
it('should return an error if an invalid volume id is provided', function(done) {
87+
books.lookup('this is not a real volume id', function(error, result) {
88+
should.exist(error);
89+
should.not.exist(result);
90+
done();
91+
});
92+
});
93+
94+
});

0 commit comments

Comments
 (0)