cky-image-public
Version:
public image to public host
468 lines (389 loc) • 10.1 kB
JavaScript
const path = require('path');
const async = require('async');
const fs = require('fs');
const _ = require('lodash');
const debug = require('debug');
const ImgBB = require('./lib/imgbb');
const Imgur = require('./lib/imgur');
const Filestack = require('./lib/filestack');
const Dropbox = require('./lib/dropbox');
const Drive = require('./lib/drive');
const Pinterest = require('./lib/pinterest');
const Postimg = require('./lib/postimg');
const Imageshack = require('./lib/imageshack');
const Dropshots = require('./lib/dropshots');
const Imgbox = require('./lib/imgbox');
const Cloudinary = require('./lib/cloudinary');
const Imgeto = require('./lib/imgeto');
const Imggmi = require('./lib/imggmi');
let log = debug('CKY-IMAGE-PUBLIC')
let __defaultOpts = {
imgbb: {},
imgur: {
access_token: '',
},
filestack: {
api_key: ''
},
dropbox: {
token: ''
},
drive: {
access_token: ''
},
pinterest: {
token: ''
},
postimg: {},
imageshack: {
api_key: ''
},
imgeto: {},
imggmi: {},
cloudinary: {
cloud_name: '',
api_key: '',
api_secret: ''
},
dropshots: {
user_name: ''
},
imgbox: {}
}
let ERROR_CODE = {
EUPLOADTYPE: 'Unsupport this type',
EFILEPATH: 'Invalid File path for upload',
EFILENOTEXISTS: 'File is not exists',
EHOSTNOTSUPPORT: 'Host is not support',
EHOSTNOTINIT: 'Host was not init',
}
function roundRobin (arr) {
var _tmp = arr.shift();
arr.push(_tmp);
return _tmp;
}
let HOSTS = {
imgbb: 'IMGBB',
imgur: 'IMGUR',
filestack: 'FILESTACK',
dropbox: 'DROPBOX',
drive: 'DRIVE',
pinterest: 'PINTEREST',
postimg: 'POSTIMG',
imageshack: 'IMAGESHACK',
dropshots: 'DROPSHOTS',
imgbox: 'IMGBOX',
cloudinary: 'CLOUDINARY',
imgeto: 'IMGETO',
imggmi: 'IMGGMI',
}
let _resAdapter = (host, res) => {
log('_resAdapter host=', host);
log('_resAdapter res= %o', res);
let response = res;
let direct_url = '';
let image_url = '';
let urls = [];
try {
switch (host) {
case 'CLOUDINARY':
direct_url = res.url;
image_url = res.url;
urls.push(res.url, res.secure_url);
break;
case 'DRIVE':
direct_url = res.urlShare;
image_url = res.urlShare;
urls.push(res.urlShare);
break;
case 'DROPBOX':
direct_url = res.url;
image_url = res.url;
urls.push(res.url);
break;
case 'DRIVE':
direct_url = res.url;
image_url = res.url;
urls.push(res.url);
break;
case 'FILESTACK':
direct_url = res.url;
image_url = res.url;
urls.push(res.url);
break;
case 'IMAGESHACK':
direct_url = res.links.image_link;
image_url = res.links.done;
urls.push(res.links.image_link, res.links.done, res.links.thumb_link);
break;
case 'IMGBB':
direct_url = res.image.url;
image_url = res.image.url_viewer;
urls.push(res.image.url, res.image.url_viewer, res.image.thumb.url);
break;
case 'IMGBOX':
direct_url = res.files[0].original_url;
image_url = res.files[0].original_url;
urls.push(res.files[0].original_url, res.files[0].thumbnail_url, res.files[0].square_url);
break;
case 'IMGETO':
direct_url = res.image.url;
image_url = res.image.url_viewer;
urls.push(
res.image.url,
res.image.url_viewer
);
if (res.image.thumb && res.image.thumb.url) urls.push(res.image.thumb.url);
if (res.image.medium && res.image.medium.url) urls.push(res.image.medium.url);
break;
case 'IMGGMI':
direct_url = res.viewerLink;
image_url = res.viewerLink;
urls.push(res.viewerLink, res.previewLink);
break;
case 'IMGUR':
direct_url = `https://imgur.com/${res.data.hash}${res.data.ext}`;
image_url = `https://imgur.com/${res.data.hash}${res.data.ext}`;
urls.push(`https://imgur.com/${res.data.hash}${res.data.ext}`);
break;
case 'PINTEREST':
direct_url = res.image_url;
image_url = res.image_url;
urls.push(res.image_url);
break;
case 'POSTIMG':
direct_url = res.linkDirect;
image_url = res.link;
urls.push(
res.linkDirect,
res.link,
res.url,
res.linkThumbnail
);
break;
}
} catch (ex) {
log('EX= %o', ex);
}
return {
direct_url,
image_url,
urls,
response
};
}
let _fn = (hostName, fnUpload, imgPath, callback) => {
log(`start ${hostName} ...`);
fnUpload.upload(imgPath, (err, result) => {
log(`done ${hostName}!`);
if (err) return callback(null, { error: err, result: result });
let res = _resAdapter(hostName, result);
return callback(null, res);
});
}
class ImgPublic {
constructor (options = {}) {
let { imgbb, imgur, filestack, dropbox, drive, pinterest, postimg, imageshack, dropshots, imgbox, cloudinary, imgeto, imggmi } = options;
this.useHosts = [];
if (imgbb) {
this.imgbb = new ImgBB();
this.useHosts.push(HOSTS.imgbb);
}
if (imgur) {
let { access_token } = imgur;
this.imgur = new Imgur({
access_token,
});
this.useHosts.push(HOSTS.imgur);
}
if (filestack) {
let { api_key } = filestack;
this.filestack = new Filestack({
api_key
});
this.useHosts.push(HOSTS.filestack);
}
if (dropbox) {
let { token } = dropbox;
this.dropbox = new Dropbox({
token
})
this.useHosts.push(HOSTS.dropbox);
}
if (drive) {
let { access_token, client_id, client_secret, redirect_uris } = drive;
this.drive = new Drive({
access_token,
client_id,
client_secret,
redirect_uris
})
this.useHosts.push(HOSTS.drive);
}
if (pinterest) {
let { token } = pinterest;
this.pinterest = new Pinterest({
token
})
this.useHosts.push(HOSTS.pinterest);
}
if (postimg) {
this.postimg = new Postimg();
this.useHosts.push(HOSTS.postimg);
}
if (imageshack) {
let { api_key } = imageshack;
this.imageshack = new Imageshack({
api_key
})
this.useHosts.push(HOSTS.imageshack);
}
if (dropshots) {
let { user_name } = dropshots;
this.dropshots = new Dropshots({
user_name
})
this.useHosts.push(HOSTS.dropshots);
}
if (imgbox) {
this.imgbox = new Imgbox();
this.useHosts.push(HOSTS.imgbox);
}
if (cloudinary) {
let { cloud_name, api_key, api_secret } = cloudinary;
this.cloudinary = new Cloudinary({
cloud_name,
api_key,
api_secret
})
this.useHosts.push(HOSTS.cloudinary);
}
if (imgeto) {
this.imgeto = new Imgeto();
this.useHosts.push(HOSTS.imgeto);
}
if (imggmi) {
let { cookie } = imggmi;
this.imggmi = new Imggmi({
cookie
});
this.useHosts.push(HOSTS.imggmi);
}
// shuffle
this.useHosts = _.shuffle(this.useHosts);
}
supported () {
return Object.values(HOSTS);
}
upload (opts = {}, callback) {
let { type, filePath, hosts } = opts;
if (!filePath) return callback('EFILEPATH', ERROR_CODE.EFILEPATH);
let isExists = fs.existsSync(filePath);
if (!isExists) return callback('EFILENOTEXISTS', ERROR_CODE.EFILENOTEXISTS);
type = type || 'ALL';
switch (type) {
case 'ALL':
return this.uploadAll(filePath, callback, hosts);
case 'FALLBACK':
return this.uploadFallback(filePath, callback, hosts);
case 'RANDOM':
return this.uploadRandom(filePath, callback, hosts);
case 'ROUNDROBIN':
return this.uploadRoundRobin(filePath, callback, hosts);
default:
return callback('EUPLOADTYPE', ERROR_CODE.EUPLOADTYPE);
}
}
uploadAll (filePath, callback, hosts) {
let _task = {};
let _tmpHosts = this.useHosts;
if (hosts && hosts.length > 0) _tmpHosts = hosts;
log('_tmpHosts= %o', _tmpHosts);
_tmpHosts.forEach((h) => {
if (this.supported().includes(h)) {
let key = h.toLowerCase();
if (this[key]) {
_task[key] = async.apply(_fn, h, this[key], filePath);
}
}
})
async.parallel(_task, callback);
}
uploadFallback (filePath, callback, hosts) {
let _tmpHosts = this.useHosts;
if (hosts && hosts.length > 0) _tmpHosts = hosts;
let index = 0;
let done = false;
let _result = null
let _test = (cb) => {
let isRunning = true;
if (index >= _tmpHosts.length || done) isRunning = false;
return cb(null, isRunning);
}
let _iter = (cb) => {
let host = _tmpHosts[index];
log('_iter host= %s', host);
if (!this.supported().includes(host)) cb('EHOSTNOTSUPPORT', ERROR_CODE.EHOSTNOTSUPPORT);
let key = host.toLowerCase();
if (!this[key]) return cb('EHOSTNOTINIT', ERROR_CODE.EHOSTNOTINIT);
this[key].upload(filePath, (err, result) => {
if (err) {
index++;
done = false;
return cb(err);
}
log('_iter result= %o', result);
_result = result;
done = true;
return cb(null);
});
}
async.whilst(_test, _iter, (err, result) => {
if (err) return callback(err);
_result = _resAdapter(_tmpHosts[index], _result);
return callback(null, _result);
});
}
uploadRoundRobin (filePath, callback, hosts) {
let _tmpHosts = this.useHosts;
if (hosts && hosts.length > 0) _tmpHosts = hosts;
let host = roundRobin(_tmpHosts);
if (!this.supported().includes(host)) return callback('EHOSTNOTSUPPORT', ERROR_CODE.EHOSTNOTSUPPORT);
let key = host.toLowerCase();
if (!this[key]) return callback('EHOSTNOTINIT', ERROR_CODE.EHOSTNOTINIT);
return this[key].upload(filePath, (err, result) => {
if (err) return callback(err, result);
let res = _resAdapter(host, result);
return callback(null, res);
});
}
uploadRandom (filePath, callback, hosts) {
let _tmpHosts = this.useHosts;
if (hosts && hosts.length > 0) _tmpHosts = hosts;
let host = _.sample(_tmpHosts);
if (!this.supported().includes(host)) return callback('EHOSTNOTSUPPORT', ERROR_CODE.EHOSTNOTSUPPORT);
let key = host.toLowerCase();
if (!this[key]) return callback('EHOSTNOTINIT', ERROR_CODE.EHOSTNOTINIT);
return this[key].upload(filePath, (err, result) => {
if (err) return callback(err, result);
let res = _resAdapter(host, result);
return callback(null, res);
});
}
}
module.exports = {
ImgPublic,
ImgBB,
Imgur,
Filestack,
Dropbox,
Drive,
Pinterest,
Postimg,
Imageshack,
Dropshots,
Imgbox,
Cloudinary,
Imgeto,
Imggmi,
};