Giter Site home page Giter Site logo

plhery / node-twitter-api-v2 Goto Github PK

View Code? Open in Web Editor NEW
1.2K 13.0 175.0 4.24 MB

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

Home Page: https://www.npmjs.com/package/twitter-api-v2

License: Apache License 2.0

TypeScript 99.64% JavaScript 0.36%
twitter-api npm-package streaming-api

node-twitter-api-v2's Introduction

Twitter API v2

Version badge Checks badge Package size badge

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

Main maintainer: @alkihis - Buy Me A Coffee

Important Note

Twitter will significantly reduce its API capabilities by end of April (see this thread).

This change has major implications, and as a result, this library may no longer be maintained.

We are disappointed and discouraged by the recent turn of events at Twitter since the takeover by Elon Musk. We are saddened to see that much of the hard work of the past few years on the API, led by an amazing team including @andypiper, has been shelved.

For a more detailed explanation, please see this discussion.

Highlights

Ready for v2 and good ol' v1.1 Twitter API

Light: No dependencies, 23kb minified+gzipped

Bundled types for request parameters and responses

Streaming support

Pagination utils

User-context authentication with OAuth2

Media upload helpers

How to use

Install it through your favorite package manager:

yarn add twitter-api-v2
# or
npm i twitter-api-v2

Here's a quick example of usage:

import { TwitterApi } from 'twitter-api-v2';

// Instantiate with desired auth type (here's Bearer v2 auth)
const twitterClient = new TwitterApi('<YOUR_APP_USER_TOKEN>');

// Tell typescript it's a readonly app
const readOnlyClient = twitterClient.readOnly;

// Play with the built in methods
const user = await readOnlyClient.v2.userByUsername('plhery');
await twitterClient.v2.tweet('Hello, this is a test.');
// You can upload media easily!
await twitterClient.v1.uploadMedia('./big-buck-bunny.mp4');

Why?

Sometimes, you just want to quickly bootstrap an application using the Twitter API. Even though there are a lot of libraries available on the JavaScript ecosystem, they usually just provide wrappers around HTTP methods, and some of them are bloated with many dependencies.

twitter-api-v2 is meant to provide full endpoint wrapping, from method name to response data, using descriptive typings for read/write/DMs rights, request parameters and response payload.

A small feature comparison with other libs:

Package API version(s) Response typings Media helpers Pagination Subdeps Size (gzip) Install size
twitter-api-v2 v1.1, v2, labs 0 ~23 kB twitter-api-v2 install size badge
twit v1.1 51 ~214.5 kB twit install size badge
twitter v1.1 50 ~182.1 kB twitter install size badge
twitter-lite v1.1, v2 4 ~5.3 kB twitter-lite install size badge
twitter-v2 v2 7 ~4.5 kB twitter-v2 install size badge

Features

Here's everything twitter-api-v2 can do:

Basics:

  • Support for v1.1 and v2 of Twitter API
  • Make signed HTTP requests to Twitter with every auth type: OAuth 1.0a, OAuth2 (even brand new user context OAuth2!) and Basic HTTP Authorization
  • Helpers for numerous HTTP request methods (GET, POST, PUT, DELETE and PATCH), that handle query string parse & format, automatic body formatting and more
  • High-class support for stream endpoints, with easy data consumption and auto-reconnect on stream errors

Request helpers:

  • Automatic paginator for endpoints like user and tweet timelines, allowing payload consumption with modern asynchronous iterators until your rate-limit is hit
  • Convenient methods for authentication - generate auth links and ask for tokens to your users
  • Media upload with API v1.1, including long video & subtitles support, automatic media type detection, chunked upload and support for concurrent uploads
  • Dedicated methods that wraps API v1.1 & v2 endpoints, with typed arguments and fully typed responses
  • Typed errors, meaningful error messages, error enumerations for both v1.1 and v2

