Skip to content

Instantly share code, notes, and snippets.

@cacheflow
Last active May 12, 2017 05:57
Show Gist options
  • Save cacheflow/5eeb22092a3a776d2f69825cd6d919cf to your computer and use it in GitHub Desktop.
Save cacheflow/5eeb22092a3a776d2f69825cd6d919cf to your computer and use it in GitHub Desktop.
'use strict'
var imgur = exports;
var request = require('request');
var Q = require('q');
var fs = require('fs');
var urlParser = require('url');
var glob = require('glob');
// The following client ID is tied to the
// registered 'node-imgur' app and is available
// here for public, anonymous usage via this node
// module only.
var IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID || 'f0ea04148a54268';
var IMGUR_API_URL = process.env.IMGUR_API_URL || 'https://api.imgur.com/3/';
var IMGUR_USERNAME = null;
var IMGUR_PASSWORD = null;
var IMGUR_ACCESS_TOKEN = null;
var IMGUR_MASHAPE_KEY = process.env.IMGUR_MASHAPE_KEY;
// An IIFE that returns the OS-specific home directory
// as a location to optionally store the imgur client id
var DEFAULT_CLIENT_ID_PATH = (function() {
var envHome = (process.platform === 'win32') ? 'USERPROFILE' : 'HOME'
return process.env[envHome] + '/.imgur';
}());
imgur.VERSION = require('../package.json').version;
/**
* Send a request to imgur's public API
*
* @param {string} operation - operation to perform; 'info' or 'upload'
* @param {mixed} payload - image data
* @returns {promise}
*/
imgur._imgurRequest = function (operation, payload, extraFormParams) {
var deferred = Q.defer();
var form = null;
var options = {
uri: IMGUR_API_URL,
method: null,
encoding: 'utf8',
json: true
};
if (!operation || typeof operation !== 'string' || ( !payload && operation !== ('credits' && 'search') ) ) {
return deferred.promise;
}
switch(operation) {
case 'upload':
options.method = 'POST';
options.uri += 'image';
break;
case 'credits':
options.method = 'GET';
options.uri += 'credits';
break;
case 'info':
options.method = 'GET';
options.uri += 'image/' + payload;
break;
case 'album':
options.method = 'GET';
options.uri += 'album/' + payload;
break;
case 'createAlbum':
options.method = 'POST';
options.uri += 'album';
break;
case 'delete':
options.method = 'DELETE';
options.uri += 'image/' + payload;
break;
case 'search':
options.method = 'GET';
options.uri += '/gallery/search/' + payload
break;
default:
deferred.reject(new Error('Invalid operation'));
return deferred.promise;
}
imgur._getAuthorizationHeader()
.then(function (authorizationHeader) {
if(IMGUR_MASHAPE_KEY) {
options.headers = {
Authorization: authorizationHeader,
'X-Mashape-Key': IMGUR_MASHAPE_KEY
};
} else {
options.headers = {
Authorization: authorizationHeader
};
}
var r = request(options, function (err, res, body) {
if (err) {
deferred.reject(err);
} else if (body && !body.success) {
deferred.reject({status: body.status, message: body.data ? body.data.error : 'No body data response'});
} else {
deferred.resolve(body);
}
});
if (operation === 'upload') {
form = r.form();
form.append('image', payload);
if (typeof extraFormParams === 'object') {
for (var param in extraFormParams) {
form.append(param, extraFormParams[param]);
}
}
}
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Make a request, handling potential errors
*
* @param {object} options
* @returns {promise}
*/
imgur._request = function (options) {
var deferred = Q.defer();
request(options, function (err, res, body) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(res);
}
});
return deferred.promise;
}
/**
* Get imgur access token using credentials
*
* @returns {promise}
*/
imgur._getAuthorizationHeader = function () {
var deferred = Q.defer();
if (IMGUR_ACCESS_TOKEN) {
deferred.resolve('Bearer ' + IMGUR_ACCESS_TOKEN);
} else if (IMGUR_USERNAME && IMGUR_PASSWORD) {
var options = {
uri: 'https://api.imgur.com/oauth2/authorize',
method: 'GET',
encoding: 'utf8',
qs: {
client_id: IMGUR_CLIENT_ID,
response_type: 'token'
}
};
imgur._request(options).then(function (res) {
var authorize_token = res.headers['set-cookie'][0].match('(^|;)[\s]*authorize_token=([^;]*)')[2];
options.method = 'POST';
options.json = true;
options.form = {
username: IMGUR_USERNAME,
password: IMGUR_PASSWORD,
allow: authorize_token
};
options.headers = {
Cookie: 'authorize_token=' + authorize_token
};
imgur._request(options).then(function (res) {
var location = res.headers.location;
var token = JSON.parse('{"' + decodeURI(location.slice(location.indexOf('#') + 1)).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
IMGUR_ACCESS_TOKEN = token.access_token;
deferred.resolve('Bearer ' + IMGUR_ACCESS_TOKEN);
}).catch(function (err) {
deferred.reject(err);
});
}).catch(function (err) {
deferred.reject(err);
});
} else {
deferred.resolve('Client-ID ' + IMGUR_CLIENT_ID);
}
return deferred.promise;
}
/**
* Set your credentials
* @link https://api.imgur.com/#register
* @param {string} username
* @param {string} password
* @param {string} clientId
*/
imgur.setCredentials = function (username, password, clientId) {
if (clientId && typeof clientId === 'string') {
IMGUR_CLIENT_ID = clientId;
}
if (username && typeof username === 'string') {
IMGUR_USERNAME = username;
}
if (password && typeof password === 'string') {
IMGUR_PASSWORD = password;
}
}
/**
* Attempt to load the client ID from disk
* @param {string} path - path to file with client id
* @returns {promise}
*/
imgur.loadClientId = function (path) {
var deferred = Q.defer();
var clientId = null;
path = path || DEFAULT_CLIENT_ID_PATH;
fs.readFile(path, { encoding: 'utf8' }, function (err, data) {
if (err) {
return deferred.reject(err);
}
if (!data) {
deferred.reject(new Error('File is empty'));
return deferred.promise;
}
return deferred.resolve(data);
});
return deferred.promise;
}
/**
* Attempt to save the client ID to disk
* @param {string} path - path to save the client id to
* @returns {promise}
*/
imgur.saveClientId = function (clientId, path) {
var deferred = Q.defer();
path = path || DEFAULT_CLIENT_ID_PATH;
fs.writeFile(path, clientId, function (err) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve();
});
return deferred.promise;
}
/**
* Attempt to remove a saved client ID from disk
* NOTE: File remains but is emptied
*
* @param {string} path - path to save the client id to
* @returns {promise}
*/
imgur.clearClientId = function (path) {
return imgur.saveClientId('', path);
}
/**
* Set your client ID
* @link https://api.imgur.com/#register
* @param {string} clientId
*/
imgur.setClientId = function (clientId) {
if (clientId && typeof clientId === 'string') {
IMGUR_CLIENT_ID = clientId;
}
}
/**
* Get currently set client ID
* @returns {string} client ID
*/
imgur.getClientId = function () {
return IMGUR_CLIENT_ID;
}
/**
* Set Imgur API URL
* @link https://api.imgur.com/#register or https://imgur-apiv3.p.mashape.com
* @param {string} URL - URL to make the API calls to imgur
*/
imgur.setAPIUrl = function(URL) {
if(URL && typeof URL === 'string') {
IMGUR_API_URL = URL;
}
}
/**
* Get Imgur API Url
* @returns {string} API Url
*/
imgur.getAPIUrl = function() {
return IMGUR_API_URL;
}
/**
* Set Mashape Key
* @link https://market.mashape.com/imgur/imgur-9
* @param {string} mashapeKey
*/
imgur.setMashapeKey = function(mashapeKey) {
if(mashapeKey && typeof mashapeKey === 'string') {
IMGUR_MASHAPE_KEY = mashapeKey;
}
}
/**
* Get Mashape Key
* @returns {string} Mashape Key
*/
imgur.getMashapeKey = function() {
return IMGUR_MASHAPE_KEY;
}
/**
* Delete image
* @param {string} deletehash - deletehash of the image generated during upload
* @returns {promise}
*/
imgur.deleteImage = function (deletehash) {
var deferred = Q.defer();
if(!deletehash) {
deferred.reject('Missing deletehash');
}
imgur._imgurRequest('delete', deletehash)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Get image metadata
* @param {string} id - unique image id
* @returns {promise}
*/
imgur.getInfo = function (id) {
var deferred = Q.defer();
if (!id) {
deferred.reject('Invalid image ID');
return deferred.promise;
}
imgur._imgurRequest('info', id)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Create an album
* @returns {promise}
*/
imgur.createAlbum = function () {
var deferred = Q.defer();
imgur._imgurRequest('createAlbum', 'dummy')
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Get album metadata
* @param {string} id - unique album id
* @returns {promise}
*/
imgur.getAlbumInfo = function (id) {
var deferred = Q.defer();
if (!id) {
deferred.reject(new Error('Invalid album ID'));
return deferred.promise;
}
imgur._imgurRequest('album', id)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
imgur.search = function(query, options) {
var deferred = Q.defer();
var err = imgur.checkForSearchError(query, options)
if(!err) {
var params = imgur.initSearchParams(query, options || {});
imgur._imgurRequest('search', params.queryStr)
.then(function (json) {
var copyOfParams = params
delete copyOfParams['queryStr']
deferred.resolve({data: json.data, params: copyOfParams});
})
.catch(function (err) {
deferred.reject(err);
});
}
else {
deferred.reject(err)
}
return deferred.promise
}
imgur.checkForSearchError = function (query, options) {
var errMsg;
var ifOptionsArray = options instanceof Array
var ifOptionsNullOrUndefiend = options === (null || undefined)
var ifObject = typeof options != 'object'
if(!query) {
errMsg = "Search requires a query. Try searching with a query (e.g cats)."
}
else if(typeof query != 'string') {
errMsg = "You did not pass a string as a query."
}
else if (ifOptionsArray || ifOptionsNullOrUndefiend || ifObject) {
var errMsg;
var sortOptions = "sort: Accepts 'time', 'viral', or 'top' as a value. Defaults to top."
var dateRangeOptions = "dateRange: Accepts 'day', 'week', 'month', 'year', or 'all' as a value. Defaults to all."
var pageOptions = "page: Accepts an integer (e.g. 1, 2, 3, 4) as a value. Defaults to 1."
var helpMsg = "\n" + sortOptions + "\n" + dateRangeOptions + "\n" + pageOptions
errMsg = 'You did not pass an object to options. Pass in an object of options, or an empty object {} to return the default parameters.' + "\n" + helpMsg
}
else {
errMsg = ""
}
return errMsg
}
imgur.initSearchParams = function(query, options) {
query = query ? query : "";
var params = {sort: 'time', dateRange: 'all', page: '1'};
for(var key in options) {
params[key] = params[key] != options[key] ? options[key] : params[key]
}
var queryStr = "";
Object.keys(params).forEach(function(param) {
queryStr += '/' + params[param];
})
queryStr += "?q=" + query;
params['queryStr'] = queryStr
return params
}
/**
* Upload an image file
* @param {string} file - path to a binary image file
* @param {string=} albumId - the album id to upload to
* @returns {promise}
*/
imgur.uploadFile = function (file, albumId) {
var deferred = Q.defer(),
extraFormParams = {};
if (typeof albumId === 'string' && albumId.length) {
extraFormParams.album = albumId;
}
glob(file, function (err, files) {
if (err) {
deferred.reject(err);
return deferred.promise;
} else if (!files.length) {
deferred.reject(new Error('Invalid file or glob'));
return deferred.promise;
}
files.forEach(function (f, index, arr) {
var readStream = fs.createReadStream(f);
readStream.on('error', deferred.reject);
imgur._imgurRequest('upload', readStream, extraFormParams)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
});
});
return deferred.promise;
}
/**
* Upload a url
* @param {string} url - address to an image on the web
* @param {string=} albumId - the album id to upload to
* @returns {promise}
*/
imgur.uploadUrl = function (url, albumId) {
var deferred = Q.defer(),
extraFormParams = {};
if (typeof albumId === 'string' && albumId.length) {
extraFormParams.album = albumId;
}
if (!url || !urlParser.parse(url).protocol) {
deferred.reject(new Error('Invalid URL'));
return deferred.promise;
}
imgur._imgurRequest('upload', url, extraFormParams)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Upload a Base64-encoded string
* @link http://en.wikipedia.org/wiki/Base64
* @param {string} base64 - a base-64 encoded string
* @param {string=} albumId - the album id to upload to
* @returns {promise} - on resolve, returns the resulting image object from imgur
*/
imgur.uploadBase64 = function (base64, albumId) {
var
deferred = Q.defer(),
extraFormParams = {};
if (typeof albumId === 'string' && albumId.length) {
extraFormParams.album = albumId;
}
if (typeof base64 !== 'string' || !base64 || !base64.length) {
deferred.reject(new Error('Invalid Base64 input'));
return deferred.promise;
}
imgur._imgurRequest('upload', base64, extraFormParams)
.then(function (image) {
deferred.resolve(image);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Upload an entire album of images
* @param {Array} images - array of image strings of desired type
* @param {string} uploadType - the type of the upload ('File', 'Url', 'Base64')
* @param {boolean=} failSafe - if true, it won't fail on invalid or empty image input and will return an object with empty album data and an empty image array
* @returns {promise} - on resolve, returns an object with the album data and and an array of image data objects {data: {...}, images: [{...}, ...]}
*/
imgur.uploadAlbum = function (images, uploadType, failSafe) {
var deferred = Q.defer();
if (!images || !images.length || !(typeof images === 'string' || images instanceof Array)) {
if (failSafe) {
deferred.resolve({data: {}, images: []});
} else {
deferred.reject(new Error('Invalid image input, only arrays supported'));
}
return deferred.promise;
}
imgur.createAlbum()
.then(function(album) {
imgur.uploadImages(images, uploadType, album.data.id)
.then(function (images) {
deferred.resolve({data: album.data, images: images});
})
.catch(function (err) {
return deferred.reject(err);
});
})
.catch(function (err) {
return deferred.reject(err);
});
return deferred.promise;
}
/**
* Upload an entire album of images
* @param {Array} images - array of image strings of desired type
* @param {string} uploadType - the type of the upload ('File', 'Url', 'Base64')
* @param {string=} albumId - the album id to upload to
* @returns {promise} - on resolve, returns an array of image data objects {album: {...}, images: [{...}, ...]}
*/
imgur.uploadImages = function (images, uploadType, albumId) {
var deferred = Q.defer();
var upload = imgur['upload' + uploadType];
if (!images || !images.length || !(typeof images === 'string' || images instanceof Array)) {
deferred.reject(new Error('Invalid image input, only arrays supported'));
return deferred.promise;
}
var results = [];
var progress = 0;
var done = images.length;
for (var i = 0; i < done; i++) {
upload(images[i], albumId)
.then(function (image) {
results.push(image.data);
++progress;
if (progress == done) {
deferred.resolve(results);
}
})
.catch(function (err) {
deferred.reject(err);
return deferred.promise;
});
}
return deferred.promise;
}
/**
* Get current credit limits
* @returns {promise}
*/
imgur.getCredits = function () {
var deferred = Q.defer();
imgur._imgurRequest('credits')
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
'use strict'
var imgur = exports;
var request = require('request');
var Q = require('q');
var fs = require('fs');
var urlParser = require('url');
var glob = require('glob');
// The following client ID is tied to the
// registered 'node-imgur' app and is available
// here for public, anonymous usage via this node
// module only.
var IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID || 'f0ea04148a54268';
var IMGUR_API_URL = process.env.IMGUR_API_URL || 'https://api.imgur.com/3/';
var IMGUR_USERNAME = null;
var IMGUR_PASSWORD = null;
var IMGUR_ACCESS_TOKEN = null;
var IMGUR_MASHAPE_KEY = process.env.IMGUR_MASHAPE_KEY;
// An IIFE that returns the OS-specific home directory
// as a location to optionally store the imgur client id
var DEFAULT_CLIENT_ID_PATH = (function() {
var envHome = (process.platform === 'win32') ? 'USERPROFILE' : 'HOME'
return process.env[envHome] + '/.imgur';
}());
imgur.VERSION = require('../package.json').version;
/**
* Send a request to imgur's public API
*
* @param {string} operation - operation to perform; 'info' or 'upload'
* @param {mixed} payload - image data
* @returns {promise}
*/
imgur._imgurRequest = function (operation, payload, extraFormParams) {
var deferred = Q.defer();
var form = null;
var options = {
uri: IMGUR_API_URL,
method: null,
encoding: 'utf8',
json: true
};
if (!operation || typeof operation !== 'string' || ( !payload && operation !== ('credits' && 'search') ) ) {
return deferred.promise;
}
switch(operation) {
case 'upload':
options.method = 'POST';
options.uri += 'image';
break;
case 'credits':
options.method = 'GET';
options.uri += 'credits';
break;
case 'info':
options.method = 'GET';
options.uri += 'image/' + payload;
break;
case 'album':
options.method = 'GET';
options.uri += 'album/' + payload;
break;
case 'createAlbum':
options.method = 'POST';
options.uri += 'album';
break;
case 'delete':
options.method = 'DELETE';
options.uri += 'image/' + payload;
break;
case 'search':
options.method = 'GET';
options.uri += '/gallery/search/' + payload
break;
default:
deferred.reject(new Error('Invalid operation'));
return deferred.promise;
}
imgur._getAuthorizationHeader()
.then(function (authorizationHeader) {
if(IMGUR_MASHAPE_KEY) {
options.headers = {
Authorization: authorizationHeader,
'X-Mashape-Key': IMGUR_MASHAPE_KEY
};
} else {
options.headers = {
Authorization: authorizationHeader
};
}
var r = request(options, function (err, res, body) {
if (err) {
deferred.reject(err);
} else if (body && !body.success) {
deferred.reject({status: body.status, message: body.data ? body.data.error : 'No body data response'});
} else {
deferred.resolve(body);
}
});
if (operation === 'upload') {
form = r.form();
form.append('image', payload);
if (typeof extraFormParams === 'object') {
for (var param in extraFormParams) {
form.append(param, extraFormParams[param]);
}
}
}
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Make a request, handling potential errors
*
* @param {object} options
* @returns {promise}
*/
imgur._request = function (options) {
var deferred = Q.defer();
request(options, function (err, res, body) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(res);
}
});
return deferred.promise;
}
/**
* Get imgur access token using credentials
*
* @returns {promise}
*/
imgur._getAuthorizationHeader = function () {
var deferred = Q.defer();
if (IMGUR_ACCESS_TOKEN) {
deferred.resolve('Bearer ' + IMGUR_ACCESS_TOKEN);
} else if (IMGUR_USERNAME && IMGUR_PASSWORD) {
var options = {
uri: 'https://api.imgur.com/oauth2/authorize',
method: 'GET',
encoding: 'utf8',
qs: {
client_id: IMGUR_CLIENT_ID,
response_type: 'token'
}
};
imgur._request(options).then(function (res) {
var authorize_token = res.headers['set-cookie'][0].match('(^|;)[\s]*authorize_token=([^;]*)')[2];
options.method = 'POST';
options.json = true;
options.form = {
username: IMGUR_USERNAME,
password: IMGUR_PASSWORD,
allow: authorize_token
};
options.headers = {
Cookie: 'authorize_token=' + authorize_token
};
imgur._request(options).then(function (res) {
var location = res.headers.location;
var token = JSON.parse('{"' + decodeURI(location.slice(location.indexOf('#') + 1)).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
IMGUR_ACCESS_TOKEN = token.access_token;
deferred.resolve('Bearer ' + IMGUR_ACCESS_TOKEN);
}).catch(function (err) {
deferred.reject(err);
});
}).catch(function (err) {
deferred.reject(err);
});
} else {
deferred.resolve('Client-ID ' + IMGUR_CLIENT_ID);
}
return deferred.promise;
}
/**
* Set your credentials
* @link https://api.imgur.com/#register
* @param {string} username
* @param {string} password
* @param {string} clientId
*/
imgur.setCredentials = function (username, password, clientId) {
if (clientId && typeof clientId === 'string') {
IMGUR_CLIENT_ID = clientId;
}
if (username && typeof username === 'string') {
IMGUR_USERNAME = username;
}
if (password && typeof password === 'string') {
IMGUR_PASSWORD = password;
}
}
/**
* Attempt to load the client ID from disk
* @param {string} path - path to file with client id
* @returns {promise}
*/
imgur.loadClientId = function (path) {
var deferred = Q.defer();
var clientId = null;
path = path || DEFAULT_CLIENT_ID_PATH;
fs.readFile(path, { encoding: 'utf8' }, function (err, data) {
if (err) {
return deferred.reject(err);
}
if (!data) {
deferred.reject(new Error('File is empty'));
return deferred.promise;
}
return deferred.resolve(data);
});
return deferred.promise;
}
/**
* Attempt to save the client ID to disk
* @param {string} path - path to save the client id to
* @returns {promise}
*/
imgur.saveClientId = function (clientId, path) {
var deferred = Q.defer();
path = path || DEFAULT_CLIENT_ID_PATH;
fs.writeFile(path, clientId, function (err) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve();
});
return deferred.promise;
}
/**
* Attempt to remove a saved client ID from disk
* NOTE: File remains but is emptied
*
* @param {string} path - path to save the client id to
* @returns {promise}
*/
imgur.clearClientId = function (path) {
return imgur.saveClientId('', path);
}
/**
* Set your client ID
* @link https://api.imgur.com/#register
* @param {string} clientId
*/
imgur.setClientId = function (clientId) {
if (clientId && typeof clientId === 'string') {
IMGUR_CLIENT_ID = clientId;
}
}
/**
* Get currently set client ID
* @returns {string} client ID
*/
imgur.getClientId = function () {
return IMGUR_CLIENT_ID;
}
/**
* Set Imgur API URL
* @link https://api.imgur.com/#register or https://imgur-apiv3.p.mashape.com
* @param {string} URL - URL to make the API calls to imgur
*/
imgur.setAPIUrl = function(URL) {
if(URL && typeof URL === 'string') {
IMGUR_API_URL = URL;
}
}
/**
* Get Imgur API Url
* @returns {string} API Url
*/
imgur.getAPIUrl = function() {
return IMGUR_API_URL;
}
/**
* Set Mashape Key
* @link https://market.mashape.com/imgur/imgur-9
* @param {string} mashapeKey
*/
imgur.setMashapeKey = function(mashapeKey) {
if(mashapeKey && typeof mashapeKey === 'string') {
IMGUR_MASHAPE_KEY = mashapeKey;
}
}
/**
* Get Mashape Key
* @returns {string} Mashape Key
*/
imgur.getMashapeKey = function() {
return IMGUR_MASHAPE_KEY;
}
/**
* Delete image
* @param {string} deletehash - deletehash of the image generated during upload
* @returns {promise}
*/
imgur.deleteImage = function (deletehash) {
var deferred = Q.defer();
if(!deletehash) {
deferred.reject('Missing deletehash');
}
imgur._imgurRequest('delete', deletehash)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Get image metadata
* @param {string} id - unique image id
* @returns {promise}
*/
imgur.getInfo = function (id) {
var deferred = Q.defer();
if (!id) {
deferred.reject('Invalid image ID');
return deferred.promise;
}
imgur._imgurRequest('info', id)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Create an album
* @returns {promise}
*/
imgur.createAlbum = function () {
var deferred = Q.defer();
imgur._imgurRequest('createAlbum', 'dummy')
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Get album metadata
* @param {string} id - unique album id
* @returns {promise}
*/
imgur.getAlbumInfo = function (id) {
var deferred = Q.defer();
if (!id) {
deferred.reject(new Error('Invalid album ID'));
return deferred.promise;
}
imgur._imgurRequest('album', id)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
imgur.search = function(query, options) {
var deferred = Q.defer();
var checkQuery = imgur.checkQuery(query)
var params;
options = options || {}
if(checkQuery.constructor === Error) {
deferred.reject(checkQuery)
}
else {
var params = imgur.initSearchParams(query, options);
imgur._imgurRequest('search', params.queryStr)
.then(function (json) {
var copyOfParams = params
delete copyOfParams['queryStr']
deferred.resolve({data: json.data, params: copyOfParams});
})
.catch(function (err) {
deferred.reject(err);
});
}
return deferred.promise
}
imgur.checkQuery = function(query) {
var errMsg;
if(!query) {
errMsg = new Error("Search requires a query. Try searching with a query (e.g cats).")
}
else if(typeof query != 'string') {
errMsg = new Error("You did not pass a string as a query.")
}
else {
errMsg = ''
}
return errMsg
}
imgur.initSearchParams = function(query, options) {
var params = {sort: 'time', dateRange: 'all', page: '1'};
for(var key in options) {
if ( key == 'sort' || key == 'dateRange' || key == 'page' ) {
params[key] = params[key] != options[key] ? options[key] : params[key]
}
}
var queryStr = "";
Object.keys(params).forEach(function(param) {
queryStr += '/' + params[param];
})
queryStr += "?q=" + query;
params['queryStr'] = queryStr
return params
}
/**
* Upload an image file
* @param {string} file - path to a binary image file
* @param {string=} albumId - the album id to upload to
* @returns {promise}
*/
imgur.uploadFile = function (file, albumId) {
var deferred = Q.defer(),
extraFormParams = {};
if (typeof albumId === 'string' && albumId.length) {
extraFormParams.album = albumId;
}
glob(file, function (err, files) {
if (err) {
deferred.reject(err);
return deferred.promise;
} else if (!files.length) {
deferred.reject(new Error('Invalid file or glob'));
return deferred.promise;
}
files.forEach(function (f, index, arr) {
var readStream = fs.createReadStream(f);
readStream.on('error', deferred.reject);
imgur._imgurRequest('upload', readStream, extraFormParams)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
});
});
return deferred.promise;
}
/**
* Upload a url
* @param {string} url - address to an image on the web
* @param {string=} albumId - the album id to upload to
* @returns {promise}
*/
imgur.uploadUrl = function (url, albumId) {
var deferred = Q.defer(),
extraFormParams = {};
if (typeof albumId === 'string' && albumId.length) {
extraFormParams.album = albumId;
}
if (!url || !urlParser.parse(url).protocol) {
deferred.reject(new Error('Invalid URL'));
return deferred.promise;
}
imgur._imgurRequest('upload', url, extraFormParams)
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Upload a Base64-encoded string
* @link http://en.wikipedia.org/wiki/Base64
* @param {string} base64 - a base-64 encoded string
* @param {string=} albumId - the album id to upload to
* @returns {promise} - on resolve, returns the resulting image object from imgur
*/
imgur.uploadBase64 = function (base64, albumId) {
var
deferred = Q.defer(),
extraFormParams = {};
if (typeof albumId === 'string' && albumId.length) {
extraFormParams.album = albumId;
}
if (typeof base64 !== 'string' || !base64 || !base64.length) {
deferred.reject(new Error('Invalid Base64 input'));
return deferred.promise;
}
imgur._imgurRequest('upload', base64, extraFormParams)
.then(function (image) {
deferred.resolve(image);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
/**
* Upload an entire album of images
* @param {Array} images - array of image strings of desired type
* @param {string} uploadType - the type of the upload ('File', 'Url', 'Base64')
* @param {boolean=} failSafe - if true, it won't fail on invalid or empty image input and will return an object with empty album data and an empty image array
* @returns {promise} - on resolve, returns an object with the album data and and an array of image data objects {data: {...}, images: [{...}, ...]}
*/
imgur.uploadAlbum = function (images, uploadType, failSafe) {
var deferred = Q.defer();
if (!images || !images.length || !(typeof images === 'string' || images instanceof Array)) {
if (failSafe) {
deferred.resolve({data: {}, images: []});
} else {
deferred.reject(new Error('Invalid image input, only arrays supported'));
}
return deferred.promise;
}
imgur.createAlbum()
.then(function(album) {
imgur.uploadImages(images, uploadType, album.data.id)
.then(function (images) {
deferred.resolve({data: album.data, images: images});
})
.catch(function (err) {
return deferred.reject(err);
});
})
.catch(function (err) {
return deferred.reject(err);
});
return deferred.promise;
}
/**
* Upload an entire album of images
* @param {Array} images - array of image strings of desired type
* @param {string} uploadType - the type of the upload ('File', 'Url', 'Base64')
* @param {string=} albumId - the album id to upload to
* @returns {promise} - on resolve, returns an array of image data objects {album: {...}, images: [{...}, ...]}
*/
imgur.uploadImages = function (images, uploadType, albumId) {
var deferred = Q.defer();
var upload = imgur['upload' + uploadType];
if (!images || !images.length || !(typeof images === 'string' || images instanceof Array)) {
deferred.reject(new Error('Invalid image input, only arrays supported'));
return deferred.promise;
}
var results = [];
var progress = 0;
var done = images.length;
for (var i = 0; i < done; i++) {
upload(images[i], albumId)
.then(function (image) {
results.push(image.data);
++progress;
if (progress == done) {
deferred.resolve(results);
}
})
.catch(function (err) {
deferred.reject(err);
return deferred.promise;
});
}
return deferred.promise;
}
/**
* Get current credit limits
* @returns {promise}
*/
imgur.getCredits = function () {
var deferred = Q.defer();
imgur._imgurRequest('credits')
.then(function (json) {
deferred.resolve(json);
})
.catch(function (err) {
deferred.reject(err);
});
return deferred.promise;
}
var imgur = require('../lib/imgur.js'),
chai = require('chai'),
chaiAsPromised = require('chai-as-promised'),
expect = chai.expect,
Q = require('q'),
sinon = require('sinon'),
sinonChai = require("sinon-chai")
chai.use(sinonChai);
chai.use(chaiAsPromised);
describe('SEARCH', function() {
describe('search options validations', function() {
it('should fail when options are not an object', function(done) {
var sortOptions = "sort: Accepts 'time', 'viral', or 'top' as a value. Defaults to top."
var dateRangeOptions = "dateRange: Accepts 'day', 'week', 'month', 'year', or 'all' as a value. Defaults to all."
var pageOptions = "page: Accepts an integer (e.g. 1, 2, 3, 4) as a value. Defaults to 1."
var helpMsg = "\n" + sortOptions + "\n" + dateRangeOptions + "\n" + pageOptions
errMsg = 'You did not pass an object to options. Pass in an object of options, or an empty object {} to return the default parameters.' + "\n" + helpMsg
expect(imgur.search('meme', [])).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is not passed', function(done) {
var errMsg = "Search requires a query. Try searching with a query (e.g cats)."
expect(imgur.search()).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is passed a boolean', function(done) {
var errMsg = "You did not pass a string as a query."
expect(imgur.search(true)).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is passed a number', function(done) {
var errMsg = "You did not pass a string as a query."
expect(imgur.search(1)).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is passed a number', function(done) {
var errMsg = "You did not pass a string as a query."
expect(imgur.search(1)).to.be.rejectedWith(errMsg).and.notify(done)
})
})
describe('delegates to #_imgurRequest(\'search\', ...)', function() {
var mockResult = {
"data": [],
"params": {
"page": "1",
"dateRange": "month",
"sort": "viral"
}
};
var payload = "/viral/month/1?q=meme";
beforeEach(function() {
var deferred = Q.defer();
sinon.stub(imgur, "_imgurRequest").returns(deferred.promise);
deferred.resolve(mockResult);
});
afterEach(function () {
imgur._imgurRequest.restore();
});
it('should delegate', function(done) {
var promise = imgur.search('meme', {sort: "viral", dateRange: 'month', page: '1'});
expect(imgur._imgurRequest)
.to.have.been.calledWith('search', payload)
expect(promise)
.to.eventually.deep.equal(mockResult).and.notify(done)
});
});
})
var imgur = require('../lib/imgur.js'),
chai = require('chai'),
chaiAsPromised = require('chai-as-promised'),
expect = chai.expect,
Q = require('q'),
sinon = require('sinon'),
sinonChai = require("sinon-chai")
chai.use(sinonChai);
chai.use(chaiAsPromised);
describe('SEARCH', function() {
describe('search options validations', function() {
it('should fail when query is not passed', function(done) {
var errMsg = "Search requires a query. Try searching with a query (e.g cats)."
expect(imgur.search()).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is passed a boolean', function(done) {
var errMsg = "You did not pass a string as a query."
expect(imgur.search(true)).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is passed a number', function(done) {
var errMsg = "You did not pass a string as a query."
expect(imgur.search(1)).to.be.rejectedWith(errMsg).and.notify(done)
})
it('should fail when query is passed a number', function(done) {
var errMsg = "You did not pass a string as a query."
expect(imgur.search(1)).to.be.rejectedWith(errMsg).and.notify(done)
})
})
describe('delegates to #_imgurRequest(\'search\', ...)', function() {
var mockResult = {
"data": [],
"params": {
"page": "1",
"dateRange": "month",
"sort": "viral"
}
};
var payload = "/viral/month/1?q=meme";
beforeEach(function() {
var deferred = Q.defer();
sinon.stub(imgur, "_imgurRequest").returns(deferred.promise);
deferred.resolve(mockResult);
});
afterEach(function () {
imgur._imgurRequest.restore();
});
it('should delegate', function(done) {
var promise = imgur.search('meme', {sort: "viral", dateRange: 'month', page: '1'});
expect(imgur._imgurRequest)
.to.have.been.calledWith('search', payload)
expect(promise)
.to.eventually.deep.equal(mockResult).and.notify(done)
});
});
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment