giphy-api
Version:
JavaScript module for the giphy.com API that supports promises and callbacks.
267 lines (237 loc) • 7.9 kB
JavaScript
var queryStringify = require('./util/queryStringify');
var httpService = require('./util/http');
/**
* Hostname of the Giphy API
*/
var API_HOSTNAME = 'api.giphy.com';
/**
* Base PATH of the Giphy API
*/
var API_BASE_PATH = '/v1/';
/**
* Public API key provided by Giphy for anyone to use. This is used as a fallback
* if no API key is provided
*/
var PUBLIC_BETA_API_KEY = 'dc6zaTOxFJmzC';
/**
* True if promises exist in this engine. Otherwise false.
*/
var promisesExist = typeof Promise !== 'undefined';
/**
* Error handler that supports promises and callbacks
* @param err {String} - Error message
* @param callback
*/
function _handleErr (err, callback) {
if (callback) {
return callback(err);
} else if (promisesExist) {
return Promise.reject(err);
} else {
throw new Error(err);
}
}
/**
* @param options {String|Object} - Options object. If this is a string, it is considered the api key
* options.https {Boolean} - Whether to utilize HTTPS library for requests or HTTP. Defaults to HTTP.
* options.timeout {Number} - Request timeout before returning an error. Defaults to 30000 milliseconds
* options.apiKey {String} - Giphy API key. Defaults to the public beta API key
*/
var GiphyAPI = function (options) {
if (typeof options === 'string' ||
typeof options === 'undefined' ||
options === null) {
this.apiKey = options || PUBLIC_BETA_API_KEY;
options = {};
} else if (typeof options === 'object') {
this.apiKey = options.apiKey || PUBLIC_BETA_API_KEY;
} else {
throw new Error('Invalid options passed to giphy-api');
}
this.https = options.https;
this.timeout = options.timeout || 30000;
this.httpService = httpService.create(this.https);
};
GiphyAPI.prototype = {
/**
* Search all Giphy gifs by word or phrase
*
* @param options Giphy API search options
* options.q {String} - search query term or phrase
* options.limit {Number} - (optional) number of results to return, maximum 100. Default 25.
* options.offset {Number} - (optional) results offset, defaults to 0.
* options.rating {String}- limit results to those rated (y,g, pg, pg-13 or r).
* options.fmt {String} - (optional) return results in html or json format (useful for viewing responses as GIFs to debug/test)
* @param callback
*/
search: function (options, callback) {
if (!options) {
return _handleErr('Search phrase cannot be empty.', callback);
}
return this._request({
api: options.api || 'gifs',
endpoint: 'search',
query: typeof options === 'string' ? {
q: options
} : options
}, callback);
},
/**
* Search all Giphy gifs for a single Id or an array of Id's
*
* @param id {String} - Single Giphy gif string Id or array of string Id's
* @param callback
*/
id: function (id, callback) {
var idIsArr = Array.isArray(id);
if (!id || (idIsArr && id.length === 0)) {
return _handleErr('Id required for id API call', callback);
}
// If an array of Id's was passed, generate a comma delimited string for
// the query string.
if (idIsArr) {
id = id.join();
}
return this._request({
api: 'gifs',
query: {
ids: id
}
}, callback);
},
/**
* Search for Giphy gifs by phrase with Gify vocabulary
*
* @param options Giphy API translate options
* options.s {String} - term or phrase to translate into a GIF
* options.rating {String} - limit results to those rated (y,g, pg, pg-13 or r).
* options.fmt {String} - (optional) return results in html or json format (useful for viewing responses as GIFs to debug/test)
*/
translate: function (options, callback) {
if (!options) {
return _handleErr('Translate phrase cannot be empty.', callback);
}
return this._request({
api: options.api || 'gifs',
endpoint: 'translate',
query: typeof options === 'string' ? {
s: options
} : options
}, callback);
},
/**
* Fetch random gif filtered by tag
*
* @param options Giphy API random options
* options.tag {String} - the GIF tag to limit randomness by
* options.rating {String} - limit results to those rated (y,g, pg, pg-13 or r).
* options.fmt {Stirng} - (optional) return results in html or json format (useful for viewing responses as GIFs to debug/test)
*/
random: function (options, callback) {
var reqOptions = {
api: (options ? options.api : null) || 'gifs',
endpoint: 'random'
};
if (typeof options === 'string') {
reqOptions.query = {
tag: options
};
} else if (typeof options === 'object') {
reqOptions.query = options;
} else if (typeof options === 'function') {
callback = options;
}
return this._request(reqOptions, callback);
},
/**
* Fetch trending gifs
*
* @param options Giphy API random options
* options.limit {Number} - (optional) limits the number of results returned. By default returns 25 results.
* options.rating {String} - limit results to those rated (y,g, pg, pg-13 or r).
* options.fmt {String} - (optional) return results in html or json format (useful for viewing responses as GIFs to debug/test)
*/
trending: function (options, callback) {
var reqOptions = {
endpoint: 'trending'
};
reqOptions.api = (options ? options.api : null) || 'gifs';
// Cleanup so we don't add this to our query
if (options) {
delete options.api;
}
if (typeof options === 'object' &&
Object.keys(options).length !== 0) {
reqOptions.query = options;
} else if (typeof options === 'function') {
callback = options;
}
return this._request(reqOptions, callback);
},
/**
* Prepares the HTTP request and query string for the Giphy API
*
* @param options
* options.endpoint {String} - The API endpoint e.g. search
* options.query {String|Object} Query string parameters. If these are left
* out then we default to an empty string. If this is passed as a string,
* we default to the 'q' query string field used by Giphy.
*/
_request: function (options, callback) {
if (!callback && !promisesExist) {
throw new Error('Callback must be provided if promises are unavailable');
}
var endpoint = '';
if (options.endpoint) {
endpoint = '/' + options.endpoint;
}
var query;
var self = this;
if (typeof options.query !== 'undefined' && typeof options.query === 'object') {
if (Object.keys(options.query).length === 0) {
if (callback) {
return callback(new Error('Options object should not be empty'));
}
return Promise.reject(new Error('Options object should not be empty'));
}
options.query.api_key = this.apiKey;
query = queryStringify(options.query);
} else {
query = queryStringify({
api_key: self.apiKey
});
}
var httpOptions = {
httpService: this.httpService,
request: {
host: API_HOSTNAME,
path: API_BASE_PATH + options.api + endpoint + query
},
timeout: this.timeout,
fmt: options.query && options.query.fmt,
https: this.https
};
var makeRequest = function (resolve, reject) {
httpService.get(httpOptions, resolve, reject);
};
if (callback) {
var resolve = function (res) {
callback(null, res);
};
var reject = function (err) {
callback(err);
};
makeRequest(resolve, reject);
} else {
if (!promisesExist) {
throw new Error('Callback must be provided unless Promises are available');
}
return new Promise(function (resolve, reject) {
makeRequest(resolve, reject);
});
}
}
};
module.exports = function (apiKey, options) {
return new GiphyAPI(apiKey, options);
};