Type-safe first:

  • Typings for tweet, user, media entities (and more) are bundled!
  • Type-safe wrapping of dedicated methods in 3 right level: DM/Read-write/Read-only (just like Twitter API do!) - you can declare a read-only client - you will only see the methods associated with read-only endpoints

And last but not least, fully powered by native Promises.

Documentation

Learn how to use the full potential of twitter-api-v2.

Plugins

Official plugins for twitter-api-v2:

See how to use plugins here.

node-twitter-api-v2's People

Contributors

abdullah-malik avatar alkihis avatar auroradysis avatar deadcoder0904 avatar dependabot-preview[bot] avatar haplifeman avatar jamashita avatar jmmwangi007 avatar jonah-saltzman avatar lima-eduardo avatar machinaexdeo avatar melvinmcrn avatar nathansmithbz avatar nolbuzanis avatar noname202 avatar orimdominic avatar petrbela avatar plhery avatar rare0b avatar roncli avatar ry0y4n avatar sebastianspiegel avatar shubhamkushwah avatar thelebdev avatar viniciuskneves avatar wass08 avatar weswalla avatar will0101 avatar will2022 avatar yangpten avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-twitter-api-v2's Issues

Explain rate limiting

From the documentation is not clear how this library handles rate-limiting.

What happens if I try to fetch too much data, too fast. Will it internally pause until it's safe to continue? So, for me -as a library user- will be transparent and I'll get my data eventually?

Thanks!

Remove or Document id keys

id_str does not equal to id, probably some kind of casting malfunction:

console.log(+"1436278513418522630")
> 1436278513418522600

It could cause some serious harm due to the problem's nature. Please fix or document it!

Minimal working example -- await is only valid in async function

Hi, I'm only lightly familiar with Promises and always get confused by them. Realize that as noted in the docs all return types are wrapped inside Promises. However, when I try to run any of the short examples (verbatim) I get hit with the await is only valid in async function error.

Was wondering if you had any minimal example that would work or resolve the Promise? I tried a few paradigms (from Google) but none seemed to work. Thanks.

TwitterApi is not a constructor

I have the same issue as in #17 but with version 1.1.1 and node 16.5.0.

import TwitterApi from 'twitter-api-v2';
const twitterClient = new TwitterApi('<YOUR_APP_USER_TOKEN>');

Getting this error when trying to execute:

const twitterClient = new TwitterApi('<YOUR_APP_USER_TOKEN>');
                      ^

TypeError: TwitterApi is not a constructor
    at file:///D:/Ohad/Projects/Twitter/Source/program.js:4:23
    at ModuleJob.run (node:internal/modules/esm/module_job:183:25)
    at async Loader.import (node:internal/modules/esm/loader:178:24)
    at async Object.loadESM (node:internal/process/esm_loader:68:5)
    at async handleMainPromise (node:internal/modules/run_main:63:12)

"TwitterApi is not a constructor" error

I'm using twitter-api-v2 0.3.0 with this code:

const TwitterApi = require('twitter-api-v2')

const twitter = new TwitterApi(process.env.TWT_TOKEN)

But i get this problem when trying to execute:

const twitter = new TwitterApi(process.env.TWT_TOKEN)
                ^

TypeError: TwitterApi is not a constructor
    at Object.<anonymous> (/mnt/d/Projects/bots/twt/src/index.js:3:17)
    at Module._compile (node:internal/modules/cjs/loader:1102:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1131:10)
    at Module.load (node:internal/modules/cjs/loader:967:32)
    at Function.Module._load (node:internal/modules/cjs/loader:807:14)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47

If there's anything more needed for that issue, just ask me!

Not able to use .post method

Hi, I'm trying to upload an image using twitterApi.post("media/upload.json", { media_data: data });
but this doesn't seem to be working and i'm getting a vague error in my terminal:

