Giter Site home page Giter Site logo

hunterlarco / twitter-v2 Goto Github PK

View Code? Open in Web Editor NEW
163.0 2.0 35.0 111 KB

An asynchronous client library for the Twitter REST and Streaming API's

License: MIT License

JavaScript 61.42% TypeScript 38.58%
twitter-api twitter node-js nodejs node twitter-client stream-apis

twitter-v2's Introduction

Twitter V2 API for Node.js

v2

An asynchronous client library for the Twitter REST and Streaming V2 API's.

Try it now

const Twitter = require('twitter-v2');

const client = new Twitter({
  consumer_key: '',
  consumer_secret: '',
  access_token_key: '',
  access_token_secret: '',
});

const { data } = await client.get('tweets', { ids: '1228393702244134912' });
console.log(data);

Installation

npm install twitter-v2

NPM

Quick Start

You will need valid Twitter developer credentials in the form of a set of consumer keys. You can get early access V2 keys here.

For user based authentication:

User authentication requires your app's consumer keys and access tokens obtained from oauth 1.0a.

const client = new Twitter({
  consumer_key: '',
  consumer_secret: '',
  access_token_key: '',
  access_token_secret: '',
});

For app based authentication:

Alternatively, app authentication (which can only access public data but is often suitable for server applications) only needs your app's consumer keys and/or bearer token.

const client = new Twitter({
  consumer_key: '',
  consumer_secret: '',
});

or

const client = new Twitter({
  bearer_token: '',
});

REST API

You can make GET, POST, and DELETE requests against the REST API via the convenience methods.

client.get(path, urlParams);
client.post(path, body, urlParams);
client.delete(path, urlParams);

The REST API convenience methods return Promises.

Streaming API

Use the streaming convenience methods for any stream APIs.

client.stream(path, urlParams);

The Streaming API will return an async iterator with the convenience method close(). Ensure that you call close() when done with a stream, otherwise it will continue to download content from Twitter in the background.

const stream = client.stream(path, urlParams);

// Close the stream after 30s.
setTimeout(() => {
  stream.close();
}, 30000);

for await (const { data } of stream) {
  console.log(data);
}

Note that reconnect logic is not handled by this package, you're responsible for implementing it based on the needs of your application. The stream will close itself in two cases:

  1. If the stream becomes disconnected for an unknown reason, a TwitterError will be thrown.
  2. If Twitter's backend disconnects the stream healthily, the stream will be closed with no error.

If you wish to continuously listen to a stream, you'll need to handle both of these cases. For example:

async function listenForever(streamFactory, dataConsumer) {
  try {
    for await (const { data } of streamFactory()) {
      dataConsumer(data);
    }
    // The stream has been closed by Twitter. It is usually safe to reconnect.
    console.log('Stream disconnected healthily. Reconnecting.');
    listenForever(streamFactory, dataConsumer);
  } catch (error) {
    // An error occurred so we reconnect to the stream. Note that we should
    // probably have retry logic here to prevent reconnection after a number of
    // closely timed failures (may indicate a problem that is not downstream).
    console.warn('Stream disconnected with error. Retrying.', error);
    listenForever(streamFactory, dataConsumer);
  }
}

listenForever(
  () => client.stream('tweets/search/stream'),
  (data) => console.log(data)
);

V1.1 API Support

This module does not support previous versions of the Twitter API, however it works well with the following V1.1 modules

NPM

NPM

twitter-v2's People

Contributors

brandongregoryscott avatar hunterlarco avatar juanjosechiroque avatar lexmarionb avatar losunny avatar lotti 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

twitter-v2's Issues

Can't resolve 'crypto' in '/project/node_modules/twitter-v2/build'

Prerequisites

  • Checked that your issue isn't already filed: [x]
  • Checked the [x]

Description

First time trying to use the API in my TypeScript project and I see that there is an issue with the crypto dependency of the package.

Steps to Reproduce

  1. npm install twitter-v2
  2. attempt to instantiate package new Twitter(opts)
  3. See compilation error, when using WebPack.

NOTE: TypeScript compilation does not complain here.

Expected behavior:

The package to have all of it's dependencies.

Actual behavior:

Crypto is needed but it is not included as a dependency, thus WebPack is unhappy.

resolve 'crypto' in '/Users/keneucker/Dev/biketag-api/node_modules/twitter-v2/build'
  Parsed request is a module
  using description file: /Users/keneucker/Dev/biketag-api/node_modules/twitter-v2/package.json (relative path: ./build)
    Field 'browser' doesn't contain a valid alias configuration
    resolve as module
      /Users/keneucker/Dev/biketag-api/node_modules/twitter-v2/build/node_modules doesn't exist or is not a directory
      looking for modules in /Users/keneucker/Dev/biketag-api/node_modules/twitter-v2/node_modules
        single file module
          using description file: /Users/keneucker/Dev/biketag-api/node_modules/twitter-v2/package.json (relative path: ./node_modules/crypto)
            no extension

Reproduces how often:

100%

Versions

latest (1.1.0)

Could not find tweet with ids: [1341761249646956500].

I am doing a simple get request like this for a tweet id I have grabbed using V1.1 API

