From 91c72d107ed14f8f203046189fb999807eb32d23 Mon Sep 17 00:00:00 2001 From: shahramdj Date: Fri, 7 Oct 2022 15:45:45 -0400 Subject: [PATCH] Add files via upload --- .../dist/client-mixins/form-data.helper.d.ts | 24 + .../dist/client-mixins/form-data.helper.js | 83 +++ .../dist/client-mixins/oauth1.helper.d.ts | 40 ++ .../dist/client-mixins/oauth1.helper.js | 187 ++++++ .../dist/client-mixins/oauth2.helper.d.ts | 7 + .../dist/client-mixins/oauth2.helper.js | 54 ++ .../client-mixins/request-handler.helper.d.ts | 60 ++ .../client-mixins/request-handler.helper.js | 391 ++++++++++++ .../client-mixins/request-maker.mixin.d.ts | 58 ++ .../dist/client-mixins/request-maker.mixin.js | 323 ++++++++++ .../client-mixins/request-param.helper.d.ts | 20 + .../client-mixins/request-param.helper.js | 145 +++++ .../twitter-api-v2/dist/client.base.d.ts | 134 +++++ .../twitter-api-v2/dist/client.base.js | 179 ++++++ .../twitter-api-v2/dist/client.subclient.d.ts | 7 + .../twitter-api-v2/dist/client.subclient.js | 18 + .../twitter-api-v2/dist/client/index.d.ts | 22 + .../twitter-api-v2/dist/client/index.js | 70 +++ .../twitter-api-v2/dist/client/readonly.d.ts | 157 +++++ .../twitter-api-v2/dist/client/readonly.js | 305 ++++++++++ .../twitter-api-v2/dist/client/readwrite.d.ts | 16 + .../twitter-api-v2/dist/client/readwrite.js | 31 + .../twitter-api-v2/dist/globals.d.ts | 5 + .../twitter-api-v2/dist/globals.js | 8 + .../twitter-api-v2/dist/helpers.d.ts | 16 + .../twitter-api-v2/dist/helpers.js | 60 ++ .../twitter-api-v2/dist/index.d.ts | 10 + .../node_modules/twitter-api-v2/dist/index.js | 31 + .../dist/paginators/TwitterPaginator.d.ts | 86 +++ .../dist/paginators/TwitterPaginator.js | 173 ++++++ .../dist/paginators/dm.paginator.v1.d.ts | 19 + .../dist/paginators/dm.paginator.v1.js | 55 ++ .../twitter-api-v2/dist/paginators/index.d.ts | 9 + .../twitter-api-v2/dist/paginators/index.js | 25 + .../dist/paginators/list.paginator.v1.d.ts | 36 ++ .../dist/paginators/list.paginator.v1.js | 83 +++ .../dist/paginators/list.paginator.v2.d.ts | 26 + .../dist/paginators/list.paginator.v2.js | 40 ++ .../dist/paginators/mutes.paginator.v1.d.ts | 23 + .../dist/paginators/mutes.paginator.v1.js | 59 ++ .../dist/paginators/paginator.v1.d.ts | 13 + .../dist/paginators/paginator.v1.js | 33 + .../dist/paginators/tweet.paginator.v1.d.ts | 37 ++ .../dist/paginators/tweet.paginator.v1.js | 92 +++ .../dist/paginators/tweet.paginator.v2.d.ts | 74 +++ .../dist/paginators/tweet.paginator.v2.js | 205 +++++++ .../dist/paginators/user.paginator.v1.d.ts | 37 ++ .../dist/paginators/user.paginator.v1.js | 85 +++ .../dist/paginators/user.paginator.v2.d.ts | 52 ++ .../dist/paginators/user.paginator.v2.js | 76 +++ .../dist/paginators/v2.paginator.d.ts | 36 ++ .../dist/paginators/v2.paginator.js | 113 ++++ .../twitter-api-v2/dist/plugins/helpers.d.ts | 7 + .../twitter-api-v2/dist/plugins/helpers.js | 46 ++ .../twitter-api-v2/dist/settings.d.ts | 9 + .../twitter-api-v2/dist/settings.js | 8 + .../dist/stream/TweetStream.d.ts | 80 +++ .../twitter-api-v2/dist/stream/TweetStream.js | 303 ++++++++++ .../dist/stream/TweetStreamEventCombiner.d.ts | 27 + .../dist/stream/TweetStreamEventCombiner.js | 55 ++ .../dist/stream/TweetStreamParser.d.ts | 12 + .../dist/stream/TweetStreamParser.js | 54 ++ .../twitter-api-v2/dist/test/utils.d.ts | 25 + .../twitter-api-v2/dist/test/utils.js | 99 +++ .../dist/v2-labs/client.v2.labs.d.ts | 12 + .../dist/v2-labs/client.v2.labs.js | 25 + .../dist/v2-labs/client.v2.labs.read.d.ts | 7 + .../dist/v2-labs/client.v2.labs.read.js | 17 + .../dist/v2-labs/client.v2.labs.write.d.ts | 11 + .../dist/v2-labs/client.v2.labs.write.js | 23 + .../twitter-api-v2/dist/v2/client.v2.d.ts | 18 + .../twitter-api-v2/dist/v2/client.v2.js | 35 ++ .../dist/v2/client.v2.read.d.ts | 302 ++++++++++ .../twitter-api-v2/dist/v2/client.v2.read.js | 568 ++++++++++++++++++ .../dist/v2/client.v2.write.d.ts | 187 ++++++ .../twitter-api-v2/dist/v2/client.v2.write.js | 296 +++++++++ .../dist/v2/includes.v2.helper.d.ts | 82 +++ .../dist/v2/includes.v2.helper.js | 211 +++++++ 78 files changed, 6467 insertions(+) create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/form-data.helper.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth1.helper.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/oauth2.helper.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-maker.mixin.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client-mixins/request-param.helper.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client.base.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client.base.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client.subclient.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client.subclient.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client/index.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client/index.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client/readonly.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client/readonly.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/client/readwrite.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/globals.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/globals.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/helpers.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/helpers.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/index.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/index.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/TwitterPaginator.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/dm.paginator.v1.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/index.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/index.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v1.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/list.paginator.v2.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/mutes.paginator.v1.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/paginator.v1.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v1.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/tweet.paginator.v2.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v1.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/user.paginator.v2.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/paginators/v2.paginator.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/plugins/helpers.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/settings.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/settings.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStream.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamEventCombiner.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/stream/TweetStreamParser.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/test/utils.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/test/utils.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.read.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2-labs/client.v2.labs.write.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.js create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.d.ts create mode 100644 social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.js 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; + /** + * Returns Quote Tweets for a Tweet specified by the requested Tweet ID. + * https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets + * + * OAuth2 scopes: `users.read` `tweet.read` + */ + quotes(tweetId: string, options?: Partial): Promise; + /** + * Allows you to get information about a authenticated user’s 800 most recent bookmarked Tweets. + * https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks + * + * OAuth2 scopes: `users.read` `tweet.read` `bookmark.read` + */ + bookmarks(options?: Partial): Promise; + /** + * Returns information about an authorized user. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me + * + * OAuth2 scopes: `tweet.read` & `users.read` + */ + me(options?: Partial): Promise; + /** + * Returns a variety of information about a single user specified by the requested ID. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id + */ + user(userId: string, options?: Partial): Promise; + /** + * Returns a variety of information about one or more users specified by the requested IDs. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users + */ + users(userIds: string | string[], options?: Partial): Promise; + /** + * Returns a variety of information about a single user specified by their username. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by-username-username + */ + userByUsername(username: string, options?: Partial): Promise; + /** + * Returns a variety of information about one or more users specified by their usernames. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by + * + * OAuth2 scope: `users.read`, `tweet.read` + */ + usersByUsernames(usernames: string | string[], options?: Partial): Promise; + /** + * Returns a list of users who are followers of the specified user ID. + * https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers + */ + followers(userId: string, options?: Partial): Promise; + followers(userId: string, options: FollowersV2ParamsWithPaginator): Promise; + /** + * Returns a list of users the specified user ID is following. + * https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following + * + * OAuth2 scope: `follows.read` + */ + following(userId: string, options?: Partial): Promise; + following(userId: string, options: FollowersV2ParamsWithPaginator): Promise; + /** + * Allows you to get information about a user’s liked Tweets. + * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets + */ + userLikedTweets(userId: string, options?: Partial): Promise; + /** + * Returns a list of users who are blocked by the authenticating user. + * https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking + */ + userBlockingUsers(userId: string, options?: Partial): Promise; + /** + * Returns a list of users who are muted by the authenticating user. + * https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting + */ + userMutingUsers(userId: string, options?: Partial): Promise; + /** + * Returns the details of a specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id + */ + list(id: string, options?: Partial): Promise; + /** + * Returns all Lists owned by the specified user. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists + */ + listsOwned(userId: string, options?: Partial): Promise; + /** + * Returns all Lists a specified user is a member of. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships + */ + listMemberships(userId: string, options?: Partial): Promise; + /** + * Returns all Lists a specified user follows. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists + */ + listFollowed(userId: string, options?: Partial): Promise; + /** + * Returns a list of Tweets from the specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets + */ + listTweets(listId: string, options?: Partial): Promise; + /** + * Returns a list of users who are members of the specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-lists-id-members + */ + listMembers(listId: string, options?: Partial): Promise; + /** + * Returns a list of users who are followers of the specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers + */ + listFollowers(listId: string, options?: Partial): Promise; + /** + * Get a single space by ID. + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + space(spaceId: string, options?: Partial): Promise; + /** + * Get spaces using their IDs. + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + spaces(spaceIds: string | string[], options?: Partial): Promise; + /** + * Get spaces using their creator user ID(s). (no pagination available) + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-by-creator-ids + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + spacesByCreators(creatorIds: string | string[], options?: Partial): Promise; + /** + * Search through spaces using multiple params. (no pagination available) + * https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search + */ + searchSpaces(options: SpaceV2SearchParams): Promise; + /** + * Returns a list of user who purchased a ticket to the requested Space. + * You must authenticate the request using the Access Token of the creator of the requested Space. + * + * **OAuth 2.0 Access Token required** + * + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-buyers + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + spaceBuyers(spaceId: string, options?: Partial): Promise; + /** + * Streams Tweets in real-time based on a specific set of filter rules. + * https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream + */ + searchStream(options?: Partial & { + autoConnect?: true; + }): Promise>; + searchStream(options: Partial & { + autoConnect: false; + }): TweetStream; + searchStream(options?: Partial & { + autoConnect?: boolean; + }): PromiseOrType>; + /** + * Return a list of rules currently active on the streaming endpoint, either as a list or individually. + * https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream-rules + */ + streamRules(options?: Partial): Promise; + /** + * Add or delete rules to your stream. + * To create one or more rules, submit an add JSON body with an array of rules and operators. + * Similarly, to delete one or more rules, submit a delete JSON body with an array of list of existing rule IDs. + * https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/post-tweets-search-stream-rules + */ + updateStreamRules(options: StreamingV2AddRulesParams, query?: Partial): Promise; + updateStreamRules(options: StreamingV2DeleteRulesParams, query?: Partial): Promise; + /** + * Streams about 1% of all Tweets in real-time. + * https://developer.twitter.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream + */ + sampleStream(options?: Partial & { + autoConnect?: true; + }): Promise>; + sampleStream(options: Partial & { + autoConnect: false; + }): TweetStream; + sampleStream(options?: Partial & { + autoConnect?: boolean; + }): PromiseOrType>; + /** + * Returns a list of recent compliance jobs. + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs + */ + complianceJobs(options: BatchComplianceSearchV2Params): Promise; + /** + * Get a single compliance job with the specified ID. + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id + */ + complianceJob(jobId: string): Promise; + /** + * Creates a new compliance job for Tweet IDs or user IDs, send your file, await result and parse it into an array. + * You can run one batch job at a time. Returns the created job, but **not the job result!**. + * + * You can obtain the result (**after job is completed**) with `.complianceJobResult`. + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs + */ + sendComplianceJob(jobParams: BatchComplianceV2Params): Promise; + /** + * Get the result of a running or completed job, obtained through `.complianceJob`, `.complianceJobs` or `.sendComplianceJob`. + * If job is still running (`in_progress`), it will await until job is completed. **This could be quite long!** + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs + */ + complianceJobResult(job: BatchComplianceJobV2): Promise; +} diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.js b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.js new file mode 100644 index 00000000..7a9d6d68 --- /dev/null +++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.read.js @@ -0,0 +1,568 @@ +"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"); +const paginators_1 = require("../paginators"); +const client_v2_labs_read_1 = __importDefault(require("../v2-labs/client.v2.labs.read")); +const user_paginator_v2_1 = require("../paginators/user.paginator.v2"); +const helpers_1 = require("../helpers"); +/** + * Base Twitter v2 client with only read right. + */ +class TwitterApiv2ReadOnly extends client_subclient_1.default { + constructor() { + super(...arguments); + this._prefix = globals_1.API_V2_PREFIX; + } + /* Sub-clients */ + /** + * Get a client for v2 labs endpoints. + */ + get labs() { + if (this._labs) + return this._labs; + return this._labs = new client_v2_labs_read_1.default(this); + } + async search(queryOrOptions, options = {}) { + const query = typeof queryOrOptions === 'string' ? queryOrOptions : undefined; + const realOptions = typeof queryOrOptions === 'object' && queryOrOptions !== null ? queryOrOptions : options; + const queryParams = { ...realOptions, query }; + const initialRq = await this.get('tweets/search/recent', queryParams, { fullResponse: true }); + return new paginators_1.TweetSearchRecentV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams, + }); + } + /** + * 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 + */ + async searchAll(query, options = {}) { + const queryParams = { ...options, query }; + const initialRq = await this.get('tweets/search/all', queryParams, { fullResponse: true }); + return new paginators_1.TweetSearchAllV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams, + }); + } + /** + * 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, options = {}) { + return this.get('tweets/:id', options, { params: { id: tweetId } }); + } + /** + * 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, options = {}) { + return this.get('tweets', { ids: tweetIds, ...options }); + } + /** + * 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, options = {}) { + return this.get('tweets/counts/recent', { query, ...options }); + } + /** + * 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, options = {}) { + return this.get('tweets/counts/all', { query, ...options }); + } + async tweetRetweetedBy(tweetId, options = {}) { + const { asPaginator, ...parameters } = options; + const initialRq = await this.get('tweets/:id/retweeted_by', parameters, { + fullResponse: true, + params: { id: tweetId }, + }); + if (!asPaginator) { + return initialRq.data; + } + return new user_paginator_v2_1.TweetRetweetersUsersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: parameters, + sharedParams: { id: tweetId }, + }); + } + async tweetLikedBy(tweetId, options = {}) { + const { asPaginator, ...parameters } = options; + const initialRq = await this.get('tweets/:id/liking_users', parameters, { + fullResponse: true, + params: { id: tweetId }, + }); + if (!asPaginator) { + return initialRq.data; + } + return new user_paginator_v2_1.TweetLikingUsersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: parameters, + sharedParams: { id: tweetId }, + }); + } + /** + * 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` + */ + async homeTimeline(options = {}) { + const meUser = await this.getCurrentUserV2Object(); + const initialRq = await this.get('users/:id/timelines/reverse_chronological', options, { + fullResponse: true, + params: { id: meUser.data.id }, + }); + return new paginators_1.TweetHomeTimelineV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: options, + sharedParams: { id: meUser.data.id }, + }); + } + /** + * 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 + */ + async userTimeline(userId, options = {}) { + const initialRq = await this.get('users/:id/tweets', options, { + fullResponse: true, + params: { id: userId }, + }); + return new paginators_1.TweetUserTimelineV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: options, + sharedParams: { id: userId }, + }); + } + /** + * 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 + */ + async userMentionTimeline(userId, options = {}) { + const initialRq = await this.get('users/:id/mentions', options, { + fullResponse: true, + params: { id: userId }, + }); + return new paginators_1.TweetUserMentionTimelineV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: options, + sharedParams: { id: userId }, + }); + } + /** + * Returns Quote Tweets for a Tweet specified by the requested Tweet ID. + * https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets + * + * OAuth2 scopes: `users.read` `tweet.read` + */ + async quotes(tweetId, options = {}) { + const initialRq = await this.get('tweets/:id/quote_tweets', options, { + fullResponse: true, + params: { id: tweetId }, + }); + return new paginators_1.QuotedTweetsTimelineV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: options, + sharedParams: { id: tweetId }, + }); + } + /* Bookmarks */ + /** + * Allows you to get information about a authenticated user’s 800 most recent bookmarked Tweets. + * https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks + * + * OAuth2 scopes: `users.read` `tweet.read` `bookmark.read` + */ + async bookmarks(options = {}) { + const user = await this.getCurrentUserV2Object(); + const initialRq = await this.get('users/:id/bookmarks', options, { + fullResponse: true, + params: { id: user.data.id }, + }); + return new paginators_1.TweetBookmarksTimelineV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: options, + sharedParams: { id: user.data.id }, + }); + } + /* Users */ + /** + * Returns information about an authorized user. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me + * + * OAuth2 scopes: `tweet.read` & `users.read` + */ + me(options = {}) { + return this.get('users/me', options); + } + /** + * Returns a variety of information about a single user specified by the requested ID. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id + */ + user(userId, options = {}) { + return this.get('users/:id', options, { params: { id: userId } }); + } + /** + * Returns a variety of information about one or more users specified by the requested IDs. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users + */ + users(userIds, options = {}) { + const ids = Array.isArray(userIds) ? userIds.join(',') : userIds; + return this.get('users', { ...options, ids }); + } + /** + * Returns a variety of information about a single user specified by their username. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by-username-username + */ + userByUsername(username, options = {}) { + return this.get('users/by/username/:username', options, { params: { username } }); + } + /** + * Returns a variety of information about one or more users specified by their usernames. + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by + * + * OAuth2 scope: `users.read`, `tweet.read` + */ + usersByUsernames(usernames, options = {}) { + usernames = Array.isArray(usernames) ? usernames.join(',') : usernames; + return this.get('users/by', { ...options, usernames }); + } + async followers(userId, options = {}) { + const { asPaginator, ...parameters } = options; + const params = { id: userId }; + if (!asPaginator) { + return this.get('users/:id/followers', parameters, { params }); + } + const initialRq = await this.get('users/:id/followers', parameters, { fullResponse: true, params }); + return new user_paginator_v2_1.UserFollowersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: parameters, + sharedParams: params, + }); + } + async following(userId, options = {}) { + const { asPaginator, ...parameters } = options; + const params = { id: userId }; + if (!asPaginator) { + return this.get('users/:id/following', parameters, { params }); + } + const initialRq = await this.get('users/:id/following', parameters, { fullResponse: true, params }); + return new user_paginator_v2_1.UserFollowingV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: parameters, + sharedParams: params, + }); + } + /** + * Allows you to get information about a user’s liked Tweets. + * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets + */ + async userLikedTweets(userId, options = {}) { + const params = { id: userId }; + const initialRq = await this.get('users/:id/liked_tweets', options, { fullResponse: true, params }); + return new paginators_1.TweetV2UserLikedTweetsPaginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns a list of users who are blocked by the authenticating user. + * https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking + */ + async userBlockingUsers(userId, options = {}) { + const params = { id: userId }; + const initialRq = await this.get('users/:id/blocking', options, { fullResponse: true, params }); + return new user_paginator_v2_1.UserBlockingUsersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns a list of users who are muted by the authenticating user. + * https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting + */ + async userMutingUsers(userId, options = {}) { + const params = { id: userId }; + const initialRq = await this.get('users/:id/muting', options, { fullResponse: true, params }); + return new user_paginator_v2_1.UserMutingUsersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /* Lists */ + /** + * Returns the details of a specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id + */ + list(id, options = {}) { + return this.get('lists/:id', options, { params: { id } }); + } + /** + * Returns all Lists owned by the specified user. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists + */ + async listsOwned(userId, options = {}) { + const params = { id: userId }; + const initialRq = await this.get('users/:id/owned_lists', options, { fullResponse: true, params }); + return new paginators_1.UserOwnedListsV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns all Lists a specified user is a member of. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships + */ + async listMemberships(userId, options = {}) { + const params = { id: userId }; + const initialRq = await this.get('users/:id/list_memberships', options, { fullResponse: true, params }); + return new paginators_1.UserListMembershipsV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns all Lists a specified user follows. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists + */ + async listFollowed(userId, options = {}) { + const params = { id: userId }; + const initialRq = await this.get('users/:id/followed_lists', options, { fullResponse: true, params }); + return new paginators_1.UserListFollowedV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns a list of Tweets from the specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets + */ + async listTweets(listId, options = {}) { + const params = { id: listId }; + const initialRq = await this.get('lists/:id/tweets', options, { fullResponse: true, params }); + return new paginators_1.TweetV2ListTweetsPaginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns a list of users who are members of the specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-lists-id-members + */ + async listMembers(listId, options = {}) { + const params = { id: listId }; + const initialRq = await this.get('lists/:id/members', options, { fullResponse: true, params }); + return new user_paginator_v2_1.UserListMembersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /** + * Returns a list of users who are followers of the specified List. + * https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers + */ + async listFollowers(listId, options = {}) { + const params = { id: listId }; + const initialRq = await this.get('lists/:id/followers', options, { fullResponse: true, params }); + return new user_paginator_v2_1.UserListFollowersV2Paginator({ + realData: initialRq.data, + rateLimit: initialRq.rateLimit, + instance: this, + queryParams: { ...options }, + sharedParams: params, + }); + } + /* Spaces */ + /** + * Get a single space by ID. + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + space(spaceId, options = {}) { + return this.get('spaces/:id', options, { params: { id: spaceId } }); + } + /** + * Get spaces using their IDs. + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + spaces(spaceIds, options = {}) { + return this.get('spaces', { ids: spaceIds, ...options }); + } + /** + * Get spaces using their creator user ID(s). (no pagination available) + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-by-creator-ids + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + spacesByCreators(creatorIds, options = {}) { + return this.get('spaces/by/creator_ids', { user_ids: creatorIds, ...options }); + } + /** + * Search through spaces using multiple params. (no pagination available) + * https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search + */ + searchSpaces(options) { + return this.get('spaces/search', options); + } + /** + * Returns a list of user who purchased a ticket to the requested Space. + * You must authenticate the request using the Access Token of the creator of the requested Space. + * + * **OAuth 2.0 Access Token required** + * + * https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-buyers + * + * OAuth2 scopes: `tweet.read`, `users.read`, `space.read`. + */ + spaceBuyers(spaceId, options = {}) { + return this.get('spaces/:id/buyers', options, { params: { id: spaceId } }); + } + searchStream({ autoConnect, ...options } = {}) { + return this.getStream('tweets/search/stream', options, { payloadIsError: helpers_1.isTweetStreamV2ErrorPayload, autoConnect }); + } + /** + * Return a list of rules currently active on the streaming endpoint, either as a list or individually. + * https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream-rules + */ + streamRules(options = {}) { + return this.get('tweets/search/stream/rules', options); + } + updateStreamRules(options, query = {}) { + return this.post('tweets/search/stream/rules', options, { query }); + } + sampleStream({ autoConnect, ...options } = {}) { + return this.getStream('tweets/sample/stream', options, { payloadIsError: helpers_1.isTweetStreamV2ErrorPayload, autoConnect }); + } + /* Batch compliance */ + /** + * Returns a list of recent compliance jobs. + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs + */ + complianceJobs(options) { + return this.get('compliance/jobs', options); + } + /** + * Get a single compliance job with the specified ID. + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id + */ + complianceJob(jobId) { + return this.get('compliance/jobs/:id', undefined, { params: { id: jobId } }); + } + /** + * Creates a new compliance job for Tweet IDs or user IDs, send your file, await result and parse it into an array. + * You can run one batch job at a time. Returns the created job, but **not the job result!**. + * + * You can obtain the result (**after job is completed**) with `.complianceJobResult`. + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs + */ + async sendComplianceJob(jobParams) { + const job = await this.post('compliance/jobs', { type: jobParams.type, name: jobParams.name }); + // Send the IDs + const rawIdsBody = jobParams.ids instanceof Buffer ? jobParams.ids : Buffer.from(jobParams.ids.join('\n')); + // Upload the IDs + await this.put(job.data.upload_url, rawIdsBody, { + forceBodyMode: 'raw', + enableAuth: false, + headers: { 'Content-Type': 'text/plain' }, + prefix: '', + }); + return job; + } + /** + * Get the result of a running or completed job, obtained through `.complianceJob`, `.complianceJobs` or `.sendComplianceJob`. + * If job is still running (`in_progress`), it will await until job is completed. **This could be quite long!** + * https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs + */ + async complianceJobResult(job) { + let runningJob = job; + while (runningJob.status !== 'complete') { + if (runningJob.status === 'expired' || runningJob.status === 'failed') { + throw new Error('Job failed to be completed.'); + } + await new Promise(resolve => setTimeout(resolve, 3500)); + runningJob = (await this.complianceJob(job.id)).data; + } + // Download and parse result + const result = await this.get(job.download_url, undefined, { + enableAuth: false, + prefix: '', + }); + return result + .trim() + .split('\n') + .filter(line => line) + .map(line => JSON.parse(line)); + } +} +exports.default = TwitterApiv2ReadOnly; diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.d.ts new file mode 100644 index 00000000..d0ae6206 --- /dev/null +++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.d.ts @@ -0,0 +1,187 @@ +import TwitterApiv2ReadOnly from './client.v2.read'; +import type { ListCreateV2Params, ListCreateV2Result, ListDeleteV2Result, ListFollowV2Result, ListMemberV2Result, ListPinV2Result, ListUpdateV2Params, ListUpdateV2Result, TweetV2DeleteTweetResult, SendTweetV2Params, TweetV2HideReplyResult, TweetV2LikeResult, TweetV2PostTweetResult, TweetV2RetweetResult, UserV2BlockResult, UserV2FollowResult, UserV2MuteResult, UserV2UnfollowResult, TweetV2BookmarkResult } from '../types'; +import TwitterApiv2LabsReadWrite from '../v2-labs/client.v2.labs.write'; +/** + * Base Twitter v2 client with read/write rights. + */ +export default class TwitterApiv2ReadWrite extends TwitterApiv2ReadOnly { + protected _prefix: string; + protected _labs?: TwitterApiv2LabsReadWrite; + /** + * Get a client with only read rights. + */ + get readOnly(): TwitterApiv2ReadOnly; + /** + * Get a client for v2 labs endpoints. + */ + get labs(): TwitterApiv2LabsReadWrite; + /** + * Hides or unhides a reply to a Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden + */ + hideReply(tweetId: string, makeHidden: boolean): Promise; + /** + * Causes the user ID identified in the path parameter to Like the target Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-user_id-likes + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + like(loggedUserId: string, targetTweetId: string): Promise; + /** + * Allows a user or authenticated user ID to unlike a Tweet. + * The request succeeds with no action when the user sends a request to a user they're not liking the Tweet or have already unliked the Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unlike(loggedUserId: string, targetTweetId: string): Promise; + /** + * Causes the user ID identified in the path parameter to Retweet the target Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + retweet(loggedUserId: string, targetTweetId: string): Promise; + /** + * Allows a user or authenticated user ID to remove the Retweet of a Tweet. + * The request succeeds with no action when the user sends a request to a user they're not Retweeting the Tweet or have already removed the Retweet of. + * https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unretweet(loggedUserId: string, targetTweetId: string): Promise; + /** + * Creates a Tweet on behalf of an authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + tweet(status: string, payload?: Partial): Promise; + tweet(payload: SendTweetV2Params): Promise; + /** + * Reply to a Tweet on behalf of an authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + reply(status: string, toTweetId: string, payload?: Partial): Promise; + /** + * Quote an existing Tweet on behalf of an authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + quote(status: string, quotedTweetId: string, payload?: Partial): Promise; + /** + * Post a series of tweets. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + tweetThread(tweets: (SendTweetV2Params | string)[]): Promise; + /** + * Allows a user or authenticated user ID to delete a Tweet + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id + */ + deleteTweet(tweetId: string): Promise; + /** + * Causes the user ID of an authenticated user identified in the path parameter to Bookmark the target Tweet provided in the request body. + * https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks + * + * OAuth2 scopes: `users.read` `tweet.read` `bookmark.write` + */ + bookmark(tweetId: string): Promise; + /** + * Allows a user or authenticated user ID to remove a Bookmark of a Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id + * + * OAuth2 scopes: `users.read` `tweet.read` `bookmark.write` + */ + deleteBookmark(tweetId: string): Promise; + /** + * Allows a user ID to follow another user. + * If the target user does not have public Tweets, this endpoint will send a follow request. + * https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/post-users-source_user_id-following + * + * OAuth2 scope: `follows.write` + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + follow(loggedUserId: string, targetUserId: string): Promise; + /** + * Allows a user ID to unfollow another user. + * https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_id-following + * + * OAuth2 scope: `follows.write` + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unfollow(loggedUserId: string, targetUserId: string): Promise; + /** + * Causes the user (in the path) to block the target user. + * The user (in the path) must match the user context authorizing the request. + * https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/post-users-user_id-blocking + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + block(loggedUserId: string, targetUserId: string): Promise; + /** + * Allows a user or authenticated user ID to unblock another user. + * https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/delete-users-user_id-blocking + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unblock(loggedUserId: string, targetUserId: string): Promise; + /** + * Allows an authenticated user ID to mute the target user. + * https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + mute(loggedUserId: string, targetUserId: string): Promise; + /** + * Allows an authenticated user ID to unmute the target user. + * The request succeeds with no action when the user sends a request to a user they're not muting or have already unmuted. + * https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unmute(loggedUserId: string, targetUserId: string): Promise; + /** + * Creates a new list for the authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists + */ + createList(options: ListCreateV2Params): Promise; + /** + * Updates the specified list. The authenticated user must own the list to be able to update it. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id + */ + updateList(listId: string, options?: ListUpdateV2Params): Promise; + /** + * Deletes the specified list. The authenticated user must own the list to be able to destroy it. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id + */ + removeList(listId: string): Promise; + /** + * Adds a member to a list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists-id-members + */ + addListMember(listId: string, userId: string): Promise; + /** + * Remember a member to a list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id-members-user_id + */ + removeListMember(listId: string, userId: string): Promise; + /** + * Subscribes the authenticated user to the specified list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-users-id-followed-lists + */ + subscribeToList(loggedUserId: string, listId: string): Promise; + /** + * Unsubscribes the authenticated user to the specified list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-users-id-followed-lists-list_id + */ + unsubscribeOfList(loggedUserId: string, listId: string): Promise; + /** + * Enables the authenticated user to pin a List. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-users-id-pinned-lists + */ + pinList(loggedUserId: string, listId: string): Promise; + /** + * Enables the authenticated user to unpin a List. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-users-id-pinned-lists-list_id + */ + unpinList(loggedUserId: string, listId: string): Promise; +} diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.js b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.js new file mode 100644 index 00000000..4797b06e --- /dev/null +++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/client.v2.write.js @@ -0,0 +1,296 @@ +"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_read_1 = __importDefault(require("./client.v2.read")); +const client_v2_labs_write_1 = __importDefault(require("../v2-labs/client.v2.labs.write")); +/** + * Base Twitter v2 client with read/write rights. + */ +class TwitterApiv2ReadWrite extends client_v2_read_1.default { + constructor() { + super(...arguments); + this._prefix = globals_1.API_V2_PREFIX; + } + /* Sub-clients */ + /** + * Get a client with only read rights. + */ + get readOnly() { + return this; + } + /** + * Get a client for v2 labs endpoints. + */ + get labs() { + if (this._labs) + return this._labs; + return this._labs = new client_v2_labs_write_1.default(this); + } + /* Tweets */ + /** + * Hides or unhides a reply to a Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden + */ + hideReply(tweetId, makeHidden) { + return this.put('tweets/:id/hidden', { hidden: makeHidden }, { params: { id: tweetId } }); + } + /** + * Causes the user ID identified in the path parameter to Like the target Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-user_id-likes + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + like(loggedUserId, targetTweetId) { + return this.post('users/:id/likes', { tweet_id: targetTweetId }, { params: { id: loggedUserId } }); + } + /** + * Allows a user or authenticated user ID to unlike a Tweet. + * The request succeeds with no action when the user sends a request to a user they're not liking the Tweet or have already unliked the Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unlike(loggedUserId, targetTweetId) { + return this.delete('users/:id/likes/:tweet_id', undefined, { + params: { id: loggedUserId, tweet_id: targetTweetId }, + }); + } + /** + * Causes the user ID identified in the path parameter to Retweet the target Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + retweet(loggedUserId, targetTweetId) { + return this.post('users/:id/retweets', { tweet_id: targetTweetId }, { params: { id: loggedUserId } }); + } + /** + * Allows a user or authenticated user ID to remove the Retweet of a Tweet. + * The request succeeds with no action when the user sends a request to a user they're not Retweeting the Tweet or have already removed the Retweet of. + * https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unretweet(loggedUserId, targetTweetId) { + return this.delete('users/:id/retweets/:tweet_id', undefined, { + params: { id: loggedUserId, tweet_id: targetTweetId }, + }); + } + tweet(status, payload = {}) { + if (typeof status === 'object') { + payload = status; + } + else { + payload = { text: status, ...payload }; + } + return this.post('tweets', payload); + } + /** + * Reply to a Tweet on behalf of an authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + reply(status, toTweetId, payload = {}) { + var _a; + const reply = { in_reply_to_tweet_id: toTweetId, ...(_a = payload.reply) !== null && _a !== void 0 ? _a : {} }; + return this.post('tweets', { text: status, ...payload, reply }); + } + /** + * Quote an existing Tweet on behalf of an authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + quote(status, quotedTweetId, payload = {}) { + return this.tweet(status, { ...payload, quote_tweet_id: quotedTweetId }); + } + /** + * Post a series of tweets. + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets + */ + async tweetThread(tweets) { + var _a, _b; + const postedTweets = []; + for (const tweet of tweets) { + // Retrieve the last sent tweet + const lastTweet = postedTweets.length ? postedTweets[postedTweets.length - 1] : null; + // Build the tweet query params + const queryParams = { ...(typeof tweet === 'string' ? ({ text: tweet }) : tweet) }; + // Reply to an existing tweet if needed + const inReplyToId = lastTweet ? lastTweet.data.id : (_a = queryParams.reply) === null || _a === void 0 ? void 0 : _a.in_reply_to_tweet_id; + const status = (_b = queryParams.text) !== null && _b !== void 0 ? _b : ''; + if (inReplyToId) { + postedTweets.push(await this.reply(status, inReplyToId, queryParams)); + } + else { + postedTweets.push(await this.tweet(status, queryParams)); + } + } + return postedTweets; + } + /** + * Allows a user or authenticated user ID to delete a Tweet + * https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id + */ + deleteTweet(tweetId) { + return this.delete('tweets/:id', undefined, { + params: { + id: tweetId, + }, + }); + } + /* Bookmarks */ + /** + * Causes the user ID of an authenticated user identified in the path parameter to Bookmark the target Tweet provided in the request body. + * https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks + * + * OAuth2 scopes: `users.read` `tweet.read` `bookmark.write` + */ + async bookmark(tweetId) { + const user = await this.getCurrentUserV2Object(); + return this.post('users/:id/bookmarks', { tweet_id: tweetId }, { params: { id: user.data.id } }); + } + /** + * Allows a user or authenticated user ID to remove a Bookmark of a Tweet. + * https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id + * + * OAuth2 scopes: `users.read` `tweet.read` `bookmark.write` + */ + async deleteBookmark(tweetId) { + const user = await this.getCurrentUserV2Object(); + return this.delete('users/:id/bookmarks/:tweet_id', undefined, { params: { id: user.data.id, tweet_id: tweetId } }); + } + /* Users */ + /** + * Allows a user ID to follow another user. + * If the target user does not have public Tweets, this endpoint will send a follow request. + * https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/post-users-source_user_id-following + * + * OAuth2 scope: `follows.write` + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + follow(loggedUserId, targetUserId) { + return this.post('users/:id/following', { target_user_id: targetUserId }, { params: { id: loggedUserId } }); + } + /** + * Allows a user ID to unfollow another user. + * https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_id-following + * + * OAuth2 scope: `follows.write` + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unfollow(loggedUserId, targetUserId) { + return this.delete('users/:source_user_id/following/:target_user_id', undefined, { + params: { source_user_id: loggedUserId, target_user_id: targetUserId }, + }); + } + /** + * Causes the user (in the path) to block the target user. + * The user (in the path) must match the user context authorizing the request. + * https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/post-users-user_id-blocking + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + block(loggedUserId, targetUserId) { + return this.post('users/:id/blocking', { target_user_id: targetUserId }, { params: { id: loggedUserId } }); + } + /** + * Allows a user or authenticated user ID to unblock another user. + * https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/delete-users-user_id-blocking + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unblock(loggedUserId, targetUserId) { + return this.delete('users/:source_user_id/blocking/:target_user_id', undefined, { + params: { source_user_id: loggedUserId, target_user_id: targetUserId }, + }); + } + /** + * Allows an authenticated user ID to mute the target user. + * https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + mute(loggedUserId, targetUserId) { + return this.post('users/:id/muting', { target_user_id: targetUserId }, { params: { id: loggedUserId } }); + } + /** + * Allows an authenticated user ID to unmute the target user. + * The request succeeds with no action when the user sends a request to a user they're not muting or have already unmuted. + * https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting + * + * **Note**: You must specify the currently logged user ID ; you can obtain it through v1.1 API. + */ + unmute(loggedUserId, targetUserId) { + return this.delete('users/:source_user_id/muting/:target_user_id', undefined, { + params: { source_user_id: loggedUserId, target_user_id: targetUserId }, + }); + } + /* Lists */ + /** + * Creates a new list for the authenticated user. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists + */ + createList(options) { + return this.post('lists', options); + } + /** + * Updates the specified list. The authenticated user must own the list to be able to update it. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id + */ + updateList(listId, options = {}) { + return this.put('lists/:id', options, { params: { id: listId } }); + } + /** + * Deletes the specified list. The authenticated user must own the list to be able to destroy it. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id + */ + removeList(listId) { + return this.delete('lists/:id', undefined, { params: { id: listId } }); + } + /** + * Adds a member to a list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists-id-members + */ + addListMember(listId, userId) { + return this.post('lists/:id/members', { user_id: userId }, { params: { id: listId } }); + } + /** + * Remember a member to a list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id-members-user_id + */ + removeListMember(listId, userId) { + return this.delete('lists/:id/members/:user_id', undefined, { params: { id: listId, user_id: userId } }); + } + /** + * Subscribes the authenticated user to the specified list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-users-id-followed-lists + */ + subscribeToList(loggedUserId, listId) { + return this.post('users/:id/followed_lists', { list_id: listId }, { params: { id: loggedUserId } }); + } + /** + * Unsubscribes the authenticated user to the specified list. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-users-id-followed-lists-list_id + */ + unsubscribeOfList(loggedUserId, listId) { + return this.delete('users/:id/followed_lists/:list_id', undefined, { params: { id: loggedUserId, list_id: listId } }); + } + /** + * Enables the authenticated user to pin a List. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-users-id-pinned-lists + */ + pinList(loggedUserId, listId) { + return this.post('users/:id/pinned_lists', { list_id: listId }, { params: { id: loggedUserId } }); + } + /** + * Enables the authenticated user to unpin a List. + * https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-users-id-pinned-lists-list_id + */ + unpinList(loggedUserId, listId) { + return this.delete('users/:id/pinned_lists/:list_id', undefined, { params: { id: loggedUserId, list_id: listId } }); + } +} +exports.default = TwitterApiv2ReadWrite; diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.d.ts b/social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.d.ts new file mode 100644 index 00000000..639f9ebf --- /dev/null +++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.d.ts @@ -0,0 +1,82 @@ +import type { ApiV2Includes, ListV2, SpaceV2, TweetV2, UserV2 } from '../types'; +export declare type TTwitterV2IncludesResult = { + includes?: ApiV2Includes; +}; +/** + * Provide helpers for `.includes` of a v2 API result. + * Needed expansions for a method to work are specified (*`like this`*). + */ +export declare class TwitterV2IncludesHelper implements ApiV2Includes { + protected result: TTwitterV2IncludesResult; + constructor(result: TTwitterV2IncludesResult); + get tweets(): TweetV2[]; + static tweets(result: TTwitterV2IncludesResult): TweetV2[]; + tweetById(id: string): TweetV2 | undefined; + static tweetById(result: TTwitterV2IncludesResult, id: string): TweetV2 | undefined; + /** Retweet associated with the given tweet (*`referenced_tweets.id`*) */ + retweet(tweet: TweetV2): TweetV2 | undefined; + /** Retweet associated with the given tweet (*`referenced_tweets.id`*) */ + static retweet(result: TTwitterV2IncludesResult, tweet: TweetV2): TweetV2 | undefined; + /** Quoted tweet associated with the given tweet (*`referenced_tweets.id`*) */ + quote(tweet: TweetV2): TweetV2 | undefined; + /** Quoted tweet associated with the given tweet (*`referenced_tweets.id`*) */ + static quote(result: TTwitterV2IncludesResult, tweet: TweetV2): TweetV2 | undefined; + /** Tweet whose has been answered by the given tweet (*`referenced_tweets.id`*) */ + repliedTo(tweet: TweetV2): TweetV2 | undefined; + /** Tweet whose has been answered by the given tweet (*`referenced_tweets.id`*) */ + static repliedTo(result: TTwitterV2IncludesResult, tweet: TweetV2): TweetV2 | undefined; + /** Tweet author user object of the given tweet (*`author_id`* or *`referenced_tweets.id.author_id`*) */ + author(tweet: TweetV2): UserV2 | undefined; + /** Tweet author user object of the given tweet (*`author_id`* or *`referenced_tweets.id.author_id`*) */ + static author(result: TTwitterV2IncludesResult, tweet: TweetV2): UserV2 | undefined; + /** Tweet author user object of the tweet answered by the given tweet (*`in_reply_to_user_id`*) */ + repliedToAuthor(tweet: TweetV2): UserV2 | undefined; + /** Tweet author user object of the tweet answered by the given tweet (*`in_reply_to_user_id`*) */ + static repliedToAuthor(result: TTwitterV2IncludesResult, tweet: TweetV2): UserV2 | undefined; + get users(): UserV2[]; + static users(result: TTwitterV2IncludesResult): UserV2[]; + userById(id: string): UserV2 | undefined; + static userById(result: TTwitterV2IncludesResult, id: string): UserV2 | undefined; + /** Pinned tweet of the given user (*`pinned_tweet_id`*) */ + pinnedTweet(user: UserV2): TweetV2 | undefined; + /** Pinned tweet of the given user (*`pinned_tweet_id`*) */ + static pinnedTweet(result: TTwitterV2IncludesResult, user: UserV2): TweetV2 | undefined; + get media(): import("../types").MediaObjectV2[]; + static media(result: TTwitterV2IncludesResult): import("../types").MediaObjectV2[]; + /** Medias associated with the given tweet (*`attachments.media_keys`*) */ + medias(tweet: TweetV2): import("../types").MediaObjectV2[]; + /** Medias associated with the given tweet (*`attachments.media_keys`*) */ + static medias(result: TTwitterV2IncludesResult, tweet: TweetV2): import("../types").MediaObjectV2[]; + get polls(): import("../types").PollV2[]; + static polls(result: TTwitterV2IncludesResult): import("../types").PollV2[]; + /** Poll associated with the given tweet (*`attachments.poll_ids`*) */ + poll(tweet: TweetV2): import("../types").PollV2 | undefined; + /** Poll associated with the given tweet (*`attachments.poll_ids`*) */ + static poll(result: TTwitterV2IncludesResult, tweet: TweetV2): import("../types").PollV2 | undefined; + get places(): import("../types").PlaceV2[]; + static places(result: TTwitterV2IncludesResult): import("../types").PlaceV2[]; + /** Place associated with the given tweet (*`geo.place_id`*) */ + place(tweet: TweetV2): import("../types").PlaceV2 | undefined; + /** Place associated with the given tweet (*`geo.place_id`*) */ + static place(result: TTwitterV2IncludesResult, tweet: TweetV2): import("../types").PlaceV2 | undefined; + /** List owner of the given list (*`owner_id`*) */ + listOwner(list: ListV2): UserV2 | undefined; + /** List owner of the given list (*`owner_id`*) */ + static listOwner(result: TTwitterV2IncludesResult, list: ListV2): UserV2 | undefined; + /** Creator of the given space (*`creator_id`*) */ + spaceCreator(space: SpaceV2): UserV2 | undefined; + /** Creator of the given space (*`creator_id`*) */ + static spaceCreator(result: TTwitterV2IncludesResult, space: SpaceV2): UserV2 | undefined; + /** Current hosts of the given space (*`host_ids`*) */ + spaceHosts(space: SpaceV2): UserV2[]; + /** Current hosts of the given space (*`host_ids`*) */ + static spaceHosts(result: TTwitterV2IncludesResult, space: SpaceV2): UserV2[]; + /** Current speakers of the given space (*`speaker_ids`*) */ + spaceSpeakers(space: SpaceV2): UserV2[]; + /** Current speakers of the given space (*`speaker_ids`*) */ + static spaceSpeakers(result: TTwitterV2IncludesResult, space: SpaceV2): UserV2[]; + /** Current invited users of the given space (*`invited_user_ids`*) */ + spaceInvitedUsers(space: SpaceV2): UserV2[]; + /** Current invited users of the given space (*`invited_user_ids`*) */ + static spaceInvitedUsers(result: TTwitterV2IncludesResult, space: SpaceV2): UserV2[]; +} diff --git a/social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.js b/social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.js new file mode 100644 index 00000000..e4690cdd --- /dev/null +++ b/social/twitter/node_modules/twitter-api-v2/dist/v2/includes.v2.helper.js @@ -0,0 +1,211 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TwitterV2IncludesHelper = void 0; +/** + * Provide helpers for `.includes` of a v2 API result. + * Needed expansions for a method to work are specified (*`like this`*). + */ +class TwitterV2IncludesHelper { + constructor(result) { + this.result = result; + } + /* Tweets */ + get tweets() { + return TwitterV2IncludesHelper.tweets(this.result); + } + static tweets(result) { + var _a, _b; + return (_b = (_a = result.includes) === null || _a === void 0 ? void 0 : _a.tweets) !== null && _b !== void 0 ? _b : []; + } + tweetById(id) { + return TwitterV2IncludesHelper.tweetById(this.result, id); + } + static tweetById(result, id) { + return this.tweets(result).find(tweet => tweet.id === id); + } + /** Retweet associated with the given tweet (*`referenced_tweets.id`*) */ + retweet(tweet) { + return TwitterV2IncludesHelper.retweet(this.result, tweet); + } + /** Retweet associated with the given tweet (*`referenced_tweets.id`*) */ + static retweet(result, tweet) { + var _a; + const retweetIds = ((_a = tweet.referenced_tweets) !== null && _a !== void 0 ? _a : []) + .filter(ref => ref.type === 'retweeted') + .map(ref => ref.id); + return this.tweets(result).find(t => retweetIds.includes(t.id)); + } + /** Quoted tweet associated with the given tweet (*`referenced_tweets.id`*) */ + quote(tweet) { + return TwitterV2IncludesHelper.quote(this.result, tweet); + } + /** Quoted tweet associated with the given tweet (*`referenced_tweets.id`*) */ + static quote(result, tweet) { + var _a; + const quoteIds = ((_a = tweet.referenced_tweets) !== null && _a !== void 0 ? _a : []) + .filter(ref => ref.type === 'quoted') + .map(ref => ref.id); + return this.tweets(result).find(t => quoteIds.includes(t.id)); + } + /** Tweet whose has been answered by the given tweet (*`referenced_tweets.id`*) */ + repliedTo(tweet) { + return TwitterV2IncludesHelper.repliedTo(this.result, tweet); + } + /** Tweet whose has been answered by the given tweet (*`referenced_tweets.id`*) */ + static repliedTo(result, tweet) { + var _a; + const repliesIds = ((_a = tweet.referenced_tweets) !== null && _a !== void 0 ? _a : []) + .filter(ref => ref.type === 'replied_to') + .map(ref => ref.id); + return this.tweets(result).find(t => repliesIds.includes(t.id)); + } + /** Tweet author user object of the given tweet (*`author_id`* or *`referenced_tweets.id.author_id`*) */ + author(tweet) { + return TwitterV2IncludesHelper.author(this.result, tweet); + } + /** Tweet author user object of the given tweet (*`author_id`* or *`referenced_tweets.id.author_id`*) */ + static author(result, tweet) { + const authorId = tweet.author_id; + return authorId ? this.users(result).find(u => u.id === authorId) : undefined; + } + /** Tweet author user object of the tweet answered by the given tweet (*`in_reply_to_user_id`*) */ + repliedToAuthor(tweet) { + return TwitterV2IncludesHelper.repliedToAuthor(this.result, tweet); + } + /** Tweet author user object of the tweet answered by the given tweet (*`in_reply_to_user_id`*) */ + static repliedToAuthor(result, tweet) { + const inReplyUserId = tweet.in_reply_to_user_id; + return inReplyUserId ? this.users(result).find(u => u.id === inReplyUserId) : undefined; + } + /* Users */ + get users() { + return TwitterV2IncludesHelper.users(this.result); + } + static users(result) { + var _a, _b; + return (_b = (_a = result.includes) === null || _a === void 0 ? void 0 : _a.users) !== null && _b !== void 0 ? _b : []; + } + userById(id) { + return TwitterV2IncludesHelper.userById(this.result, id); + } + static userById(result, id) { + return this.users(result).find(u => u.id === id); + } + /** Pinned tweet of the given user (*`pinned_tweet_id`*) */ + pinnedTweet(user) { + return TwitterV2IncludesHelper.pinnedTweet(this.result, user); + } + /** Pinned tweet of the given user (*`pinned_tweet_id`*) */ + static pinnedTweet(result, user) { + return user.pinned_tweet_id ? this.tweets(result).find(t => t.id === user.pinned_tweet_id) : undefined; + } + /* Medias */ + get media() { + return TwitterV2IncludesHelper.media(this.result); + } + static media(result) { + var _a, _b; + return (_b = (_a = result.includes) === null || _a === void 0 ? void 0 : _a.media) !== null && _b !== void 0 ? _b : []; + } + /** Medias associated with the given tweet (*`attachments.media_keys`*) */ + medias(tweet) { + return TwitterV2IncludesHelper.medias(this.result, tweet); + } + /** Medias associated with the given tweet (*`attachments.media_keys`*) */ + static medias(result, tweet) { + var _a, _b; + const keys = (_b = (_a = tweet.attachments) === null || _a === void 0 ? void 0 : _a.media_keys) !== null && _b !== void 0 ? _b : []; + return this.media(result).filter(m => keys.includes(m.media_key)); + } + /* Polls */ + get polls() { + return TwitterV2IncludesHelper.polls(this.result); + } + static polls(result) { + var _a, _b; + return (_b = (_a = result.includes) === null || _a === void 0 ? void 0 : _a.polls) !== null && _b !== void 0 ? _b : []; + } + /** Poll associated with the given tweet (*`attachments.poll_ids`*) */ + poll(tweet) { + return TwitterV2IncludesHelper.poll(this.result, tweet); + } + /** Poll associated with the given tweet (*`attachments.poll_ids`*) */ + static poll(result, tweet) { + var _a, _b; + const pollIds = (_b = (_a = tweet.attachments) === null || _a === void 0 ? void 0 : _a.poll_ids) !== null && _b !== void 0 ? _b : []; + if (pollIds.length) { + const pollId = pollIds[0]; + return this.polls(result).find(p => p.id === pollId); + } + return undefined; + } + /* Places */ + get places() { + return TwitterV2IncludesHelper.places(this.result); + } + static places(result) { + var _a, _b; + return (_b = (_a = result.includes) === null || _a === void 0 ? void 0 : _a.places) !== null && _b !== void 0 ? _b : []; + } + /** Place associated with the given tweet (*`geo.place_id`*) */ + place(tweet) { + return TwitterV2IncludesHelper.place(this.result, tweet); + } + /** Place associated with the given tweet (*`geo.place_id`*) */ + static place(result, tweet) { + var _a; + const placeId = (_a = tweet.geo) === null || _a === void 0 ? void 0 : _a.place_id; + return placeId ? this.places(result).find(p => p.id === placeId) : undefined; + } + /* Lists */ + /** List owner of the given list (*`owner_id`*) */ + listOwner(list) { + return TwitterV2IncludesHelper.listOwner(this.result, list); + } + /** List owner of the given list (*`owner_id`*) */ + static listOwner(result, list) { + const creatorId = list.owner_id; + return creatorId ? this.users(result).find(p => p.id === creatorId) : undefined; + } + /* Spaces */ + /** Creator of the given space (*`creator_id`*) */ + spaceCreator(space) { + return TwitterV2IncludesHelper.spaceCreator(this.result, space); + } + /** Creator of the given space (*`creator_id`*) */ + static spaceCreator(result, space) { + const creatorId = space.creator_id; + return creatorId ? this.users(result).find(p => p.id === creatorId) : undefined; + } + /** Current hosts of the given space (*`host_ids`*) */ + spaceHosts(space) { + return TwitterV2IncludesHelper.spaceHosts(this.result, space); + } + /** Current hosts of the given space (*`host_ids`*) */ + static spaceHosts(result, space) { + var _a; + const hostIds = (_a = space.host_ids) !== null && _a !== void 0 ? _a : []; + return this.users(result).filter(u => hostIds.includes(u.id)); + } + /** Current speakers of the given space (*`speaker_ids`*) */ + spaceSpeakers(space) { + return TwitterV2IncludesHelper.spaceSpeakers(this.result, space); + } + /** Current speakers of the given space (*`speaker_ids`*) */ + static spaceSpeakers(result, space) { + var _a; + const speakerIds = (_a = space.speaker_ids) !== null && _a !== void 0 ? _a : []; + return this.users(result).filter(u => speakerIds.includes(u.id)); + } + /** Current invited users of the given space (*`invited_user_ids`*) */ + spaceInvitedUsers(space) { + return TwitterV2IncludesHelper.spaceInvitedUsers(this.result, space); + } + /** Current invited users of the given space (*`invited_user_ids`*) */ + static spaceInvitedUsers(result, space) { + var _a; + const invitedUserIds = (_a = space.invited_user_ids) !== null && _a !== void 0 ? _a : []; + return this.users(result).filter(u => invitedUserIds.includes(u.id)); + } +} +exports.TwitterV2IncludesHelper = TwitterV2IncludesHelper;