ApiRequestError: Request failed.
    at RequestHandlerHelper.createRequestError (/Users/fayd/Projects/Twack/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js:41:16)
    at ClientRequest.<anonymous> (/Users/fayd/Projects/Twack/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js:98:25)
    at ClientRequest.emit (events.js:375:28)
    at ClientRequest.emit (domain.js:470:12)
    at TLSSocket.socketErrorListener (_http_client.js:475:9)
    at TLSSocket.emit (events.js:375:28)
    at TLSSocket.emit (domain.js:470:12)
    at emitErrorNT (internal/streams/destroy.js:106:8)
    at emitErrorCloseNT (internal/streams/destroy.js:74:3)
    at processTicksAndRejections (internal/process/task_queues.js:82:21) {
  error: true,
  type: 'request',
  request: <ref *1> ClientRequest {
    _events: [Object: null prototype] {
      error: [Function (anonymous)],
      response: [Function (anonymous)]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    destroyed: false,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    _defaultKeepAlive: true,
    useChunkedEncodingByDefault: true,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: null,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: false,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: true,
      _SNICallback: null,
      servername: null,
      alpnProtocol: null,
      authorized: false,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 11,
      connecting: false,
      _hadError: true,
      _parent: null,
      _host: 'media',
      _readableState: [ReadableState],
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: [Array],
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: null,
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [Circular *1],
      [Symbol(res)]: [TLSWrap],
      [Symbol(verified)]: false,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 512,
      [Symbol(kHandle)]: null,
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object]
    },
    _header: 'POST /upload.json HTTP/1.1\r\n' +
      'x-user-agent: Node.twitter-api-v2\r\n' +
      'Authorization: OAuth oauth_consumer_key="faefaefaefaefae%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1629642186",oauth_token="feafeafaefae-faefae",oauth_version="1.0"\r\n' +
      'content-type: application/x-www-form-urlencoded;charset=UTF-8\r\n' +
      'content-length: 2768019\r\n' +
      'Host: media\r\n' +
      'Connection: close\r\n' +
      '\r\n',
    _keepAliveTimeout: 0,
    _onPendingData: [Function: noopPendingOutput],
    agent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 443,
      protocol: 'https:',
      options: [Object],
      requests: {},
      sockets: [Object],
      freeSockets: {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      scheduling: 'lifo',
      maxTotalSockets: Infinity,
      totalSocketCount: 1,
      maxCachedSessions: 100,
      _sessionCache: [Object],
      [Symbol(kCapture)]: false
    },
    socketPath: undefined,
    method: 'POST',
    maxHeaderSize: undefined,
    insecureHTTPParser: undefined,
    path: '/upload.json',
    _ended: false,
    res: null,
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    host: 'media',
    protocol: 'https:',
    [Symbol(kCapture)]: false,
    [Symbol(kNeedDrain)]: true,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      'x-user-agent': [Array],
      authorization: [Array],
      'content-type': [Array],
      'content-length': [Array],
      host: [Array]
    }
  },
  requestError: Error: getaddrinfo ENOTFOUND media
      at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:69:26) {
    errno: -3008,
    code: 'ENOTFOUND',
    syscall: 'getaddrinfo',
    hostname: 'media'
  }
}

I have no idea what's wrong, this also happened with statuses/destroy but i fixed it by appending .v1 to post(), but this work-around doesn't seem to be working for this error. Any help is appreciated

How to access meta prop from search/recent (v2)?

Hi! This is great work, thanks for putting it together.

Is there a way to access the meta property from the search/recent v2 API result?

const result = await twitterClient.search('something');
// @ts-ignore
const meta = result._realData.meta; // Is there a clean/direct way to access the meta property from the API results?

Feature Request: List of projects that use your API

Last night, I ported the twitter integration code for a Twitch bot I use from the standard twitter nodejs library to yours and found the transition to be mostly painless. Great job, and I’d love to see more projects move to your library. Twitter V2 is coming in full at some point meaning that the old library just won’t cut it long term.