response = await client.get('tweets', { ids: '1341761249646956500' });
if (response) {
    console.log(data);
}

It is responding with this error

detail:'Could not find tweet with ids: [1341761249646956500].'
parameter:'ids'
resource_type:'tweet'
title:'Not Found Error'
type:'https://api.twitter.com/2/problems/resource-not-found'
value:'1341761249646956500'

await is only valid in async function

Description

await is only valid in async function when running getting started example in readme

Steps to Reproduce

create a node app with the following code (copied from readme):

const Twitter = require('twitter-v2');

const client = new Twitter({
    bearer_token:  //bearer_token

  });

const { data } = await client.get('tweets', { ids: '1228393702244134912' });
console.log(data);

Expected behavior:

should log the output of the tweet

Actual behavior:

console error:
await is only valid in async function

Reproduces how often:

100%

Versions

^1.1.0

Additional Information

Unauthorized when POST to Tweets endpoint

https://twittercommunity.com/t/post-request-returning-error-401-unauthorized/162950/4

following the example in the README, let response = await client.get('tweets', { ids: id }) works as expected, but let response = await client.post('tweets', { text: message }) fails with { code: 401, details: 'Unauthorized' }. nodejs 17.2.0, windows.

It's expected that POST should authenticate using the same method and send a tweet successfully.

Full code example:

const Twitter = require("twitter-v2")

const client = new Twitter({
  consumer_key: process.env.TWITTER_CONSUMER_KEY,
  consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
  access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
  access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
});

async function sendTweet(message) {
  try {
    const response = await client.post('tweets', { text: message })
    console.log(response)
  } catch (err) {
    console.error(err)
  }
}

async function getTweet(id) {
  try {
    const response = await client.get('tweets', { ids: id })
    console.log(response)
  } catch (err) {
    console.error(err)
  }
}

sendTweet('test tweet!')

getTweet('1228393702244134912')

The "errors" field is a legitimate field returned by Twitter v2 - should not result in error thrown

In Twitter V2, the errors field of what's returned by Twitter is a legitimate field.

e.g. When we are looking up a tweet id that has been suspended, we would look in the errors field for this case.

Thus, it should not result in an error thrown, instead just return the errors field results

e.g. This tweet is from an account that is suspended, so
client.get('tweets', {ids:'1000082502030065665'})
is a valid api call

It should return:
{"errors":[{"value":"1000082502030065665","parameter":"ids","resource_type":"tweet","section":"data","title":"Authorization Error","detail":"Sorry, you are not authorized to see the Tweet with ids: [1000082502030065665].","type":"https://api.twitter.com/2/problems/not-authorized-for-resource"}]}

Unauthorized(401) when using tweets/search/recent

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:

Description

I'm trying to get the recent tweets from an user excluding the retweets.
The documentation says that I can use -is:retweet on my query and I tried this:

const client = new Twitter({
  consumer_key: process.env.TWITTER_API_KEY,
  consumer_secret: process.env.TWITTER_API_SECRET,
  access_token_key: process.env.TWITTER_ACCESS_TOKEN,
  access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
});

const getLatestTweets = async (limit = 20) => {
  const { data } = await client.get('tweets/search/recent', {
    query: 'from:levxyca -is:retweet',
    'tweet.fields': 'created_at,public_metrics,entities',
    max_results: limit,
  });

  if (!data) { /* Not important for this issue. :D */ }

  return data;
};

getLatestTweets();

The point is on query: 'from:levxyca -is:retweet'. If a change it to query: 'from:levxyca', I can get the user tweets but I need to remove the retweets manually. When I add the -is:retweet I get the error specified below.

Do I need to do any dealings with my query?

Actual behavior:

I'm getting a Unauthorized error:

:\Users\Me\Desktop\Repositories\pandadomalbot\node_modules\twitter-v2\build\TwitterError.js:23
        return new module.exports(json.title, json.status, json.detail);
               ^

TwitterError: Unauthorized
    at Function.module.exports.fromJson (C:\Users\Me\Desktop\Repositories\pandadomalbot\node_modules\twitter-v2\build\TwitterError.js:23:16)
    at Twitter.get (C:\Users\Me\Desktop\Repositories\pandadomalbot\node_modules\twitter-v2\build\twitter.js:43:49)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async getLatestTweets (C:\Users\Me\Desktop\Repositories\pandadomalbot\utils\twitter.js:35:20)
    at async getTodaysLiveAnnouncement (C:\Users\Me\Desktop\Repositories\pandadomalbot\utils\twitter.js:70:18)
    at async Object.exports.default (C:\Users\Me\Desktop\Repositories\pandadomalbot\commands\rt.js:9:19) {
  code: 401,
  details: 'Unauthorized'
}

Versions

1.1.0

expansions missing and example

let tweetsRawData = await client.get( 'users/1407591434660761602/tweets', { tweet: { fields: ['attachments,created_at,lang,text'], }, media: { fields: ['preview_image_url,type,url'] } }, );

Does not the create the to be expected call to:
https://api.twitter.com/2/users/1407591434660761602/tweets?tweet.fields=lang&**expansions**=attachments.media_keys&media.fields=preview_image_url,url

