diff options
author | pluralcafe-docker <docker@plural.cafe> | 2018-08-22 07:57:04 +0000 |
---|---|---|
committer | pluralcafe-docker <docker@plural.cafe> | 2018-08-22 07:57:04 +0000 |
commit | e530b55b8dc55f4c8974d2999b7e572b19941c4c (patch) | |
tree | 5ecfcd1a1a8cfff43cf43948998b089253df10d6 /node-mastodon/lib | |
parent | 331a28d01d4e35805200d8d6236ec81d105e9ccd (diff) |
Don't use node-mastodon and instead use fetch
Diffstat (limited to 'node-mastodon/lib')
-rw-r--r-- | node-mastodon/lib/helpers.js | 65 | ||||
-rw-r--r-- | node-mastodon/lib/mastodon.js | 340 | ||||
-rw-r--r-- | node-mastodon/lib/settings.js | 2 |
3 files changed, 0 insertions, 407 deletions
diff --git a/node-mastodon/lib/helpers.js b/node-mastodon/lib/helpers.js deleted file mode 100644 index 8833968..0000000 --- a/node-mastodon/lib/helpers.js +++ /dev/null @@ -1,65 +0,0 @@ -var querystring = require('querystring'); -var request = require('request'); - -/** - * For each `/:param` fragment in path, move the value in params - * at that key to path. If the key is not found in params, throw. - * Modifies both params and path values. - * - * @param {Objet} params Object used to build path. - * @param {String} path String to transform. - * @return {Undefined} - * - */ -exports.moveParamsIntoPath = function (params, path) { - var rgxParam = /\/:(\w+)/g - var missingParamErr = null - - path = path.replace(rgxParam, function (hit) { - var paramName = hit.slice(2) - var suppliedVal = params[paramName] - if (!suppliedVal) { - throw new Error('Mastodon: Params object is missing a required parameter for this request: `'+paramName+'`') - } - var retVal = '/' + suppliedVal - delete params[paramName] - return retVal - }) - return path -} - -/** - * When Mastodon returns a response that looks like an error response, - * use this function to attach the error info in the response body to `err`. - * - * @param {Error} err Error instance to which body info will be attached - * @param {Object} body JSON object that is the deserialized HTTP response body received from Mastodon - * @return {Undefined} - */ -exports.attachBodyInfoToError = function (err, body) { - err.mastodonReply = body; - if (!body) { - return - } - if (body.error) { - // the body itself is an error object - err.message = body.error - err.allErrors = err.allErrors.concat([body]) - } else if (body.errors && body.errors.length) { - // body contains multiple error objects - err.message = body.errors[0].message; - err.code = body.errors[0].code; - err.allErrors = err.allErrors.concat(body.errors) - } -} - -exports.makeMastodonError = function (message) { - var err = new Error() - if (message) { - err.message = message - } - err.code = null - err.allErrors = [] - err.mastodonReply = null - return err -} diff --git a/node-mastodon/lib/mastodon.js b/node-mastodon/lib/mastodon.js deleted file mode 100644 index 7f5c8c1..0000000 --- a/node-mastodon/lib/mastodon.js +++ /dev/null @@ -1,340 +0,0 @@ -// -// Mastodon API Wrapper -// -var assert = require('assert'); -var Promise = require('bluebird'); -var request = require('request'); -var util = require('util'); -var helpers = require('./helpers'); -var STATUS_CODES_TO_ABORT_ON = require('./settings').STATUS_CODES_TO_ABORT_ON; - -var DEFAULT_REST_ROOT = 'https://mastodon.social/api/v1/'; - -var required_for_user_auth = [ - 'access_token', -]; - -// -// Mastodon -// -var Mastodon = function (config) { - if (!(this instanceof Mastodon)) { - return new Mastodon(config); - } - - var self = this - var credentials = { - access_token : config.access_token - } - - this.apiUrl = config.api_url || DEFAULT_REST_ROOT; - - this._validateConfigOrThrow(config); - this.config = config; - this._mastodon_time_minus_local_time_ms = 0; -} - -Mastodon.prototype.get = function (path, params, callback) { - return this.request('GET', path, params, callback) -} - -Mastodon.prototype.post = function (path, params, callback) { - return this.request('POST', path, params, callback) -} - -Mastodon.prototype.patch = function (path, params, callback) { - return this.request('PATCH', path, params, callback) -} - -Mastodon.prototype.delete = function (path, params, callback) { - return this.request('DELETE', path, params, callback) -} - -Mastodon.prototype.request = function (method, path, params, callback) { - var self = this; - assert(method == 'GET' || method == 'POST' || method == 'PATCH' || method == 'DELETE'); - // if no `params` is specified but a callback is, use default params - if (typeof params === 'function') { - callback = params - params = {} - } - - return new Promise(function (resolve, reject) { - var _returnErrorToUser = function (err) { - if (callback && typeof callback === 'function') { - callback(err, null, null); - } - reject(err); - } - - self._buildReqOpts(method, path, params, function (err, reqOpts) { - if (err) { - _returnErrorToUser(err); - return - } - - var mastoOptions = (params && params.masto_options) || {}; - - process.nextTick(function () { - // ensure all HTTP i/o occurs after the user has a chance to bind their event handlers - self._doRestApiRequest(reqOpts, mastoOptions, method, function (err, parsedBody, resp) { - if (err) { - _returnErrorToUser(err); - return - } - self._updateClockOffsetFromResponse(resp); - - if (self.config.trusted_cert_fingerprints) { - if (!resp.socket.authorized) { - // The peer certificate was not signed by one of the authorized CA's. - var authErrMsg = resp.socket.authorizationError.toString(); - var err = helpers.makeMastodonError('The peer certificate was not signed; ' + authErrMsg); - _returnErrorToUser(err); - return; - } - var fingerprint = resp.socket.getPeerCertificate().fingerprint; - var trustedFingerprints = self.config.trusted_cert_fingerprints; - if (trustedFingerprints.indexOf(fingerprint) === -1) { - var errMsg = util.format('Certificate untrusted. Trusted fingerprints are: %s. Got fingerprint: %s.', - trustedFingerprints.join(','), fingerprint); - var err = new Error(errMsg); - _returnErrorToUser(err); - return; - } - } - - if (callback && typeof callback === 'function') { - callback(err, parsedBody, resp); - } - - resolve({ data: parsedBody, resp: resp }); - return; - }) - }) - }); - }); -} - -Mastodon.prototype._updateClockOffsetFromResponse = function (resp) { - var self = this; - if (resp && resp.headers && resp.headers.date && - new Date(resp.headers.date).toString() !== 'Invalid Date' - ) { - var mastodonTimeMs = new Date(resp.headers.date).getTime() - self._mastodon_time_minus_local_time_ms = mastodonTimeMs - Date.now(); - } -} - -/** - * Builds and returns an options object ready to pass to `request()` - * @param {String} method "GET", "POST", or "DELETE" - * @param {String} path REST API resource uri (eg. "statuses/destroy/:id") - * @param {Object} params user's params object - * @returns {Undefined} - * - * Calls `callback` with Error, Object where Object is an options object ready to pass to `request()`. - * - * Returns error raised (if any) by `helpers.moveParamsIntoPath()` - */ -Mastodon.prototype._buildReqOpts = function (method, path, params, callback) { - var self = this - if (!params) { - params = {} - } - var finalParams = params; - delete finalParams.masto_options - - // the options object passed to `request` used to perform the HTTP request - var reqOpts = { - headers: { - 'Accept': '*/*', - 'User-Agent': 'node-mastodon-client', - 'Authorization': 'Bearer ' + self.config.access_token - }, - gzip: true, - encoding: null, - rejectUnauthorized: false, - insecure: true, - } - - if (typeof self.config.timeout_ms !== 'undefined') { - reqOpts.timeout = self.config.timeout_ms; - } - - try { - // finalize the `path` value by building it using user-supplied params - path = helpers.moveParamsIntoPath(finalParams, path) - } catch (e) { - callback(e, null, null) - return - } - - if (path.match(/^https?:\/\//i)) { - // This is a full url request - reqOpts.url = path - } else { - // This is a REST API request. - reqOpts.url = this.apiUrl + path; - } - - if (finalParams.file) { - // If we're sending a file - reqOpts.headers['Content-type'] = 'multipart/form-data'; - reqOpts.formData = finalParams; - } else { - // Non-file-upload params should be url-encoded - if (Object.keys(finalParams).length > 0) { - reqOpts.url += this.formEncodeParams(finalParams); - } - } - - callback(null, reqOpts); - return; -} - -/** - * Make HTTP request to Mastodon REST API. - * @param {Object} reqOpts options object passed to `request()` - * @param {Object} mastoOptions - * @param {String} method "GET", "POST", or "DELETE" - * @param {Function} callback user's callback - * @return {Undefined} - */ -Mastodon.prototype._doRestApiRequest = function (reqOpts, mastoOptions, method, callback) { - var request_method = request[method.toLowerCase()]; - var req = request_method(reqOpts); - - var body = ''; - var response = null; - - var onRequestComplete = function () { - if (body !== '') { - try { - body = JSON.parse(body) - } catch (jsonDecodeError) { - // there was no transport-level error, but a JSON object could not be decoded from the request body - // surface this to the caller - var err = helpers.makeMastodonError('JSON decode error: Mastodon HTTP response body was not valid JSON') - err.statusCode = response ? response.statusCode: null; - err.allErrors.concat({error: jsonDecodeError.toString()}) - callback(err, body, response); - return - } - } - - if (typeof body === 'object' && (body.error || body.errors)) { - // we got a Mastodon API-level error response - // place the errors in the HTTP response body into the Error object and pass control to caller - var err = helpers.makeMastodonError('Mastodon API Error') - err.statusCode = response ? response.statusCode: null; - helpers.attachBodyInfoToError(err, body); - callback(err, body, response); - return - } - - // success case - no errors in HTTP response body - callback(err, body, response) - } - - req.on('response', function (res) { - response = res - // read data from `request` object which contains the decompressed HTTP response body, - // `response` is the unmodified http.IncomingMessage object which may contain compressed data - req.on('data', function (chunk) { - body += chunk.toString('utf8') - }) - // we're done reading the response - req.on('end', function () { - onRequestComplete() - }) - }) - - req.on('error', function (err) { - // transport-level error occurred - likely a socket error - if (mastoOptions.retry && - STATUS_CODES_TO_ABORT_ON.indexOf(err.statusCode) !== -1 - ) { - // retry the request since retries were specified and we got a status code we should retry on - self.request(method, path, params, callback); - return; - } else { - // pass the transport-level error to the caller - err.statusCode = null - err.code = null - err.allErrors = []; - helpers.attachBodyInfoToError(err, body) - callback(err, body, response); - return; - } - }) -} - -Mastodon.prototype.formEncodeParams = function (params, noQuestionMark) { - var encoded = ''; - for (var key in params) { - var value = params[key]; - if (encoded === '') { - if (!noQuestionMark) { - encoded = '?'; - } - } else { - encoded += '&'; - } - - if (Array.isArray(value)) { - value.forEach(function(v) { - encoded += encodeURIComponent(key) + '[]=' + encodeURIComponent(v) + '&'; - }); - } else { - encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value); - } - } - - return (encoded); -} - -Mastodon.prototype.setAuth = function (auth) { - var self = this - var configKeys = [ - 'access_token' - ]; - - // update config - configKeys.forEach(function (k) { - if (auth[k]) { - self.config[k] = auth[k] - } - }) - this._validateConfigOrThrow(self.config); -} - -Mastodon.prototype.getAuth = function () { - return this.config -} - -// -// Check that the required auth credentials are present in `config`. -// @param {Object} config Object containing credentials for REST API auth -// -Mastodon.prototype._validateConfigOrThrow = function (config) { - //check config for proper format - if (typeof config !== 'object') { - throw new TypeError('config must be object, got ' + typeof config) - } - - if (typeof config.timeout_ms !== 'undefined' && isNaN(Number(config.timeout_ms))) { - throw new TypeError('Mastodon config `timeout_ms` must be a Number. Got: ' + config.timeout_ms + '.'); - } - - var auth_type = 'user auth' - var required_keys = required_for_user_auth - - required_keys.forEach(function (req_key) { - if (!config[req_key]) { - var err_msg = util.format('Mastodon config must include `%s` when using %s.', req_key, auth_type) - throw new Error(err_msg) - } - }) -} - -module.exports = Mastodon diff --git a/node-mastodon/lib/settings.js b/node-mastodon/lib/settings.js deleted file mode 100644 index f6d5411..0000000 --- a/node-mastodon/lib/settings.js +++ /dev/null @@ -1,2 +0,0 @@ -// set of status codes where we don't attempt reconnecting to Mastodon -exports.STATUS_CODES_TO_ABORT_ON = [ 400, 401, 403, 404, 406, 410, 422 ]; |