UNPKG

twitter-api-v2

Version:

Strongly typed, full-featured, light, versatile yet powerful Twitter API v1.1 and v2 client for Node.js.

144 lines (143 loc) 6.37 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClientRequestMaker = void 0; const TweetStream_1 = __importDefault(require("../stream/TweetStream")); const helpers_1 = require("../helpers"); const oauth1_helper_1 = __importDefault(require("./oauth1.helper")); const request_handler_helper_1 = __importDefault(require("./request-handler.helper")); const request_param_helper_1 = __importDefault(require("./request-param.helper")); class ClientRequestMaker { constructor() { this._rateLimits = {}; } saveRateLimit(originalUrl, rateLimit) { this._rateLimits[originalUrl] = rateLimit; } /** Send a new request and returns a wrapped `Promise<TwitterResponse<T>`. */ send(requestParams) { const args = this.getHttpRequestArgs(requestParams); const options = { method: args.method, headers: args.headers, timeout: requestParams.timeout }; const enableRateLimitSave = requestParams.enableRateLimitSave !== false; if (args.body) { request_param_helper_1.default.setBodyLengthHeader(options, args.body); } return new request_handler_helper_1.default({ url: args.url, options, body: args.body, rateLimitSaver: enableRateLimitSave ? this.saveRateLimit.bind(this, args.rawUrl) : undefined, }) .makeRequest(); } sendStream(requestParams) { const args = this.getHttpRequestArgs(requestParams); const options = { method: args.method, headers: args.headers }; const enableRateLimitSave = requestParams.enableRateLimitSave !== false; const enableAutoConnect = requestParams.autoConnect !== false; if (args.body) { request_param_helper_1.default.setBodyLengthHeader(options, args.body); } const requestData = { url: args.url, options, body: args.body, rateLimitSaver: enableRateLimitSave ? this.saveRateLimit.bind(this, args.rawUrl) : undefined, payloadIsError: requestParams.payloadIsError, }; const stream = new TweetStream_1.default(requestData); if (!enableAutoConnect) { return stream; } return stream.connect(); } /* Token helpers */ buildOAuth() { if (!this._consumerSecret || !this._consumerToken) throw new Error('Invalid consumer tokens'); return new oauth1_helper_1.default({ consumerKeys: { key: this._consumerToken, secret: this._consumerSecret }, }); } getOAuthAccessTokens() { if (!this._accessSecret || !this._accessToken) return; return { key: this._accessToken, secret: this._accessSecret, }; } /* Request helpers */ writeAuthHeaders({ headers, bodyInSignature, url, method, query, body }) { headers = { ...headers }; if (this._bearerToken) { headers.Authorization = 'Bearer ' + this._bearerToken; } else if (this._basicToken) { // Basic auth, to request a bearer token headers.Authorization = 'Basic ' + this._basicToken; } else if (this._consumerSecret && this._oauth) { // Merge query and body const data = bodyInSignature ? request_param_helper_1.default.mergeQueryAndBodyForOAuth(query, body) : query; const auth = this._oauth.authorize({ url: url.toString(), method, data, }, this.getOAuthAccessTokens()); headers = { ...headers, ...this._oauth.toHeader(auth) }; } return headers; } getHttpRequestArgs({ url, method, query: rawQuery = {}, body: rawBody = {}, headers, forceBodyMode, enableAuth, params, }) { let body = undefined; method = method.toUpperCase(); headers = headers !== null && headers !== void 0 ? headers : {}; // Add user agent header (Twitter recommands it) if (!headers['x-user-agent']) { headers['x-user-agent'] = 'Node.twitter-api-v2'; } // Add protocol to URL if needed if (!url.startsWith('http')) { url = 'https://' + url; } // Convert URL to object that will receive all URL modifications const urlObject = new URL(url); // URL without query string to save as endpoint name const rawUrl = urlObject.origin + urlObject.pathname; // Apply URL parameters if (params) { request_param_helper_1.default.applyRequestParametersToUrl(urlObject, params); } // Build an URL without anything in QS, and QSP in query const query = request_param_helper_1.default.formatQueryToString(rawQuery); request_param_helper_1.default.moveUrlQueryParamsIntoObject(urlObject, query); // Delete undefined parameters if (!(rawBody instanceof Buffer)) { helpers_1.trimUndefinedProperties(rawBody); } // OAuth signature should not include parameters when using multipart. const bodyType = forceBodyMode !== null && forceBodyMode !== void 0 ? forceBodyMode : request_param_helper_1.default.autoDetectBodyType(urlObject); // If undefined or true, enable auth by headers if (enableAuth !== false) { // OAuth needs body signature only if body is URL encoded. const bodyInSignature = ClientRequestMaker.BODY_METHODS.has(method) && bodyType === 'url'; headers = this.writeAuthHeaders({ headers, bodyInSignature, method, query, url: urlObject, body: rawBody }); } if (ClientRequestMaker.BODY_METHODS.has(method)) { body = request_param_helper_1.default.constructBodyParams(rawBody, headers, bodyType) || undefined; } request_param_helper_1.default.addQueryParamsToUrl(urlObject, query); return { rawUrl, url: urlObject, method, headers, body, }; } } exports.ClientRequestMaker = ClientRequestMaker; ClientRequestMaker.BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);