Result is this:
https://api.twitter.com/2/users/1407591434660761602/tweets?tweet.fields=attachments%2Ccreated_at%2Clang%2Ctext&media.fields=preview_image_url%2Ctype%2Curl

Also a "hint" in the documentation, that Twitter sends the "inclues" in a 2nd JSON Part would be nice.

Question

Hey, i just tried this out and it works a treat! Great job

I was wondering if i could help out at all?

There were one or two things i had to dig around the api docs for which might benefit from some extra code snippet examples in the README

For example i'm trying to get the last 100 tweets for my username and it took me a while to work out how to pass the params

  const { data } = await client.get('tweets/search/recent', {
    query: 'PaulieScanlon',
    max_results: '100',
    tweet: {
      fields:
    'author_id,context_annotations,conversation_id,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,referenced_tweets,source,text,withheld',
    },
  })

Error on adding multiple query parameters separated by space, in urlParams

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:
    • Checked that your issue isn't already filed: [open issues]
    • Checked the [bug report guidelines]

Description

When adding multiple query operators in urlParams in the form of an object, it throws an error. On checking it closely, it looks like the error is due to url module in applyParameters function in the source code that encodes space between the parameters as + and Twitter API expects it to be encoded as %20. The code mentioned in the examples results in the same error.

Steps to Reproduce

node v12, v14, v16

const urlParams = {
  'query' : 'conversation_id:1305403243388829696 from:pbshgthm',
 ...other_params
}

client.get(`tweets/search/recent`,urlParams);

Expected behavior:

conversation_id:1305403243388829696 from:pbshgthm gets encoded as conversation_id%3A1305403243388829696%20from%3Apbshgthm

API call goes through

Actual behavior:

conversation_id:1305403243388829696 from:pbshgthm gets encoded as conversation_id%3A1305403243388829696+from%3Apbshgthm

Results in the following error

handledPromiseRejectionWarning: Error: Unauthorized at Function.module.exports.fromJson (/home/runner/threads/node_modules/twitter-v2/build/TwitterError.js:23:16)

Reproduces how often:

Always

Versions

1.1.0 (latest)

Additional Information

N.A.

Streams unreliable for collecting tweets from slow tweeting accounts

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:
    • Checked that your issue isn't already filed: [open issues][open-issues]
    • Checked the [bug report guidelines][bug-report-guidelines]

Description

The streams part of twitter-v2 is unreliable. I've set it to monitor five twitter accounts that tweet about once every six hours.

Steps to Reproduce

  1. Watch several accounts in a filtered stream that don't post that often.
  2. Start streaming tweets
  3. Streams randomly quit within 30-45 minutes or less.

Expected behaviour:

Should be able to run indefinitely. twitter-v2 should not disconnect the stream just because it thinks the stream is unresponsive. The sample code by Twitter themselves does not have this behaviour.

Actual behaviour:

Streams randomly hit this._closeWithError.

    at Timeout.<anonymous> (/home/rctgamer3/project/node_modules/twitter-v2/src/TwitterStream.js:50:30)
    at listOnTimeout (internal/timers.js:554:17)
    at processTimers (internal/timers.js:497:7)

Stream timeout's, and throws a TwitterError that the stream is unresponsive.
Reproduces how often:
Always, the only variable is the time until it closes the stream.

Versions

1.0.8

Additional Information

If you need any further information to triage things, let me know.

Searching tweets/search/recent

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:

Description

I'm trying to search the recent tweets for a specific user. Here's the URL if I use Insomnia:

https://api.twitter.com/2/tweets/search/recent?start_time=2021-04-23T00:00:00Z&query=from%3A_TWITTER_HANDLE_GOES_HERE&tweet.fields=id,author_id,text

and GET on that URL returns data. This does not work:

twitterClient.get('tweets/search/recent', {
		query: 'from%3Athe_churchnews',
		start_time: '2021-04-23T00:00:00Z',
	});

In addition, the commented out parts of the above object cause an error, which is why they are commented out. I've looked at the source code to try and build that object correctly, but haven't been able to get it to work properly.

In addition, in the URL string I have the tweet.fields query param. I tried adding it to the options object in both of the following ways, with no success. The first way causes an error, the second way there is no error but I'm not sure if it's working since I don't get any data back.

tweet: {
	fields: 'id,author_id,text',
},

// And

'tweet.fields': 'id,author_id,text',

Any docs or pointers here would be greatly appreciated.

Steps to Reproduce

async function getTweets() {
	const dt = new Date();
	dt.setHours(dt.getHours() - 12);

	const dateString = dt.toISOString();

	const { data } = await twitterClient.get('tweets/search/recent', {
		query: 'from%3A_twitter_handle',
		start_time: dateString,
		'tweet.fields': 'id,author_id,text',
	});
	console.log(data);
	return data;
}

Expected behavior:

Tweets should print to the console

Actual behavior:
undefined is printed to the console.

Reproduces how often:
Every time

Versions

v1.1.0

Additional Information

Error: Build typescript error

node_modules/twitter-v2/src/Credentials.d.ts:29:37 - error TS2304: Cannot find name 'ApplicationCredentials'.

