mirror of
https://github.com/node-red/node-red-nodes.git
synced 2025-03-01 10:37:43 +00:00
Add files via upload
This commit is contained in:
24
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.d.ts
generated
vendored
Normal file
24
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference types="node" />
|
||||
declare type TStringable = {
|
||||
toString(): string;
|
||||
};
|
||||
export declare class FormDataHelper {
|
||||
protected _boundary: string;
|
||||
protected _chunks: Buffer[];
|
||||
protected _footerChunk?: Buffer;
|
||||
protected static readonly LINE_BREAK = "\r\n";
|
||||
protected static readonly DEFAULT_CONTENT_TYPE = "application/octet-stream";
|
||||
protected bodyAppend(...values: (Buffer | string)[]): void;
|
||||
append(field: string, value: Buffer | string | TStringable, contentType?: string): void;
|
||||
getHeaders(): {
|
||||
'content-type': string;
|
||||
};
|
||||
/** Length of form-data (including footer length). */
|
||||
protected getLength(): number;
|
||||
getBuffer(): Buffer;
|
||||
protected getBoundary(): string;
|
||||
protected generateBoundary(): void;
|
||||
protected getMultipartHeader(field: string, value: string | Buffer, contentType?: string): string;
|
||||
protected getMultipartFooter(): Buffer;
|
||||
}
|
||||
export {};
|
83
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.js
generated
vendored
Normal file
83
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FormDataHelper = void 0;
|
||||
const helpers_1 = require("../helpers");
|
||||
// This class is partially inspired by https://github.com/form-data/form-data/blob/master/lib/form_data.js
|
||||
// All credits to their authors.
|
||||
class FormDataHelper {
|
||||
constructor() {
|
||||
this._boundary = '';
|
||||
this._chunks = [];
|
||||
}
|
||||
bodyAppend(...values) {
|
||||
const allAsBuffer = values.map(val => val instanceof Buffer ? val : Buffer.from(val));
|
||||
this._chunks.push(...allAsBuffer);
|
||||
}
|
||||
append(field, value, contentType) {
|
||||
const convertedValue = value instanceof Buffer ? value : value.toString();
|
||||
const header = this.getMultipartHeader(field, convertedValue, contentType);
|
||||
this.bodyAppend(header, convertedValue, FormDataHelper.LINE_BREAK);
|
||||
}
|
||||
getHeaders() {
|
||||
return {
|
||||
'content-type': 'multipart/form-data; boundary=' + this.getBoundary(),
|
||||
};
|
||||
}
|
||||
/** Length of form-data (including footer length). */
|
||||
getLength() {
|
||||
return this._chunks.reduce((acc, cur) => acc + cur.length, this.getMultipartFooter().length);
|
||||
}
|
||||
getBuffer() {
|
||||
const allChunks = [...this._chunks, this.getMultipartFooter()];
|
||||
const totalBuffer = Buffer.alloc(this.getLength());
|
||||
let i = 0;
|
||||
for (const chunk of allChunks) {
|
||||
for (let j = 0; j < chunk.length; i++, j++) {
|
||||
totalBuffer[i] = chunk[j];
|
||||
}
|
||||
}
|
||||
return totalBuffer;
|
||||
}
|
||||
getBoundary() {
|
||||
if (!this._boundary) {
|
||||
this.generateBoundary();
|
||||
}
|
||||
return this._boundary;
|
||||
}
|
||||
generateBoundary() {
|
||||
// This generates a 50 character boundary similar to those used by Firefox.
|
||||
let boundary = '--------------------------';
|
||||
for (let i = 0; i < 24; i++) {
|
||||
boundary += Math.floor(Math.random() * 10).toString(16);
|
||||
}
|
||||
this._boundary = boundary;
|
||||
}
|
||||
getMultipartHeader(field, value, contentType) {
|
||||
// In this lib no need to guess more the content type, octet stream is ok of buffers
|
||||
if (!contentType) {
|
||||
contentType = value instanceof Buffer ? FormDataHelper.DEFAULT_CONTENT_TYPE : '';
|
||||
}
|
||||
const headers = {
|
||||
'Content-Disposition': ['form-data', `name="${field}"`],
|
||||
'Content-Type': contentType,
|
||||
};
|
||||
let contents = '';
|
||||
for (const [prop, header] of Object.entries(headers)) {
|
||||
// skip nullish headers.
|
||||
if (!header.length) {
|
||||
continue;
|
||||
}
|
||||
contents += prop + ': ' + (0, helpers_1.arrayWrap)(header).join('; ') + FormDataHelper.LINE_BREAK;
|
||||
}
|
||||
return '--' + this.getBoundary() + FormDataHelper.LINE_BREAK + contents + FormDataHelper.LINE_BREAK;
|
||||
}
|
||||
getMultipartFooter() {
|
||||
if (this._footerChunk) {
|
||||
return this._footerChunk;
|
||||
}
|
||||
return this._footerChunk = Buffer.from('--' + this.getBoundary() + '--' + FormDataHelper.LINE_BREAK);
|
||||
}
|
||||
}
|
||||
exports.FormDataHelper = FormDataHelper;
|
||||
FormDataHelper.LINE_BREAK = '\r\n';
|
||||
FormDataHelper.DEFAULT_CONTENT_TYPE = 'application/octet-stream';
|
40
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.d.ts
generated
vendored
Normal file
40
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.d.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
export interface OAuth1Tokens {
|
||||
key: string;
|
||||
secret: string;
|
||||
}
|
||||
export interface OAuth1MakerArgs {
|
||||
consumerKeys: OAuth1Tokens;
|
||||
}
|
||||
export interface OAuth1RequestOptions {
|
||||
url: string;
|
||||
method: string;
|
||||
data?: any;
|
||||
}
|
||||
export interface OAuth1AuthInfo {
|
||||
oauth_consumer_key: string;
|
||||
oauth_nonce: string;
|
||||
oauth_signature_method: string;
|
||||
oauth_timestamp: number;
|
||||
oauth_version: string;
|
||||
oauth_token: string;
|
||||
oauth_signature: string;
|
||||
}
|
||||
export declare class OAuth1Helper {
|
||||
nonceLength: number;
|
||||
protected consumerKeys: OAuth1Tokens;
|
||||
constructor(options: OAuth1MakerArgs);
|
||||
static percentEncode(str: string): string;
|
||||
protected hash(base: string, key: string): string;
|
||||
authorize(request: OAuth1RequestOptions, accessTokens?: Partial<OAuth1Tokens>): OAuth1AuthInfo;
|
||||
toHeader(oauthInfo: OAuth1AuthInfo): {
|
||||
Authorization: string;
|
||||
};
|
||||
protected getNonce(): string;
|
||||
protected getTimestamp(): number;
|
||||
protected getSignature(request: OAuth1RequestOptions, tokenSecret: string | undefined, oauthInfo: OAuth1AuthInfo): string;
|
||||
protected getSigningKey(tokenSecret: string | undefined): string;
|
||||
protected getBaseString(request: OAuth1RequestOptions, oauthInfo: OAuth1AuthInfo): string;
|
||||
protected getParameterString(request: OAuth1RequestOptions, oauthInfo: OAuth1AuthInfo): string;
|
||||
protected getBaseUrl(url: string): string;
|
||||
}
|
||||
export default OAuth1Helper;
|
187
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.js
generated
vendored
Normal file
187
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.js
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OAuth1Helper = void 0;
|
||||
const crypto = __importStar(require("crypto"));
|
||||
class OAuth1Helper {
|
||||
constructor(options) {
|
||||
this.nonceLength = 32;
|
||||
this.consumerKeys = options.consumerKeys;
|
||||
}
|
||||
static percentEncode(str) {
|
||||
return encodeURIComponent(str)
|
||||
.replace(/!/g, '%21')
|
||||
.replace(/\*/g, '%2A')
|
||||
.replace(/'/g, '%27')
|
||||
.replace(/\(/g, '%28')
|
||||
.replace(/\)/g, '%29');
|
||||
}
|
||||
hash(base, key) {
|
||||
return crypto
|
||||
.createHmac('sha1', key)
|
||||
.update(base)
|
||||
.digest('base64');
|
||||
}
|
||||
authorize(request, accessTokens = {}) {
|
||||
const oauthInfo = {
|
||||
oauth_consumer_key: this.consumerKeys.key,
|
||||
oauth_nonce: this.getNonce(),
|
||||
oauth_signature_method: 'HMAC-SHA1',
|
||||
oauth_timestamp: this.getTimestamp(),
|
||||
oauth_version: '1.0',
|
||||
};
|
||||
if (accessTokens.key !== undefined) {
|
||||
oauthInfo.oauth_token = accessTokens.key;
|
||||
}
|
||||
if (!request.data) {
|
||||
request.data = {};
|
||||
}
|
||||
oauthInfo.oauth_signature = this.getSignature(request, accessTokens.secret, oauthInfo);
|
||||
return oauthInfo;
|
||||
}
|
||||
toHeader(oauthInfo) {
|
||||
const sorted = sortObject(oauthInfo);
|
||||
let header_value = 'OAuth ';
|
||||
for (const element of sorted) {
|
||||
if (element.key.indexOf('oauth_') !== 0) {
|
||||
continue;
|
||||
}
|
||||
header_value += OAuth1Helper.percentEncode(element.key) + '="' + OAuth1Helper.percentEncode(element.value) + '",';
|
||||
}
|
||||
return {
|
||||
// Remove the last ,
|
||||
Authorization: header_value.slice(0, header_value.length - 1),
|
||||
};
|
||||
}
|
||||
getNonce() {
|
||||
const wordCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
let result = '';
|
||||
for (let i = 0; i < this.nonceLength; i++) {
|
||||
result += wordCharacters[Math.trunc(Math.random() * wordCharacters.length)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
getTimestamp() {
|
||||
return Math.trunc(new Date().getTime() / 1000);
|
||||
}
|
||||
getSignature(request, tokenSecret, oauthInfo) {
|
||||
return this.hash(this.getBaseString(request, oauthInfo), this.getSigningKey(tokenSecret));
|
||||
}
|
||||
getSigningKey(tokenSecret) {
|
||||
return OAuth1Helper.percentEncode(this.consumerKeys.secret) + '&' + OAuth1Helper.percentEncode(tokenSecret || '');
|
||||
}
|
||||
getBaseString(request, oauthInfo) {
|
||||
return request.method.toUpperCase() + '&'
|
||||
+ OAuth1Helper.percentEncode(this.getBaseUrl(request.url)) + '&'
|
||||
+ OAuth1Helper.percentEncode(this.getParameterString(request, oauthInfo));
|
||||
}
|
||||
getParameterString(request, oauthInfo) {
|
||||
const baseStringData = sortObject(percentEncodeData(mergeObject(oauthInfo, mergeObject(request.data, deParamUrl(request.url)))));
|
||||
let dataStr = '';
|
||||
for (const { key, value } of baseStringData) {
|
||||
// check if the value is an array
|
||||
// this means that this key has multiple values
|
||||
if (value && Array.isArray(value)) {
|
||||
// sort the array first
|
||||
value.sort();
|
||||
let valString = '';
|
||||
// serialize all values for this key: e.g. formkey=formvalue1&formkey=formvalue2
|
||||
value.forEach((item, i) => {
|
||||
valString += key + '=' + item;
|
||||
if (i < value.length) {
|
||||
valString += '&';
|
||||
}
|
||||
});
|
||||
dataStr += valString;
|
||||
}
|
||||
else {
|
||||
dataStr += key + '=' + value + '&';
|
||||
}
|
||||
}
|
||||
// Remove the last character
|
||||
return dataStr.slice(0, dataStr.length - 1);
|
||||
}
|
||||
getBaseUrl(url) {
|
||||
return url.split('?')[0];
|
||||
}
|
||||
}
|
||||
exports.OAuth1Helper = OAuth1Helper;
|
||||
exports.default = OAuth1Helper;
|
||||
// Helper functions //
|
||||
function mergeObject(obj1, obj2) {
|
||||
return {
|
||||
...obj1 || {},
|
||||
...obj2 || {},
|
||||
};
|
||||
}
|
||||
function sortObject(data) {
|
||||
return Object.keys(data)
|
||||
.sort()
|
||||
.map(key => ({ key, value: data[key] }));
|
||||
}
|
||||
function deParam(string) {
|
||||
const splitted = string.split('&');
|
||||
const data = {};
|
||||
for (const coupleKeyValue of splitted) {
|
||||
const [key, value = ''] = coupleKeyValue.split('=');
|
||||
// check if the key already exists
|
||||
// this can occur if the QS part of the url contains duplicate keys like this: ?formkey=formvalue1&formkey=formvalue2
|
||||
if (data[key]) {
|
||||
// the key exists already
|
||||
if (!Array.isArray(data[key])) {
|
||||
// replace the value with an array containing the already present value
|
||||
data[key] = [data[key]];
|
||||
}
|
||||
// and add the new found value to it
|
||||
data[key].push(decodeURIComponent(value));
|
||||
}
|
||||
else {
|
||||
// it doesn't exist, just put the found value in the data object
|
||||
data[key] = decodeURIComponent(value);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
function deParamUrl(url) {
|
||||
const tmp = url.split('?');
|
||||
if (tmp.length === 1)
|
||||
return {};
|
||||
return deParam(tmp[1]);
|
||||
}
|
||||
function percentEncodeData(data) {
|
||||
const result = {};
|
||||
for (const key in data) {
|
||||
let value = data[key];
|
||||
// check if the value is an array
|
||||
if (value && Array.isArray(value)) {
|
||||
value = value.map(v => OAuth1Helper.percentEncode(v));
|
||||
}
|
||||
else {
|
||||
value = OAuth1Helper.percentEncode(value);
|
||||
}
|
||||
result[OAuth1Helper.percentEncode(key)] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
7
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.d.ts
generated
vendored
Normal file
7
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export declare class OAuth2Helper {
|
||||
static getCodeVerifier(): string;
|
||||
static getCodeChallengeFromVerifier(verifier: string): string;
|
||||
static getAuthHeader(clientId: string, clientSecret: string): string;
|
||||
static generateRandomString(length: number): string;
|
||||
private static escapeBase64Url;
|
||||
}
|
54
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.js
generated
vendored
Normal file
54
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OAuth2Helper = void 0;
|
||||
const crypto = __importStar(require("crypto"));
|
||||
class OAuth2Helper {
|
||||
static getCodeVerifier() {
|
||||
return this.generateRandomString(128);
|
||||
}
|
||||
static getCodeChallengeFromVerifier(verifier) {
|
||||
return this.escapeBase64Url(crypto
|
||||
.createHash('sha256')
|
||||
.update(verifier)
|
||||
.digest('base64'));
|
||||
}
|
||||
static getAuthHeader(clientId, clientSecret) {
|
||||
const key = encodeURIComponent(clientId) + ':' + encodeURIComponent(clientSecret);
|
||||
return Buffer.from(key).toString('base64');
|
||||
}
|
||||
static generateRandomString(length) {
|
||||
let text = '';
|
||||
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
|
||||
for (let i = 0; i < length; i++) {
|
||||
text += possible[Math.floor(Math.random() * possible.length)];
|
||||
}
|
||||
return text;
|
||||
}
|
||||
static escapeBase64Url(string) {
|
||||
return string.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
||||
}
|
||||
}
|
||||
exports.OAuth2Helper = OAuth2Helper;
|
60
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.d.ts
generated
vendored
Normal file
60
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.d.ts
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/// <reference types="node" />
|
||||
import type { Socket } from 'net';
|
||||
import type { IncomingMessage, ClientRequest } from 'http';
|
||||
import TweetStream from '../stream/TweetStream';
|
||||
import { ApiPartialResponseError, ApiRequestError, ApiResponseError } from '../types';
|
||||
import type { ErrorV1, ErrorV2, TwitterRateLimit, TwitterResponse } from '../types';
|
||||
import type { TRequestFullData, TRequestFullStreamData, TResponseParseMode } from '../types/request-maker.mixin.types';
|
||||
import * as zlib from 'zlib';
|
||||
import { Readable } from 'stream';
|
||||
declare type TRequestReadyPayload = {
|
||||
req: ClientRequest;
|
||||
res: Readable;
|
||||
originalResponse: IncomingMessage;
|
||||
requestData: TRequestFullData | TRequestFullStreamData;
|
||||
};
|
||||
declare type TReadyRequestResolver = (value: TRequestReadyPayload) => void;
|
||||
declare type TResponseResolver<T> = (value: TwitterResponse<T>) => void;
|
||||
declare type TRequestRejecter = (error: ApiRequestError) => void;
|
||||
declare type TResponseRejecter = (error: ApiResponseError | ApiPartialResponseError) => void;
|
||||
interface IBuildErrorParams {
|
||||
res: IncomingMessage;
|
||||
data: any;
|
||||
rateLimit?: TwitterRateLimit;
|
||||
code: number;
|
||||
}
|
||||
export declare class RequestHandlerHelper<T> {
|
||||
protected requestData: TRequestFullData | TRequestFullStreamData;
|
||||
protected req: ClientRequest;
|
||||
protected res: IncomingMessage;
|
||||
protected requestErrorHandled: boolean;
|
||||
protected responseData: Buffer[];
|
||||
constructor(requestData: TRequestFullData | TRequestFullStreamData);
|
||||
get hrefPathname(): string;
|
||||
protected isCompressionDisabled(): boolean;
|
||||
protected isFormEncodedEndpoint(): boolean;
|
||||
protected createRequestError(error: Error): ApiRequestError;
|
||||
protected createPartialResponseError(error: Error, abortClose: boolean): ApiPartialResponseError;
|
||||
protected formatV1Errors(errors: ErrorV1[]): string;
|
||||
protected formatV2Error(error: ErrorV2): string;
|
||||
protected createResponseError({ res, data, rateLimit, code }: IBuildErrorParams): ApiResponseError;
|
||||
protected getResponseDataStream(res: IncomingMessage): IncomingMessage | zlib.BrotliDecompress;
|
||||
protected detectResponseType(res: IncomingMessage): TResponseParseMode;
|
||||
protected getParsedResponse(res: IncomingMessage): any;
|
||||
protected getRateLimitFromResponse(res: IncomingMessage): TwitterRateLimit | undefined;
|
||||
protected onSocketEventHandler(reject: TRequestRejecter, socket: Socket): void;
|
||||
protected onSocketCloseHandler(reject: TRequestRejecter): void;
|
||||
protected requestErrorHandler(reject: TRequestRejecter, requestError: Error): void;
|
||||
protected timeoutErrorHandler(): void;
|
||||
protected classicResponseHandler(resolve: TResponseResolver<T>, reject: TResponseRejecter, res: IncomingMessage): void;
|
||||
protected onResponseEndHandler(resolve: TResponseResolver<T>, reject: TResponseRejecter): void;
|
||||
protected onResponseCloseHandler(resolve: TResponseResolver<T>, reject: TResponseRejecter): void;
|
||||
protected streamResponseHandler(resolve: TReadyRequestResolver, reject: TResponseRejecter, res: IncomingMessage): void;
|
||||
protected debugRequest(): void;
|
||||
protected buildRequest(): void;
|
||||
protected registerRequestEventDebugHandlers(req: ClientRequest): void;
|
||||
makeRequest(): Promise<TwitterResponse<T>>;
|
||||
makeRequestAsStream(): Promise<TweetStream<T>>;
|
||||
makeRequestAndResolveWhenReady(): Promise<TRequestReadyPayload>;
|
||||
}
|
||||
export default RequestHandlerHelper;
|
391
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js
generated
vendored
Normal file
391
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js
generated
vendored
Normal file
@@ -0,0 +1,391 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RequestHandlerHelper = void 0;
|
||||
const https_1 = require("https");
|
||||
const settings_1 = require("../settings");
|
||||
const TweetStream_1 = __importDefault(require("../stream/TweetStream"));
|
||||
const types_1 = require("../types");
|
||||
const zlib = __importStar(require("zlib"));
|
||||
class RequestHandlerHelper {
|
||||
constructor(requestData) {
|
||||
this.requestData = requestData;
|
||||
this.requestErrorHandled = false;
|
||||
this.responseData = [];
|
||||
}
|
||||
/* Request helpers */
|
||||
get hrefPathname() {
|
||||
const url = this.requestData.url;
|
||||
return url.hostname + url.pathname;
|
||||
}
|
||||
isCompressionDisabled() {
|
||||
return !this.requestData.compression || this.requestData.compression === 'identity';
|
||||
}
|
||||
isFormEncodedEndpoint() {
|
||||
return this.requestData.url.href.startsWith('https://api.twitter.com/oauth/');
|
||||
}
|
||||
/* Error helpers */
|
||||
createRequestError(error) {
|
||||
if (settings_1.TwitterApiV2Settings.debug) {
|
||||
settings_1.TwitterApiV2Settings.logger.log('Request error:', error);
|
||||
}
|
||||
return new types_1.ApiRequestError('Request failed.', {
|
||||
request: this.req,
|
||||
error,
|
||||
});
|
||||
}
|
||||
createPartialResponseError(error, abortClose) {
|
||||
const res = this.res;
|
||||
let message = `Request failed with partial response with HTTP code ${res.statusCode}`;
|
||||
if (abortClose) {
|
||||
message += ' (connection abruptly closed)';
|
||||
}
|
||||
else {
|
||||
message += ' (parse error)';
|
||||
}
|
||||
return new types_1.ApiPartialResponseError(message, {
|
||||
request: this.req,
|
||||
response: this.res,
|
||||
responseError: error,
|
||||
rawContent: Buffer.concat(this.responseData).toString(),
|
||||
});
|
||||
}
|
||||
formatV1Errors(errors) {
|
||||
return errors
|
||||
.map(({ code, message }) => `${message} (Twitter code ${code})`)
|
||||
.join(', ');
|
||||
}
|
||||
formatV2Error(error) {
|
||||
return `${error.title}: ${error.detail} (see ${error.type})`;
|
||||
}
|
||||
createResponseError({ res, data, rateLimit, code }) {
|
||||
var _a;
|
||||
if (settings_1.TwitterApiV2Settings.debug) {
|
||||
settings_1.TwitterApiV2Settings.logger.log(`Request failed with code ${code}, data:`, data);
|
||||
settings_1.TwitterApiV2Settings.logger.log('Response headers:', res.headers);
|
||||
}
|
||||
// Errors formatting.
|
||||
let errorString = `Request failed with code ${code}`;
|
||||
if ((_a = data === null || data === void 0 ? void 0 : data.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
||||
const errors = data.errors;
|
||||
if ('code' in errors[0]) {
|
||||
errorString += ' - ' + this.formatV1Errors(errors);
|
||||
}
|
||||
else {
|
||||
errorString += ' - ' + this.formatV2Error(data);
|
||||
}
|
||||
}
|
||||
return new types_1.ApiResponseError(errorString, {
|
||||
code,
|
||||
data,
|
||||
headers: res.headers,
|
||||
request: this.req,
|
||||
response: res,
|
||||
rateLimit,
|
||||
});
|
||||
}
|
||||
/* Response helpers */
|
||||
getResponseDataStream(res) {
|
||||
if (this.isCompressionDisabled()) {
|
||||
return res;
|
||||
}
|
||||
const contentEncoding = (res.headers['content-encoding'] || 'identity').trim().toLowerCase();
|
||||
if (contentEncoding === 'br') {
|
||||
const brotli = zlib.createBrotliDecompress({
|
||||
flush: zlib.constants.BROTLI_OPERATION_FLUSH,
|
||||
finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH,
|
||||
});
|
||||
res.pipe(brotli);
|
||||
return brotli;
|
||||
}
|
||||
if (contentEncoding === 'gzip') {
|
||||
const gunzip = zlib.createGunzip({
|
||||
flush: zlib.constants.Z_SYNC_FLUSH,
|
||||
finishFlush: zlib.constants.Z_SYNC_FLUSH,
|
||||
});
|
||||
res.pipe(gunzip);
|
||||
return gunzip;
|
||||
}
|
||||
if (contentEncoding === 'deflate') {
|
||||
const inflate = zlib.createInflate({
|
||||
flush: zlib.constants.Z_SYNC_FLUSH,
|
||||
finishFlush: zlib.constants.Z_SYNC_FLUSH,
|
||||
});
|
||||
res.pipe(inflate);
|
||||
return inflate;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
detectResponseType(res) {
|
||||
var _a, _b;
|
||||
// Auto parse if server responds with JSON body
|
||||
if (((_a = res.headers['content-type']) === null || _a === void 0 ? void 0 : _a.includes('application/json')) || ((_b = res.headers['content-type']) === null || _b === void 0 ? void 0 : _b.includes('application/problem+json'))) {
|
||||
return 'json';
|
||||
}
|
||||
// f-e oauth token endpoints
|
||||
else if (this.isFormEncodedEndpoint()) {
|
||||
return 'url';
|
||||
}
|
||||
return 'text';
|
||||
}
|
||||
getParsedResponse(res) {
|
||||
const data = this.responseData;
|
||||
const mode = this.requestData.forceParseMode || this.detectResponseType(res);
|
||||
if (mode === 'buffer') {
|
||||
return Buffer.concat(data);
|
||||
}
|
||||
else if (mode === 'text') {
|
||||
return Buffer.concat(data).toString();
|
||||
}
|
||||
else if (mode === 'json') {
|
||||
const asText = Buffer.concat(data).toString();
|
||||
return asText.length ? JSON.parse(asText) : undefined;
|
||||
}
|
||||
else if (mode === 'url') {
|
||||
const asText = Buffer.concat(data).toString();
|
||||
const formEntries = {};
|
||||
for (const [item, value] of new URLSearchParams(asText)) {
|
||||
formEntries[item] = value;
|
||||
}
|
||||
return formEntries;
|
||||
}
|
||||
else {
|
||||
// mode === 'none'
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
getRateLimitFromResponse(res) {
|
||||
let rateLimit = undefined;
|
||||
if (res.headers['x-rate-limit-limit']) {
|
||||
rateLimit = {
|
||||
limit: Number(res.headers['x-rate-limit-limit']),
|
||||
remaining: Number(res.headers['x-rate-limit-remaining']),
|
||||
reset: Number(res.headers['x-rate-limit-reset']),
|
||||
};
|
||||
if (this.requestData.rateLimitSaver) {
|
||||
this.requestData.rateLimitSaver(rateLimit);
|
||||
}
|
||||
}
|
||||
return rateLimit;
|
||||
}
|
||||
/* Request event handlers */
|
||||
onSocketEventHandler(reject, socket) {
|
||||
socket.on('close', this.onSocketCloseHandler.bind(this, reject));
|
||||
}
|
||||
onSocketCloseHandler(reject) {
|
||||
this.req.removeAllListeners('timeout');
|
||||
const res = this.res;
|
||||
if (res) {
|
||||
// Response ok, res.close/res.end can handle request ending
|
||||
return;
|
||||
}
|
||||
if (!this.requestErrorHandled) {
|
||||
return reject(this.createRequestError(new Error('Socket closed without any information.')));
|
||||
}
|
||||
// else: other situation
|
||||
}
|
||||
requestErrorHandler(reject, requestError) {
|
||||
var _a, _b;
|
||||
(_b = (_a = this.requestData).requestEventDebugHandler) === null || _b === void 0 ? void 0 : _b.call(_a, 'request-error', { requestError });
|
||||
this.requestErrorHandled = true;
|
||||
reject(this.createRequestError(requestError));
|
||||
}
|
||||
timeoutErrorHandler() {
|
||||
this.requestErrorHandled = true;
|
||||
this.req.destroy(new Error('Request timeout.'));
|
||||
}
|
||||
/* Response event handlers */
|
||||
classicResponseHandler(resolve, reject, res) {
|
||||
this.res = res;
|
||||
const dataStream = this.getResponseDataStream(res);
|
||||
// Register the response data
|
||||
dataStream.on('data', chunk => this.responseData.push(chunk));
|
||||
dataStream.on('end', this.onResponseEndHandler.bind(this, resolve, reject));
|
||||
dataStream.on('close', this.onResponseCloseHandler.bind(this, resolve, reject));
|
||||
// Debug handlers
|
||||
if (this.requestData.requestEventDebugHandler) {
|
||||
this.requestData.requestEventDebugHandler('response', { res });
|
||||
res.on('aborted', error => this.requestData.requestEventDebugHandler('response-aborted', { error }));
|
||||
res.on('error', error => this.requestData.requestEventDebugHandler('response-error', { error }));
|
||||
res.on('close', () => this.requestData.requestEventDebugHandler('response-close', { data: this.responseData }));
|
||||
res.on('end', () => this.requestData.requestEventDebugHandler('response-end'));
|
||||
}
|
||||
}
|
||||
onResponseEndHandler(resolve, reject) {
|
||||
const rateLimit = this.getRateLimitFromResponse(this.res);
|
||||
let data;
|
||||
try {
|
||||
data = this.getParsedResponse(this.res);
|
||||
}
|
||||
catch (e) {
|
||||
reject(this.createPartialResponseError(e, false));
|
||||
return;
|
||||
}
|
||||
// Handle bad error codes
|
||||
const code = this.res.statusCode;
|
||||
if (code >= 400) {
|
||||
reject(this.createResponseError({ data, res: this.res, rateLimit, code }));
|
||||
return;
|
||||
}
|
||||
if (settings_1.TwitterApiV2Settings.debug) {
|
||||
settings_1.TwitterApiV2Settings.logger.log(`[${this.requestData.options.method} ${this.hrefPathname}]: Request succeeds with code ${this.res.statusCode}`);
|
||||
settings_1.TwitterApiV2Settings.logger.log('Response body:', data);
|
||||
}
|
||||
resolve({
|
||||
data,
|
||||
headers: this.res.headers,
|
||||
rateLimit,
|
||||
});
|
||||
}
|
||||
onResponseCloseHandler(resolve, reject) {
|
||||
const res = this.res;
|
||||
if (res.aborted) {
|
||||
// Try to parse the request (?)
|
||||
try {
|
||||
this.getParsedResponse(this.res);
|
||||
// Ok, try to resolve normally the request
|
||||
return this.onResponseEndHandler(resolve, reject);
|
||||
}
|
||||
catch (e) {
|
||||
// Parse error, just drop with content
|
||||
return reject(this.createPartialResponseError(e, true));
|
||||
}
|
||||
}
|
||||
if (!res.complete) {
|
||||
return reject(this.createPartialResponseError(new Error('Response has been interrupted before response could be parsed.'), true));
|
||||
}
|
||||
// else: end has been called
|
||||
}
|
||||
streamResponseHandler(resolve, reject, res) {
|
||||
const code = res.statusCode;
|
||||
if (code < 400) {
|
||||
if (settings_1.TwitterApiV2Settings.debug) {
|
||||
settings_1.TwitterApiV2Settings.logger.log(`[${this.requestData.options.method} ${this.hrefPathname}]: Request succeeds with code ${res.statusCode} (starting stream)`);
|
||||
}
|
||||
const dataStream = this.getResponseDataStream(res);
|
||||
// HTTP code ok, consume stream
|
||||
resolve({ req: this.req, res: dataStream, originalResponse: res, requestData: this.requestData });
|
||||
}
|
||||
else {
|
||||
// Handle response normally, can only rejects
|
||||
this.classicResponseHandler(() => undefined, reject, res);
|
||||
}
|
||||
}
|
||||
/* Wrappers for request lifecycle */
|
||||
debugRequest() {
|
||||
const url = this.requestData.url;
|
||||
settings_1.TwitterApiV2Settings.logger.log(`[${this.requestData.options.method} ${this.hrefPathname}]`, this.requestData.options);
|
||||
if (url.search) {
|
||||
settings_1.TwitterApiV2Settings.logger.log('Request parameters:', [...url.searchParams.entries()].map(([key, value]) => `${key}: ${value}`));
|
||||
}
|
||||
if (this.requestData.body) {
|
||||
settings_1.TwitterApiV2Settings.logger.log('Request body:', this.requestData.body);
|
||||
}
|
||||
}
|
||||
buildRequest() {
|
||||
var _a;
|
||||
const url = this.requestData.url;
|
||||
const auth = url.username ? `${url.username}:${url.password}` : undefined;
|
||||
const headers = (_a = this.requestData.options.headers) !== null && _a !== void 0 ? _a : {};
|
||||
if (this.requestData.compression === true || this.requestData.compression === 'brotli') {
|
||||
headers['accept-encoding'] = 'br;q=1.0, gzip;q=0.8, deflate;q=0.5, *;q=0.1';
|
||||
}
|
||||
else if (this.requestData.compression === 'gzip') {
|
||||
headers['accept-encoding'] = 'gzip;q=1, deflate;q=0.5, *;q=0.1';
|
||||
}
|
||||
else if (this.requestData.compression === 'deflate') {
|
||||
headers['accept-encoding'] = 'deflate;q=1, *;q=0.1';
|
||||
}
|
||||
if (settings_1.TwitterApiV2Settings.debug) {
|
||||
this.debugRequest();
|
||||
}
|
||||
this.req = (0, https_1.request)({
|
||||
...this.requestData.options,
|
||||
// Define URL params manually, addresses dependencies error https://github.com/PLhery/node-twitter-api-v2/issues/94
|
||||
host: url.hostname,
|
||||
port: url.port || undefined,
|
||||
path: url.pathname + url.search,
|
||||
protocol: url.protocol,
|
||||
auth,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
registerRequestEventDebugHandlers(req) {
|
||||
req.on('close', () => this.requestData.requestEventDebugHandler('close'));
|
||||
req.on('abort', () => this.requestData.requestEventDebugHandler('abort'));
|
||||
req.on('socket', socket => {
|
||||
this.requestData.requestEventDebugHandler('socket', { socket });
|
||||
socket.on('error', error => this.requestData.requestEventDebugHandler('socket-error', { socket, error }));
|
||||
socket.on('connect', () => this.requestData.requestEventDebugHandler('socket-connect', { socket }));
|
||||
socket.on('close', withError => this.requestData.requestEventDebugHandler('socket-close', { socket, withError }));
|
||||
socket.on('end', () => this.requestData.requestEventDebugHandler('socket-end', { socket }));
|
||||
socket.on('lookup', (...data) => this.requestData.requestEventDebugHandler('socket-lookup', { socket, data }));
|
||||
socket.on('timeout', () => this.requestData.requestEventDebugHandler('socket-timeout', { socket }));
|
||||
});
|
||||
}
|
||||
makeRequest() {
|
||||
this.buildRequest();
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = this.req;
|
||||
// Handle request errors
|
||||
req.on('error', this.requestErrorHandler.bind(this, reject));
|
||||
req.on('socket', this.onSocketEventHandler.bind(this, reject));
|
||||
req.on('response', this.classicResponseHandler.bind(this, resolve, reject));
|
||||
if (this.requestData.options.timeout) {
|
||||
req.on('timeout', this.timeoutErrorHandler.bind(this));
|
||||
}
|
||||
// Debug handlers
|
||||
if (this.requestData.requestEventDebugHandler) {
|
||||
this.registerRequestEventDebugHandlers(req);
|
||||
}
|
||||
if (this.requestData.body) {
|
||||
req.write(this.requestData.body);
|
||||
}
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
async makeRequestAsStream() {
|
||||
const { req, res, requestData, originalResponse } = await this.makeRequestAndResolveWhenReady();
|
||||
return new TweetStream_1.default(requestData, { req, res, originalResponse });
|
||||
}
|
||||
makeRequestAndResolveWhenReady() {
|
||||
this.buildRequest();
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = this.req;
|
||||
// Handle request errors
|
||||
req.on('error', this.requestErrorHandler.bind(this, reject));
|
||||
req.on('response', this.streamResponseHandler.bind(this, resolve, reject));
|
||||
if (this.requestData.body) {
|
||||
req.write(this.requestData.body);
|
||||
}
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.RequestHandlerHelper = RequestHandlerHelper;
|
||||
exports.default = RequestHandlerHelper;
|
58
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.d.ts
generated
vendored
Normal file
58
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.d.ts
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/// <reference types="node" />
|
||||
import { IClientSettings, ITwitterApiClientPlugin, TClientTokens, TwitterApiPluginResponseOverride, TwitterRateLimit, TwitterResponse } from '../types';
|
||||
import TweetStream from '../stream/TweetStream';
|
||||
import type { ClientRequestArgs } from 'http';
|
||||
import OAuth1Helper from './oauth1.helper';
|
||||
import type { IGetHttpRequestArgs, IGetStreamRequestArgs, IGetStreamRequestArgsAsync, IGetStreamRequestArgsSync, IWriteAuthHeadersArgs, TAcceptedInitToken } from '../types/request-maker.mixin.types';
|
||||
import { IComputedHttpRequestArgs } from '../types/request-maker.mixin.types';
|
||||
export declare class ClientRequestMaker {
|
||||
bearerToken?: string;
|
||||
consumerToken?: string;
|
||||
consumerSecret?: string;
|
||||
accessToken?: string;
|
||||
accessSecret?: string;
|
||||
basicToken?: string;
|
||||
clientId?: string;
|
||||
clientSecret?: string;
|
||||
rateLimits: {
|
||||
[endpoint: string]: TwitterRateLimit;
|
||||
};
|
||||
clientSettings: Partial<IClientSettings>;
|
||||
protected _oauth?: OAuth1Helper;
|
||||
protected static readonly BODY_METHODS: Set<string>;
|
||||
constructor(settings?: Partial<IClientSettings>);
|
||||
/** @deprecated - Switch to `@twitter-api-v2/plugin-rate-limit` */
|
||||
getRateLimits(): {
|
||||
[endpoint: string]: TwitterRateLimit;
|
||||
};
|
||||
protected saveRateLimit(originalUrl: string, rateLimit: TwitterRateLimit): void;
|
||||
/** Send a new request and returns a wrapped `Promise<TwitterResponse<T>`. */
|
||||
send<T = any>(requestParams: IGetHttpRequestArgs): Promise<TwitterResponse<T>>;
|
||||
/**
|
||||
* Create a new request, then creates a stream from it as a `TweetStream`.
|
||||
*
|
||||
* Request will be sent only if `autoConnect` is not set or `true`: return type will be `Promise<TweetStream>`.
|
||||
* If `autoConnect` is `false`, a `TweetStream` is directly returned and you should call `stream.connect()` by yourself.
|
||||
*/
|
||||
sendStream<T = any>(requestParams: IGetHttpRequestArgs & IGetStreamRequestArgsSync): TweetStream<T>;
|
||||
sendStream<T = any>(requestParams: IGetHttpRequestArgs & IGetStreamRequestArgsAsync): Promise<TweetStream<T>>;
|
||||
sendStream<T = any>(requestParams: IGetHttpRequestArgs & IGetStreamRequestArgs): Promise<TweetStream<T>> | TweetStream<T>;
|
||||
initializeToken(token?: TAcceptedInitToken): void;
|
||||
getActiveTokens(): TClientTokens;
|
||||
protected buildOAuth(): OAuth1Helper;
|
||||
protected getOAuthAccessTokens(): {
|
||||
key: string;
|
||||
secret: string;
|
||||
} | undefined;
|
||||
getPlugins(): ITwitterApiClientPlugin[];
|
||||
hasPlugins(): boolean;
|
||||
applyPluginMethod<K extends keyof ITwitterApiClientPlugin>(method: K, args: Parameters<Required<ITwitterApiClientPlugin>[K]>[0]): Promise<TwitterApiPluginResponseOverride | undefined>;
|
||||
protected writeAuthHeaders({ headers, bodyInSignature, url, method, query, body }: IWriteAuthHeadersArgs): Record<string, string>;
|
||||
protected getUrlObjectFromUrlString(url: string): URL;
|
||||
protected getHttpRequestArgs({ url: stringUrl, method, query: rawQuery, body: rawBody, headers, forceBodyMode, enableAuth, params, }: IGetHttpRequestArgs): IComputedHttpRequestArgs;
|
||||
protected applyPreRequestConfigHooks(requestParams: IGetHttpRequestArgs): Promise<TwitterResponse<any> | undefined>;
|
||||
protected applyPreStreamRequestConfigHooks(requestParams: IGetHttpRequestArgs): void;
|
||||
protected applyPreRequestHooks(requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial<ClientRequestArgs>): Promise<void>;
|
||||
protected applyPostRequestHooks(requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial<ClientRequestArgs>, response: TwitterResponse<any>): Promise<TwitterApiPluginResponseOverride | undefined>;
|
||||
protected applyResponseErrorHooks(requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial<ClientRequestArgs>, promise: Promise<TwitterResponse<any>>): Promise<TwitterResponse<any>>;
|
||||
}
|
323
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.js
generated
vendored
Normal file
323
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.js
generated
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
"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 types_1 = require("../types");
|
||||
const TweetStream_1 = __importDefault(require("../stream/TweetStream"));
|
||||
const helpers_1 = require("../plugins/helpers");
|
||||
const helpers_2 = 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"));
|
||||
const oauth2_helper_1 = require("./oauth2.helper");
|
||||
class ClientRequestMaker {
|
||||
constructor(settings) {
|
||||
this.rateLimits = {};
|
||||
this.clientSettings = {};
|
||||
if (settings) {
|
||||
this.clientSettings = settings;
|
||||
}
|
||||
}
|
||||
/** @deprecated - Switch to `@twitter-api-v2/plugin-rate-limit` */
|
||||
getRateLimits() {
|
||||
return this.rateLimits;
|
||||
}
|
||||
saveRateLimit(originalUrl, rateLimit) {
|
||||
this.rateLimits[originalUrl] = rateLimit;
|
||||
}
|
||||
/** Send a new request and returns a wrapped `Promise<TwitterResponse<T>`. */
|
||||
async send(requestParams) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
// Pre-request config hooks
|
||||
if ((_a = this.clientSettings.plugins) === null || _a === void 0 ? void 0 : _a.length) {
|
||||
const possibleResponse = await this.applyPreRequestConfigHooks(requestParams);
|
||||
if (possibleResponse) {
|
||||
return possibleResponse;
|
||||
}
|
||||
}
|
||||
const args = this.getHttpRequestArgs(requestParams);
|
||||
const options = {
|
||||
method: args.method,
|
||||
headers: args.headers,
|
||||
timeout: requestParams.timeout,
|
||||
agent: this.clientSettings.httpAgent,
|
||||
};
|
||||
const enableRateLimitSave = requestParams.enableRateLimitSave !== false;
|
||||
if (args.body) {
|
||||
request_param_helper_1.default.setBodyLengthHeader(options, args.body);
|
||||
}
|
||||
// Pre-request hooks
|
||||
if ((_b = this.clientSettings.plugins) === null || _b === void 0 ? void 0 : _b.length) {
|
||||
await this.applyPreRequestHooks(requestParams, args, options);
|
||||
}
|
||||
let request = new request_handler_helper_1.default({
|
||||
url: args.url,
|
||||
options,
|
||||
body: args.body,
|
||||
rateLimitSaver: enableRateLimitSave ? this.saveRateLimit.bind(this, args.rawUrl) : undefined,
|
||||
requestEventDebugHandler: requestParams.requestEventDebugHandler,
|
||||
compression: (_d = (_c = requestParams.compression) !== null && _c !== void 0 ? _c : this.clientSettings.compression) !== null && _d !== void 0 ? _d : true,
|
||||
forceParseMode: requestParams.forceParseMode,
|
||||
})
|
||||
.makeRequest();
|
||||
if ((0, helpers_1.hasRequestErrorPlugins)(this)) {
|
||||
request = this.applyResponseErrorHooks(requestParams, args, options, request);
|
||||
}
|
||||
const response = await request;
|
||||
// Post-request hooks
|
||||
if ((_e = this.clientSettings.plugins) === null || _e === void 0 ? void 0 : _e.length) {
|
||||
const responseOverride = await this.applyPostRequestHooks(requestParams, args, options, response);
|
||||
if (responseOverride) {
|
||||
return responseOverride.value;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
sendStream(requestParams) {
|
||||
var _a, _b;
|
||||
// Pre-request hooks
|
||||
if (this.clientSettings.plugins) {
|
||||
this.applyPreStreamRequestConfigHooks(requestParams);
|
||||
}
|
||||
const args = this.getHttpRequestArgs(requestParams);
|
||||
const options = {
|
||||
method: args.method,
|
||||
headers: args.headers,
|
||||
agent: this.clientSettings.httpAgent,
|
||||
};
|
||||
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,
|
||||
compression: (_b = (_a = requestParams.compression) !== null && _a !== void 0 ? _a : this.clientSettings.compression) !== null && _b !== void 0 ? _b : true,
|
||||
};
|
||||
const stream = new TweetStream_1.default(requestData);
|
||||
if (!enableAutoConnect) {
|
||||
return stream;
|
||||
}
|
||||
return stream.connect();
|
||||
}
|
||||
/* Token helpers */
|
||||
initializeToken(token) {
|
||||
if (typeof token === 'string') {
|
||||
this.bearerToken = token;
|
||||
}
|
||||
else if (typeof token === 'object' && 'appKey' in token) {
|
||||
this.consumerToken = token.appKey;
|
||||
this.consumerSecret = token.appSecret;
|
||||
if (token.accessToken && token.accessSecret) {
|
||||
this.accessToken = token.accessToken;
|
||||
this.accessSecret = token.accessSecret;
|
||||
}
|
||||
this._oauth = this.buildOAuth();
|
||||
}
|
||||
else if (typeof token === 'object' && 'username' in token) {
|
||||
const key = encodeURIComponent(token.username) + ':' + encodeURIComponent(token.password);
|
||||
this.basicToken = Buffer.from(key).toString('base64');
|
||||
}
|
||||
else if (typeof token === 'object' && 'clientId' in token) {
|
||||
this.clientId = token.clientId;
|
||||
this.clientSecret = token.clientSecret;
|
||||
}
|
||||
}
|
||||
getActiveTokens() {
|
||||
if (this.bearerToken) {
|
||||
return {
|
||||
type: 'oauth2',
|
||||
bearerToken: this.bearerToken,
|
||||
};
|
||||
}
|
||||
else if (this.basicToken) {
|
||||
return {
|
||||
type: 'basic',
|
||||
token: this.basicToken,
|
||||
};
|
||||
}
|
||||
else if (this.consumerSecret && this._oauth) {
|
||||
return {
|
||||
type: 'oauth-1.0a',
|
||||
appKey: this.consumerToken,
|
||||
appSecret: this.consumerSecret,
|
||||
accessToken: this.accessToken,
|
||||
accessSecret: this.accessSecret,
|
||||
};
|
||||
}
|
||||
else if (this.clientId) {
|
||||
return {
|
||||
type: 'oauth2-user',
|
||||
clientId: this.clientId,
|
||||
};
|
||||
}
|
||||
return { type: 'none' };
|
||||
}
|
||||
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,
|
||||
};
|
||||
}
|
||||
/* Plugin helpers */
|
||||
getPlugins() {
|
||||
var _a;
|
||||
return (_a = this.clientSettings.plugins) !== null && _a !== void 0 ? _a : [];
|
||||
}
|
||||
hasPlugins() {
|
||||
var _a;
|
||||
return !!((_a = this.clientSettings.plugins) === null || _a === void 0 ? void 0 : _a.length);
|
||||
}
|
||||
async applyPluginMethod(method, args) {
|
||||
var _a;
|
||||
let returnValue;
|
||||
for (const plugin of this.getPlugins()) {
|
||||
const value = await ((_a = plugin[method]) === null || _a === void 0 ? void 0 : _a.call(plugin, args));
|
||||
if (value && value instanceof types_1.TwitterApiPluginResponseOverride) {
|
||||
returnValue = value;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
/* 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.clientId && this.clientSecret) {
|
||||
// Basic auth with clientId + clientSecret
|
||||
headers.Authorization = 'Basic ' + oauth2_helper_1.OAuth2Helper.getAuthHeader(this.clientId, this.clientSecret);
|
||||
}
|
||||
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;
|
||||
}
|
||||
getUrlObjectFromUrlString(url) {
|
||||
// Add protocol to URL if needed
|
||||
if (!url.startsWith('http')) {
|
||||
url = 'https://' + url;
|
||||
}
|
||||
// Convert URL to object that will receive all URL modifications
|
||||
return new URL(url);
|
||||
}
|
||||
getHttpRequestArgs({ url: stringUrl, 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 recommends it)
|
||||
if (!headers['x-user-agent']) {
|
||||
headers['x-user-agent'] = 'Node.twitter-api-v2';
|
||||
}
|
||||
const url = this.getUrlObjectFromUrlString(stringUrl);
|
||||
// URL without query string to save as endpoint name
|
||||
const rawUrl = url.origin + url.pathname;
|
||||
// Apply URL parameters
|
||||
if (params) {
|
||||
request_param_helper_1.default.applyRequestParametersToUrl(url, params);
|
||||
}
|
||||
// Build a URL without anything in QS, and QSP in query
|
||||
const query = request_param_helper_1.default.formatQueryToString(rawQuery);
|
||||
request_param_helper_1.default.moveUrlQueryParamsIntoObject(url, query);
|
||||
// Delete undefined parameters
|
||||
if (!(rawBody instanceof Buffer)) {
|
||||
(0, helpers_2.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(url);
|
||||
// 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, 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(url, query);
|
||||
return {
|
||||
rawUrl,
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
};
|
||||
}
|
||||
/* Plugin helpers */
|
||||
async applyPreRequestConfigHooks(requestParams) {
|
||||
var _a;
|
||||
const url = this.getUrlObjectFromUrlString(requestParams.url);
|
||||
for (const plugin of this.getPlugins()) {
|
||||
const result = await ((_a = plugin.onBeforeRequestConfig) === null || _a === void 0 ? void 0 : _a.call(plugin, {
|
||||
client: this,
|
||||
url,
|
||||
params: requestParams,
|
||||
}));
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
applyPreStreamRequestConfigHooks(requestParams) {
|
||||
var _a;
|
||||
const url = this.getUrlObjectFromUrlString(requestParams.url);
|
||||
for (const plugin of this.getPlugins()) {
|
||||
(_a = plugin.onBeforeStreamRequestConfig) === null || _a === void 0 ? void 0 : _a.call(plugin, {
|
||||
client: this,
|
||||
url,
|
||||
params: requestParams,
|
||||
});
|
||||
}
|
||||
}
|
||||
async applyPreRequestHooks(requestParams, computedParams, requestOptions) {
|
||||
await this.applyPluginMethod('onBeforeRequest', {
|
||||
client: this,
|
||||
url: this.getUrlObjectFromUrlString(requestParams.url),
|
||||
params: requestParams,
|
||||
computedParams,
|
||||
requestOptions,
|
||||
});
|
||||
}
|
||||
async applyPostRequestHooks(requestParams, computedParams, requestOptions, response) {
|
||||
return await this.applyPluginMethod('onAfterRequest', {
|
||||
client: this,
|
||||
url: this.getUrlObjectFromUrlString(requestParams.url),
|
||||
params: requestParams,
|
||||
computedParams,
|
||||
requestOptions,
|
||||
response,
|
||||
});
|
||||
}
|
||||
applyResponseErrorHooks(requestParams, computedParams, requestOptions, promise) {
|
||||
return promise.catch(helpers_1.applyResponseHooks.bind(this, requestParams, computedParams, requestOptions));
|
||||
}
|
||||
}
|
||||
exports.ClientRequestMaker = ClientRequestMaker;
|
||||
ClientRequestMaker.BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
|
20
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.d.ts
generated
vendored
Normal file
20
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.d.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/// <reference types="node" />
|
||||
import type { RequestOptions } from 'https';
|
||||
import type { TBodyMode, TRequestBody, TRequestQuery, TRequestStringQuery } from '../types/request-maker.mixin.types';
|
||||
export declare class RequestParamHelpers {
|
||||
static readonly JSON_1_1_ENDPOINTS: Set<string>;
|
||||
static formatQueryToString(query: TRequestQuery): TRequestStringQuery;
|
||||
static autoDetectBodyType(url: URL): TBodyMode;
|
||||
static addQueryParamsToUrl(url: URL, query: TRequestQuery): void;
|
||||
static constructBodyParams(body: TRequestBody, headers: Record<string, string>, mode: TBodyMode): string | Buffer;
|
||||
static setBodyLengthHeader(options: RequestOptions, body: string | Buffer): void;
|
||||
static isOAuthSerializable(item: any): boolean;
|
||||
static mergeQueryAndBodyForOAuth(query: TRequestQuery, body: TRequestBody): any;
|
||||
static moveUrlQueryParamsIntoObject(url: URL, query: TRequestQuery): URL;
|
||||
/**
|
||||
* Replace URL parameters available in pathname, like `:id`, with data given in `parameters`:
|
||||
* `https://twitter.com/:id.json` + `{ id: '20' }` => `https://twitter.com/20.json`
|
||||
*/
|
||||
static applyRequestParametersToUrl(url: URL, parameters: TRequestQuery): URL;
|
||||
}
|
||||
export default RequestParamHelpers;
|
145
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.js
generated
vendored
Normal file
145
social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RequestParamHelpers = void 0;
|
||||
const form_data_helper_1 = require("./form-data.helper");
|
||||
const oauth1_helper_1 = __importDefault(require("./oauth1.helper"));
|
||||
/* Helpers functions that are specific to this class but do not depends on instance */
|
||||
class RequestParamHelpers {
|
||||
static formatQueryToString(query) {
|
||||
const formattedQuery = {};
|
||||
for (const prop in query) {
|
||||
if (typeof query[prop] === 'string') {
|
||||
formattedQuery[prop] = query[prop];
|
||||
}
|
||||
else if (typeof query[prop] !== 'undefined') {
|
||||
formattedQuery[prop] = String(query[prop]);
|
||||
}
|
||||
}
|
||||
return formattedQuery;
|
||||
}
|
||||
static autoDetectBodyType(url) {
|
||||
if (url.pathname.startsWith('/2/') || url.pathname.startsWith('/labs/2/')) {
|
||||
// oauth2 takes url encoded
|
||||
if (url.password.startsWith('/2/oauth2')) {
|
||||
return 'url';
|
||||
}
|
||||
// Twitter API v2 has JSON-encoded requests for everything else
|
||||
return 'json';
|
||||
}
|
||||
if (url.hostname === 'upload.twitter.com') {
|
||||
if (url.pathname === '/1.1/media/upload.json') {
|
||||
return 'form-data';
|
||||
}
|
||||
// json except for media/upload command, that is form-data.
|
||||
return 'json';
|
||||
}
|
||||
const endpoint = url.pathname.split('/1.1/', 2)[1];
|
||||
if (this.JSON_1_1_ENDPOINTS.has(endpoint)) {
|
||||
return 'json';
|
||||
}
|
||||
return 'url';
|
||||
}
|
||||
static addQueryParamsToUrl(url, query) {
|
||||
const queryEntries = Object.entries(query);
|
||||
if (queryEntries.length) {
|
||||
let search = '';
|
||||
for (const [key, value] of queryEntries) {
|
||||
search += (search.length ? '&' : '?') + `${oauth1_helper_1.default.percentEncode(key)}=${oauth1_helper_1.default.percentEncode(value)}`;
|
||||
}
|
||||
url.search = search;
|
||||
}
|
||||
}
|
||||
static constructBodyParams(body, headers, mode) {
|
||||
if (body instanceof Buffer) {
|
||||
return body;
|
||||
}
|
||||
if (mode === 'json') {
|
||||
headers['content-type'] = 'application/json;charset=UTF-8';
|
||||
return JSON.stringify(body);
|
||||
}
|
||||
else if (mode === 'url') {
|
||||
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
|
||||
if (Object.keys(body).length) {
|
||||
return new URLSearchParams(body)
|
||||
.toString()
|
||||
.replace(/\*/g, '%2A'); // URLSearchParams doesnt encode '*', but Twitter wants it encoded.
|
||||
}
|
||||
return '';
|
||||
}
|
||||
else if (mode === 'raw') {
|
||||
throw new Error('You can only use raw body mode with Buffers. To give a string, use Buffer.from(str).');
|
||||
}
|
||||
else {
|
||||
const form = new form_data_helper_1.FormDataHelper();
|
||||
for (const parameter in body) {
|
||||
form.append(parameter, body[parameter]);
|
||||
}
|
||||
const formHeaders = form.getHeaders();
|
||||
headers['content-type'] = formHeaders['content-type'];
|
||||
return form.getBuffer();
|
||||
}
|
||||
}
|
||||
static setBodyLengthHeader(options, body) {
|
||||
var _a;
|
||||
options.headers = (_a = options.headers) !== null && _a !== void 0 ? _a : {};
|
||||
if (typeof body === 'string') {
|
||||
options.headers['content-length'] = Buffer.byteLength(body);
|
||||
}
|
||||
else {
|
||||
options.headers['content-length'] = body.length;
|
||||
}
|
||||
}
|
||||
static isOAuthSerializable(item) {
|
||||
return !(item instanceof Buffer);
|
||||
}
|
||||
static mergeQueryAndBodyForOAuth(query, body) {
|
||||
const parameters = {};
|
||||
for (const prop in query) {
|
||||
parameters[prop] = query[prop];
|
||||
}
|
||||
if (this.isOAuthSerializable(body)) {
|
||||
for (const prop in body) {
|
||||
const bodyProp = body[prop];
|
||||
if (this.isOAuthSerializable(bodyProp)) {
|
||||
parameters[prop] = typeof bodyProp === 'object' && bodyProp !== null && 'toString' in bodyProp
|
||||
? bodyProp.toString()
|
||||
: bodyProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
static moveUrlQueryParamsIntoObject(url, query) {
|
||||
for (const [param, value] of url.searchParams) {
|
||||
query[param] = value;
|
||||
}
|
||||
// Remove the query string
|
||||
url.search = '';
|
||||
return url;
|
||||
}
|
||||
/**
|
||||
* Replace URL parameters available in pathname, like `:id`, with data given in `parameters`:
|
||||
* `https://twitter.com/:id.json` + `{ id: '20' }` => `https://twitter.com/20.json`
|
||||
*/
|
||||
static applyRequestParametersToUrl(url, parameters) {
|
||||
url.pathname = url.pathname.replace(/:([A-Z_-]+)/ig, (fullMatch, paramName) => {
|
||||
if (parameters[paramName] !== undefined) {
|
||||
return String(parameters[paramName]);
|
||||
}
|
||||
return fullMatch;
|
||||
});
|
||||
return url;
|
||||
}
|
||||
}
|
||||
exports.RequestParamHelpers = RequestParamHelpers;
|
||||
RequestParamHelpers.JSON_1_1_ENDPOINTS = new Set([
|
||||
'direct_messages/events/new.json',
|
||||
'direct_messages/welcome_messages/new.json',
|
||||
'direct_messages/welcome_messages/rules/new.json',
|
||||
'media/metadata/create.json',
|
||||
'collections/entries/curate.json',
|
||||
]);
|
||||
exports.default = RequestParamHelpers;
|
Reference in New Issue
Block a user