giphy-api
Version:
JavaScript module for the giphy.com API that supports promises and callbacks.
349 lines (304 loc) • 11 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GiphyAPI = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
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);
};
},{"./util/http":2,"./util/queryStringify":3}],2:[function(require,module,exports){
/* globals XMLHttpRequest */
exports.create = function () {
return this;
};
/**
* Browser based GET request
* @param options {Object}
* options.request {Object} - Request data including host and path
* 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.fmt {String} - Return results in html or json format (useful for viewing responses as GIFs to debug/test)
*/
exports.get = function (options, resolve, reject) {
var request = options.request;
var timeout = options.timeout;
var fmt = options.fmt;
var timerId = setTimeout(function () {
reject(new Error('Timeout while fetching asset'));
}, timeout);
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
var onFail = function (err) {
clearTimeout(timerId);
err = err || new Error('Giphy API request failed!');
reject(err);
};
xhr.addEventListener('error', onFail);
xhr.addEventListener('abort', onFail);
xhr.addEventListener('load', function () {
clearTimeout(timerId);
var body = xhr.response;
if (fmt !== 'html') {
body = JSON.parse(body);
}
resolve(body);
});
var protocol = options.https ? 'https' : 'http';
var host = request.host;
var path = request.path;
var url = protocol + '://' + host + path;
xhr.open('GET', url, true);
xhr.send();
};
},{}],3:[function(require,module,exports){
// Adapted with small modifications from: https://github.com/unshiftio/querystringify/blob/master/index.js
var has = Object.prototype.hasOwnProperty;
/**
* Transform a query string to an object.
*
* @param {Object} obj Object that should be transformed.
* @param {String} prefix Optional prefix.
* @returns {String}
* @api public
*/
module.exports = function (obj) {
var pairs = [];
for (var key in obj) {
if (has.call(obj, key)) {
pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
}
return pairs.length ? '?' + pairs.join('&') : '';
};
},{}]},{},[1])(1)
});