export class Credentials implements ApplicationCredentials, UserCredentials {

I get error that says I need to define the access_token and access_token_secret when using user auth

So I am building react application that allows users to login using twitter auth from firebase and once they login it displays their user timeline. So I am trying to use this npm package to be able to give me the user's twitter username which I will pass into another component to retrieve the user timeline to be displayed.

I made sure to install the twitter-v2 package, and I set up my client variable with all the needed keys. Right now I am trying to test it out to see if it works by retrieveing tweets with a tweets id:
github_twitterv2issue

But then I get this weird issue:
github_twitterv2issue2

I also made sure this app is inside a approved project allowed to use the v2 endpoint and I have the correct keys to be able to pass in. I was wondering do you guys know how I would be able to fix this issue? Thank you all for the help I really appreciate it!

TypeScript definitions

Are there any plans for writing TypeScript definitions for this package? I was planning on writing a wrapper library in TS to provide some utility functions around these base API calls and I've found myself filling in some of the types for this package anyway.

Twitter returned invalid request with parameters

When trying to apply url parameters to links that have :parameters, it will return 'One or more parameters to your request was invalid.'

The problem code

const {data} = client.get('users/by/username/:username',{username :'INSERT NAME HERE'});

It will return the error I mentioned above.

Error: Unauthorized

undefined
(node:7472) UnhandledPromiseRejectionWarning: Error: Unauthorized
    at Function.module.exports.fromJson (C:\Users\Asus\Desktop\Veljko\twitterAPI
\node_modules\twitter-v2\src\TwitterError.js:25:12)
    at Twitter.get (C:\Users\GV9Jm2u7rmsCe65wKzPTw5jtS38n2tVEGie_modules\twitter
-v2\src\twitter.js:46:32)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:7472) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This
error originated either by throwing inside of an async function without a catch
block, or by rejecting a promise which was not handled with .catch(). To termina
te the node process on unhandled promise rejection, use the CLI flag `--unhandle
d-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejectio
ns_mode). (rejection id: 1)
(node:7472) [DEP0018] DeprecationWarning: Unhandled promise rejections are depre
cated. In the future, promise rejections that are not handled will terminate the
 Node.js process with a non-zero exit code.

TypeError: url_1.URL is not a constructor

Im trying to create first step, from oficial instruction

const Twitter = require('twitter-v2');

const client = new Twitter({
  bearer_token: token,
  consumer_key: '***',
  consumer_secret: '***',

});

const { data } = await client.get('tweets', { ids: '1228393702244134912' });
console.log(data);

And get an error:

TypeError: url_1.URL is not a constructor.

I cant undestand what im do wrong, how i can get tweets from specific user? Help pls/

Handle connection timeouts in stream

Hi (again), this is more of a feature request: I like the provision of stream data through an async iterator. It's clean and simple. But I am trying to implement a reconnection logic and there seems no way to know the status of the connection 'from the outside' as twitters 'ping' signals are not propagated by the iterator (or I am missing something).

ImO it would be helpful to either

  • propagate twitters 'connection alive' info to the user through the iterator (arguably making it slightly less elegant as the user then has to check the data) or
  • handle disconnects within the TwitterStream class (e.g. throwing/rejecting if no signal was received for a certain amount of time, Twitter suggests 20 seconds).

Cheers,
Thilo

PS I am aware that this is a rather small project and my limited JS skills mean that I am unlikely of much help with the code. Just indicate if you think this won't be taken much further and I'll stop bugging you with issues.

Sample codes for client.post(path, body, urlParams);

Hi, is it possible to post twit with version 2? Could I get sample codes for this: client.post(path, body, urlParams);
?
I'm getting an error when trying to post. Maybe the endpoint is not yet available on version 2?

Iteration through paginated data

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:
    • Checked this feature isn't already filed: [open features]
    • Checked the [feature request guidelines]

Summary

It would be helpful to be able to iterate through paginated data, via an async iterator.

Motivation

At the moment the user has to manually handle paginated responses by reading meta.next_token and setting it as params.pagination_token on a new request.

It would be helpful if it was possible to use for await (const item of client.get(path, params)) { … } (where item is an item from the data array in each response) to iterate through each item automatically.

Describe alternatives you've considered

Making requests in a do { … } while (params.pagination_token) loop.

[BUG] Twitter deep links don't linking to the intended page

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:
    • Checked that your issue isn't already filed: [X]
    • Checked the [X]

Description

I'm a Samsung developer, and work on Bixby Project. I found a bug while developing a new feature of Twitter.
This feature works getting the user to explore tabs (For You, News, Sports, Entertainment).

Steps to Reproduce

  1. Ask Bixby to go to Sports Tab
  2. Bixby opens https://twitter.com/explore/tabs/sports_unified
  3. Ask Bixby to go to Entretainment Tab

Expected behavior:

Opens the Entretainment Tab

Actual behavior:

It keeps in the same initial tab of Sports, instead of going to Entratainment

Reproduces how often:

Always 100%

Versions

Twitter API v2

Additional Information

This issue only happens when using the Twitter app, when using twitter on browser it works normally.
If possible please contact us: [email protected]

How do we use the Bearer token?

I just want to get a tweet as a json from it's id.

I tried the following, but it won't work, I get this error.

const express = require("express");
const app = express();
const Twitter = require("twitter-v2");
const axios = require("axios");

var client = new Twitter({
  consumer_key: process.env.TWITTER_CONSUMER_KEY,
  consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
  bearer_token: process.env.TWITTER_BEARER_TOKEN
});

app.get("/", async (request, response) => {
  const { data } = await client.get("tweets", { ids: "1343068487405596672" });
  response.send(data);
});

const listener = app.listen(process.env.PORT, () => {
  console.log("Your app is listening on port " + listener.address().port);
});
(node:3865) UnhandledPromiseRejectionWarning: Error: Client Forbidden: When authenticating requests to the Twitter API v2 endpoints, you must use keys and tokens from a Twitter developer app that is attached to a Project. You can create a project via the developer portal.
    at Function.module.exports.fromJson (/rbd/pnpm-volume/9f6f5ef1-e8fd-449a-bc06-21e1a90a3bac/node_modules/.registry.npmjs.org/twitter-v2/1.0.0/node_modules/twitter-v2/src/TwitterError.js:29:12)
    at Twitter.get (/rbd/pnpm-volume/9f6f5ef1-e8fd-449a-bc06-21e1a90a3bac/node_modules/.registry.npmjs.org/twitter-v2/1.0.0/node_modules/twitter-v2/src/twitter.js:46:32)
    at processTicksAndRejections (internal/process/task_queues.js:88:5)
at async /app/server.js:13:20
(node:3865) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)

Reconnection logic example in readme

Prerequisites

Summary

Hey! I was thinking it would be great if someone more experienced than myself could code a nice general retry logic in case a steam disconnects and throws a TwitterError error. Would be cool to have it in README instead of "probably should have retry logic here" :)

Motivation

Well, my stream died a few times without me noticing ;) Also would useful when you restart an app and stream is already in use.

Describe alternatives you've considered

I've tried to implement something on my own but I've noticed sometimes the stream doesn't reconnect, so there must be something wrong with my approach. Would rather not post it. ;)

List of urlParams ?

Hello,

where might I find a list of the urlParams mentioned in the docs?

e.g.:

client.get(path, urlParams);

Thank you

I can't reply to a specific tweet

Hello,

As i said in the title i can't reply to a specific tweet using his id, i probably do it wrong but it look like good for me,
so could someone help me ? Thank you for how will help me.

image

My tokens are good because i can get throw the stream all tweet ( with client2) , but it's not working for client

And it's working from postman with same tokens :
image

Getting "TypeError: undefined is not a constructor (evaluating 'new url_1.URL)"

Prerequisites

  • [x ] Put an X between the brackets on this line if you have done all of the
    following:
    • Checked that your issue isn't already filed: [open issues]
    • Checked the [bug report guidelines]

Description

Trying to run the readme example, it is throwing error Unhandled Promise Rejection: TypeError: undefined is not a constructor (evaluating 'new url_1.URL(https://api.twitter.com/2/${endpoint}`)')`.