The bot is called SogeBot, the developer is super friendly and has put a substantial amount of work into it. I’m still fairly new to Javascript and Typescript but plan on doing more with your library.

The PR for my port: sogebot/sogeBot#4827

Thanks again. :)

Application cannot perform write actions.

Hi,
With the readOnly client I make roClient.v1.filterStream and it say me: (node:13276) UnhandledPromiseRejectionWarning: Error: Request failed with code 403 - Application cannot perform write actions. Contact Twitter Platform Operations through https://help.twitter.com/forms/platform. (Twitter code 261)
But in your docs the level for this is read-only.

image

My code:
image

Feature suggestion: handling two tokens as a way around rate limits

I was asking about rate limits on the Twitter dev forums and someone suggested this:

you should use both the App auth (bearer token) and user auth (access token) together to give you 30 calls in 15 minutes

Would it be feasible to instantiate a client with both kinds of tokens and have this library automatically switch from one to the other when rate limits are being hit?

uploadMedia fails with buffer input

Hi, I've been trying to use this wrapper for the upload media endpoint in a project and it works pretty well for local files but when I try to pass a buffer created from binary data it prompts:

Error: Failed to process media

This is how I get the binary data:

const getVideoBuffer = (previewUrl: string) => {
  return new Promise((resolve, reject) => {
    request.defaults({ encoding: null });
    request.get(previewUrl!, async (error, response, body) => {
      if (error) {
        reject(new Error(`Something went wrong getting binary data from preview url ${error}`));
      }
      resolve(Buffer.from(body));
    });
  });
};

Here I get the buffer and start the upload:

 const buffer: any = await getVideoBuffer(previewUrl || '');
 const mediaId = await client.v1.uploadMedia(buffer, { type: 'mp4', target: 'tweet'});
 const tweet = await client.v1.tweet('Hello!', { media_ids: mediaId });
 console.log(tweet);

Am I missing something?
Thanks in advance

How to retweet/like a given tweet

Hi,

I have the problem that I could not find a way to retweet/like a tweet in the v1 API. Is there any method for that?

Greetings
Michael

Module 'fs' has no default export

I'm receiving Module '"fs"' has no default export. error when trying to compile and deploy script containing twitter-api-v2 package, is there any specific requirement so this error won't appear?
image

ApiResponseError: Request failed with code 401 - Request token missing

This is the code I tried (the right tokens and secrets are there):

import { TwitterApi } from "twitter-api-v2";

const consumerClient = new TwitterApi({
    appKey: "APP KEY",
    appSecret: "APP SECRET",
    accessToken: "ACCESS TOKEN",
    accessSecret: "ACCESS TOKEN SECRET"
}).readWrite;
const client = await consumerClient.login();

This throws an ApiResponseError: Request failed with code 401 error. I tried the twit package and it worked just fine, so I think this is an issue specific to this library. The error's data property is { 'Request token missing': '' }.

got error id undefine

await client.v1.deleteWelcomeDm(welcomeDm[EDirectMessageEventTypeV1.WelcomeCreate].id);
How to define the id?

Only getting partial information from tweet and user retrieval

Hello, I have been messing around with this library for a while now but despite whichever authentication method I use (bearer token, or app/access credential object), I am unable to get the full information from tweet and user retrieval.
For instance, for tweets I am only able to get { id, text } while I want to be able to get { created_at?, attachments?, etc. } - this also applies to retrieving the user data for a user, I always am only able to get partial information.
I am unable to find any hint or clue in the available documents, am I doing something wrong with authentication or am I missing something else?
Thanks in advance, great library nevertheless!

Paginated requests don't use max_results value

I'm using the package as follows:

   const result = await roClient.v2.following(twitterId, {
      asPaginator: true,
      max_results: 1000,
    });

    for await (const following of result) {
      followings.push(following);
    }

But I can only fetch 2400 result before reaching the 15 API queries rate limit, which I assume is one query for the first 1000 items and then 14 queries for 100 items (1 * 1000 + 14 * 100 = 2400).

