UNPKG

thera

Version:

An ES6 Promise driven Eve Online API client.

184 lines (160 loc) 5.29 kB
import request from 'request'; import xml2js from 'xml2js'; import _ from 'lodash'; import moment from 'moment'; import MemoryCache from '../cache/MemoryCache.js'; import { install } from 'source-map-support'; const xml2jsOptions = { explicitArray: false, explicitRoot: false, explicitChildren: false, mergeAttrs: true }; function getMsDiff(start, end) { start = moment(start); end = moment(end); return end.diff(start); } class HTTPError { constructor(statusCode, url, msg, code) { this.errorType = 'HTTP_ERR'; this.error = {}; if (statusCode) this.error.statusCode = statusCode; if (url) this.error.url = url; if (msg) this.error.msg = msg; if (code) this.error.code = code; } } class ApiRequest { constructor(url, keyID, vCode, characterID) { this.requestOptions = { url: url, }; this.baseQueryParams = { keyID: keyID, vCode: vCode }; if (characterID) this.baseQueryParams.characterID = characterID; install(); } get(extraParams, extraRequestOptions) { return new Promise((resolve, reject) => { var requestParams = {qs:{}}; Object.assign(requestParams, this.requestOptions); Object.assign(requestParams.qs, this.baseQueryParams, extraParams); if (extraRequestOptions) Object.assign(requestParams, extraRequestOptions); request.get(requestParams, (err, res, body) => { if (err) { reject({errorType: 'REQUEST_FAIL', error: err}); return; } if (res.statusCode !== 200) { if (body) { xml2js.parseString(body, xml2jsOptions, (err, result) => { if (err) reject(new HTTPError(res.statusCode, requestParams.url)); else reject(new HTTPError(res.statusCode, requestParams.url, result.error._, result.error.code)); }); } else { reject({errorType: 'HTTP_ERR',error: {statusCode: res.statusCode, url: requestParams.url}}); } return; } xml2js.parseString(body, xml2jsOptions, (err, result) => { if (err) reject({errorType: 'XML_PARSE_ERR', error: err }); resolve(result); }); }); }); } } class XmlApiClient { constructor(options) { if (!options) options = {}; this.keyID = options.keyID ? options.keyID : null; this.vCode = options.vCode ? options.vCode : null; this.characterID = options.characterID ? options.characterID : null; this.rootURL = 'https://api.eveonline.com'; this.endpointSuffix = '.xml.aspx'; this.cache = options.cache ? options.cache : new MemoryCache(); install(); } get (path, extraParams, requestOptions, force) { return new Promise((resolve, reject) => { if (typeof extraParams === 'boolean') force = extraParams; if (typeof requestOptions === 'boolean') force = requestOptions; if (!extraParams) extraParams = {}; if (!requestOptions) requestOptions = {}; // pick up cached response, if one exists in the cache this.cache.exists(path).then(exists => { // resolve cached version if (exists && !force) { return this.cache.get(path).then(body => { body.isCached = true; return resolve(body); }); } var url = this.getFullUrl(path); return new ApiRequest(url, this.keyID, this.vCode, this.characterID) .get(extraParams, requestOptions) .then( body => { // handle GET response if (!body.result) { return reject({errorType: 'INVALID_RESPONSE', error: 'The Response from ' + url + ' was invalid.'}); } var cacheStart = _.get(body, 'currentTime', false); var cacheEnd = _.get(body, 'cachedUntil', false); body.isCached = false; if (cacheStart && cacheEnd) { // cache this response until the received cachedUntil time // (timezone differences are taken into account as we're using the offset from currentTime) timeout = getMsDiff(cacheStart, cacheEnd); return this.cache.put(path, body, timeout).then(() => { return resolve(body); }); } else { return resolve(body); } }); }).catch((err) => { reject(err); }); }); } /** * sets the characterID which will be used in all API requests * @param {Number} id - characterID */ setCharacterID(id) { this.characterID = id; return this; } /** * sets the keyID which will be used in all API requests * @param {Number} keyID - Eve Online API keyID */ setKeyID(keyID) { this.keyID = keyID; return this; } /** * sets the verification code which will be used in all API requests */ setVCode(vCode) { this.vCode = vCode; return this; } /** * Sets multiple configuration parameters at once * @param {Object} config - e.g {characterID: <charID>, keyID: <keyID>, cache: new CustomCache()} */ setConfig(config) { for (var key in config) { this[key] = config.key; } return this; } getFullUrl(path) { return this.rootURL + '/' + path + this.endpointSuffix; } } export default XmlApiClient;