2021-04-14 at 12 15

Steps to Reproduce

  1. Init Twitter v2 and try to console log data as below
const Twitter = require('twitter-v2');

const client = new Twitter({
  consumer_key: '',
  consumer_secret: '',
  access_token_key: '',
  access_token_secret: '',
});

const { data } = await client.get('tweets', { ids: '1228393702244134912' });
console.log(data);
  1. This will throw the error mentioned above and shown in the screenshot

Expected behavior:

It should console the response

Actual behavior:

It throws error as shown in the above screenshot

Reproduces how often:

All the time

1.1.0

error code 410 error description unauthorized

working of code: I am making a twitter bot that tweet from my text file named as tweet.txt after fixed time interval using javascript language.
Code:
const Twitter = require('twitter-v2');
const fs = require('fs');

const client = new Twitter({
consumer_key:'',
consumer_secret:'',
access_token_key:'',
access_token_secret:'',
});

function readTweetsFromFile() {
const tweets = fs.readFileSync('tweets.txt', 'utf8').split('\n');
return tweets.filter((tweet) => tweet.trim() !== '');
}

async function postTweet(tweet) {
console.log('Posting tweet:', tweet);
try {
console.log('client:', client);
console.log('client.tweets:', client.tweets);
console.log('client.tweets.createTweet:', client.tweets.createTweet);
const response = await client.tweet.createTweet({
text: tweet,
});
console.log('Tweet posted successfully:', response.data.text);
} catch (error) {
console.error('Error posting tweet:', error);
if (error.response) {
console.error('Response status:', error.response.status);
console.error('Response data:', error.response.data);
}
}
}

const tweets = readTweetsFromFile();
const interval = 1000 * 60 * 60; // 1 hour

function tweetInterval() {
for (let i = 0; i < tweets.length; i++) {
setTimeout(() => {
postTweet(tweets[i]);
}, interval * i);
}
}

tweetInterval();
setInterval(tweetInterval, interval * tweets.length);

const Twitter = require('twitter-v2');
const fs = require('fs');

const client = new Twitter({
consumer_key:'',
consumer_secret:'',
access_token_key:'',
access_token_secret:'',
});

