diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.d.ts
new file mode 100644
index 00000000..78af26c2
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.d.ts
@@ -0,0 +1,24 @@
+///
+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 {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.js b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.js
new file mode 100644
index 00000000..6a035b37
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.js
@@ -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';
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.d.ts
new file mode 100644
index 00000000..b897933b
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.d.ts
@@ -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): 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;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.js b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.js
new file mode 100644
index 00000000..25a76f55
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.js
@@ -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;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.d.ts
new file mode 100644
index 00000000..7b8c8863
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.d.ts
@@ -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;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.js b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.js
new file mode 100644
index 00000000..3e414101
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.js
@@ -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;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.d.ts
new file mode 100644
index 00000000..08de241d
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.d.ts
@@ -0,0 +1,60 @@
+///
+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 = (value: TwitterResponse) => 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 {
+ 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, reject: TResponseRejecter, res: IncomingMessage): void;
+ protected onResponseEndHandler(resolve: TResponseResolver, reject: TResponseRejecter): void;
+ protected onResponseCloseHandler(resolve: TResponseResolver, 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>;
+ makeRequestAsStream(): Promise>;
+ makeRequestAndResolveWhenReady(): Promise;
+}
+export default RequestHandlerHelper;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js
new file mode 100644
index 00000000..0a546e38
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js
@@ -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;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.d.ts
new file mode 100644
index 00000000..f4160c43
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.d.ts
@@ -0,0 +1,58 @@
+///
+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;
+ protected _oauth?: OAuth1Helper;
+ protected static readonly BODY_METHODS: Set;
+ constructor(settings?: Partial);
+ /** @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`. */
+ send(requestParams: IGetHttpRequestArgs): Promise>;
+ /**
+ * 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`.
+ * If `autoConnect` is `false`, a `TweetStream` is directly returned and you should call `stream.connect()` by yourself.
+ */
+ sendStream(requestParams: IGetHttpRequestArgs & IGetStreamRequestArgsSync): TweetStream;
+ sendStream(requestParams: IGetHttpRequestArgs & IGetStreamRequestArgsAsync): Promise>;
+ sendStream(requestParams: IGetHttpRequestArgs & IGetStreamRequestArgs): Promise> | TweetStream;
+ initializeToken(token?: TAcceptedInitToken): void;
+ getActiveTokens(): TClientTokens;
+ protected buildOAuth(): OAuth1Helper;
+ protected getOAuthAccessTokens(): {
+ key: string;
+ secret: string;
+ } | undefined;
+ getPlugins(): ITwitterApiClientPlugin[];
+ hasPlugins(): boolean;
+ applyPluginMethod(method: K, args: Parameters[K]>[0]): Promise;
+ protected writeAuthHeaders({ headers, bodyInSignature, url, method, query, body }: IWriteAuthHeadersArgs): Record;
+ 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 | undefined>;
+ protected applyPreStreamRequestConfigHooks(requestParams: IGetHttpRequestArgs): void;
+ protected applyPreRequestHooks(requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial): Promise;
+ protected applyPostRequestHooks(requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial, response: TwitterResponse): Promise;
+ protected applyResponseErrorHooks(requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial, promise: Promise>): Promise>;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.js b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.js
new file mode 100644
index 00000000..3dab72fc
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.js
@@ -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`. */
+ 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']);
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.d.ts
new file mode 100644
index 00000000..97525674
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.d.ts
@@ -0,0 +1,20 @@
+///
+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;
+ static formatQueryToString(query: TRequestQuery): TRequestStringQuery;
+ static autoDetectBodyType(url: URL): TBodyMode;
+ static addQueryParamsToUrl(url: URL, query: TRequestQuery): void;
+ static constructBodyParams(body: TRequestBody, headers: Record, 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;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.js b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.js
new file mode 100644
index 00000000..9c741c56
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.js
@@ -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;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client.base.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client.base.d.ts
new file mode 100644
index 00000000..2bc89c22
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client.base.d.ts
@@ -0,0 +1,134 @@
+import type { IClientSettings, ITwitterApiClientPlugin, TwitterApiBasicAuth, TwitterApiOAuth2Init, TwitterApiTokens, TwitterRateLimit, TwitterResponse, UserV1, UserV2Result } from './types';
+import { ClientRequestMaker } from './client-mixins/request-maker.mixin';
+import TweetStream from './stream/TweetStream';
+import { SharedPromise } from './helpers';
+import type { TCustomizableRequestArgs, TRequestBody, TRequestQuery } from './types/request-maker.mixin.types';
+export declare type TGetClientRequestArgs = TCustomizableRequestArgs & {
+ prefix?: string;
+ fullResponse?: boolean;
+};
+declare type TGetClientRequestArgsFullResponse = TClientRequestArgs & {
+ fullResponse: true;
+};
+declare type TGetClientRequestArgsDataResponse = TClientRequestArgs & {
+ fullResponse?: false;
+};
+export declare type TClientRequestArgs = TCustomizableRequestArgs & {
+ prefix?: string;
+ fullResponse?: boolean;
+ query?: TRequestQuery;
+};
+declare type TClientRequestArgsFullResponse = TClientRequestArgs & {
+ fullResponse: true;
+};
+declare type TClientRequestArgsDataResponse = TClientRequestArgs & {
+ fullResponse?: false;
+};
+export declare type TStreamClientRequestArgs = TCustomizableRequestArgs & {
+ prefix?: string;
+ query?: TRequestQuery;
+ payloadIsError?: (data: any) => boolean;
+ /**
+ * Choose to make or not initial connection.
+ * Method `.connect` must be called on returned `TweetStream` object
+ * to start stream if `autoConnect` is set to `false`.
+ * Defaults to `true`.
+ */
+ autoConnect?: boolean;
+};
+export declare type TStreamClientRequestArgsWithAutoConnect = TStreamClientRequestArgs & {
+ autoConnect?: true;
+};
+export declare type TStreamClientRequestArgsWithoutAutoConnect = TStreamClientRequestArgs & {
+ autoConnect: false;
+};
+/**
+ * Base class for Twitter instances
+ */
+export default abstract class TwitterApiBase {
+ protected _prefix: string | undefined;
+ protected _currentUser: SharedPromise | null;
+ protected _currentUserV2: SharedPromise | null;
+ protected _requestMaker: ClientRequestMaker;
+ /**
+ * Create a new TwitterApi object without authentication.
+ */
+ constructor(_?: undefined, settings?: Partial);
+ /**
+ * Create a new TwitterApi object with OAuth 2.0 Bearer authentication.
+ */
+ constructor(bearerToken: string, settings?: Partial);
+ /**
+ * Create a new TwitterApi object with three-legged OAuth 1.0a authentication.
+ */
+ constructor(tokens: TwitterApiTokens, settings?: Partial);
+ /**
+ * Create a new TwitterApi object with only client ID needed for OAuth2 user-flow.
+ */
+ constructor(oauth2Init: TwitterApiOAuth2Init, settings?: Partial);
+ /**
+ * Create a new TwitterApi object with Basic HTTP authentication.
+ */
+ constructor(credentials: TwitterApiBasicAuth, settings?: Partial);
+ /**
+ * Create a clone of {instance}.
+ */
+ constructor(instance: TwitterApiBase, settings?: Partial);
+ protected setPrefix(prefix: string | undefined): void;
+ cloneWithPrefix(prefix: string): this;
+ getActiveTokens(): import("./types").TClientTokens;
+ getPlugins(): ITwitterApiClientPlugin[];
+ getPluginOfType(type: {
+ new (...args: any[]): T;
+ }): T | undefined;
+ /**
+ * @deprecated - Migrate to plugin `@twitter-api-v2/plugin-rate-limit`
+ *
+ * Tells if you hit the Twitter rate limit for {endpoint}.
+ * (local data only, this should not ask anything to Twitter)
+ */
+ hasHitRateLimit(endpoint: string): boolean;
+ /**
+ * @deprecated - Migrate to plugin `@twitter-api-v2/plugin-rate-limit`
+ *
+ * Tells if you hit the returned Twitter rate limit for {endpoint} has expired.
+ * If client has no saved rate limit data for {endpoint}, this will gives you `true`.
+ */
+ isRateLimitStatusObsolete(endpoint: string): boolean;
+ /**
+ * @deprecated - Migrate to plugin `@twitter-api-v2/plugin-rate-limit`
+ *
+ * Get the last obtained Twitter rate limit information for {endpoint}.
+ * (local data only, this should not ask anything to Twitter)
+ */
+ getLastRateLimitStatus(endpoint: string): TwitterRateLimit | undefined;
+ /** Get cached current user. */
+ protected getCurrentUserObject(forceFetch?: boolean): Promise;
+ /**
+ * Get cached current user from v2 API.
+ * This can only be the slimest available `UserV2` object, with only `id`, `name` and `username` properties defined.
+ *
+ * To get a customized `UserV2Result`, use `.v2.me()`
+ *
+ * OAuth2 scopes: `tweet.read` & `users.read`
+ */
+ protected getCurrentUserV2Object(forceFetch?: boolean): Promise;
+ get(url: string, query?: TRequestQuery, args?: TGetClientRequestArgsDataResponse): Promise;
+ get(url: string, query?: TRequestQuery, args?: TGetClientRequestArgsFullResponse): Promise>;
+ delete(url: string, query?: TRequestQuery, args?: TGetClientRequestArgsDataResponse): Promise;
+ delete(url: string, query?: TRequestQuery, args?: TGetClientRequestArgsFullResponse): Promise>;
+ post(url: string, body?: TRequestBody, args?: TClientRequestArgsDataResponse): Promise;
+ post(url: string, body?: TRequestBody, args?: TClientRequestArgsFullResponse): Promise>;
+ put(url: string, body?: TRequestBody, args?: TClientRequestArgsDataResponse): Promise;
+ put(url: string, body?: TRequestBody, args?: TClientRequestArgsFullResponse): Promise>;
+ patch(url: string, body?: TRequestBody, args?: TClientRequestArgsDataResponse): Promise;
+ patch(url: string, body?: TRequestBody, args?: TClientRequestArgsFullResponse): Promise>;
+ /** Stream request helpers */
+ getStream(url: string, query: TRequestQuery | undefined, options: TStreamClientRequestArgsWithoutAutoConnect): TweetStream;
+ getStream(url: string, query?: TRequestQuery, options?: TStreamClientRequestArgsWithAutoConnect): Promise>;
+ getStream(url: string, query?: TRequestQuery, options?: TStreamClientRequestArgs): Promise> | TweetStream;
+ postStream(url: string, body: TRequestBody | undefined, options: TStreamClientRequestArgsWithoutAutoConnect): TweetStream;
+ postStream(url: string, body?: TRequestBody, options?: TStreamClientRequestArgsWithAutoConnect): Promise>;
+ postStream(url: string, body?: TRequestBody, options?: TStreamClientRequestArgs): Promise> | TweetStream;
+}
+export {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client.base.js b/social/twitter/node_modules/twitter-api-v2/dist/client.base.js
new file mode 100644
index 00000000..926fb566
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client.base.js
@@ -0,0 +1,179 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const request_maker_mixin_1 = require("./client-mixins/request-maker.mixin");
+const helpers_1 = require("./helpers");
+const globals_1 = require("./globals");
+/**
+ * Base class for Twitter instances
+ */
+class TwitterApiBase {
+ constructor(token, settings = {}) {
+ this._currentUser = null;
+ this._currentUserV2 = null;
+ if (token instanceof TwitterApiBase) {
+ this._requestMaker = token._requestMaker;
+ }
+ else {
+ this._requestMaker = new request_maker_mixin_1.ClientRequestMaker(settings);
+ this._requestMaker.initializeToken(token);
+ }
+ }
+ /* Prefix/Token handling */
+ setPrefix(prefix) {
+ this._prefix = prefix;
+ }
+ cloneWithPrefix(prefix) {
+ const clone = this.constructor(this);
+ clone.setPrefix(prefix);
+ return clone;
+ }
+ getActiveTokens() {
+ return this._requestMaker.getActiveTokens();
+ }
+ /* Rate limit cache / Plugins */
+ getPlugins() {
+ return this._requestMaker.getPlugins();
+ }
+ getPluginOfType(type) {
+ return this.getPlugins().find(plugin => plugin instanceof type);
+ }
+ /**
+ * @deprecated - Migrate to plugin `@twitter-api-v2/plugin-rate-limit`
+ *
+ * Tells if you hit the Twitter rate limit for {endpoint}.
+ * (local data only, this should not ask anything to Twitter)
+ */
+ hasHitRateLimit(endpoint) {
+ var _a;
+ if (this.isRateLimitStatusObsolete(endpoint)) {
+ return false;
+ }
+ return ((_a = this.getLastRateLimitStatus(endpoint)) === null || _a === void 0 ? void 0 : _a.remaining) === 0;
+ }
+ /**
+ * @deprecated - Migrate to plugin `@twitter-api-v2/plugin-rate-limit`
+ *
+ * Tells if you hit the returned Twitter rate limit for {endpoint} has expired.
+ * If client has no saved rate limit data for {endpoint}, this will gives you `true`.
+ */
+ isRateLimitStatusObsolete(endpoint) {
+ const rateLimit = this.getLastRateLimitStatus(endpoint);
+ if (rateLimit === undefined) {
+ return true;
+ }
+ // Timestamps are exprimed in seconds, JS works with ms
+ return (rateLimit.reset * 1000) < Date.now();
+ }
+ /**
+ * @deprecated - Migrate to plugin `@twitter-api-v2/plugin-rate-limit`
+ *
+ * Get the last obtained Twitter rate limit information for {endpoint}.
+ * (local data only, this should not ask anything to Twitter)
+ */
+ getLastRateLimitStatus(endpoint) {
+ const endpointWithPrefix = endpoint.match(/^https?:\/\//) ? endpoint : (this._prefix + endpoint);
+ return this._requestMaker.getRateLimits()[endpointWithPrefix];
+ }
+ /* Current user cache */
+ /** Get cached current user. */
+ getCurrentUserObject(forceFetch = false) {
+ if (!forceFetch && this._currentUser) {
+ if (this._currentUser.value) {
+ return Promise.resolve(this._currentUser.value);
+ }
+ return this._currentUser.promise;
+ }
+ this._currentUser = (0, helpers_1.sharedPromise)(() => this.get('account/verify_credentials.json', { tweet_mode: 'extended' }, { prefix: globals_1.API_V1_1_PREFIX }));
+ return this._currentUser.promise;
+ }
+ /**
+ * Get cached current user from v2 API.
+ * This can only be the slimest available `UserV2` object, with only `id`, `name` and `username` properties defined.
+ *
+ * To get a customized `UserV2Result`, use `.v2.me()`
+ *
+ * OAuth2 scopes: `tweet.read` & `users.read`
+ */
+ getCurrentUserV2Object(forceFetch = false) {
+ if (!forceFetch && this._currentUserV2) {
+ if (this._currentUserV2.value) {
+ return Promise.resolve(this._currentUserV2.value);
+ }
+ return this._currentUserV2.promise;
+ }
+ this._currentUserV2 = (0, helpers_1.sharedPromise)(() => this.get('users/me', undefined, { prefix: globals_1.API_V2_PREFIX }));
+ return this._currentUserV2.promise;
+ }
+ async get(url, query = {}, { fullResponse, prefix = this._prefix, ...rest } = {}) {
+ if (prefix)
+ url = prefix + url;
+ const resp = await this._requestMaker.send({
+ url,
+ method: 'GET',
+ query,
+ ...rest,
+ });
+ return fullResponse ? resp : resp.data;
+ }
+ async delete(url, query = {}, { fullResponse, prefix = this._prefix, ...rest } = {}) {
+ if (prefix)
+ url = prefix + url;
+ const resp = await this._requestMaker.send({
+ url,
+ method: 'DELETE',
+ query,
+ ...rest,
+ });
+ return fullResponse ? resp : resp.data;
+ }
+ async post(url, body, { fullResponse, prefix = this._prefix, ...rest } = {}) {
+ if (prefix)
+ url = prefix + url;
+ const resp = await this._requestMaker.send({
+ url,
+ method: 'POST',
+ body,
+ ...rest,
+ });
+ return fullResponse ? resp : resp.data;
+ }
+ async put(url, body, { fullResponse, prefix = this._prefix, ...rest } = {}) {
+ if (prefix)
+ url = prefix + url;
+ const resp = await this._requestMaker.send({
+ url,
+ method: 'PUT',
+ body,
+ ...rest,
+ });
+ return fullResponse ? resp : resp.data;
+ }
+ async patch(url, body, { fullResponse, prefix = this._prefix, ...rest } = {}) {
+ if (prefix)
+ url = prefix + url;
+ const resp = await this._requestMaker.send({
+ url,
+ method: 'PATCH',
+ body,
+ ...rest,
+ });
+ return fullResponse ? resp : resp.data;
+ }
+ getStream(url, query, { prefix = this._prefix, ...rest } = {}) {
+ return this._requestMaker.sendStream({
+ url: prefix ? prefix + url : url,
+ method: 'GET',
+ query,
+ ...rest,
+ });
+ }
+ postStream(url, body, { prefix = this._prefix, ...rest } = {}) {
+ return this._requestMaker.sendStream({
+ url: prefix ? prefix + url : url,
+ method: 'POST',
+ body,
+ ...rest,
+ });
+ }
+}
+exports.default = TwitterApiBase;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client.subclient.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client.subclient.d.ts
new file mode 100644
index 00000000..e468a03b
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client.subclient.d.ts
@@ -0,0 +1,7 @@
+import TwitterApiBase from './client.base';
+/**
+ * Base subclient for every v1 and v2 client.
+ */
+export default abstract class TwitterApiSubClient extends TwitterApiBase {
+ constructor(instance: TwitterApiBase);
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client.subclient.js b/social/twitter/node_modules/twitter-api-v2/dist/client.subclient.js
new file mode 100644
index 00000000..078ca022
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client.subclient.js
@@ -0,0 +1,18 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const client_base_1 = __importDefault(require("./client.base"));
+/**
+ * Base subclient for every v1 and v2 client.
+ */
+class TwitterApiSubClient extends client_base_1.default {
+ constructor(instance) {
+ if (!(instance instanceof client_base_1.default)) {
+ throw new Error('You must instance SubTwitterApi instance from existing TwitterApi instance.');
+ }
+ super(instance);
+ }
+}
+exports.default = TwitterApiSubClient;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client/index.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client/index.d.ts
new file mode 100644
index 00000000..5d7285bd
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client/index.d.ts
@@ -0,0 +1,22 @@
+import TwitterApiv1 from '../v1/client.v1';
+import TwitterApiv2 from '../v2/client.v2';
+import TwitterApiReadWrite from './readwrite';
+/**
+ * Twitter v1.1 and v2 API client.
+ */
+export declare class TwitterApi extends TwitterApiReadWrite {
+ protected _v1?: TwitterApiv1;
+ protected _v2?: TwitterApiv2;
+ get v1(): TwitterApiv1;
+ get v2(): TwitterApiv2;
+ /**
+ * Get a client with read/write rights.
+ */
+ get readWrite(): TwitterApiReadWrite;
+ static getErrors(error: any): (import("../types").ErrorV1 | import("../types").ErrorV2)[];
+ /** Extract another image size than obtained in a `profile_image_url` or `profile_image_url_https` field of a user object. */
+ static getProfileImageInSize(profileImageUrl: string, size: 'normal' | 'bigger' | 'mini' | 'original'): string;
+}
+export { default as TwitterApiReadWrite } from './readwrite';
+export { default as TwitterApiReadOnly } from './readonly';
+export default TwitterApi;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client/index.js b/social/twitter/node_modules/twitter-api-v2/dist/client/index.js
new file mode 100644
index 00000000..07bac3bc
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client/index.js
@@ -0,0 +1,70 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TwitterApiReadOnly = exports.TwitterApiReadWrite = exports.TwitterApi = void 0;
+const client_v1_1 = __importDefault(require("../v1/client.v1"));
+const client_v2_1 = __importDefault(require("../v2/client.v2"));
+const readwrite_1 = __importDefault(require("./readwrite"));
+// "Real" exported client for usage of TwitterApi.
+/**
+ * Twitter v1.1 and v2 API client.
+ */
+class TwitterApi extends readwrite_1.default {
+ /* Direct access to subclients */
+ get v1() {
+ if (this._v1)
+ return this._v1;
+ return this._v1 = new client_v1_1.default(this);
+ }
+ get v2() {
+ if (this._v2)
+ return this._v2;
+ return this._v2 = new client_v2_1.default(this);
+ }
+ /**
+ * Get a client with read/write rights.
+ */
+ get readWrite() {
+ return this;
+ }
+ /* Static helpers */
+ static getErrors(error) {
+ var _a;
+ if (typeof error !== 'object')
+ return [];
+ if (!('data' in error))
+ return [];
+ return (_a = error.data.errors) !== null && _a !== void 0 ? _a : [];
+ }
+ /** Extract another image size than obtained in a `profile_image_url` or `profile_image_url_https` field of a user object. */
+ static getProfileImageInSize(profileImageUrl, size) {
+ const lastPart = profileImageUrl.split('/').pop();
+ const sizes = ['normal', 'bigger', 'mini'];
+ let originalUrl = profileImageUrl;
+ for (const availableSize of sizes) {
+ if (lastPart.includes(`_${availableSize}`)) {
+ originalUrl = profileImageUrl.replace(`_${availableSize}`, '');
+ break;
+ }
+ }
+ if (size === 'original') {
+ return originalUrl;
+ }
+ const extPos = originalUrl.lastIndexOf('.');
+ if (extPos !== -1) {
+ const ext = originalUrl.slice(extPos + 1);
+ return originalUrl.slice(0, extPos) + '_' + size + '.' + ext;
+ }
+ else {
+ return originalUrl + '_' + size;
+ }
+ }
+}
+exports.TwitterApi = TwitterApi;
+var readwrite_2 = require("./readwrite");
+Object.defineProperty(exports, "TwitterApiReadWrite", { enumerable: true, get: function () { return __importDefault(readwrite_2).default; } });
+var readonly_1 = require("./readonly");
+Object.defineProperty(exports, "TwitterApiReadOnly", { enumerable: true, get: function () { return __importDefault(readonly_1).default; } });
+exports.default = TwitterApi;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client/readonly.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client/readonly.d.ts
new file mode 100644
index 00000000..d3806897
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client/readonly.d.ts
@@ -0,0 +1,157 @@
+import TwitterApi from '.';
+import TwitterApiBase from '../client.base';
+import { AccessOAuth2TokenArgs, AccessOAuth2TokenResult, BuildOAuth2RequestLinkArgs, IOAuth2RequestTokenResult, IParsedOAuth2TokenResult, LoginResult, RequestTokenArgs, Tweetv2SearchParams } from '../types';
+import TwitterApiv1ReadOnly from '../v1/client.v1.read';
+import TwitterApiv2ReadOnly from '../v2/client.v2.read';
+/**
+ * Twitter v1.1 and v2 API client.
+ */
+export default class TwitterApiReadOnly extends TwitterApiBase {
+ protected _v1?: TwitterApiv1ReadOnly;
+ protected _v2?: TwitterApiv2ReadOnly;
+ get v1(): TwitterApiv1ReadOnly;
+ get v2(): TwitterApiv2ReadOnly;
+ /**
+ * Fetch and cache current user.
+ * This method can only be called with a OAuth 1.0a user authentication.
+ *
+ * You can use this method to test if authentication was successful.
+ * Next calls to this methods will use the cached user, unless `forceFetch: true` is given.
+ */
+ currentUser(forceFetch?: boolean): Promise;
+ /**
+ * Fetch and cache current user.
+ * This method can only be called with a OAuth 1.0a or OAuth2 user authentication.
+ *
+ * This can only be the slimest available `UserV2` object, with only id, name and username properties defined.
+ * To get a customized `UserV2Result`, use `.v2.me()`
+ *
+ * You can use this method to test if authentication was successful.
+ * Next calls to this methods will use the cached user, unless `forceFetch: true` is given.
+ *
+ * OAuth2 scopes: `tweet.read` & `users.read`
+ */
+ currentUserV2(forceFetch?: boolean): Promise;
+ search(what: string, options?: Partial): Promise;
+ /**
+ * Generate the OAuth request token link for user-based OAuth 1.0 auth.
+ *
+ * ```ts
+ * // Instanciate TwitterApi with consumer keys
+ * const client = new TwitterApi({ appKey: 'consumer_key', appSecret: 'consumer_secret' });
+ *
+ * const tokenRequest = await client.generateAuthLink('oob-or-your-callback-url');
+ * // redirect end-user to tokenRequest.url
+ *
+ * // Save tokenRequest.oauth_token_secret somewhere, it will be needed for next auth step.
+ * ```
+ */
+ generateAuthLink(oauth_callback?: string, { authAccessType, linkMode, forceLogin, screenName, }?: Partial): Promise<{
+ oauth_token: string;
+ oauth_token_secret: string;
+ oauth_callback_confirmed: "true";
+ url: string;
+ }>;
+ /**
+ * Obtain access to user-based OAuth 1.0 auth.
+ *
+ * After user is redirect from your callback, use obtained oauth_token and oauth_verifier to
+ * instanciate the new TwitterApi instance.
+ *
+ * ```ts
+ * // Use the saved oauth_token_secret associated to oauth_token returned by callback
+ * const requestClient = new TwitterApi({
+ * appKey: 'consumer_key',
+ * appSecret: 'consumer_secret',
+ * accessToken: 'oauth_token',
+ * accessSecret: 'oauth_token_secret'
+ * });
+ *
+ * // Use oauth_verifier obtained from callback request
+ * const { client: userClient } = await requestClient.login('oauth_verifier');
+ *
+ * // {userClient} is a valid {TwitterApi} object you can use for future requests
+ * ```
+ */
+ login(oauth_verifier: string): Promise;
+ /**
+ * Enable application-only authentication.
+ *
+ * To make the request, instanciate TwitterApi with consumer and secret.
+ *
+ * ```ts
+ * const requestClient = new TwitterApi({ appKey: 'consumer', appSecret: 'secret' });
+ * const appClient = await requestClient.appLogin();
+ *
+ * // Use {appClient} to make requests
+ * ```
+ */
+ appLogin(): Promise;
+ /**
+ * Generate the OAuth request token link for user-based OAuth 2.0 auth.
+ *
+ * - **You can only use v2 API endpoints with this authentication method.**
+ * - **You need to specify which scope you want to have when you create your auth link. Make sure it matches your needs.**
+ *
+ * See https://developer.twitter.com/en/docs/authentication/oauth-2-0/user-access-token for details.
+ *
+ * ```ts
+ * // Instanciate TwitterApi with client ID
+ * const client = new TwitterApi({ clientId: 'yourClientId' });
+ *
+ * // Generate a link to callback URL that will gives a token with tweet+user read access
+ * const link = client.generateOAuth2AuthLink('your-callback-url', { scope: ['tweet.read', 'users.read'] });
+ *
+ * // Extract props from generate link
+ * const { url, state, codeVerifier } = link;
+ *
+ * // redirect end-user to url
+ * // Save `state` and `codeVerifier` somewhere, it will be needed for next auth step.
+ * ```
+ */
+ generateOAuth2AuthLink(redirectUri: string, options?: Partial): IOAuth2RequestTokenResult;
+ /**
+ * Obtain access to user-based OAuth 2.0 auth.
+ *
+ * After user is redirect from your callback, use obtained code to
+ * instanciate the new TwitterApi instance.
+ *
+ * You need to obtain `codeVerifier` from a call to `.generateOAuth2AuthLink`.
+ *
+ * ```ts
+ * // Use the saved codeVerifier associated to state (present in query string of callback)
+ * const requestClient = new TwitterApi({ clientId: 'yourClientId' });
+ *
+ * const { client: userClient, refreshToken } = await requestClient.loginWithOAuth2({
+ * code: 'codeFromQueryString',
+ * // the same URL given to generateOAuth2AuthLink
+ * redirectUri,
+ * // the verifier returned by generateOAuth2AuthLink
+ * codeVerifier,
+ * });
+ *
+ * // {userClient} is a valid {TwitterApi} object you can use for future requests
+ * // {refreshToken} is defined if 'offline.access' is in scope.
+ * ```
+ */
+ loginWithOAuth2({ code, codeVerifier, redirectUri }: AccessOAuth2TokenArgs): Promise;
+ /**
+ * Obtain a new access token to user-based OAuth 2.0 auth from a refresh token.
+ *
+ * ```ts
+ * const requestClient = new TwitterApi({ clientId: 'yourClientId' });
+ *
+ * const { client: userClient } = await requestClient.refreshOAuth2Token('refreshToken');
+ * // {userClient} is a valid {TwitterApi} object you can use for future requests
+ * ```
+ */
+ refreshOAuth2Token(refreshToken: string): Promise;
+ /**
+ * Revoke a single user-based OAuth 2.0 token.
+ *
+ * You must specify its source, access token (directly after login)
+ * or refresh token (if you've called `.refreshOAuth2Token` before).
+ */
+ revokeOAuth2Token(token: string, tokenType?: 'access_token' | 'refresh_token'): Promise;
+ protected parseOAuth2AccessTokenResult(result: AccessOAuth2TokenResult): IParsedOAuth2TokenResult;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client/readonly.js b/social/twitter/node_modules/twitter-api-v2/dist/client/readonly.js
new file mode 100644
index 00000000..d26dfcaf
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client/readonly.js
@@ -0,0 +1,305 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const _1 = __importDefault(require("."));
+const client_base_1 = __importDefault(require("../client.base"));
+const client_v1_read_1 = __importDefault(require("../v1/client.v1.read"));
+const client_v2_read_1 = __importDefault(require("../v2/client.v2.read"));
+const oauth2_helper_1 = require("../client-mixins/oauth2.helper");
+const request_param_helper_1 = __importDefault(require("../client-mixins/request-param.helper"));
+/**
+ * Twitter v1.1 and v2 API client.
+ */
+class TwitterApiReadOnly extends client_base_1.default {
+ /* Direct access to subclients */
+ get v1() {
+ if (this._v1)
+ return this._v1;
+ return this._v1 = new client_v1_read_1.default(this);
+ }
+ get v2() {
+ if (this._v2)
+ return this._v2;
+ return this._v2 = new client_v2_read_1.default(this);
+ }
+ /**
+ * Fetch and cache current user.
+ * This method can only be called with a OAuth 1.0a user authentication.
+ *
+ * You can use this method to test if authentication was successful.
+ * Next calls to this methods will use the cached user, unless `forceFetch: true` is given.
+ */
+ async currentUser(forceFetch = false) {
+ return await this.getCurrentUserObject(forceFetch);
+ }
+ /**
+ * Fetch and cache current user.
+ * This method can only be called with a OAuth 1.0a or OAuth2 user authentication.
+ *
+ * This can only be the slimest available `UserV2` object, with only id, name and username properties defined.
+ * To get a customized `UserV2Result`, use `.v2.me()`
+ *
+ * You can use this method to test if authentication was successful.
+ * Next calls to this methods will use the cached user, unless `forceFetch: true` is given.
+ *
+ * OAuth2 scopes: `tweet.read` & `users.read`
+ */
+ async currentUserV2(forceFetch = false) {
+ return await this.getCurrentUserV2Object(forceFetch);
+ }
+ /* Shortcuts to endpoints */
+ search(what, options) {
+ return this.v2.search(what, options);
+ }
+ /* Authentication */
+ /**
+ * Generate the OAuth request token link for user-based OAuth 1.0 auth.
+ *
+ * ```ts
+ * // Instanciate TwitterApi with consumer keys
+ * const client = new TwitterApi({ appKey: 'consumer_key', appSecret: 'consumer_secret' });
+ *
+ * const tokenRequest = await client.generateAuthLink('oob-or-your-callback-url');
+ * // redirect end-user to tokenRequest.url
+ *
+ * // Save tokenRequest.oauth_token_secret somewhere, it will be needed for next auth step.
+ * ```
+ */
+ async generateAuthLink(oauth_callback = 'oob', { authAccessType, linkMode = 'authenticate', forceLogin, screenName, } = {}) {
+ const oauthResult = await this.post('https://api.twitter.com/oauth/request_token', { oauth_callback, x_auth_access_type: authAccessType });
+ let url = `https://api.twitter.com/oauth/${linkMode}?oauth_token=${encodeURIComponent(oauthResult.oauth_token)}`;
+ if (forceLogin !== undefined) {
+ url += `&force_login=${encodeURIComponent(forceLogin)}`;
+ }
+ if (screenName !== undefined) {
+ url += `&screen_name=${encodeURIComponent(screenName)}`;
+ }
+ if (this._requestMaker.hasPlugins()) {
+ this._requestMaker.applyPluginMethod('onOAuth1RequestToken', {
+ client: this._requestMaker,
+ url,
+ oauthResult,
+ });
+ }
+ return {
+ url,
+ ...oauthResult,
+ };
+ }
+ /**
+ * Obtain access to user-based OAuth 1.0 auth.
+ *
+ * After user is redirect from your callback, use obtained oauth_token and oauth_verifier to
+ * instanciate the new TwitterApi instance.
+ *
+ * ```ts
+ * // Use the saved oauth_token_secret associated to oauth_token returned by callback
+ * const requestClient = new TwitterApi({
+ * appKey: 'consumer_key',
+ * appSecret: 'consumer_secret',
+ * accessToken: 'oauth_token',
+ * accessSecret: 'oauth_token_secret'
+ * });
+ *
+ * // Use oauth_verifier obtained from callback request
+ * const { client: userClient } = await requestClient.login('oauth_verifier');
+ *
+ * // {userClient} is a valid {TwitterApi} object you can use for future requests
+ * ```
+ */
+ async login(oauth_verifier) {
+ const tokens = this.getActiveTokens();
+ if (tokens.type !== 'oauth-1.0a')
+ throw new Error('You must setup TwitterApi instance with consumer keys to accept OAuth 1.0 login');
+ const oauth_result = await this.post('https://api.twitter.com/oauth/access_token', { oauth_token: tokens.accessToken, oauth_verifier });
+ const client = new _1.default({
+ appKey: tokens.appKey,
+ appSecret: tokens.appSecret,
+ accessToken: oauth_result.oauth_token,
+ accessSecret: oauth_result.oauth_token_secret,
+ }, this._requestMaker.clientSettings);
+ return {
+ accessToken: oauth_result.oauth_token,
+ accessSecret: oauth_result.oauth_token_secret,
+ userId: oauth_result.user_id,
+ screenName: oauth_result.screen_name,
+ client,
+ };
+ }
+ /**
+ * Enable application-only authentication.
+ *
+ * To make the request, instanciate TwitterApi with consumer and secret.
+ *
+ * ```ts
+ * const requestClient = new TwitterApi({ appKey: 'consumer', appSecret: 'secret' });
+ * const appClient = await requestClient.appLogin();
+ *
+ * // Use {appClient} to make requests
+ * ```
+ */
+ async appLogin() {
+ const tokens = this.getActiveTokens();
+ if (tokens.type !== 'oauth-1.0a')
+ throw new Error('You must setup TwitterApi instance with consumer keys to accept app-only login');
+ // Create a client with Basic authentication
+ const basicClient = new _1.default({ username: tokens.appKey, password: tokens.appSecret });
+ const res = await basicClient.post('https://api.twitter.com/oauth2/token', { grant_type: 'client_credentials' });
+ // New object with Bearer token
+ return new _1.default(res.access_token, this._requestMaker.clientSettings);
+ }
+ /* OAuth 2 user authentication */
+ /**
+ * Generate the OAuth request token link for user-based OAuth 2.0 auth.
+ *
+ * - **You can only use v2 API endpoints with this authentication method.**
+ * - **You need to specify which scope you want to have when you create your auth link. Make sure it matches your needs.**
+ *
+ * See https://developer.twitter.com/en/docs/authentication/oauth-2-0/user-access-token for details.
+ *
+ * ```ts
+ * // Instanciate TwitterApi with client ID
+ * const client = new TwitterApi({ clientId: 'yourClientId' });
+ *
+ * // Generate a link to callback URL that will gives a token with tweet+user read access
+ * const link = client.generateOAuth2AuthLink('your-callback-url', { scope: ['tweet.read', 'users.read'] });
+ *
+ * // Extract props from generate link
+ * const { url, state, codeVerifier } = link;
+ *
+ * // redirect end-user to url
+ * // Save `state` and `codeVerifier` somewhere, it will be needed for next auth step.
+ * ```
+ */
+ generateOAuth2AuthLink(redirectUri, options = {}) {
+ var _a, _b;
+ if (!this._requestMaker.clientId) {
+ throw new Error('Twitter API instance is not initialized with client ID. You can find your client ID in Twitter Developer Portal. ' +
+ 'Please build an instance with: new TwitterApi({ clientId: \'\' })');
+ }
+ const state = (_a = options.state) !== null && _a !== void 0 ? _a : oauth2_helper_1.OAuth2Helper.generateRandomString(32);
+ const codeVerifier = oauth2_helper_1.OAuth2Helper.getCodeVerifier();
+ const codeChallenge = oauth2_helper_1.OAuth2Helper.getCodeChallengeFromVerifier(codeVerifier);
+ const rawScope = (_b = options.scope) !== null && _b !== void 0 ? _b : '';
+ const scope = Array.isArray(rawScope) ? rawScope.join(' ') : rawScope;
+ const url = new URL('https://twitter.com/i/oauth2/authorize');
+ const query = {
+ response_type: 'code',
+ client_id: this._requestMaker.clientId,
+ redirect_uri: redirectUri,
+ state,
+ code_challenge: codeChallenge,
+ code_challenge_method: 's256',
+ scope,
+ };
+ request_param_helper_1.default.addQueryParamsToUrl(url, query);
+ const result = {
+ url: url.toString(),
+ state,
+ codeVerifier,
+ codeChallenge,
+ };
+ if (this._requestMaker.hasPlugins()) {
+ this._requestMaker.applyPluginMethod('onOAuth2RequestToken', {
+ client: this._requestMaker,
+ result,
+ redirectUri,
+ });
+ }
+ return result;
+ }
+ /**
+ * Obtain access to user-based OAuth 2.0 auth.
+ *
+ * After user is redirect from your callback, use obtained code to
+ * instanciate the new TwitterApi instance.
+ *
+ * You need to obtain `codeVerifier` from a call to `.generateOAuth2AuthLink`.
+ *
+ * ```ts
+ * // Use the saved codeVerifier associated to state (present in query string of callback)
+ * const requestClient = new TwitterApi({ clientId: 'yourClientId' });
+ *
+ * const { client: userClient, refreshToken } = await requestClient.loginWithOAuth2({
+ * code: 'codeFromQueryString',
+ * // the same URL given to generateOAuth2AuthLink
+ * redirectUri,
+ * // the verifier returned by generateOAuth2AuthLink
+ * codeVerifier,
+ * });
+ *
+ * // {userClient} is a valid {TwitterApi} object you can use for future requests
+ * // {refreshToken} is defined if 'offline.access' is in scope.
+ * ```
+ */
+ async loginWithOAuth2({ code, codeVerifier, redirectUri }) {
+ if (!this._requestMaker.clientId) {
+ throw new Error('Twitter API instance is not initialized with client ID. ' +
+ 'Please build an instance with: new TwitterApi({ clientId: \'\' })');
+ }
+ const accessTokenResult = await this.post('https://api.twitter.com/2/oauth2/token', {
+ code,
+ code_verifier: codeVerifier,
+ redirect_uri: redirectUri,
+ grant_type: 'authorization_code',
+ client_id: this._requestMaker.clientId,
+ client_secret: this._requestMaker.clientSecret,
+ });
+ return this.parseOAuth2AccessTokenResult(accessTokenResult);
+ }
+ /**
+ * Obtain a new access token to user-based OAuth 2.0 auth from a refresh token.
+ *
+ * ```ts
+ * const requestClient = new TwitterApi({ clientId: 'yourClientId' });
+ *
+ * const { client: userClient } = await requestClient.refreshOAuth2Token('refreshToken');
+ * // {userClient} is a valid {TwitterApi} object you can use for future requests
+ * ```
+ */
+ async refreshOAuth2Token(refreshToken) {
+ if (!this._requestMaker.clientId) {
+ throw new Error('Twitter API instance is not initialized with client ID. ' +
+ 'Please build an instance with: new TwitterApi({ clientId: \'\' })');
+ }
+ const accessTokenResult = await this.post('https://api.twitter.com/2/oauth2/token', {
+ refresh_token: refreshToken,
+ grant_type: 'refresh_token',
+ client_id: this._requestMaker.clientId,
+ client_secret: this._requestMaker.clientSecret,
+ });
+ return this.parseOAuth2AccessTokenResult(accessTokenResult);
+ }
+ /**
+ * Revoke a single user-based OAuth 2.0 token.
+ *
+ * You must specify its source, access token (directly after login)
+ * or refresh token (if you've called `.refreshOAuth2Token` before).
+ */
+ async revokeOAuth2Token(token, tokenType = 'access_token') {
+ if (!this._requestMaker.clientId) {
+ throw new Error('Twitter API instance is not initialized with client ID. ' +
+ 'Please build an instance with: new TwitterApi({ clientId: \'\' })');
+ }
+ return await this.post('https://api.twitter.com/2/oauth2/revoke', {
+ client_id: this._requestMaker.clientId,
+ client_secret: this._requestMaker.clientSecret,
+ token,
+ token_type_hint: tokenType,
+ });
+ }
+ parseOAuth2AccessTokenResult(result) {
+ const client = new _1.default(result.access_token, this._requestMaker.clientSettings);
+ const scope = result.scope.split(' ').filter(e => e);
+ return {
+ client,
+ expiresIn: result.expires_in,
+ accessToken: result.access_token,
+ scope,
+ refreshToken: result.refresh_token,
+ };
+ }
+}
+exports.default = TwitterApiReadOnly;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.d.ts
new file mode 100644
index 00000000..c2e35b8c
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.d.ts
@@ -0,0 +1,16 @@
+import TwitterApiv1ReadWrite from '../v1/client.v1.write';
+import TwitterApiv2ReadWrite from '../v2/client.v2.write';
+import TwitterApiReadOnly from './readonly';
+/**
+ * Twitter v1.1 and v2 API client.
+ */
+export default class TwitterApiReadWrite extends TwitterApiReadOnly {
+ protected _v1?: TwitterApiv1ReadWrite;
+ protected _v2?: TwitterApiv2ReadWrite;
+ get v1(): TwitterApiv1ReadWrite;
+ get v2(): TwitterApiv2ReadWrite;
+ /**
+ * Get a client with read only rights.
+ */
+ get readOnly(): TwitterApiReadOnly;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.js b/social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.js
new file mode 100644
index 00000000..93efb163
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.js
@@ -0,0 +1,31 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const client_v1_write_1 = __importDefault(require("../v1/client.v1.write"));
+const client_v2_write_1 = __importDefault(require("../v2/client.v2.write"));
+const readonly_1 = __importDefault(require("./readonly"));
+/**
+ * Twitter v1.1 and v2 API client.
+ */
+class TwitterApiReadWrite extends readonly_1.default {
+ /* Direct access to subclients */
+ get v1() {
+ if (this._v1)
+ return this._v1;
+ return this._v1 = new client_v1_write_1.default(this);
+ }
+ get v2() {
+ if (this._v2)
+ return this._v2;
+ return this._v2 = new client_v2_write_1.default(this);
+ }
+ /**
+ * Get a client with read only rights.
+ */
+ get readOnly() {
+ return this;
+ }
+}
+exports.default = TwitterApiReadWrite;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/globals.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/globals.d.ts
new file mode 100644
index 00000000..dcb64a65
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/globals.d.ts
@@ -0,0 +1,5 @@
+export declare const API_V2_PREFIX = "https://api.twitter.com/2/";
+export declare const API_V2_LABS_PREFIX = "https://api.twitter.com/labs/2/";
+export declare const API_V1_1_PREFIX = "https://api.twitter.com/1.1/";
+export declare const API_V1_1_UPLOAD_PREFIX = "https://upload.twitter.com/1.1/";
+export declare const API_V1_1_STREAM_PREFIX = "https://stream.twitter.com/1.1/";
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/globals.js b/social/twitter/node_modules/twitter-api-v2/dist/globals.js
new file mode 100644
index 00000000..84a51b4c
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/globals.js
@@ -0,0 +1,8 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.API_V1_1_STREAM_PREFIX = exports.API_V1_1_UPLOAD_PREFIX = exports.API_V1_1_PREFIX = exports.API_V2_LABS_PREFIX = exports.API_V2_PREFIX = void 0;
+exports.API_V2_PREFIX = 'https://api.twitter.com/2/';
+exports.API_V2_LABS_PREFIX = 'https://api.twitter.com/labs/2/';
+exports.API_V1_1_PREFIX = 'https://api.twitter.com/1.1/';
+exports.API_V1_1_UPLOAD_PREFIX = 'https://upload.twitter.com/1.1/';
+exports.API_V1_1_STREAM_PREFIX = 'https://stream.twitter.com/1.1/';
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/helpers.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/helpers.d.ts
new file mode 100644
index 00000000..bbc3fa93
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/helpers.d.ts
@@ -0,0 +1,16 @@
+export interface SharedPromise {
+ value: T | undefined;
+ promise: Promise;
+}
+export declare function sharedPromise(getter: () => Promise): SharedPromise;
+export declare function arrayWrap(value: T | T[]): T[];
+export declare function trimUndefinedProperties(object: any): void;
+export declare function isTweetStreamV2ErrorPayload(payload: any): boolean;
+export declare function hasMultipleItems(item: string | string[]): boolean;
+export interface IDeprecationWarning {
+ instance: string;
+ method: string;
+ problem: string;
+ resolution: string;
+}
+export declare function safeDeprecationWarning(message: IDeprecationWarning): void;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/helpers.js b/social/twitter/node_modules/twitter-api-v2/dist/helpers.js
new file mode 100644
index 00000000..f0d84a07
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/helpers.js
@@ -0,0 +1,60 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.safeDeprecationWarning = exports.hasMultipleItems = exports.isTweetStreamV2ErrorPayload = exports.trimUndefinedProperties = exports.arrayWrap = exports.sharedPromise = void 0;
+const settings_1 = require("./settings");
+function sharedPromise(getter) {
+ const sharedPromise = {
+ value: undefined,
+ promise: getter().then(val => {
+ sharedPromise.value = val;
+ return val;
+ }),
+ };
+ return sharedPromise;
+}
+exports.sharedPromise = sharedPromise;
+function arrayWrap(value) {
+ if (Array.isArray(value)) {
+ return value;
+ }
+ return [value];
+}
+exports.arrayWrap = arrayWrap;
+function trimUndefinedProperties(object) {
+ // Delete undefined parameters
+ for (const parameter in object) {
+ if (object[parameter] === undefined)
+ delete object[parameter];
+ }
+}
+exports.trimUndefinedProperties = trimUndefinedProperties;
+function isTweetStreamV2ErrorPayload(payload) {
+ // Is error only if 'errors' is present and 'data' does not exists
+ return typeof payload === 'object'
+ && 'errors' in payload
+ && !('data' in payload);
+}
+exports.isTweetStreamV2ErrorPayload = isTweetStreamV2ErrorPayload;
+function hasMultipleItems(item) {
+ if (Array.isArray(item) && item.length > 1) {
+ return true;
+ }
+ return item.toString().includes(',');
+}
+exports.hasMultipleItems = hasMultipleItems;
+const deprecationWarningsCache = new Set();
+function safeDeprecationWarning(message) {
+ if (typeof console === 'undefined' || !console.warn || !settings_1.TwitterApiV2Settings.deprecationWarnings) {
+ return;
+ }
+ const hash = `${message.instance}-${message.method}-${message.problem}`;
+ if (deprecationWarningsCache.has(hash)) {
+ return;
+ }
+ const formattedMsg = `[twitter-api-v2] Deprecation warning: In ${message.instance}.${message.method}() call` +
+ `, ${message.problem}.\n${message.resolution}.`;
+ console.warn(formattedMsg);
+ console.warn('To disable this message, import variable TwitterApiV2Settings from twitter-api-v2 and set TwitterApiV2Settings.deprecationWarnings to false.');
+ deprecationWarningsCache.add(hash);
+}
+exports.safeDeprecationWarning = safeDeprecationWarning;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/index.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/index.d.ts
new file mode 100644
index 00000000..98a08f9f
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/index.d.ts
@@ -0,0 +1,10 @@
+export { default as default } from './client';
+export * from './client';
+export * from './v1/client.v1';
+export * from './v2/client.v2';
+export * from './v2/includes.v2.helper';
+export * from './v2-labs/client.v2.labs';
+export * from './types';
+export * from './paginators';
+export * from './stream/TweetStream';
+export * from './settings';
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/index.js b/social/twitter/node_modules/twitter-api-v2/dist/index.js
new file mode 100644
index 00000000..aed5f970
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/index.js
@@ -0,0 +1,31 @@
+"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.default = void 0;
+var client_1 = require("./client");
+Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(client_1).default; } });
+__exportStar(require("./client"), exports);
+__exportStar(require("./v1/client.v1"), exports);
+__exportStar(require("./v2/client.v2"), exports);
+__exportStar(require("./v2/includes.v2.helper"), exports);
+__exportStar(require("./v2-labs/client.v2.labs"), exports);
+__exportStar(require("./types"), exports);
+__exportStar(require("./paginators"), exports);
+__exportStar(require("./stream/TweetStream"), exports);
+__exportStar(require("./settings"), exports);
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.d.ts
new file mode 100644
index 00000000..9957b126
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.d.ts
@@ -0,0 +1,86 @@
+import { TwitterRateLimit, TwitterResponse } from '../types';
+import TwitterApiSubClient from '../client.subclient';
+export interface ITwitterPaginatorArgs {
+ realData: TApiResult;
+ rateLimit: TwitterRateLimit;
+ instance: TwitterApiSubClient;
+ queryParams: Partial;
+ sharedParams?: TParams;
+}
+/** TwitterPaginator: able to get consume data from initial request, then fetch next data sequentially. */
+export declare abstract class TwitterPaginator {
+ protected _realData: TApiResult;
+ protected _rateLimit: TwitterRateLimit;
+ protected _instance: TwitterApiSubClient;
+ protected _queryParams: Partial;
+ protected _maxResultsWhenFetchLast: number;
+ /** informations unrelated to response data/query params that will be shared between paginator instances */
+ protected _sharedParams: TParams;
+ protected abstract _endpoint: string;
+ constructor({ realData, rateLimit, instance, queryParams, sharedParams }: ITwitterPaginatorArgs);
+ protected get _isRateLimitOk(): boolean;
+ protected makeRequest(queryParams: Partial): Promise>;
+ protected makeNewInstanceFromResult(result: TwitterResponse, queryParams: Partial): this;
+ protected getEndpoint(): string;
+ protected injectQueryParams(maxResults?: number): {
+ max_results?: number | undefined;
+ } & Partial;
+ protected abstract refreshInstanceFromResult(result: TwitterResponse, isNextPage: boolean): any;
+ protected abstract getNextQueryParams(maxResults?: number): Partial;
+ protected abstract getPageLengthFromRequest(result: TwitterResponse): number;
+ protected abstract isFetchLastOver(result: TwitterResponse): boolean;
+ protected abstract canFetchNextPage(result: TApiResult): boolean;
+ protected abstract getItemArray(): TItem[];
+ /**
+ * Next page.
+ */
+ next(maxResults?: number): Promise;
+ /**
+ * Next page, but store it in current instance.
+ */
+ fetchNext(maxResults?: number): Promise;
+ /**
+ * Fetch up to {count} items after current page,
+ * as long as rate limit is not hit and Twitter has some results
+ */
+ fetchLast(count?: number): Promise;
+ get rateLimit(): {
+ limit: number;
+ reset: number;
+ remaining: number;
+ };
+ /** Get raw data returned by Twitter API. */
+ get data(): TApiResult;
+ get done(): boolean;
+ /**
+ * Iterate over currently fetched items.
+ */
+ [Symbol.iterator](): Generator;
+ /**
+ * Iterate over items "undefinitely" (until rate limit is hit / they're no more items available)
+ * This will **mutate the current instance** and fill data, metas, etc. inside this instance.
+ *
+ * If you need to handle concurrent requests, or you need to rely on immutability, please use `.fetchAndIterate()` instead.
+ */
+ [Symbol.asyncIterator](): AsyncGenerator;
+ /**
+ * Iterate over items "undefinitely" without modifying the current instance (until rate limit is hit / they're no more items available)
+ *
+ * This will **NOT** mutate the current instance, meaning that current instance will not inherit from `includes` and `meta` (v2 API only).
+ * Use `Symbol.asyncIterator` (`for-await of`) to directly access items with current instance mutation.
+ */
+ fetchAndIterate(): AsyncGenerator<[TItem, this], void, undefined>;
+}
+/** PreviousableTwitterPaginator: a TwitterPaginator able to get consume data from both side, next and previous. */
+export declare abstract class PreviousableTwitterPaginator extends TwitterPaginator {
+ protected abstract getPreviousQueryParams(maxResults?: number): Partial;
+ /**
+ * Previous page (new tweets)
+ */
+ previous(maxResults?: number): Promise;
+ /**
+ * Previous page, but in current instance.
+ */
+ fetchPrevious(maxResults?: number): Promise;
+}
+export default TwitterPaginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.js
new file mode 100644
index 00000000..2ad7265a
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.js
@@ -0,0 +1,173 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.PreviousableTwitterPaginator = exports.TwitterPaginator = void 0;
+/** TwitterPaginator: able to get consume data from initial request, then fetch next data sequentially. */
+class TwitterPaginator {
+ // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected
+ constructor({ realData, rateLimit, instance, queryParams, sharedParams }) {
+ this._maxResultsWhenFetchLast = 100;
+ this._realData = realData;
+ this._rateLimit = rateLimit;
+ this._instance = instance;
+ this._queryParams = queryParams;
+ this._sharedParams = sharedParams;
+ }
+ get _isRateLimitOk() {
+ if (!this._rateLimit) {
+ return true;
+ }
+ const resetDate = this._rateLimit.reset * 1000;
+ if (resetDate < Date.now()) {
+ return true;
+ }
+ return this._rateLimit.remaining > 0;
+ }
+ makeRequest(queryParams) {
+ return this._instance.get(this.getEndpoint(), queryParams, { fullResponse: true, params: this._sharedParams });
+ }
+ makeNewInstanceFromResult(result, queryParams) {
+ // Construct a subclass
+ return new this.constructor({
+ realData: result.data,
+ rateLimit: result.rateLimit,
+ instance: this._instance,
+ queryParams,
+ sharedParams: this._sharedParams,
+ });
+ }
+ getEndpoint() {
+ return this._endpoint;
+ }
+ injectQueryParams(maxResults) {
+ return {
+ ...(maxResults ? { max_results: maxResults } : {}),
+ ...this._queryParams,
+ };
+ }
+ /* ---------------------- */
+ /* Real paginator methods */
+ /* ---------------------- */
+ /**
+ * Next page.
+ */
+ async next(maxResults) {
+ const queryParams = this.getNextQueryParams(maxResults);
+ const result = await this.makeRequest(queryParams);
+ return this.makeNewInstanceFromResult(result, queryParams);
+ }
+ /**
+ * Next page, but store it in current instance.
+ */
+ async fetchNext(maxResults) {
+ const queryParams = this.getNextQueryParams(maxResults);
+ const result = await this.makeRequest(queryParams);
+ // Await in case of async sub-methods
+ await this.refreshInstanceFromResult(result, true);
+ return this;
+ }
+ /**
+ * Fetch up to {count} items after current page,
+ * as long as rate limit is not hit and Twitter has some results
+ */
+ async fetchLast(count = Infinity) {
+ let queryParams = this.getNextQueryParams(this._maxResultsWhenFetchLast);
+ let resultCount = 0;
+ // Break at rate limit limit
+ while (resultCount < count && this._isRateLimitOk) {
+ const response = await this.makeRequest(queryParams);
+ await this.refreshInstanceFromResult(response, true);
+ resultCount += this.getPageLengthFromRequest(response);
+ if (this.isFetchLastOver(response)) {
+ break;
+ }
+ queryParams = this.getNextQueryParams(this._maxResultsWhenFetchLast);
+ }
+ return this;
+ }
+ get rateLimit() {
+ var _a;
+ return { ...(_a = this._rateLimit) !== null && _a !== void 0 ? _a : {} };
+ }
+ /** Get raw data returned by Twitter API. */
+ get data() {
+ return this._realData;
+ }
+ get done() {
+ return !this.canFetchNextPage(this._realData);
+ }
+ /**
+ * Iterate over currently fetched items.
+ */
+ *[Symbol.iterator]() {
+ yield* this.getItemArray();
+ }
+ /**
+ * Iterate over items "undefinitely" (until rate limit is hit / they're no more items available)
+ * This will **mutate the current instance** and fill data, metas, etc. inside this instance.
+ *
+ * If you need to handle concurrent requests, or you need to rely on immutability, please use `.fetchAndIterate()` instead.
+ */
+ async *[Symbol.asyncIterator]() {
+ yield* this.getItemArray();
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ let paginator = this;
+ let canFetchNextPage = this.canFetchNextPage(this._realData);
+ while (canFetchNextPage && this._isRateLimitOk && paginator.getItemArray().length > 0) {
+ const next = await paginator.next(this._maxResultsWhenFetchLast);
+ // Store data into current instance [needed to access includes and meta]
+ this.refreshInstanceFromResult({ data: next._realData, headers: {}, rateLimit: next._rateLimit }, true);
+ canFetchNextPage = this.canFetchNextPage(next._realData);
+ const items = next.getItemArray();
+ yield* items;
+ paginator = next;
+ }
+ }
+ /**
+ * Iterate over items "undefinitely" without modifying the current instance (until rate limit is hit / they're no more items available)
+ *
+ * This will **NOT** mutate the current instance, meaning that current instance will not inherit from `includes` and `meta` (v2 API only).
+ * Use `Symbol.asyncIterator` (`for-await of`) to directly access items with current instance mutation.
+ */
+ async *fetchAndIterate() {
+ for (const item of this.getItemArray()) {
+ yield [item, this];
+ }
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ let paginator = this;
+ let canFetchNextPage = this.canFetchNextPage(this._realData);
+ while (canFetchNextPage && this._isRateLimitOk && paginator.getItemArray().length > 0) {
+ const next = await paginator.next(this._maxResultsWhenFetchLast);
+ // Store data into current instance [needed to access includes and meta]
+ this.refreshInstanceFromResult({ data: next._realData, headers: {}, rateLimit: next._rateLimit }, true);
+ canFetchNextPage = this.canFetchNextPage(next._realData);
+ for (const item of next.getItemArray()) {
+ yield [item, next];
+ }
+ this._rateLimit = next._rateLimit;
+ paginator = next;
+ }
+ }
+}
+exports.TwitterPaginator = TwitterPaginator;
+/** PreviousableTwitterPaginator: a TwitterPaginator able to get consume data from both side, next and previous. */
+class PreviousableTwitterPaginator extends TwitterPaginator {
+ /**
+ * Previous page (new tweets)
+ */
+ async previous(maxResults) {
+ const queryParams = this.getPreviousQueryParams(maxResults);
+ const result = await this.makeRequest(queryParams);
+ return this.makeNewInstanceFromResult(result, queryParams);
+ }
+ /**
+ * Previous page, but in current instance.
+ */
+ async fetchPrevious(maxResults) {
+ const queryParams = this.getPreviousQueryParams(maxResults);
+ const result = await this.makeRequest(queryParams);
+ await this.refreshInstanceFromResult(result, false);
+ return this;
+ }
+}
+exports.PreviousableTwitterPaginator = PreviousableTwitterPaginator;
+exports.default = TwitterPaginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.d.ts
new file mode 100644
index 00000000..085f9d8e
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.d.ts
@@ -0,0 +1,19 @@
+import type { GetDmListV1Args, ReceivedDMEventsV1, TReceivedDMEvent, TwitterResponse, ReceivedWelcomeDMCreateEventV1, WelcomeDirectMessageListV1Result } from '../types';
+import { CursoredV1Paginator } from './paginator.v1';
+export declare class DmEventsV1Paginator extends CursoredV1Paginator {
+ protected _endpoint: string;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): import("../types").DirectMessageCreateV1[];
+ /**
+ * Events returned by paginator.
+ */
+ get events(): import("../types").DirectMessageCreateV1[];
+}
+export declare class WelcomeDmV1Paginator extends CursoredV1Paginator {
+ protected _endpoint: string;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): ReceivedWelcomeDMCreateEventV1[];
+ get welcomeMessages(): ReceivedWelcomeDMCreateEventV1[];
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.js
new file mode 100644
index 00000000..d2803de0
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.js
@@ -0,0 +1,55 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.WelcomeDmV1Paginator = exports.DmEventsV1Paginator = void 0;
+const paginator_v1_1 = require("./paginator.v1");
+class DmEventsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'direct_messages/events/list.json';
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.events.push(...result.events);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.events.length;
+ }
+ getItemArray() {
+ return this.events;
+ }
+ /**
+ * Events returned by paginator.
+ */
+ get events() {
+ return this._realData.events;
+ }
+}
+exports.DmEventsV1Paginator = DmEventsV1Paginator;
+class WelcomeDmV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'direct_messages/welcome_messages/list.json';
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.welcome_messages.push(...result.welcome_messages);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.welcome_messages.length;
+ }
+ getItemArray() {
+ return this.welcomeMessages;
+ }
+ get welcomeMessages() {
+ return this._realData.welcome_messages;
+ }
+}
+exports.WelcomeDmV1Paginator = WelcomeDmV1Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/index.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/index.d.ts
new file mode 100644
index 00000000..12342516
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/index.d.ts
@@ -0,0 +1,9 @@
+export * from './tweet.paginator.v2';
+export * from './TwitterPaginator';
+export * from './dm.paginator.v1';
+export * from './mutes.paginator.v1';
+export * from './tweet.paginator.v1';
+export * from './user.paginator.v1';
+export * from './user.paginator.v2';
+export * from './list.paginator.v1';
+export * from './list.paginator.v2';
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/index.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/index.js
new file mode 100644
index 00000000..a8a5cad4
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/index.js
@@ -0,0 +1,25 @@
+"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./tweet.paginator.v2"), exports);
+__exportStar(require("./TwitterPaginator"), exports);
+__exportStar(require("./dm.paginator.v1"), exports);
+__exportStar(require("./mutes.paginator.v1"), exports);
+__exportStar(require("./tweet.paginator.v1"), exports);
+__exportStar(require("./user.paginator.v1"), exports);
+__exportStar(require("./user.paginator.v2"), exports);
+__exportStar(require("./list.paginator.v1"), exports);
+__exportStar(require("./list.paginator.v2"), exports);
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.d.ts
new file mode 100644
index 00000000..7ab6bd31
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.d.ts
@@ -0,0 +1,36 @@
+import { DoubleEndedListsCursorV1Result, DoubleEndedUsersCursorV1Result, ListMembersV1Params, ListOwnershipsV1Params, ListV1, TwitterResponse, UserV1 } from '../types';
+import { CursoredV1Paginator } from './paginator.v1';
+declare abstract class ListListsV1Paginator extends CursoredV1Paginator {
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): ListV1[];
+ /**
+ * Lists returned by paginator.
+ */
+ get lists(): ListV1[];
+}
+export declare class ListMembershipsV1Paginator extends ListListsV1Paginator {
+ protected _endpoint: string;
+}
+export declare class ListOwnershipsV1Paginator extends ListListsV1Paginator {
+ protected _endpoint: string;
+}
+export declare class ListSubscriptionsV1Paginator extends ListListsV1Paginator {
+ protected _endpoint: string;
+}
+declare abstract class ListUsersV1Paginator extends CursoredV1Paginator {
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): UserV1[];
+ /**
+ * Users returned by paginator.
+ */
+ get users(): UserV1[];
+}
+export declare class ListMembersV1Paginator extends ListUsersV1Paginator {
+ protected _endpoint: string;
+}
+export declare class ListSubscribersV1Paginator extends ListUsersV1Paginator {
+ protected _endpoint: string;
+}
+export {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.js
new file mode 100644
index 00000000..906953a7
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.js
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.ListSubscribersV1Paginator = exports.ListMembersV1Paginator = exports.ListSubscriptionsV1Paginator = exports.ListOwnershipsV1Paginator = exports.ListMembershipsV1Paginator = void 0;
+const paginator_v1_1 = require("./paginator.v1");
+class ListListsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.lists.push(...result.lists);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.lists.length;
+ }
+ getItemArray() {
+ return this.lists;
+ }
+ /**
+ * Lists returned by paginator.
+ */
+ get lists() {
+ return this._realData.lists;
+ }
+}
+class ListMembershipsV1Paginator extends ListListsV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/memberships.json';
+ }
+}
+exports.ListMembershipsV1Paginator = ListMembershipsV1Paginator;
+class ListOwnershipsV1Paginator extends ListListsV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/ownerships.json';
+ }
+}
+exports.ListOwnershipsV1Paginator = ListOwnershipsV1Paginator;
+class ListSubscriptionsV1Paginator extends ListListsV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/subscriptions.json';
+ }
+}
+exports.ListSubscriptionsV1Paginator = ListSubscriptionsV1Paginator;
+class ListUsersV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.users.push(...result.users);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.users.length;
+ }
+ getItemArray() {
+ return this.users;
+ }
+ /**
+ * Users returned by paginator.
+ */
+ get users() {
+ return this._realData.users;
+ }
+}
+class ListMembersV1Paginator extends ListUsersV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/members.json';
+ }
+}
+exports.ListMembersV1Paginator = ListMembersV1Paginator;
+class ListSubscribersV1Paginator extends ListUsersV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/subscribers.json';
+ }
+}
+exports.ListSubscribersV1Paginator = ListSubscribersV1Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.d.ts
new file mode 100644
index 00000000..06ccf00c
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.d.ts
@@ -0,0 +1,26 @@
+import type { GetListTimelineV2Params, ListTimelineV2Result, ListV2 } from '../types';
+import { TimelineV2Paginator } from './v2.paginator';
+declare abstract class ListTimelineV2Paginator extends TimelineV2Paginator {
+ protected getItemArray(): ListV2[];
+ /**
+ * Lists returned by paginator.
+ */
+ get lists(): ListV2[];
+ get meta(): TResult["meta"];
+}
+export declare class UserOwnedListsV2Paginator extends ListTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserListMembershipsV2Paginator extends ListTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserListFollowedV2Paginator extends ListTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.js
new file mode 100644
index 00000000..1c502021
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.js
@@ -0,0 +1,40 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.UserListFollowedV2Paginator = exports.UserListMembershipsV2Paginator = exports.UserOwnedListsV2Paginator = void 0;
+const v2_paginator_1 = require("./v2.paginator");
+class ListTimelineV2Paginator extends v2_paginator_1.TimelineV2Paginator {
+ getItemArray() {
+ return this.lists;
+ }
+ /**
+ * Lists returned by paginator.
+ */
+ get lists() {
+ var _a;
+ return (_a = this._realData.data) !== null && _a !== void 0 ? _a : [];
+ }
+ get meta() {
+ return super.meta;
+ }
+}
+class UserOwnedListsV2Paginator extends ListTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/owned_lists';
+ }
+}
+exports.UserOwnedListsV2Paginator = UserOwnedListsV2Paginator;
+class UserListMembershipsV2Paginator extends ListTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/list_memberships';
+ }
+}
+exports.UserListMembershipsV2Paginator = UserListMembershipsV2Paginator;
+class UserListFollowedV2Paginator extends ListTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/followed_lists';
+ }
+}
+exports.UserListFollowedV2Paginator = UserListFollowedV2Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.d.ts
new file mode 100644
index 00000000..f54f937f
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.d.ts
@@ -0,0 +1,23 @@
+import { CursoredV1Paginator } from './paginator.v1';
+import type { MuteUserIdsV1Params, MuteUserIdsV1Result, MuteUserListV1Params, MuteUserListV1Result, TwitterResponse, UserV1 } from '../types';
+export declare class MuteUserListV1Paginator extends CursoredV1Paginator {
+ protected _endpoint: string;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): UserV1[];
+ /**
+ * Users returned by paginator.
+ */
+ get users(): UserV1[];
+}
+export declare class MuteUserIdsV1Paginator extends CursoredV1Paginator {
+ protected _endpoint: string;
+ protected _maxResultsWhenFetchLast: number;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): string[];
+ /**
+ * Users IDs returned by paginator.
+ */
+ get ids(): string[];
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.js
new file mode 100644
index 00000000..00e09f17
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.js
@@ -0,0 +1,59 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MuteUserIdsV1Paginator = exports.MuteUserListV1Paginator = void 0;
+const paginator_v1_1 = require("./paginator.v1");
+class MuteUserListV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'mutes/users/list.json';
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.users.push(...result.users);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.users.length;
+ }
+ getItemArray() {
+ return this.users;
+ }
+ /**
+ * Users returned by paginator.
+ */
+ get users() {
+ return this._realData.users;
+ }
+}
+exports.MuteUserListV1Paginator = MuteUserListV1Paginator;
+class MuteUserIdsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'mutes/users/ids.json';
+ this._maxResultsWhenFetchLast = 5000;
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.ids.push(...result.ids);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.ids.length;
+ }
+ getItemArray() {
+ return this.ids;
+ }
+ /**
+ * Users IDs returned by paginator.
+ */
+ get ids() {
+ return this._realData.ids;
+ }
+}
+exports.MuteUserIdsV1Paginator = MuteUserIdsV1Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.d.ts
new file mode 100644
index 00000000..fc55abb0
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.d.ts
@@ -0,0 +1,13 @@
+import { TwitterResponse } from '../types';
+import TwitterPaginator from './TwitterPaginator';
+export declare abstract class CursoredV1Paginator extends TwitterPaginator {
+ protected getNextQueryParams(maxResults?: number): Partial;
+ protected isFetchLastOver(result: TwitterResponse): boolean;
+ protected canFetchNextPage(result: TApiResult): boolean;
+ private isNextCursorInvalid;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.js
new file mode 100644
index 00000000..fc5e7e82
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.js
@@ -0,0 +1,33 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.CursoredV1Paginator = void 0;
+const TwitterPaginator_1 = __importDefault(require("./TwitterPaginator"));
+class CursoredV1Paginator extends TwitterPaginator_1.default {
+ getNextQueryParams(maxResults) {
+ var _a;
+ return {
+ ...this._queryParams,
+ cursor: (_a = this._realData.next_cursor_str) !== null && _a !== void 0 ? _a : this._realData.next_cursor,
+ ...(maxResults ? { count: maxResults } : {}),
+ };
+ }
+ isFetchLastOver(result) {
+ // If we cant fetch next page
+ return !this.canFetchNextPage(result.data);
+ }
+ canFetchNextPage(result) {
+ // If one of cursor is valid
+ return !this.isNextCursorInvalid(result.next_cursor) || !this.isNextCursorInvalid(result.next_cursor_str);
+ }
+ isNextCursorInvalid(value) {
+ return value === undefined
+ || value === 0
+ || value === -1
+ || value === '0'
+ || value === '-1';
+ }
+}
+exports.CursoredV1Paginator = CursoredV1Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.d.ts
new file mode 100644
index 00000000..3172df69
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.d.ts
@@ -0,0 +1,37 @@
+import TwitterPaginator from './TwitterPaginator';
+import { TwitterResponse, TweetV1, TweetV1TimelineResult, TweetV1TimelineParams, TweetV1UserTimelineParams, ListStatusesV1Params } from '../types';
+/** A generic TwitterPaginator able to consume TweetV1 timelines. */
+declare abstract class TweetTimelineV1Paginator extends TwitterPaginator {
+ protected hasFinishedFetch: boolean;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getNextQueryParams(maxResults?: number): {
+ max_results?: number | undefined;
+ } & Partial & {
+ max_id: string;
+ };
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected isFetchLastOver(result: TwitterResponse): boolean;
+ protected canFetchNextPage(result: TResult): boolean;
+ protected getItemArray(): TResult;
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets(): TResult;
+ get done(): boolean;
+}
+export declare class HomeTimelineV1Paginator extends TweetTimelineV1Paginator {
+ protected _endpoint: string;
+}
+export declare class MentionTimelineV1Paginator extends TweetTimelineV1Paginator {
+ protected _endpoint: string;
+}
+export declare class UserTimelineV1Paginator extends TweetTimelineV1Paginator {
+ protected _endpoint: string;
+}
+export declare class ListTimelineV1Paginator extends TweetTimelineV1Paginator {
+ protected _endpoint: string;
+}
+export declare class UserFavoritesV1Paginator extends TweetTimelineV1Paginator {
+ protected _endpoint: string;
+}
+export {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.js
new file mode 100644
index 00000000..43a12966
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.js
@@ -0,0 +1,92 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.UserFavoritesV1Paginator = exports.ListTimelineV1Paginator = exports.UserTimelineV1Paginator = exports.MentionTimelineV1Paginator = exports.HomeTimelineV1Paginator = void 0;
+const TwitterPaginator_1 = __importDefault(require("./TwitterPaginator"));
+/** A generic TwitterPaginator able to consume TweetV1 timelines. */
+class TweetTimelineV1Paginator extends TwitterPaginator_1.default {
+ constructor() {
+ super(...arguments);
+ this.hasFinishedFetch = false;
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.push(...result);
+ // HINT: This is an approximation, as "end" of pagination cannot be safely determined without cursors.
+ this.hasFinishedFetch = result.length === 0;
+ }
+ }
+ getNextQueryParams(maxResults) {
+ const lastestId = BigInt(this._realData[this._realData.length - 1].id_str);
+ return {
+ ...this.injectQueryParams(maxResults),
+ max_id: (lastestId - BigInt(1)).toString(),
+ };
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.length;
+ }
+ isFetchLastOver(result) {
+ return !result.data.length;
+ }
+ canFetchNextPage(result) {
+ return result.length > 0;
+ }
+ getItemArray() {
+ return this.tweets;
+ }
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets() {
+ return this._realData;
+ }
+ get done() {
+ return super.done || this.hasFinishedFetch;
+ }
+}
+// Timelines
+// Home
+class HomeTimelineV1Paginator extends TweetTimelineV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'statuses/home_timeline.json';
+ }
+}
+exports.HomeTimelineV1Paginator = HomeTimelineV1Paginator;
+// Mention
+class MentionTimelineV1Paginator extends TweetTimelineV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'statuses/mentions_timeline.json';
+ }
+}
+exports.MentionTimelineV1Paginator = MentionTimelineV1Paginator;
+// User
+class UserTimelineV1Paginator extends TweetTimelineV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'statuses/user_timeline.json';
+ }
+}
+exports.UserTimelineV1Paginator = UserTimelineV1Paginator;
+// Lists
+class ListTimelineV1Paginator extends TweetTimelineV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/statuses.json';
+ }
+}
+exports.ListTimelineV1Paginator = ListTimelineV1Paginator;
+// Favorites
+class UserFavoritesV1Paginator extends TweetTimelineV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'favorites/list.json';
+ }
+}
+exports.UserFavoritesV1Paginator = UserFavoritesV1Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.d.ts
new file mode 100644
index 00000000..d0b4f6ce
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.d.ts
@@ -0,0 +1,74 @@
+import { Tweetv2SearchParams, Tweetv2SearchResult, TwitterResponse, TweetV2, Tweetv2TimelineResult, TweetV2TimelineParams, TweetV2PaginableTimelineResult, TweetV2UserTimelineParams, Tweetv2ListResult, TweetV2PaginableListParams, TweetV2PaginableTimelineParams, TweetV2HomeTimelineParams } from '../types';
+import { TimelineV2Paginator, TwitterV2Paginator } from './v2.paginator';
+/** A generic PreviousableTwitterPaginator able to consume TweetV2 timelines with since_id, until_id and next_token (when available). */
+declare abstract class TweetTimelineV2Paginator extends TwitterV2Paginator {
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: boolean): void;
+ protected getNextQueryParams(maxResults?: number): Partial;
+ protected getPreviousQueryParams(maxResults?: number): Partial;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected isFetchLastOver(result: TwitterResponse): boolean;
+ protected canFetchNextPage(result: TResult): boolean;
+ protected getItemArray(): TweetV2[];
+ protected dateStringToSnowflakeId(dateStr: string): string;
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets(): TweetV2[];
+ get meta(): TResult["meta"];
+}
+/** A generic PreviousableTwitterPaginator able to consume TweetV2 timelines with pagination_tokens. */
+declare abstract class TweetPaginableTimelineV2Paginator extends TimelineV2Paginator {
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: boolean): void;
+ protected getItemArray(): TweetV2[];
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets(): TweetV2[];
+ get meta(): TResult["meta"];
+}
+export declare class TweetSearchRecentV2Paginator extends TweetTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetSearchAllV2Paginator extends TweetTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class QuotedTweetsTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetHomeTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ protected _endpoint: string;
+}
+declare type TUserTimelinePaginatorShared = {
+ id: string;
+};
+export declare class TweetUserTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetUserMentionTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetBookmarksTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ protected _endpoint: string;
+}
+/** A generic TwitterPaginator able to consume TweetV2 timelines. */
+declare abstract class TweetListV2Paginator extends TimelineV2Paginator {
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets(): TweetV2[];
+ get meta(): TResult["meta"];
+ protected getItemArray(): TweetV2[];
+}
+export declare class TweetV2UserLikedTweetsPaginator extends TweetListV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetV2ListTweetsPaginator extends TweetListV2Paginator {
+ protected _endpoint: string;
+}
+export {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.js
new file mode 100644
index 00000000..41fc4699
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.js
@@ -0,0 +1,205 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TweetV2ListTweetsPaginator = exports.TweetV2UserLikedTweetsPaginator = exports.TweetBookmarksTimelineV2Paginator = exports.TweetUserMentionTimelineV2Paginator = exports.TweetUserTimelineV2Paginator = exports.TweetHomeTimelineV2Paginator = exports.QuotedTweetsTimelineV2Paginator = exports.TweetSearchAllV2Paginator = exports.TweetSearchRecentV2Paginator = void 0;
+const v2_paginator_1 = require("./v2.paginator");
+/** A generic PreviousableTwitterPaginator able to consume TweetV2 timelines with since_id, until_id and next_token (when available). */
+class TweetTimelineV2Paginator extends v2_paginator_1.TwitterV2Paginator {
+ refreshInstanceFromResult(response, isNextPage) {
+ var _a;
+ const result = response.data;
+ const resultData = (_a = result.data) !== null && _a !== void 0 ? _a : [];
+ this._rateLimit = response.rateLimit;
+ if (!this._realData.data) {
+ this._realData.data = [];
+ }
+ if (isNextPage) {
+ this._realData.meta.oldest_id = result.meta.oldest_id;
+ this._realData.meta.result_count += result.meta.result_count;
+ this._realData.meta.next_token = result.meta.next_token;
+ this._realData.data.push(...resultData);
+ }
+ else {
+ this._realData.meta.newest_id = result.meta.newest_id;
+ this._realData.meta.result_count += result.meta.result_count;
+ this._realData.data.unshift(...resultData);
+ }
+ this.updateIncludes(result);
+ }
+ getNextQueryParams(maxResults) {
+ this.assertUsable();
+ const params = { ...this.injectQueryParams(maxResults) };
+ if (this._realData.meta.next_token) {
+ params.next_token = this._realData.meta.next_token;
+ }
+ else {
+ if (params.start_time) {
+ // until_id and start_time are forbidden together for some reason, so convert start_time to a since_id.
+ params.since_id = this.dateStringToSnowflakeId(params.start_time);
+ delete params.start_time;
+ }
+ if (params.end_time) {
+ // until_id overrides end_time, so delete it
+ delete params.end_time;
+ }
+ params.until_id = this._realData.meta.oldest_id;
+ }
+ return params;
+ }
+ getPreviousQueryParams(maxResults) {
+ this.assertUsable();
+ return {
+ ...this.injectQueryParams(maxResults),
+ since_id: this._realData.meta.newest_id,
+ };
+ }
+ getPageLengthFromRequest(result) {
+ var _a, _b;
+ return (_b = (_a = result.data.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
+ }
+ isFetchLastOver(result) {
+ var _a;
+ return !((_a = result.data.data) === null || _a === void 0 ? void 0 : _a.length) || !this.canFetchNextPage(result.data);
+ }
+ canFetchNextPage(result) {
+ return !!result.meta.next_token;
+ }
+ getItemArray() {
+ return this.tweets;
+ }
+ dateStringToSnowflakeId(dateStr) {
+ const TWITTER_START_EPOCH = BigInt('1288834974657');
+ const date = new Date(dateStr);
+ if (isNaN(date.valueOf())) {
+ throw new Error('Unable to convert start_time/end_time to a valid date. A ISO 8601 DateTime is excepted, please check your input.');
+ }
+ const dateTimestamp = BigInt(date.valueOf());
+ return ((dateTimestamp - TWITTER_START_EPOCH) << BigInt('22')).toString();
+ }
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets() {
+ var _a;
+ return (_a = this._realData.data) !== null && _a !== void 0 ? _a : [];
+ }
+ get meta() {
+ return super.meta;
+ }
+}
+/** A generic PreviousableTwitterPaginator able to consume TweetV2 timelines with pagination_tokens. */
+class TweetPaginableTimelineV2Paginator extends v2_paginator_1.TimelineV2Paginator {
+ refreshInstanceFromResult(response, isNextPage) {
+ super.refreshInstanceFromResult(response, isNextPage);
+ const result = response.data;
+ if (isNextPage) {
+ this._realData.meta.oldest_id = result.meta.oldest_id;
+ }
+ else {
+ this._realData.meta.newest_id = result.meta.newest_id;
+ }
+ }
+ getItemArray() {
+ return this.tweets;
+ }
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets() {
+ var _a;
+ return (_a = this._realData.data) !== null && _a !== void 0 ? _a : [];
+ }
+ get meta() {
+ return super.meta;
+ }
+}
+// ----------------
+// - Tweet search -
+// ----------------
+class TweetSearchRecentV2Paginator extends TweetTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'tweets/search/recent';
+ }
+}
+exports.TweetSearchRecentV2Paginator = TweetSearchRecentV2Paginator;
+class TweetSearchAllV2Paginator extends TweetTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'tweets/search/all';
+ }
+}
+exports.TweetSearchAllV2Paginator = TweetSearchAllV2Paginator;
+class QuotedTweetsTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'tweets/:id/quote_tweets';
+ }
+}
+exports.QuotedTweetsTimelineV2Paginator = QuotedTweetsTimelineV2Paginator;
+// -----------------
+// - Home timeline -
+// -----------------
+class TweetHomeTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/timelines/reverse_chronological';
+ }
+}
+exports.TweetHomeTimelineV2Paginator = TweetHomeTimelineV2Paginator;
+class TweetUserTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/tweets';
+ }
+}
+exports.TweetUserTimelineV2Paginator = TweetUserTimelineV2Paginator;
+class TweetUserMentionTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/mentions';
+ }
+}
+exports.TweetUserMentionTimelineV2Paginator = TweetUserMentionTimelineV2Paginator;
+// -------------
+// - Bookmarks -
+// -------------
+class TweetBookmarksTimelineV2Paginator extends TweetPaginableTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/bookmarks';
+ }
+}
+exports.TweetBookmarksTimelineV2Paginator = TweetBookmarksTimelineV2Paginator;
+// ---------------------------------------------------------------------------------
+// - Tweet lists (consume tweets with pagination tokens instead of since/until id) -
+// ---------------------------------------------------------------------------------
+/** A generic TwitterPaginator able to consume TweetV2 timelines. */
+class TweetListV2Paginator extends v2_paginator_1.TimelineV2Paginator {
+ /**
+ * Tweets returned by paginator.
+ */
+ get tweets() {
+ var _a;
+ return (_a = this._realData.data) !== null && _a !== void 0 ? _a : [];
+ }
+ get meta() {
+ return super.meta;
+ }
+ getItemArray() {
+ return this.tweets;
+ }
+}
+class TweetV2UserLikedTweetsPaginator extends TweetListV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/liked_tweets';
+ }
+}
+exports.TweetV2UserLikedTweetsPaginator = TweetV2UserLikedTweetsPaginator;
+class TweetV2ListTweetsPaginator extends TweetListV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/:id/tweets';
+ }
+}
+exports.TweetV2ListTweetsPaginator = TweetV2ListTweetsPaginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.d.ts
new file mode 100644
index 00000000..4bcd0ff2
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.d.ts
@@ -0,0 +1,37 @@
+import TwitterPaginator from './TwitterPaginator';
+import { FriendshipsIncomingV1Params, FriendshipsIncomingV1Result, TwitterResponse, UserSearchV1Params, UserV1 } from '../types';
+import { CursoredV1Paginator } from './paginator.v1';
+/** A generic TwitterPaginator able to consume TweetV1 timelines. */
+export declare class UserSearchV1Paginator extends TwitterPaginator {
+ _endpoint: string;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getNextQueryParams(maxResults?: number): {
+ count?: number | undefined;
+ page: number;
+ q?: string | undefined;
+ include_entities?: boolean | undefined;
+ tweet_mode?: "extended" | undefined;
+ };
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected isFetchLastOver(result: TwitterResponse): boolean;
+ protected canFetchNextPage(result: UserV1[]): boolean;
+ protected getItemArray(): UserV1[];
+ /**
+ * Users returned by paginator.
+ */
+ get users(): UserV1[];
+}
+export declare class FriendshipsIncomingV1Paginator extends CursoredV1Paginator {
+ protected _endpoint: string;
+ protected _maxResultsWhenFetchLast: number;
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
+ protected getPageLengthFromRequest(result: TwitterResponse): number;
+ protected getItemArray(): string[];
+ /**
+ * Users IDs returned by paginator.
+ */
+ get ids(): string[];
+}
+export declare class FriendshipsOutgoingV1Paginator extends FriendshipsIncomingV1Paginator {
+ protected _endpoint: string;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.js
new file mode 100644
index 00000000..39fb6703
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.js
@@ -0,0 +1,85 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.FriendshipsOutgoingV1Paginator = exports.FriendshipsIncomingV1Paginator = exports.UserSearchV1Paginator = void 0;
+const TwitterPaginator_1 = __importDefault(require("./TwitterPaginator"));
+const paginator_v1_1 = require("./paginator.v1");
+/** A generic TwitterPaginator able to consume TweetV1 timelines. */
+class UserSearchV1Paginator extends TwitterPaginator_1.default {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/search.json';
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.push(...result);
+ }
+ }
+ getNextQueryParams(maxResults) {
+ var _a;
+ const previousPage = Number((_a = this._queryParams.page) !== null && _a !== void 0 ? _a : '1');
+ return {
+ ...this._queryParams,
+ page: previousPage + 1,
+ ...maxResults ? { count: maxResults } : {},
+ };
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.length;
+ }
+ isFetchLastOver(result) {
+ return !result.data.length;
+ }
+ canFetchNextPage(result) {
+ return result.length > 0;
+ }
+ getItemArray() {
+ return this.users;
+ }
+ /**
+ * Users returned by paginator.
+ */
+ get users() {
+ return this._realData;
+ }
+}
+exports.UserSearchV1Paginator = UserSearchV1Paginator;
+class FriendshipsIncomingV1Paginator extends paginator_v1_1.CursoredV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'friendships/incoming.json';
+ this._maxResultsWhenFetchLast = 5000;
+ }
+ refreshInstanceFromResult(response, isNextPage) {
+ const result = response.data;
+ this._rateLimit = response.rateLimit;
+ if (isNextPage) {
+ this._realData.ids.push(...result.ids);
+ this._realData.next_cursor = result.next_cursor;
+ }
+ }
+ getPageLengthFromRequest(result) {
+ return result.data.ids.length;
+ }
+ getItemArray() {
+ return this.ids;
+ }
+ /**
+ * Users IDs returned by paginator.
+ */
+ get ids() {
+ return this._realData.ids;
+ }
+}
+exports.FriendshipsIncomingV1Paginator = FriendshipsIncomingV1Paginator;
+class FriendshipsOutgoingV1Paginator extends FriendshipsIncomingV1Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'friendships/outgoing.json';
+ }
+}
+exports.FriendshipsOutgoingV1Paginator = FriendshipsOutgoingV1Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.d.ts
new file mode 100644
index 00000000..ba1cd0e1
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.d.ts
@@ -0,0 +1,52 @@
+import { UserV2, UserV2TimelineParams, UserV2TimelineResult } from '../types';
+import { TimelineV2Paginator } from './v2.paginator';
+/** A generic PreviousableTwitterPaginator able to consume UserV2 timelines. */
+declare abstract class UserTimelineV2Paginator extends TimelineV2Paginator {
+ protected getItemArray(): UserV2[];
+ /**
+ * Users returned by paginator.
+ */
+ get users(): UserV2[];
+ get meta(): TResult["meta"];
+}
+export declare class UserBlockingUsersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserMutingUsersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserFollowersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserFollowingV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserListMembersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class UserListFollowersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetLikingUsersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export declare class TweetRetweetersUsersV2Paginator extends UserTimelineV2Paginator {
+ protected _endpoint: string;
+}
+export {};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.js
new file mode 100644
index 00000000..1cd54574
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.js
@@ -0,0 +1,76 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TweetRetweetersUsersV2Paginator = exports.TweetLikingUsersV2Paginator = exports.UserListFollowersV2Paginator = exports.UserListMembersV2Paginator = exports.UserFollowingV2Paginator = exports.UserFollowersV2Paginator = exports.UserMutingUsersV2Paginator = exports.UserBlockingUsersV2Paginator = void 0;
+const v2_paginator_1 = require("./v2.paginator");
+/** A generic PreviousableTwitterPaginator able to consume UserV2 timelines. */
+class UserTimelineV2Paginator extends v2_paginator_1.TimelineV2Paginator {
+ getItemArray() {
+ return this.users;
+ }
+ /**
+ * Users returned by paginator.
+ */
+ get users() {
+ var _a;
+ return (_a = this._realData.data) !== null && _a !== void 0 ? _a : [];
+ }
+ get meta() {
+ return super.meta;
+ }
+}
+class UserBlockingUsersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/blocking';
+ }
+}
+exports.UserBlockingUsersV2Paginator = UserBlockingUsersV2Paginator;
+class UserMutingUsersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/muting';
+ }
+}
+exports.UserMutingUsersV2Paginator = UserMutingUsersV2Paginator;
+class UserFollowersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/followers';
+ }
+}
+exports.UserFollowersV2Paginator = UserFollowersV2Paginator;
+class UserFollowingV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'users/:id/following';
+ }
+}
+exports.UserFollowingV2Paginator = UserFollowingV2Paginator;
+class UserListMembersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/:id/members';
+ }
+}
+exports.UserListMembersV2Paginator = UserListMembersV2Paginator;
+class UserListFollowersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'lists/:id/followers';
+ }
+}
+exports.UserListFollowersV2Paginator = UserListFollowersV2Paginator;
+class TweetLikingUsersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'tweets/:id/liking_users';
+ }
+}
+exports.TweetLikingUsersV2Paginator = TweetLikingUsersV2Paginator;
+class TweetRetweetersUsersV2Paginator extends UserTimelineV2Paginator {
+ constructor() {
+ super(...arguments);
+ this._endpoint = 'tweets/:id/retweeted_by';
+ }
+}
+exports.TweetRetweetersUsersV2Paginator = TweetRetweetersUsersV2Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.d.ts
new file mode 100644
index 00000000..1cdc52bf
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.d.ts
@@ -0,0 +1,36 @@
+import type { TwitterResponse } from '../types';
+import type { DataMetaAndIncludeV2 } from '../types/v2/shared.v2.types';
+import { TwitterV2IncludesHelper } from '../v2/includes.v2.helper';
+import { PreviousableTwitterPaginator } from './TwitterPaginator';
+/** A generic PreviousableTwitterPaginator with common v2 helper methods. */
+export declare abstract class TwitterV2Paginator, TParams extends object, TItem, TShared = any> extends PreviousableTwitterPaginator {
+ protected _includesInstance?: TwitterV2IncludesHelper;
+ protected updateIncludes(data: TResult): void;
+ /** Throw if the current paginator is not usable. */
+ protected assertUsable(): void;
+ get meta(): any;
+ get includes(): TwitterV2IncludesHelper;
+ get errors(): import("../types").InlineErrorV2[];
+ /** `true` if this paginator only contains error payload and no metadata found to consume data. */
+ get unusable(): boolean;
+}
+/** A generic TwitterV2Paginator able to consume v2 timelines that use max_results and pagination tokens. */
+export declare abstract class TimelineV2Paginator, TParams extends {
+ max_results?: number;
+ pagination_token?: string;
+}, TItem, TShared = any> extends TwitterV2Paginator {
+ protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: boolean): void;
+ protected getNextQueryParams(maxResults?: number): {
+ max_results?: number | undefined;
+ } & Partial & {
+ pagination_token: any;
+ };
+ protected getPreviousQueryParams(maxResults?: number): {
+ max_results?: number | undefined;
+ } & Partial & {
+ pagination_token: any;
+ };
+ protected getPageLengthFromRequest(result: TwitterResponse): any;
+ protected isFetchLastOver(result: TwitterResponse): boolean;
+ protected canFetchNextPage(result: TResult): boolean;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.js b/social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.js
new file mode 100644
index 00000000..6e6e3c6e
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.js
@@ -0,0 +1,113 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TimelineV2Paginator = exports.TwitterV2Paginator = void 0;
+const includes_v2_helper_1 = require("../v2/includes.v2.helper");
+const TwitterPaginator_1 = require("./TwitterPaginator");
+/** A generic PreviousableTwitterPaginator with common v2 helper methods. */
+class TwitterV2Paginator extends TwitterPaginator_1.PreviousableTwitterPaginator {
+ updateIncludes(data) {
+ // Update errors
+ if (data.errors) {
+ if (!this._realData.errors) {
+ this._realData.errors = [];
+ }
+ this._realData.errors = [...this._realData.errors, ...data.errors];
+ }
+ // Update includes
+ if (!data.includes) {
+ return;
+ }
+ if (!this._realData.includes) {
+ this._realData.includes = {};
+ }
+ const includesRealData = this._realData.includes;
+ for (const [includeKey, includeArray] of Object.entries(data.includes)) {
+ if (!includesRealData[includeKey]) {
+ includesRealData[includeKey] = [];
+ }
+ includesRealData[includeKey] = [
+ ...includesRealData[includeKey],
+ ...includeArray,
+ ];
+ }
+ }
+ /** Throw if the current paginator is not usable. */
+ assertUsable() {
+ if (this.unusable) {
+ throw new Error('Unable to use this paginator to fetch more data, as it does not contain any metadata.' +
+ ' Check .errors property for more details.');
+ }
+ }
+ get meta() {
+ return this._realData.meta;
+ }
+ get includes() {
+ var _a;
+ if (!((_a = this._realData) === null || _a === void 0 ? void 0 : _a.includes)) {
+ return new includes_v2_helper_1.TwitterV2IncludesHelper(this._realData);
+ }
+ if (this._includesInstance) {
+ return this._includesInstance;
+ }
+ return this._includesInstance = new includes_v2_helper_1.TwitterV2IncludesHelper(this._realData);
+ }
+ get errors() {
+ var _a;
+ return (_a = this._realData.errors) !== null && _a !== void 0 ? _a : [];
+ }
+ /** `true` if this paginator only contains error payload and no metadata found to consume data. */
+ get unusable() {
+ return this.errors.length > 0 && !this._realData.meta && !this._realData.data;
+ }
+}
+exports.TwitterV2Paginator = TwitterV2Paginator;
+/** A generic TwitterV2Paginator able to consume v2 timelines that use max_results and pagination tokens. */
+class TimelineV2Paginator extends TwitterV2Paginator {
+ refreshInstanceFromResult(response, isNextPage) {
+ var _a;
+ const result = response.data;
+ const resultData = (_a = result.data) !== null && _a !== void 0 ? _a : [];
+ this._rateLimit = response.rateLimit;
+ if (!this._realData.data) {
+ this._realData.data = [];
+ }
+ if (isNextPage) {
+ this._realData.meta.result_count += result.meta.result_count;
+ this._realData.meta.next_token = result.meta.next_token;
+ this._realData.data.push(...resultData);
+ }
+ else {
+ this._realData.meta.result_count += result.meta.result_count;
+ this._realData.meta.previous_token = result.meta.previous_token;
+ this._realData.data.unshift(...resultData);
+ }
+ this.updateIncludes(result);
+ }
+ getNextQueryParams(maxResults) {
+ this.assertUsable();
+ return {
+ ...this.injectQueryParams(maxResults),
+ pagination_token: this._realData.meta.next_token,
+ };
+ }
+ getPreviousQueryParams(maxResults) {
+ this.assertUsable();
+ return {
+ ...this.injectQueryParams(maxResults),
+ pagination_token: this._realData.meta.previous_token,
+ };
+ }
+ getPageLengthFromRequest(result) {
+ var _a, _b;
+ return (_b = (_a = result.data.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
+ }
+ isFetchLastOver(result) {
+ var _a;
+ return !((_a = result.data.data) === null || _a === void 0 ? void 0 : _a.length) || !this.canFetchNextPage(result.data);
+ }
+ canFetchNextPage(result) {
+ var _a;
+ return !!((_a = result.meta) === null || _a === void 0 ? void 0 : _a.next_token);
+ }
+}
+exports.TimelineV2Paginator = TimelineV2Paginator;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.d.ts
new file mode 100644
index 00000000..264d0536
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.d.ts
@@ -0,0 +1,7 @@
+///
+import type { ClientRequestArgs } from 'http';
+import type { ClientRequestMaker } from '../client-mixins/request-maker.mixin';
+import { IGetHttpRequestArgs } from '../types';
+import type { IComputedHttpRequestArgs } from '../types/request-maker.mixin.types';
+export declare function hasRequestErrorPlugins(client: ClientRequestMaker): boolean;
+export declare function applyResponseHooks(this: ClientRequestMaker, requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial, error: any): Promise;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.js b/social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.js
new file mode 100644
index 00000000..66452e24
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.js
@@ -0,0 +1,46 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.applyResponseHooks = exports.hasRequestErrorPlugins = void 0;
+const types_1 = require("../types");
+/* Plugin helpers */
+function hasRequestErrorPlugins(client) {
+ var _a;
+ if (!((_a = client.clientSettings.plugins) === null || _a === void 0 ? void 0 : _a.length)) {
+ return false;
+ }
+ for (const plugin of client.clientSettings.plugins) {
+ if (plugin.onRequestError || plugin.onResponseError) {
+ return true;
+ }
+ }
+ return false;
+}
+exports.hasRequestErrorPlugins = hasRequestErrorPlugins;
+async function applyResponseHooks(requestParams, computedParams, requestOptions, error) {
+ let override;
+ if (error instanceof types_1.ApiRequestError || error instanceof types_1.ApiPartialResponseError) {
+ override = await this.applyPluginMethod('onRequestError', {
+ client: this,
+ url: this.getUrlObjectFromUrlString(requestParams.url),
+ params: requestParams,
+ computedParams,
+ requestOptions,
+ error,
+ });
+ }
+ else if (error instanceof types_1.ApiResponseError) {
+ override = await this.applyPluginMethod('onResponseError', {
+ client: this,
+ url: this.getUrlObjectFromUrlString(requestParams.url),
+ params: requestParams,
+ computedParams,
+ requestOptions,
+ error,
+ });
+ }
+ if (override && override instanceof types_1.TwitterApiPluginResponseOverride) {
+ return override.value;
+ }
+ return Promise.reject(error);
+}
+exports.applyResponseHooks = applyResponseHooks;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/settings.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/settings.d.ts
new file mode 100644
index 00000000..5a8d18ed
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/settings.d.ts
@@ -0,0 +1,9 @@
+export interface ITwitterApiV2Settings {
+ debug: boolean;
+ deprecationWarnings: boolean;
+ logger: ITwitterApiV2SettingsLogger;
+}
+export interface ITwitterApiV2SettingsLogger {
+ log(message: string, payload?: any): void;
+}
+export declare const TwitterApiV2Settings: ITwitterApiV2Settings;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/settings.js b/social/twitter/node_modules/twitter-api-v2/dist/settings.js
new file mode 100644
index 00000000..5604a758
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/settings.js
@@ -0,0 +1,8 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TwitterApiV2Settings = void 0;
+exports.TwitterApiV2Settings = {
+ debug: false,
+ deprecationWarnings: true,
+ logger: { log: console.log.bind(console) },
+};
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.d.ts
new file mode 100644
index 00000000..e976cc69
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.d.ts
@@ -0,0 +1,80 @@
+///
+import { EventEmitter } from 'events';
+import type { IncomingMessage, ClientRequest } from 'http';
+import type { Readable } from 'stream';
+import { ETwitterStreamEvent } from '../types';
+import { TRequestFullStreamData } from '../types/request-maker.mixin.types';
+import TweetStreamParser from './TweetStreamParser';
+interface ITweetStreamError {
+ type: ETwitterStreamEvent.ConnectionError | ETwitterStreamEvent.TweetParseError | ETwitterStreamEvent.ReconnectError | ETwitterStreamEvent.DataError | ETwitterStreamEvent.ConnectError;
+ error: any;
+ message?: string;
+}
+export interface IConnectTweetStreamParams {
+ autoReconnect: boolean;
+ autoReconnectRetries: number | 'unlimited';
+ /** Check for 'lost connection' status every `keepAliveTimeout` milliseconds. Defaults to 2 minutes (`120000`). */
+ keepAliveTimeout: number | 'disable';
+ nextRetryTimeout?: TStreamConnectRetryFn;
+}
+export interface IWithConnectionTweetStream {
+ req: ClientRequest;
+ res: Readable;
+ originalResponse: IncomingMessage;
+}
+/** Returns a number of milliseconds to wait for {tryOccurence} (starting from 1) */
+export declare type TStreamConnectRetryFn = (tryOccurence: number, error?: any) => number;
+export declare class TweetStream extends EventEmitter {
+ protected requestData: TRequestFullStreamData;
+ autoReconnect: boolean;
+ autoReconnectRetries: number;
+ keepAliveTimeoutMs: number;
+ nextRetryTimeout: TStreamConnectRetryFn;
+ protected retryTimeout?: NodeJS.Timeout;
+ protected keepAliveTimeout?: NodeJS.Timeout;
+ protected parser: TweetStreamParser;
+ protected connectionProcessRunning: boolean;
+ protected req?: ClientRequest;
+ protected res?: Readable;
+ protected originalResponse?: IncomingMessage;
+ constructor(requestData: TRequestFullStreamData, connection?: IWithConnectionTweetStream);
+ on(event: ETwitterStreamEvent.Data, handler: (data: T) => any): this;
+ on(event: ETwitterStreamEvent.DataError, handler: (error: any) => any): this;
+ on(event: ETwitterStreamEvent.Error, handler: (errorPayload: ITweetStreamError) => any): this;
+ on(event: ETwitterStreamEvent.Connected, handler: () => any): this;
+ on(event: ETwitterStreamEvent.ConnectionLost, handler: () => any): this;
+ on(event: ETwitterStreamEvent.ConnectionError, handler: (error: Error) => any): this;
+ on(event: ETwitterStreamEvent.TweetParseError, handler: (error: Error) => any): this;
+ on(event: ETwitterStreamEvent.ConnectionClosed, handler: () => any): this;
+ on(event: ETwitterStreamEvent.DataKeepAlive, handler: () => any): this;
+ on(event: ETwitterStreamEvent.ReconnectAttempt, handler: (tries: number) => any): this;
+ on(event: ETwitterStreamEvent.ReconnectError, handler: (tries: number) => any): this;
+ on(event: ETwitterStreamEvent.ReconnectLimitExceeded, handler: () => any): this;
+ on(event: ETwitterStreamEvent.Reconnected, handler: () => any): this;
+ on(event: string | symbol, handler: (...args: any[]) => any): this;
+ protected initEventsFromRequest(): void;
+ protected initEventsFromParser(): void;
+ protected resetKeepAliveTimeout(): void;
+ protected onKeepAliveTimeout(): void;
+ protected unbindTimeouts(): void;
+ protected unbindKeepAliveTimeout(): void;
+ protected unbindRetryTimeout(): void;
+ protected closeWithoutEmit(): void;
+ /** Terminate connection to Twitter. */
+ close(): void;
+ /** Unbind all listeners, and close connection. */
+ destroy(): void;
+ /**
+ * Make a new request that creates a new `TweetStream` instance with
+ * the same parameters, and bind current listeners to new stream.
+ */
+ clone(): Promise>;
+ /** Start initial stream connection, setup options on current instance and returns itself. */
+ connect(options?: Partial): Promise;
+ /** Make a new request to (re)connect to Twitter. */
+ reconnect(): Promise;
+ protected onConnectionError(retryOccurence?: number): Promise;
+ protected makeAutoReconnectRetry(retryOccurence: number, error: any): void;
+ [Symbol.asyncIterator](): AsyncGenerator;
+}
+export default TweetStream;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.js b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.js
new file mode 100644
index 00000000..8bae5c5f
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.js
@@ -0,0 +1,303 @@
+"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.TweetStream = void 0;
+const events_1 = require("events");
+const request_handler_helper_1 = __importDefault(require("../client-mixins/request-handler.helper"));
+const types_1 = require("../types");
+const TweetStreamEventCombiner_1 = __importDefault(require("./TweetStreamEventCombiner"));
+const TweetStreamParser_1 = __importStar(require("./TweetStreamParser"));
+// In seconds
+const basicRetriesAttempt = [5, 15, 30, 60, 90, 120, 180, 300, 600, 900];
+// Default retry function
+const basicReconnectRetry = tryOccurence => tryOccurence > basicRetriesAttempt.length
+ ? 901000
+ : basicRetriesAttempt[tryOccurence - 1] * 1000;
+class TweetStream extends events_1.EventEmitter {
+ constructor(requestData, connection) {
+ super();
+ this.requestData = requestData;
+ this.autoReconnect = false;
+ this.autoReconnectRetries = 5;
+ // 2 minutes without any Twitter signal
+ this.keepAliveTimeoutMs = 1000 * 120;
+ this.nextRetryTimeout = basicReconnectRetry;
+ this.parser = new TweetStreamParser_1.default();
+ this.connectionProcessRunning = false;
+ this.onKeepAliveTimeout = this.onKeepAliveTimeout.bind(this);
+ this.initEventsFromParser();
+ if (connection) {
+ this.req = connection.req;
+ this.res = connection.res;
+ this.originalResponse = connection.originalResponse;
+ this.initEventsFromRequest();
+ }
+ }
+ on(event, handler) {
+ return super.on(event, handler);
+ }
+ initEventsFromRequest() {
+ if (!this.req || !this.res) {
+ throw new Error('TweetStream error: You cannot init TweetStream without a request and response object.');
+ }
+ const errorHandler = (err) => {
+ this.emit(types_1.ETwitterStreamEvent.ConnectionError, err);
+ this.emit(types_1.ETwitterStreamEvent.Error, {
+ type: types_1.ETwitterStreamEvent.ConnectionError,
+ error: err,
+ message: 'Connection lost or closed by Twitter.',
+ });
+ this.onConnectionError();
+ };
+ this.req.on('error', errorHandler);
+ this.res.on('error', errorHandler);
+ // Usually, connection should not be closed by Twitter!
+ this.res.on('close', () => errorHandler(new Error('Connection closed by Twitter.')));
+ this.res.on('data', (chunk) => {
+ this.resetKeepAliveTimeout();
+ if (chunk.toString() === '\r\n') {
+ return this.emit(types_1.ETwitterStreamEvent.DataKeepAlive);
+ }
+ this.parser.push(chunk.toString());
+ });
+ // Starts the keep alive timeout
+ this.resetKeepAliveTimeout();
+ }
+ initEventsFromParser() {
+ const payloadIsError = this.requestData.payloadIsError;
+ this.parser.on(TweetStreamParser_1.EStreamParserEvent.ParsedData, (eventData) => {
+ if (payloadIsError && payloadIsError(eventData)) {
+ this.emit(types_1.ETwitterStreamEvent.DataError, eventData);
+ this.emit(types_1.ETwitterStreamEvent.Error, {
+ type: types_1.ETwitterStreamEvent.DataError,
+ error: eventData,
+ message: 'Twitter sent a payload that is detected as an error payload.',
+ });
+ }
+ else {
+ this.emit(types_1.ETwitterStreamEvent.Data, eventData);
+ }
+ });
+ this.parser.on(TweetStreamParser_1.EStreamParserEvent.ParseError, (error) => {
+ this.emit(types_1.ETwitterStreamEvent.TweetParseError, error);
+ this.emit(types_1.ETwitterStreamEvent.Error, {
+ type: types_1.ETwitterStreamEvent.TweetParseError,
+ error,
+ message: 'Failed to parse stream data.',
+ });
+ });
+ }
+ resetKeepAliveTimeout() {
+ this.unbindKeepAliveTimeout();
+ if (this.keepAliveTimeoutMs !== Infinity) {
+ this.keepAliveTimeout = setTimeout(this.onKeepAliveTimeout, this.keepAliveTimeoutMs);
+ }
+ }
+ onKeepAliveTimeout() {
+ this.emit(types_1.ETwitterStreamEvent.ConnectionLost);
+ this.onConnectionError();
+ }
+ unbindTimeouts() {
+ this.unbindRetryTimeout();
+ this.unbindKeepAliveTimeout();
+ }
+ unbindKeepAliveTimeout() {
+ if (this.keepAliveTimeout) {
+ clearTimeout(this.keepAliveTimeout);
+ this.keepAliveTimeout = undefined;
+ }
+ }
+ unbindRetryTimeout() {
+ if (this.retryTimeout) {
+ clearTimeout(this.retryTimeout);
+ this.retryTimeout = undefined;
+ }
+ }
+ closeWithoutEmit() {
+ this.unbindTimeouts();
+ if (this.res) {
+ this.res.removeAllListeners();
+ // Close response silentely
+ this.res.destroy();
+ }
+ if (this.req) {
+ this.req.removeAllListeners();
+ // Close connection silentely
+ this.req.destroy();
+ }
+ }
+ /** Terminate connection to Twitter. */
+ close() {
+ this.emit(types_1.ETwitterStreamEvent.ConnectionClosed);
+ this.closeWithoutEmit();
+ }
+ /** Unbind all listeners, and close connection. */
+ destroy() {
+ this.removeAllListeners();
+ this.close();
+ }
+ /**
+ * Make a new request that creates a new `TweetStream` instance with
+ * the same parameters, and bind current listeners to new stream.
+ */
+ async clone() {
+ const newRequest = new request_handler_helper_1.default(this.requestData);
+ const newStream = await newRequest.makeRequestAsStream();
+ // Clone attached listeners
+ const listenerNames = this.eventNames();
+ for (const listener of listenerNames) {
+ const callbacks = this.listeners(listener);
+ for (const callback of callbacks) {
+ newStream.on(listener, callback);
+ }
+ }
+ return newStream;
+ }
+ /** Start initial stream connection, setup options on current instance and returns itself. */
+ async connect(options = {}) {
+ if (typeof options.autoReconnect !== 'undefined') {
+ this.autoReconnect = options.autoReconnect;
+ }
+ if (typeof options.autoReconnectRetries !== 'undefined') {
+ this.autoReconnectRetries = options.autoReconnectRetries === 'unlimited'
+ ? Infinity
+ : options.autoReconnectRetries;
+ }
+ if (typeof options.keepAliveTimeout !== 'undefined') {
+ this.keepAliveTimeoutMs = options.keepAliveTimeout === 'disable'
+ ? Infinity
+ : options.keepAliveTimeout;
+ }
+ if (typeof options.nextRetryTimeout !== 'undefined') {
+ this.nextRetryTimeout = options.nextRetryTimeout;
+ }
+ // Make the connection
+ this.unbindTimeouts();
+ try {
+ await this.reconnect();
+ }
+ catch (e) {
+ this.emit(types_1.ETwitterStreamEvent.ConnectError, 0);
+ this.emit(types_1.ETwitterStreamEvent.Error, {
+ type: types_1.ETwitterStreamEvent.ConnectError,
+ error: e,
+ message: 'Connect error - Initial connection just failed.',
+ });
+ // Only make a reconnection attempt if autoReconnect is true!
+ // Otherwise, let error be propagated
+ if (this.autoReconnect) {
+ this.makeAutoReconnectRetry(0, e);
+ }
+ else {
+ throw e;
+ }
+ }
+ return this;
+ }
+ /** Make a new request to (re)connect to Twitter. */
+ async reconnect() {
+ if (this.connectionProcessRunning) {
+ throw new Error('Connection process is already running.');
+ }
+ this.connectionProcessRunning = true;
+ try {
+ let initialConnection = true;
+ if (this.req) {
+ initialConnection = false;
+ this.closeWithoutEmit();
+ }
+ const { req, res, originalResponse } = await new request_handler_helper_1.default(this.requestData).makeRequestAndResolveWhenReady();
+ this.req = req;
+ this.res = res;
+ this.originalResponse = originalResponse;
+ this.emit(initialConnection ? types_1.ETwitterStreamEvent.Connected : types_1.ETwitterStreamEvent.Reconnected);
+ this.parser.reset();
+ this.initEventsFromRequest();
+ }
+ finally {
+ this.connectionProcessRunning = false;
+ }
+ }
+ async onConnectionError(retryOccurence = 0) {
+ this.unbindTimeouts();
+ // Close the request if necessary
+ this.closeWithoutEmit();
+ // Terminate stream by events if necessary (no auto-reconnect or retries exceeded)
+ if (!this.autoReconnect) {
+ this.emit(types_1.ETwitterStreamEvent.ConnectionClosed);
+ return;
+ }
+ if (retryOccurence >= this.autoReconnectRetries) {
+ this.emit(types_1.ETwitterStreamEvent.ReconnectLimitExceeded);
+ this.emit(types_1.ETwitterStreamEvent.ConnectionClosed);
+ return;
+ }
+ // If all other conditions fails, do a reconnect attempt
+ try {
+ this.emit(types_1.ETwitterStreamEvent.ReconnectAttempt, retryOccurence);
+ await this.reconnect();
+ }
+ catch (e) {
+ this.emit(types_1.ETwitterStreamEvent.ReconnectError, retryOccurence);
+ this.emit(types_1.ETwitterStreamEvent.Error, {
+ type: types_1.ETwitterStreamEvent.ReconnectError,
+ error: e,
+ message: `Reconnect error - ${retryOccurence + 1} attempts made yet.`,
+ });
+ this.makeAutoReconnectRetry(retryOccurence, e);
+ }
+ }
+ makeAutoReconnectRetry(retryOccurence, error) {
+ const nextRetry = this.nextRetryTimeout(retryOccurence + 1, error);
+ this.retryTimeout = setTimeout(() => {
+ this.onConnectionError(retryOccurence + 1);
+ }, nextRetry);
+ }
+ async *[Symbol.asyncIterator]() {
+ const eventCombiner = new TweetStreamEventCombiner_1.default(this);
+ try {
+ while (true) {
+ if (!this.req || this.req.aborted) {
+ throw new Error('Connection closed');
+ }
+ if (eventCombiner.hasStack()) {
+ yield* eventCombiner.popStack();
+ }
+ const { type, payload } = await eventCombiner.nextEvent();
+ if (type === 'error') {
+ throw payload;
+ }
+ }
+ }
+ finally {
+ eventCombiner.destroy();
+ }
+ }
+}
+exports.TweetStream = TweetStream;
+exports.default = TweetStream;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.d.ts
new file mode 100644
index 00000000..e268000b
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.d.ts
@@ -0,0 +1,27 @@
+///
+import { EventEmitter } from 'events';
+import type TweetStream from './TweetStream';
+export declare class TweetStreamEventCombiner extends EventEmitter {
+ private stream;
+ private stack;
+ private onceNewEvent;
+ constructor(stream: TweetStream);
+ /** Returns a new `Promise` that will `resolve` on next event (`data` or any sort of error). */
+ nextEvent(): Promise<{
+ type: "error";
+ payload?: any;
+ } | {
+ type: "data";
+ payload: T;
+ }>;
+ /** Returns `true` if there's something in the stack. */
+ hasStack(): boolean;
+ /** Returns stacked data events, and clean the stack. */
+ popStack(): T[];
+ /** Cleanup all the listeners attached on stream. */
+ destroy(): void;
+ private emitEvent;
+ private onStreamError;
+ private onStreamData;
+}
+export default TweetStreamEventCombiner;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.js b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.js
new file mode 100644
index 00000000..4e9a295a
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.js
@@ -0,0 +1,55 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TweetStreamEventCombiner = void 0;
+const events_1 = require("events");
+const types_1 = require("../types");
+class TweetStreamEventCombiner extends events_1.EventEmitter {
+ constructor(stream) {
+ super();
+ this.stream = stream;
+ this.stack = [];
+ this.onStreamData = this.onStreamData.bind(this);
+ this.onStreamError = this.onStreamError.bind(this);
+ this.onceNewEvent = this.once.bind(this, 'event');
+ // Init events from stream
+ stream.on(types_1.ETwitterStreamEvent.Data, this.onStreamData);
+ // Ignore reconnect errors: Don't close event combiner until connection error/closed
+ stream.on(types_1.ETwitterStreamEvent.ConnectionError, this.onStreamError);
+ stream.on(types_1.ETwitterStreamEvent.TweetParseError, this.onStreamError);
+ stream.on(types_1.ETwitterStreamEvent.ConnectionClosed, this.onStreamError);
+ }
+ /** Returns a new `Promise` that will `resolve` on next event (`data` or any sort of error). */
+ nextEvent() {
+ return new Promise(this.onceNewEvent);
+ }
+ /** Returns `true` if there's something in the stack. */
+ hasStack() {
+ return this.stack.length > 0;
+ }
+ /** Returns stacked data events, and clean the stack. */
+ popStack() {
+ const stack = this.stack;
+ this.stack = [];
+ return stack;
+ }
+ /** Cleanup all the listeners attached on stream. */
+ destroy() {
+ this.removeAllListeners();
+ this.stream.off(types_1.ETwitterStreamEvent.Data, this.onStreamData);
+ this.stream.off(types_1.ETwitterStreamEvent.ConnectionError, this.onStreamError);
+ this.stream.off(types_1.ETwitterStreamEvent.TweetParseError, this.onStreamError);
+ this.stream.off(types_1.ETwitterStreamEvent.ConnectionClosed, this.onStreamError);
+ }
+ emitEvent(type, payload) {
+ this.emit('event', { type, payload });
+ }
+ onStreamError(payload) {
+ this.emitEvent('error', payload);
+ }
+ onStreamData(payload) {
+ this.stack.push(payload);
+ this.emitEvent('data', payload);
+ }
+}
+exports.TweetStreamEventCombiner = TweetStreamEventCombiner;
+exports.default = TweetStreamEventCombiner;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.d.ts
new file mode 100644
index 00000000..459fcbb1
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.d.ts
@@ -0,0 +1,12 @@
+///
+import { EventEmitter } from 'events';
+export default class TweetStreamParser extends EventEmitter {
+ protected currentMessage: string;
+ push(chunk: string): void;
+ /** Reset the currently stored message (f.e. on connection reset) */
+ reset(): void;
+}
+export declare enum EStreamParserEvent {
+ ParsedData = "parsed data",
+ ParseError = "parse error"
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.js b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.js
new file mode 100644
index 00000000..8b8e5ee5
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.js
@@ -0,0 +1,54 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.EStreamParserEvent = void 0;
+const events_1 = require("events");
+class TweetStreamParser extends events_1.EventEmitter {
+ constructor() {
+ super(...arguments);
+ this.currentMessage = '';
+ }
+ // Code partially belongs to twitter-stream-api for this
+ // https://github.com/trygve-lie/twitter-stream-api/blob/master/lib/parser.js
+ push(chunk) {
+ this.currentMessage += chunk;
+ chunk = this.currentMessage;
+ const size = chunk.length;
+ let start = 0;
+ let offset = 0;
+ while (offset < size) {
+ // Take [offset, offset+1] inside a new string
+ if (chunk.slice(offset, offset + 2) === '\r\n') {
+ // If chunk contains \r\n after current offset,
+ // parse [start, ..., offset] as a tweet
+ const piece = chunk.slice(start, offset);
+ start = offset += 2;
+ // If empty object
+ if (!piece.length) {
+ continue;
+ }
+ try {
+ const payload = JSON.parse(piece);
+ if (payload) {
+ this.emit(EStreamParserEvent.ParsedData, payload);
+ continue;
+ }
+ }
+ catch (error) {
+ this.emit(EStreamParserEvent.ParseError, error);
+ }
+ }
+ offset++;
+ }
+ this.currentMessage = chunk.slice(start, size);
+ }
+ /** Reset the currently stored message (f.e. on connection reset) */
+ reset() {
+ this.currentMessage = '';
+ }
+}
+exports.default = TweetStreamParser;
+var EStreamParserEvent;
+(function (EStreamParserEvent) {
+ EStreamParserEvent["ParsedData"] = "parsed data";
+ EStreamParserEvent["ParseError"] = "parse error";
+})(EStreamParserEvent = exports.EStreamParserEvent || (exports.EStreamParserEvent = {}));
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/test/utils.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/test/utils.d.ts
new file mode 100644
index 00000000..840fb61d
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/test/utils.d.ts
@@ -0,0 +1,25 @@
+import { TwitterApi } from '..';
+/** User OAuth 1.0a client */
+export declare function getUserClient(this: any): TwitterApi;
+export declare function getUserKeys(): {
+ appKey: string;
+ appSecret: string;
+ accessToken: string;
+ accessSecret: string;
+};
+export declare function sleepTest(ms: number): Promise;
+/** User-unlogged OAuth 1.0a client */
+export declare function getRequestClient(): TwitterApi;
+export declare function getRequestKeys(): {
+ appKey: string;
+ appSecret: string;
+};
+export declare function getAuthLink(callback: string): Promise<{
+ oauth_token: string;
+ oauth_token_secret: string;
+ oauth_callback_confirmed: "true";
+ url: string;
+}>;
+export declare function getAccessClient(verifier: string): Promise;
+/** App OAuth 2.0 client */
+export declare function getAppClient(): Promise;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/test/utils.js b/social/twitter/node_modules/twitter-api-v2/dist/test/utils.js
new file mode 100644
index 00000000..8a73b19e
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/test/utils.js
@@ -0,0 +1,99 @@
+"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.getAppClient = exports.getAccessClient = exports.getAuthLink = exports.getRequestKeys = exports.getRequestClient = exports.sleepTest = exports.getUserKeys = exports.getUserClient = void 0;
+const __1 = require("..");
+const dotenv = __importStar(require("dotenv"));
+dotenv.config({ path: __dirname + '/../../.env' });
+/** User OAuth 1.0a client */
+function getUserClient() {
+ return new __1.TwitterApi({
+ appKey: process.env.CONSUMER_TOKEN,
+ appSecret: process.env.CONSUMER_SECRET,
+ accessToken: process.env.OAUTH_TOKEN,
+ accessSecret: process.env.OAUTH_SECRET,
+ });
+}
+exports.getUserClient = getUserClient;
+function getUserKeys() {
+ return {
+ appKey: process.env.CONSUMER_TOKEN,
+ appSecret: process.env.CONSUMER_SECRET,
+ accessToken: process.env.OAUTH_TOKEN,
+ accessSecret: process.env.OAUTH_SECRET,
+ };
+}
+exports.getUserKeys = getUserKeys;
+async function sleepTest(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+exports.sleepTest = sleepTest;
+/** User-unlogged OAuth 1.0a client */
+function getRequestClient() {
+ return new __1.TwitterApi({
+ appKey: process.env.CONSUMER_TOKEN,
+ appSecret: process.env.CONSUMER_SECRET,
+ });
+}
+exports.getRequestClient = getRequestClient;
+function getRequestKeys() {
+ return {
+ appKey: process.env.CONSUMER_TOKEN,
+ appSecret: process.env.CONSUMER_SECRET,
+ };
+}
+exports.getRequestKeys = getRequestKeys;
+// Test auth 1.0a flow
+function getAuthLink(callback) {
+ return getRequestClient().generateAuthLink(callback);
+}
+exports.getAuthLink = getAuthLink;
+async function getAccessClient(verifier) {
+ const requestClient = new __1.TwitterApi({
+ appKey: process.env.CONSUMER_TOKEN,
+ appSecret: process.env.CONSUMER_SECRET,
+ accessToken: process.env.OAUTH_TOKEN,
+ accessSecret: process.env.OAUTH_SECRET,
+ });
+ const { client } = await requestClient.login(verifier);
+ return client;
+}
+exports.getAccessClient = getAccessClient;
+/** App OAuth 2.0 client */
+function getAppClient() {
+ let requestClient;
+ if (process.env.BEARER_TOKEN) {
+ requestClient = new __1.TwitterApi(process.env.BEARER_TOKEN);
+ return Promise.resolve(requestClient);
+ }
+ else {
+ requestClient = new __1.TwitterApi({
+ appKey: process.env.CONSUMER_TOKEN,
+ appSecret: process.env.CONSUMER_SECRET,
+ });
+ return requestClient.appLogin();
+ }
+}
+exports.getAppClient = getAppClient;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.d.ts
new file mode 100644
index 00000000..fe37424f
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.d.ts
@@ -0,0 +1,12 @@
+import TwitterApiv2LabsReadWrite from './client.v2.labs.write';
+/**
+ * Twitter v2 labs client with all rights (read/write/DMs)
+ */
+export declare class TwitterApiv2Labs extends TwitterApiv2LabsReadWrite {
+ protected _prefix: string;
+ /**
+ * Get a client with read/write rights.
+ */
+ get readWrite(): TwitterApiv2LabsReadWrite;
+}
+export default TwitterApiv2Labs;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.js b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.js
new file mode 100644
index 00000000..eb0b00bb
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.js
@@ -0,0 +1,25 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TwitterApiv2Labs = void 0;
+const globals_1 = require("../globals");
+const client_v2_labs_write_1 = __importDefault(require("./client.v2.labs.write"));
+/**
+ * Twitter v2 labs client with all rights (read/write/DMs)
+ */
+class TwitterApiv2Labs extends client_v2_labs_write_1.default {
+ constructor() {
+ super(...arguments);
+ this._prefix = globals_1.API_V2_LABS_PREFIX;
+ }
+ /**
+ * Get a client with read/write rights.
+ */
+ get readWrite() {
+ return this;
+ }
+}
+exports.TwitterApiv2Labs = TwitterApiv2Labs;
+exports.default = TwitterApiv2Labs;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.d.ts
new file mode 100644
index 00000000..fb79198b
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.d.ts
@@ -0,0 +1,7 @@
+import TwitterApiSubClient from '../client.subclient';
+/**
+ * Base Twitter v2 labs client with only read right.
+ */
+export default class TwitterApiv2LabsReadOnly extends TwitterApiSubClient {
+ protected _prefix: string;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.js b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.js
new file mode 100644
index 00000000..4cd8c951
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.js
@@ -0,0 +1,17 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const client_subclient_1 = __importDefault(require("../client.subclient"));
+const globals_1 = require("../globals");
+/**
+ * Base Twitter v2 labs client with only read right.
+ */
+class TwitterApiv2LabsReadOnly extends client_subclient_1.default {
+ constructor() {
+ super(...arguments);
+ this._prefix = globals_1.API_V2_LABS_PREFIX;
+ }
+}
+exports.default = TwitterApiv2LabsReadOnly;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.d.ts
new file mode 100644
index 00000000..d546f643
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.d.ts
@@ -0,0 +1,11 @@
+import TwitterApiv2LabsReadOnly from './client.v2.labs.read';
+/**
+ * Base Twitter v2 labs client with read/write rights.
+ */
+export default class TwitterApiv2LabsReadWrite extends TwitterApiv2LabsReadOnly {
+ protected _prefix: string;
+ /**
+ * Get a client with only read rights.
+ */
+ get readOnly(): TwitterApiv2LabsReadOnly;
+}
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.js b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.js
new file mode 100644
index 00000000..acef13ef
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.js
@@ -0,0 +1,23 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const globals_1 = require("../globals");
+const client_v2_labs_read_1 = __importDefault(require("./client.v2.labs.read"));
+/**
+ * Base Twitter v2 labs client with read/write rights.
+ */
+class TwitterApiv2LabsReadWrite extends client_v2_labs_read_1.default {
+ constructor() {
+ super(...arguments);
+ this._prefix = globals_1.API_V2_LABS_PREFIX;
+ }
+ /**
+ * Get a client with only read rights.
+ */
+ get readOnly() {
+ return this;
+ }
+}
+exports.default = TwitterApiv2LabsReadWrite;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.d.ts
new file mode 100644
index 00000000..9caf1a0d
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.d.ts
@@ -0,0 +1,18 @@
+import TwitterApiv2ReadWrite from './client.v2.write';
+import TwitterApiv2Labs from '../v2-labs/client.v2.labs';
+/**
+ * Twitter v2 client with all rights (read/write/DMs)
+ */
+export declare class TwitterApiv2 extends TwitterApiv2ReadWrite {
+ protected _prefix: string;
+ protected _labs?: TwitterApiv2Labs;
+ /**
+ * Get a client with read/write rights.
+ */
+ get readWrite(): TwitterApiv2ReadWrite;
+ /**
+ * Get a client for v2 labs endpoints.
+ */
+ get labs(): TwitterApiv2Labs;
+}
+export default TwitterApiv2;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.js b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.js
new file mode 100644
index 00000000..2444f46e
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.js
@@ -0,0 +1,35 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.TwitterApiv2 = void 0;
+const globals_1 = require("../globals");
+const client_v2_write_1 = __importDefault(require("./client.v2.write"));
+const client_v2_labs_1 = __importDefault(require("../v2-labs/client.v2.labs"));
+/**
+ * Twitter v2 client with all rights (read/write/DMs)
+ */
+class TwitterApiv2 extends client_v2_write_1.default {
+ constructor() {
+ super(...arguments);
+ this._prefix = globals_1.API_V2_PREFIX;
+ }
+ /* Sub-clients */
+ /**
+ * Get a client with read/write rights.
+ */
+ get readWrite() {
+ return this;
+ }
+ /**
+ * Get a client for v2 labs endpoints.
+ */
+ get labs() {
+ if (this._labs)
+ return this._labs;
+ return this._labs = new client_v2_labs_1.default(this);
+ }
+}
+exports.TwitterApiv2 = TwitterApiv2;
+exports.default = TwitterApiv2;
diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.d.ts
new file mode 100644
index 00000000..4f859c6d
--- /dev/null
+++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.d.ts
@@ -0,0 +1,302 @@
+import TwitterApiSubClient from '../client.subclient';
+import { Tweetv2FieldsParams, Tweetv2SearchParams, UserV2Result, UsersV2Result, UsersV2Params, StreamingV2GetRulesParams, StreamingV2GetRulesResult, TweetV2LookupResult, TweetV2UserTimelineParams, StreamingV2AddRulesParams, StreamingV2DeleteRulesParams, StreamingV2UpdateRulesQuery, StreamingV2UpdateRulesDeleteResult, StreamingV2UpdateRulesAddResult, TweetV2SingleResult, TweetV2PaginableTimelineParams, TweetV2CountResult, TweetV2CountParams, TweetV2CountAllResult, TweetV2CountAllParams, TweetV2RetweetedByResult, TweetV2LikedByResult, UserV2TimelineParams, UserV2TimelineResult, FollowersV2ParamsWithPaginator, FollowersV2ParamsWithoutPaginator, TweetSearchV2StreamParams, TweetV2SingleStreamResult, TweetV2PaginableListParams, SpaceV2FieldsParams, SpaceV2LookupResult, SpaceV2CreatorLookupParams, SpaceV2SearchParams, SpaceV2SingleResult, BatchComplianceSearchV2Params, BatchComplianceListV2Result, BatchComplianceV2Result, BatchComplianceV2Params, BatchComplianceV2JobResult, BatchComplianceJobV2, GetListV2Params, ListGetV2Result, GetListTimelineV2Params, TweetRetweetedOrLikedByV2ParamsWithPaginator, TweetRetweetedOrLikedByV2ParamsWithoutPaginator, SpaceV2BuyersParams, TweetV2HomeTimelineParams } from '../types';
+import { TweetSearchAllV2Paginator, TweetSearchRecentV2Paginator, TweetUserMentionTimelineV2Paginator, TweetUserTimelineV2Paginator, TweetV2UserLikedTweetsPaginator, UserOwnedListsV2Paginator, UserListMembershipsV2Paginator, UserListFollowedV2Paginator, TweetV2ListTweetsPaginator, TweetBookmarksTimelineV2Paginator, QuotedTweetsTimelineV2Paginator, TweetHomeTimelineV2Paginator } from '../paginators';
+import TwitterApiv2LabsReadOnly from '../v2-labs/client.v2.labs.read';
+import { TweetLikingUsersV2Paginator, TweetRetweetersUsersV2Paginator, UserBlockingUsersV2Paginator, UserFollowersV2Paginator, UserFollowingV2Paginator, UserListFollowersV2Paginator, UserListMembersV2Paginator, UserMutingUsersV2Paginator } from '../paginators/user.paginator.v2';
+import TweetStream from '../stream/TweetStream';
+import { PromiseOrType } from '../types/shared.types';
+/**
+ * Base Twitter v2 client with only read right.
+ */
+export default class TwitterApiv2ReadOnly extends TwitterApiSubClient {
+ protected _prefix: string;
+ protected _labs?: TwitterApiv2LabsReadOnly;
+ /**
+ * Get a client for v2 labs endpoints.
+ */
+ get labs(): TwitterApiv2LabsReadOnly;
+ /**
+ * The recent search endpoint returns Tweets from the last seven days that match a search query.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent
+ */
+ search(options: Partial): Promise;
+ search(query: string, options?: Partial): Promise;
+ /**
+ * The full-archive search endpoint returns the complete history of public Tweets matching a search query;
+ * since the first Tweet was created March 26, 2006.
+ *
+ * This endpoint is only available to those users who have been approved for the Academic Research product track.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all
+ */
+ searchAll(query: string, options?: Partial): Promise;
+ /**
+ * Returns a variety of information about a single Tweet specified by the requested ID.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets-id
+ *
+ * OAuth2 scope: `users.read`, `tweet.read`
+ */
+ singleTweet(tweetId: string, options?: Partial): Promise;
+ /**
+ * Returns a variety of information about tweets specified by list of IDs.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets
+ *
+ * OAuth2 scope: `users.read`, `tweet.read`
+ */
+ tweets(tweetIds: string | string[], options?: Partial): Promise;
+ /**
+ * The recent Tweet counts endpoint returns count of Tweets from the last seven days that match a search query.
+ * OAuth2 Bearer auth only.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent
+ */
+ tweetCountRecent(query: string, options?: Partial): Promise;
+ /**
+ * This endpoint is only available to those users who have been approved for the Academic Research product track.
+ * The full-archive search endpoint returns the complete history of public Tweets matching a search query;
+ * since the first Tweet was created March 26, 2006.
+ * OAuth2 Bearer auth only.
+ * **This endpoint has pagination, yet it is not supported by bundled paginators. Use `next_token` to fetch next page.**
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-all
+ */
+ tweetCountAll(query: string, options?: Partial): Promise;
+ /**
+ * Allows you to get information about who has Retweeted a Tweet.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by
+ */
+ tweetRetweetedBy(tweetId: string, options?: Partial): Promise;
+ tweetRetweetedBy(tweetId: string, options: TweetRetweetedOrLikedByV2ParamsWithPaginator): Promise;
+ /**
+ * Allows you to get information about who has Liked a Tweet.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users
+ */
+ tweetLikedBy(tweetId: string, options?: Partial): Promise;
+ tweetLikedBy(tweetId: string, options: TweetRetweetedOrLikedByV2ParamsWithPaginator): Promise;
+ /**
+ * Allows you to retrieve a collection of the most recent Tweets and Retweets posted by you and users you follow, also known as home timeline.
+ * This endpoint returns up to the last 3200 Tweets.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological
+ *
+ * OAuth 2 scopes: `tweet.read` `users.read`
+ */
+ homeTimeline(options?: Partial): Promise;
+ /**
+ * Returns Tweets composed by a single user, specified by the requested user ID.
+ * By default, the most recent ten Tweets are returned per request.
+ * Using pagination, the most recent 3,200 Tweets can be retrieved.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets
+ */
+ userTimeline(userId: string, options?: Partial): Promise;
+ /**
+ * Returns Tweets mentioning a single user specified by the requested user ID.
+ * By default, the most recent ten Tweets are returned per request.
+ * Using pagination, up to the most recent 800 Tweets can be retrieved.
+ * https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions
+ */
+ userMentionTimeline(userId: string, options?: Partial): Promise