So the issue here is that subsequent retries are not using the max_results parameter. I also tried fetchLast but it seemed to have the same issue.

createMetaData error?

Hello! I'm so excited to find this package! I've been using Twit and other node.js implementations for many years and have been hoping to find something up-to-date and actively maintained!

I ran across an issue attempting to add "alt text" to an image, this fails for me with a 400 error:

const mediaId = await client.v1.uploadMedia('rainbow.png', { type: 'png' });
await client.v1.createMediaMetadata(`${mediaId}`, { alt_text: 'Rainbow!' });

However, I am able to get it to work by calling post() directly.

const mediaId = await client.v1.uploadMedia('rainbow.png', { type: 'png' });
await client.v1.post('media/metadata/create.json', {
  media_id: `${mediaId}`,
  alt_text: {
    text: 'Rainbow!',
  },
});

My repo of examples is in progress here: https://github.com/shiffman/Twitter-Bots-F21

Looking for a proper way to handle connection errors.

Hello folks, thanks for developing and maintaining this library. I have a question, or two questions actually if you don't mind.

Right now I am running a bot that is connected to a Twitter stream, which listens for tweets from an array of users, and then I do some fancy stuff with it. The problem is, every once in a while, Twitter throws a 429 error at me, maybe once every 24-48 hrs, and as a result of that I get an unhandledRejection error, and then the Stream no longer works without manually restarting the bot.

app[worker.1]: Error: Request failed with code 429
app[worker.1]: at RequestHandlerHelper.createResponseError (/app/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js:73:16)
app[worker.1]: at IncomingMessage.<anonymous> (/app/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js:114:33)
app[worker.1]: at IncomingMessage.emit (node:events:402:35)
app[worker.1]: at endReadableNT (node:internal/streams/readable:1343:12)
app[worker.1]: at processTicksAndRejections (node:internal/process/task_queues:83:21)

Here is a simplified version of my code:

class _Twitter {
    constructor({ streamName }) {
        this.streamName = streamName;
    }

    async initSources() {
        const sourceList = [
            'Barca_Buzz', 'barcacentre', 'BarcaTimes', 'BarcaUniversal', 'FCBarcelona',
            'FCBarcelonaFl', 'GSpanishFN', 'infosfcb', 'LaSenyera', 'ReshadRahman_',
        ];

        const streamRules = await this.client.v2.streamRules();

        // Cleanup all existing rules upon initiating
        if (streamRules?.data?.length > 0) {
            await this.client.v2.updateStreamRules({
                delete: {
                    ids: streamRules.data.map(rule => rule.id),
                },
            });
        }

        await this.client.v2.updateStreamRules({
            add: sourceList.map(source => ({
                value: `(from:${source}) -is:retweet -is:reply`,
                tag: source.name
            }))
        });
    }