function readTweetsFromFile() {
const tweets = fs.readFileSync('tweets.txt', 'utf8').split('\n');
return tweets.filter((tweet) => tweet.trim() !== '');
}

async function postTweet(tweet) {
console.log('Posting tweet:', tweet);
try {
console.log('client:', client);
console.log('client.tweets:', client.tweets);
console.log('client.tweets.createTweet:', client.tweets.createTweet);
const response = await client.tweet.createTweet({
text: tweet,
});
console.log('Tweet posted successfully:', response.data.text);
} catch (error) {
console.error('Error posting tweet:', error);
if (error.response) {
console.error('Response status:', error.response.status);
console.error('Response data:', error.response.data);
}
}
}

const tweets = readTweetsFromFile();
const interval = 1000 * 60 * 60; // 1 hour

function tweetInterval() {
for (let i = 0; i < tweets.length; i++) {
setTimeout(() => {
postTweet(tweets[i]);
}, interval * i);
}
}

tweetInterval();
setInterval(tweetInterval, interval * tweets.length);

Error message"
C:\Users\HANZLA\Desktop\twitter_bot>node index.js
Posting tweet: "Opportunities multiply as they are seized." - The Art of War by Sun Tzu
Error posting tweet: TwitterError: Unauthorized
at module.exports.fromJson (C:\Users\HANZLA\Desktop\twitter_bot\node_modules\twitter-v2\build\TwitterError.js:23:16)
at Twitter.post (C:\Users\HANZLA\Desktop\twitter_bot\node_modules\twitter-v2\build\twitter.js:63:49)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async postTweet (C:\Users\HANZLA\Desktop\twitter_bot\index.js:19:22) {
code: 401,
details: 'Unauthorized'
}

errro.txt

I double check all the api keys and access token keys
this is what it gave in terminal when i update the twitter v-2
library
"up to date, audited 8 packages in 4s

2 high severity vulnerabilities

Some issues need review, and may require choosing
a different dependency."

Filtered stream disconnected every 5 minutes

Hi,

this is very very likely NOT an issue with twitter-v2, but I am hoping someone here may have a thought: My filtered stream disconnects every 5 minutes without raising an error. Reconnect works just fine, but I fear I am losing data in the meantime. I am able to reproduce this across two different machines with different internet connections and different twitter accounts.

I have used twitter-v2 for several weeks without seeing this happening, it started a couple of days ago. I made a few changes to my code and updated to a more recent version of twitter-v2, but none of this seems a plausible explanation for the disconnects.

  • First question is general: Has anyone experienced the same disconnects and if so under what conditions?
  • Second question is about twitter-v2: Is there any further information coming in with the request/stream that I could access to debug this? I was thinking for instance about warning messages by twitter?

Thanks for any thoughts or suggestions!
Thilo

TypeError: Cannot read property 'startsWith' of undefined

Here is my code

let twitter = require("twitter-v2");

let client = new twitter({
    consumer_key: "...",
    consumer_secret: "...",
    access_token_key: "...",
    access_token_secret: "..."
})


const { data } = client.get('search/tweets', { q: 'Kawaki', count: 5 });
console.log(data);

and when i run it, i get following error

C:\Users\<USER>\node_modules\twitter-v2\src\Credent
ials.js:129
    this._bearer_token = bearer_token.startsWith('Bearer ')
                                      ^

