UNPKG

3.67 kBJavaScriptView Raw
1var querystring = require('querystring');
2var request = require('request');
3
4var endpoints = require('./endpoints');
5
6/**
7 * Encodes object as a querystring, to be used as the suffix of request URLs.
8 * @param {Object} obj
9 * @return {String}
10 */
11exports.makeQueryString = function (obj) {
12 var qs = querystring.stringify(obj)
13 qs = qs.replace(/\!/g, "%21")
14 .replace(/\'/g, "%27")
15 .replace(/\(/g, "%28")
16 .replace(/\)/g, "%29")
17 .replace(/\*/g, "%2A");
18 return qs
19}
20
21/**
22 * For each `/:param` fragment in path, move the value in params
23 * at that key to path. If the key is not found in params, throw.
24 * Modifies both params and path values.
25 *
26 * @param {Objet} params Object used to build path.
27 * @param {String} path String to transform.
28 * @return {Undefined}
29 *
30 */
31exports.moveParamsIntoPath = function (params, path) {
32 var rgxParam = /\/:(\w+)/g
33 var missingParamErr = null
34
35 path = path.replace(rgxParam, function (hit) {
36 var paramName = hit.slice(2)
37 var suppliedVal = params[paramName]
38 if (!suppliedVal) {
39 throw new Error('Twit: Params object is missing a required parameter for this request: `'+paramName+'`')
40 }
41 var retVal = '/' + suppliedVal
42 delete params[paramName]
43 return retVal
44 })
45 return path
46}
47
48/**
49 * When Twitter returns a response that looks like an error response,
50 * use this function to attach the error info in the response body to `err`.
51 *
52 * @param {Error} err Error instance to which body info will be attached
53 * @param {Object} body JSON object that is the deserialized HTTP response body received from Twitter
54 * @return {Undefined}
55 */
56exports.attachBodyInfoToError = function (err, body) {
57 err.twitterReply = body;
58 if (!body) {
59 return
60 }
61 if (body.error) {
62 // the body itself is an error object
63 err.message = body.error
64 err.allErrors = err.allErrors.concat([body])
65 } else if (body.errors && body.errors.length) {
66 // body contains multiple error objects
67 err.message = body.errors[0].message;
68 err.code = body.errors[0].code;
69 err.allErrors = err.allErrors.concat(body.errors)
70 }
71}
72
73exports.makeTwitError = function (message) {
74 var err = new Error()
75 if (message) {
76 err.message = message
77 }
78 err.code = null
79 err.allErrors = []
80 err.twitterReply = null
81 return err
82}
83
84/**
85 * Get a bearer token for OAuth2
86 * @param {String} consumer_key
87 * @param {String} consumer_secret
88 * @param {Function} cb
89 *
90 * Calls `cb` with Error, String
91 *
92 * Error (if it exists) is guaranteed to be Twit error-formatted.
93 * String (if it exists) is the bearer token received from Twitter.
94 */
95exports.getBearerToken = function (consumer_key, consumer_secret, cb) {
96 // use OAuth 2 for app-only auth (Twitter requires this)
97 // get a bearer token using our app's credentials
98 var b64Credentials = new Buffer(consumer_key + ':' + consumer_secret).toString('base64');
99 request.post({
100 url: endpoints.API_HOST + '/oauth2/token',
101 headers: {
102 'Authorization': 'Basic ' + b64Credentials,
103 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
104 },
105 body: 'grant_type=client_credentials',
106 json: true,
107 }, function (err, res, body) {
108 if (err) {
109 var error = exports.makeTwitError(err.toString());
110 exports.attachBodyInfoToError(error, body);
111 return cb(error, body, res);
112 }
113
114 if (body.token_type !== 'bearer') {
115 var error = exports.makeTwitError('Unexpected reply from Twitter upon obtaining bearer token');
116 exports.attachBodyInfoToError(error, body);
117 return cb(error, body, res);
118 }
119
120 return cb(err, body.access_token);
121 })
122}