    async stream() {
        try {
            this.client = new TwitterApi(TwitterBearerToken);
            await this.initSources();

            this.stream = await this.client.v2.searchStream(
                {
                    "tweet.fields": ['id', 'text', 'created_at', 'entities'],
                    "user.fields": ['username', 'name', 'profile_image_url'],
                    'media.fields': ['preview_image_url', 'url', 'width', 'height', 'type'],
                    'expansions': ['author_id', 'attachments.media_keys']
                }
            );

            this.stream.autoReconnect = true;
            this.stream.autoReconnectRetries = 999;

            // Listen for all possible events (for debugging purposes);

            this.stream.on(ETwitterStreamEvent.Data, async (data) => {
                console.log(`Event: Data (${data.includes.users[0].username})\n---`);
                // do something with the tweet here
            });

            this.stream.on(ETwitterStreamEvent.ConnectionClosed, async (data) => {
                console.log(`Event: ConnectionClosed${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.ConnectionError, async (data) => {
                console.log(`Event: ConnectionError${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.ConnectionLost, async (data) => {
                console.log(`Event: ConnectionLost${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.DataError, async (data) => {
                console.log(`Event: DataError${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.DataKeepAlive, async (data) => {
                console.log(`Event: DataKeepAlive${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.Error, async (data) => {
                console.log(`Event: Error${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.ReconnectAttempt, async (data) => {
                console.log(`Event: ReconnectAttempt${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.ReconnectLimitExceeded, async (data) => {
                console.log(`Event: ReconnectLimitExceeded${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.Reconnected, async (data) => {
                console.log(`Event: Reconnected${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });
            this.stream.on(ETwitterStreamEvent.TweetParseError, async (data) => {
                console.log(`Event: TweetParseError${data ? `\n${JSON.stringify(data, null, 4)}\n` : '\n'}---`);
            });

        } catch (error) {
            console.log(this.streamName, 'error');
            console.log(error);

            if (error.code = 429) {
                await this.stream.reconnect();
            }
        }
    }
}

const Twitter1 = new _Twitter({ streamName: 'Stream 1' });

(async () => {
    await Twitter1.stream();
})();

So as you can see, I am creating a _Twitter class, and then creating an instance of that class to connect to the Streaming API. This all works fine, except that only the Data and DataKeepAlive events are emitting properly, and the rest goes into my catch block.

It also appears that autoReconnect and autoReconnectRetries are not a properties of this.stream, and reconnect() is not a valid method either. I think the problem is that I have to use and implement the TweetStream into my code, but I am not sure how to exactly, and I can't find documentation for this either.

In any case, I don't want to make this too long, so I would just like to ask if you can point me in the right direction, such as providing a very quick example if that is possible.

Thank you for your time.

EDIT: It appears that this.stream is in fact a TweetStream object, there was just an error with my test script.

I would still like to ask, is this the proper way to implement autoReconnect? The actual code on my server does not have this try catch block, because I just assumed it would reconnect automatically on any kind of connection error. I'm not sure how to test this properly because Twitter only allows for 1 concurrent stream.

Feature suggestion: automated rate limiting handling

The library already does a pretty good job of making rate limits more explicit, but I was wondering if it could go one step further and actually delay your calls (for example with a new fetchLastWhileWaiting() function) to make them respect the rate limit? Or would that be beyond the scope of the library?

KEEP GETTING TypeError: The "listener" argument must be of type Function. Received type object

Here is the code that I have written:
`const client = new TwitterApi({
appKey: API_KEY,
appSecret: API_KEY_SECRET,
accessToken: ACCESS_TOKEN,
accessSecret: ACCESS_TOKEN_SECRET,
})
// const client = new TwitterApi(BEARER_TOKEN);

async function makeTweet() {
const createdTweet = await client.v1.tweet('twitter-api-v2 is awesome!')
console.log('Tweet', createdTweet.id_str, ':', createdTweet.full_text)
}
`

Is the API broken or am I making a mistake somewhere? Thanks

[Feature Request] Add option to disable all console.log

Hello,

Could you add an option to disable everything printing in the console?
I saw a debug property set to false by default in the settings and a condition using it but it's still printing in the console.

Is it a bug or a feature not fully implemented yet?

Thanks!

Getting 403 with correct keys

Hi i tried switching from twitter-v2 to this twitter-api-v2 package and i'm seeing a 403 when doing the following:

import TwitterApi from 'twitter-api-v2'

const client = new TwitterApi({
   appKey: import.meta.env.VITE_CONSUMER_KEY,
   appSecret: import.meta.env.VITE_CONSUMER_SECRET,
   accessToken: import.meta.env.VITE_TOKEN_KEY,
   accessSecret: import.meta.env.VITE_TOKEN_SECRET,
})

const rwClient = client.readWrite
const user = await rwClient.v2.userByUsername('Matt_Pilott')

The env variables are there and correct, the first 2 are the API key and secret from consumer keys on twitter and the second 2 are generated in the developer portal as personal access token and secret, so should all be correct and works if i switch back to the twitter-v2 package

Where have i gone wrong here?

Filter Stream too many connections when there are no streams connected

Hey Folks,

Opening this issue in case there's an off chance the issue is related to the library but I've been wrestling with a bug today where I keep getting a 429 This stream is currently at the maximum allowed connection limit. while trying to open up a filter stream even though I don't currently have any open connections.

I found this post from the twitter community forum that looks like it may be related but was curious if folks know of something that I may be doing wrong. https://twittercommunity.com/t/rate-limit-on-tweets-stream-api/144389/20

Here's a slimmed down version of the code we're using to open the stream. Things were working fine until this afternoon.

import { TwitterApi } from 'twitter-api-v2'

const client = new TwitterApi('<bearer_token>')

  let stream

  try {
    stream = await client.v2.searchStream({
      'tweet.fields': ['referenced_tweets', 'public_metrics', 'entities'],
      expansions: ['author_id', 'referenced_tweets.id.author_id', 'in_reply_to_user_id']
    })
  } catch (err) {
    console.log('error initializing stream', err)
  }

snippet of the error response

  rateLimit: { limit: 50, remaining: 48, reset: 1634603522 },
  data: {
    title: 'ConnectionException',
    detail: 'This stream is currently at the maximum allowed connection limit.',
    connection_issue: 'TooManyConnections',
    type: 'https://api.twitter.com/2/problems/streaming-connection'
  }

has anybody else ran into this issue or could point me in the right direction? :)

401: Unauthorized for statuses/filter.json error even after using appLogin

Am following this: https://github.com/PLhery/node-twitter-api-v2/blob/27fd130379d187f9c277a9c74ef4f425db01ffe5/doc/auth.md#application-only-authentification-flow to authorize the twitter client and start a filter streaming. But i get 401 error. Below is the code

this.client = new TwitterApi({ appKey: TWITTER_API_KEY, appSecret: TWITTER_KEY_SECRET, accessToken: TWITTER_ACCESS_TOKEN, accessSecret: TWITTER_TOKEN_SECRET, });
...
this.twitterBearerToken = await this.client.appLogin();
this.stream = await this.twitterBearerToken.v1.filterStream({ follow: [this.userId] });

autoReconnect not catching ECONNRESET

Hello,

I can't make autoReconnect feature work, I'm getting a ECONNRESET error that does not trigger the reconnection logic.

{
  "type": "connection error",
  "error": {
    "code": "ECONNRESET"
  }
}

My code :

this.tweetsStream = await this.twitterClient.v2.searchStream({
  ...
})
this.tweetsStream.autoReconnect = true

Session is required?

umm right now i think not is more required the session for twitter auth process, according the twitter docs only needed do three request:

1- Request Token (https://developer.twitter.com/en/docs/authentication/api-reference/request_token) -> Use Consumer Key, Secret and CallbackUrl (oauth headers) and return oauth_token and oauth_token_secret on body

2- Auth on Twitter (https://developer.twitter.com/en/docs/authentication/api-reference/authenticate) -> Use oauth_token by query params to Twitter API -> send callback to callbackUrl with oauth_token & oauth_verifier in queryparams or just get the PIN if not use callback

3- Access Token (https://developer.twitter.com/en/docs/authentication/api-reference/access_token) -> Use oauth_token & oauth_verifier (or PIN)-> receive new oauth_token, oauth_token_secret and user_id in Body

Reconnect on error

So I saw on the feature list that the package tries to reconnect on error,
image

Though my tweetStream hasn't recovered from this error...
image

Would I need to write a function to recover from any responses from the following events?
Or am I right in thinking It should be recovering automatically?

  ETwitterStreamEvent.ConnectionError
  ETwitterStreamEvent.ConnectionClosed

I did see pretty much the same issue here #36, but it looks like that thread was already resolved and merged, though this issue is persisting. I hope it's not an oversight on my part!
Where I did see in the linked issue, the previous user defined .autoReconnect = true on the tweetStream, which I have not. Is this required or true by default?

Thank you!
( Other than this the package has been spectacular and easy to use :) )

really weird issue - adding asterisk `*` to a tweet text breaks the api

okay so i found this weird issue while working with this api that whenever I add * to my tweet message, it literally breaks the api. Here's what's happening with me:

tweet = await twitterApi.v1.tweet("this is a *tweet*", { tweet_mode: "extended" });

^ this won't work, while if i tweet literally anything else which doesn't include asterisk, it will succeed. I have no idea how this happens, even tried using direct post methods, still breaks.

After this, I tested twitter-api-client and that doesn't break at all.

Cannot send direct messages

I'm having problems with sending direct messages. As far as I saw there is no wrapper function for this feature, so I made a request as follows:

const client = new TwitterApi({
    appKey: consumerKey,
    appSecret: consumerSecret,
    accessToken,
    accessSecret,
});

 await client.v1.post('direct_messages/events/new', {
      event: {
        type: 'message_create',
        message_create: {
          target: {
            recipient_id: recipientId,
          },
          message_data: {
            text,
          },
        },
      },
 });

However, I keep getting a 403 error and I'm not sure what I'm missing.

"name": "Error", "message": "Request failed with code 403"

https request vs get

I get https.request - The "listener" argument must be of type Function. Received type object and stack trace leads to client-mixins/request-handler.helper when executing 1.1/verify_credentials.

It seems in agent-base/patch-core.js the https.request method is only implemented for the signature function(_options, cb) but request-handler.helper passes in: request(this.requestData.url, this.requestData.options), so the callback argument is indeed an object (this.requestData.options). Instead, we can use the get method in https if the request is a get method making the client-mixins/request-handler.helper buildRequest method as follows :

  import { request, get } from 'https';
  protected buildRequest() {
    if (TwitterApiV2Settings.debug) {
      this.debugRequest();
    }
    if (this.requestData.options.method === 'GET') {
      this.req = request(this.requestData.url, this.requestData.options);
    } else {
      this.req = get(this.requestData.url, this.requestData.options);
    }
  }```

ETwitterStreamEvent.DataKeepAlive not emitted

`When using the Streaming API I ran into an issue with the ETwitterStreamEvent.DataKeepAlive never being fired. From looking at the source of TweetStream.ts I found out that this is caused by the use of strict string comparison (not allowing for type conversion) in the corresponding code. Changing "===" to "==" fixed the issue for me. However I didn't check if allowing for type conversion has any other implications.

this.res.on('data', chunk => {
      if (chunk === '\r\n') {
        return this.emit(ETwitterStreamEvent.DataKeepAlive);
      }

      this.parser.push(chunk);
    });
  }

listDmEvents issue

Hello, i've made an interval in order to get the dm events every 10s, but it takes the new dm events on start and then if a new dm is sent to the bot, it doesnt get the new messages, i need to restart the bot fully

Media type is not detected correctly when file is temporary

Hello,

I'm using the uploadMedia() helper to upload a file to Twitter from a user input (through HTML form).
The file is automatically uploaded to my server in the /tmp folder and I'm trying to upload this file to Twitter which has a .tmp extension, so the detection is not correct because of that:

function getMimeByName(name: string) {
if (name.endsWith('.jpeg') || name.endsWith('.jpg')) return 'image/jpeg';
if (name.endsWith('.png')) return 'image/png';
if (name.endsWith('.webp')) return 'image/webp';
if (name.endsWith('.gif')) return 'image/gif';
if (name.endsWith('.mpeg4') || name.endsWith('.mp4')) return 'video/mp4';
if (name.endsWith('.srt')) return 'text/plain';
return 'image/jpeg';
}

I know I can provide the type in the options (and it's working fine), but if that's possible to detect the mime type from the .tmp file, that would be awesome! 😊

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.