TypeError: Cannot read property 'startsWith' of undefined
    at new Credentials (C:\Users\<USER>\node_module
s\←[4mtwitter-v2←[24m\src\Credentials.js:129:39)
    at new Twitter (C:\Users\<USER>\node_modules\←[
4mtwitter-v2←[24m\src\twitter.js:30:14)
    at Object.<anonymous> (C:\Users\<USER>\index.js
:3:14)
←[90m    at Module._compile (internal/modules/cjs/loader.js:1118:30)←[39m
←[90m    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1138:1
0)←[39m
←[90m    at Module.load (internal/modules/cjs/loader.js:982:32)←[39m
←[90m    at Function.Module._load (internal/modules/cjs/loader.js:875:14)←[39m
←[90m    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_ma
in.js:71:12)←[39m
←[90m    at internal/main/run_main_module.js:17:47←[39m

what should i do ?

Stream Disconnects Too Soon - Increase Heartbeat Wait

Prerequisites

  • [ X] Put an X between the brackets on this line if you have done all of the
    following:

Description

Twitter streaming consistently disconnects at the 21 to 22 second mark depending on lag. It seems they have adjusted their heartbeat length to be slower. Please adjust the hardcoded amount to 30 seconds. There is a referenced open PR that allows for it to be adjustable.

See: #63

Steps to Reproduce

  1. Testing on AWS has shown repeated disconnects. Running it locally with breakpoints confirms the 20 second timer occurs too quickly causing the stream to think it is disconnected.

Expected behavior:

The stream to stay open. It is closing before it receives the heartbeat.

Actual behavior:

The stream closes too early.

Reproduces how often:

It depends on the time of day. It seems Twitter has extended their heartbeat length to exactly 20 seconds. Any lag causes a disconnect.

Versions

v1.0.7

Question about authentication

Dear sir,

I was given oauth v2 credentials, is there an option in your library for the bearer token style auth yet?

Thanks

Error: Unauthorized when using tweets/search/all

It works 100% perfectly when tweets/search/recent, but as soon as I switch to tweets/search/all, it falls apart

Works:

const { data } = await client.get("tweets/search/recent", { query: "test" });

Does not work:

const { data } = await client.get("tweets/search/all", {
    query: "test",
    start_time: yesterday.toUTCString(),
    end_time: new Date().toUTCString()
});

If it omit start_time and end_time, it gives:

Error: Unsupported Authentication: Authentication with OAuth 1.0a User Context is forbidden. Please, make the request with OAuth 2.0 Bearer Token authentication.

Stream exited silently

This is more of a question. In what scenario would the stream exit silently? Is there a way to capture it then attempt to reconnect? Thanks.

My Twitter bot exit silently from time to time without any error messages. My dev account only has this stream and the stream is only watching one account(1 or 2 tweets per day).

async function consumeStream() {
    try {
      const client = new Twitter(TWITTER_AUTH);
      const stream = client.stream('tweets/search/stream');
      for await (const { data } of stream) {
        if (data) {
          console.log(`Got new tweet ${data.id}`);
          const link = `https://twitter.com/i/web/status/${data.id}`;
          if (data.text.match(/(event|update|issue|maintenance)/i)) {
            await sendMessageThenPublish(CHANNEL_ID_AUTOPUBLISH, link);
          }
          else {
            await sendMessage(CHANNEL_ID_BACKUP, link);
          }
        }
      }
    }
    catch (err) {
      console.error(err);
      await sendMessage(CHANNEL_ID_BACKUP, `An error occurred while watching twitter stream. Restart in 5 mins!`);
      await new Promise(r => setTimeout(r, 5 * 60 * 1000)); // wait 5 mins
      await consumeStream();
    }
  }

User fields not returning any data

Prerequisites

  • Put an X between the brackets on this line if you have done all of the
    following:

Description

Attempting to get the username of a tweet author doesn't return information but also doesn't return an error

Steps to Reproduce

const params = {
        query:'"happiness is" -sad -worst -sucks -never -bad -disappointing -is:retweet lang:en -has:mentions -has:hashtags',
        expansions:'author_id',
        max_results:100,
        user:{
            fields: ['username']
        }
    }
const { data: tweets } = await client.get('tweets/search/recent', params)
console.log(tweets)

Expected behavior:

return user fields in console log

Actual behavior:

 {
    author_id: '731951078',
    id: '1398876897568776192',
    text: 'Happiness is the only option no matter what     What mean to be will 🙌🏻'
  },

Reproduces how often:

100%

Versions

latest

Additional Information

N/A

More streaming examples

Summary

Can you add an example on how to get streams using urlParams?

Motivation

I'm stuck trying to get real time tweets from specific accounts. The streaming example is too simple to assist me.

Describe alternatives you've considered

I read the official API docs and it didn't help

Validation error if only bearer token is provided (consumer_key and consumer_secret required)

Thanks a lot for this package, it seems to make my twitter life substantially easier! A small issue I stumbled upon:

consumer_key and consumer_secret are required and if not present the validation function in Credentials.js throws an error. However, app auth and streaming work fine just with the bearer token – with the advantage that the token can be used elsewhere, e.g. to update rules. I commented the lines out and streaming works fine.

Stream Connection Problems

Hello, I'm using this library to create a back-end to an App I'm building for my portfolio, so I don't plan on releasing it on an App Store.

One thing that it does is that it listens to tweets of the accounts the user has added to the app.

Since I'm still building it, I oftenly have to change one or two lines of code in the back-end, then save and it starts running again. But I'm having this annoying problem, that whenever the app stops and starts running again after a short time, the stream doesn't start so it can't listen to tweets.

TwitterError: ConnectionException: This stream is currently at the maximum allowed connection limit.
    at Function.module.exports.fromJson (/home/samuel/stlk-api/node_modules/twitter-v2/src/TwitterError.js:29:12)
    at Stream.<anonymous> (/home/samuel/stlk-api/node_modules/twitter-v2/src/TwitterStream.js:60:40)
    at Stream.emit (node:events:379:20)
    at Stream.EventEmitter.emit (node:domain:470:12)
    at drain (/home/samuel/stlk-api/node_modules/through/index.js:36:16)
    at Stream.stream.queue.stream.push (/home/samuel/stlk-api/node_modules/through/index.js:45:5)
    at emit (/home/samuel/stlk-api/node_modules/split/index.js:37:14)
    at Stream.<anonymous> (/home/samuel/stlk-api/node_modules/split/index.js:60:7)
    at _end (/home/samuel/stlk-api/node_modules/through/index.js:65:9)
    at Stream.stream.end (/home/samuel/stlk-api/node_modules/through/index.js:74:5) {
  details: 'https://api.twitter.com/2/problems/streaming-connection'
}

I've tried to listen to the stop events, but to no success

process.on('SIGTERM', () => {
        console.info('SIGTERM signal received.');
        console.log('Closing http server.');
        twitterService.closeStream();
    });
    process.on ('SIGINT', () => {
        console.info('SIGINT signal received.');
        console.log('Closing http server.');
        twitterService.closeStream();
        process.exit(0);
    }); 

Is there anything I can do to fix or workaround this?

Export types/interfaces/etc from central index.ts file for consumer usage

Prerequisites

Summary

Currently, while Credentials, CredentialsArgs, TwitterStream, etc. are defined in TypeScript definition files, and included in the build, they cannot be imported without digging into the structure of the package:

import Credentials, { CredentialsArgs } from "twitter-v2/build/Credentials";
import TwitterStream from "twitter-v2/build/TwitterStream";

With an index.ts file that exports these types/class definitions, it could simplify the importing structure alongside the main client:

import Twitter, { Credentials, CredentialsArgs, TwitterStream } from "twitter-v2";

Motivation

For one, users can more easily figure out what is exported for public use through the index.ts file - there may be certain types/classes that aren't meant to be publicly exported that won't exist in here, but can be used internally. It also just cleans up the number of imports that a user might have for various parts of the package, without needing to know what the structure of the package looks like.

On a related note, it may be worth defining the files property in the package.json file which would send out the built files only - there's no need to pack up the src/*.ts files when consumers are actually using the build/*.js and build/*.d.ts files.

Describe alternatives you've considered

Additional context

Confused about oauth version (?)

Hi again,

If I log a new Twitter object, I notice it says it's using Oauth 1.0

Isn't the app auth w/ bearer token oauth v2.0? Reference: https://developer.twitter.com/en/docs/authentication/oauth-2-0

This:

import * as Twitter from 'twitter-v2';
import { apiKey, apiSecretKey, bearerToken } from 'keys';

const client = new Twitter({
  consumer_key: apiKey,
  consumer_secret: apiSecretKey,
  bearer_token: bearerToken,
});

console.log(client);

Returns this:

Twitter {
  credentials: Credentials {
    _consumer_key: '...',
    _consumer_secret: '...',
    _bearer_token: '...',
    _access_token: undefined,
    _access_token_secret: undefined,
    _bearer_token_promise: null,
    _oauth: OAuth {
      consumer: [Object],
      nonce_length: 32,
      version: '1.0',
      parameter_seperator: ', ',
      realm: undefined,
      last_ampersand: true,
      signature_method: 'HMAC-SHA1',
      hash_function: [Function: hash_function],
      body_hash_function: [Function: hash_function]
    }
  }
}

FWIW, I'm GETting tweets just fine. Is the stated oauth version anything I should be concerned about?

Thanks

Handle .errors[] in streams

Prerequisites

Summary

Some chunks coming from the stream API look like the example below.
First, would it make sense to report whatever is coming in .errors[] as TwitterError?
Second, would the code become more elegant by disconnecting explicitly on receiving OperationalDisconnect?

const chunk = {
  errors: [
    {
      title: 'operational-disconnect',
      disconnect_type: 'OperationalDisconnect',
      detail: 'This stream has been disconnected for operational reasons.',
      type: 'https://api.twitter.com/2/problems/operational-disconnect',
    },
  ],
}

Motivation

My code was naively expecting to receive consistently formed chunks and errored out on this unexpected shape. Which is kind of fine, but since this is an explicit error, it probably would make sense to centralize its handling in the twitter-v2.

Describe alternatives you've considered

Leaving this for all library users to handle by themselves is also an option, a wasteful one though.

Additional context

Switch to built-in Node crypto package

When I used Node 12 (LTS)

I receive this warning, not sure if it is complicated to update.

warning twitter-v2 > [email protected]: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.

Can't get user auth working

‼️ WORKING SOLUTION BELOW ‼️

Hey! First of all - great initiative and awesome work on pushing the first twitter v2 client for node.js, thanks for that 👍 I am having some troubles using the user auth and wanted to seek your help. First question - is it supported by the library already? Second question - do the credentials that are working with API v1 work with version two also? Now closer to the code :

  1. this one throws error, just having a brief look at the code - it shall be just access_token without key
const client = new Twitter({
  consumer_key: '',
  consumer_secret: '',
  access_token_key: '',
  access_token_secret: '',
});
  1. Still this will not work for some reason:
async function main() {
  const test = new TwitterV2({
    consumer_key: TWITTER_KEY,
    consumer_secret: TWITTER_SECRET,
    access_token: TWITTER_TOKEN_KEY,
    access_token_secret: TWITTER_TOKEN_SECRET,
  });

  const { data } = await test.get('tweets', { ids: '1304072330839306240' });
  console.log(data);
}

main();

The error is following:

Unauthorized
at Function.module.exports.fromJson (path_to_project/node_modules/twitter-v2/src/TwitterError.js:25:12)

Which brings me to the question - do I need to do some specific steps for this to work outside the lib itself like on twitter dev acc or? I want to use it to get impression counts for some tweets.

Any help appreciated + if you need any help yourself with the library, I am all up to give you a hand here or there

SOLUTION ‼️

You need to sign up for the NEW dev dashboard, add your app to the project supported to version two and finally you may want to regenerate you access token and access token secret. After these steps it shall work correctly with supplied credentials. Maybe this deserves a place in docs for now, as Twitter migrates it's api 😀

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.