Giter VIP home page Giter VIP logo

twitter-api-client's Introduction

Twitter API Client

Node.js client for Twitter API

NPM Version Build Status

⚠️ Important notice

Twitter now has an official TypeScript SDK.
We recommend using that instead of this client.

This project will be maintained, but will not be developed any further.

To all contributors who added to this project: Thank you 🧡

Table of content

Features

☑️ Includes 90% of the official Twitter API endpoints.
☑️ Promise-based! No ugly callbacks.
☑️ Fully typed! Both for query parameters and responses.
☑️ Inbuilt in-memory cache for rate-limit friendly usage.

Getting Started

Get your Twitter credentials

You will need to create a set of Twitter developer credentials from your Twitter Developer account.
If you don't have one already, apply for a developer account here.
It takes about 5 minutes.

Install

npm i twitter-api-client

Usage

import { TwitterClient } from 'twitter-api-client';

const twitterClient = new TwitterClient({
  apiKey: '<YOUR-TWITTER-API-KEY>',
  apiSecret: '<YOUR-TWITTER-API-SECRET>',
  accessToken: '<YOUR-TWITTER-ACCESS-TOKEN>',
  accessTokenSecret: '<YOUR-TWITTER-ACCESS-TOKEN-SECRET>',
});

// Search for a user
const data = await twitterClient.accountsAndUsers.usersSearch({ q: 'twitterDev' });

// Get message event by Id
const data = await twitterClient.directMessages.eventsShow({ id: '1234' });

// Get most recent 25 retweets of a tweet
const data = await twitterClient.tweets.statusesRetweetsById({ id: '12345', count: 25 });

// Get local trends
const data = await twitterClient.trends.trendsAvailable();

See all available methods here.

Configuration

twitter-api-client comes with an inbuilt in-memory cache.
The stale data is served by the cache-first principle.

You can configure the caching behavior upon instantiation of the client:

const twitterClient = new TwitterClient({
  apiKey: '<YOUR-TWITTER-API-KEY>',
  apiSecret: '<YOUR-TWITTER-API-SECRET>',
  accessToken: '<YOUR-TWITTER-ACCESS-TOKEN>',
  accessTokenSecret: '<YOUR-TWITTER-ACCESS-TOKEN-SECRET>',
  ttl: 120, // seconds. Defaults to 360
  disableCache: true, // Disables the caching behavior. Defaults to 'false'
  maxByteSize: 32000000, // Maximum (approximated) memory size for cache store. Defaults to 16000000.
});

License

This project is licensed under the MIT License

Get Help

Contribute

Issues

In the case of a bug report, bugfix or a suggestions, please feel very free to open an issue.

Pull request

Pull requests are always welcome, and I'll do my best to do reviews as fast as I can. Please refer to the contribution guide to see how to get started.

twitter-api-client's People

Contributors

aapedro avatar an-dy1 avatar bajcmartinez avatar carlitosz avatar dipanjandasit avatar genehack avatar goleary avatar guillaumelamanda avatar iliran11 avatar illuzan avatar keenthinker avatar kyh avatar martiliones avatar marvelefe avatar qanuj avatar repraze avatar simonhoiberg avatar vedantnn71 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  avatar  avatar  avatar  avatar

twitter-api-client's Issues

Twitter Client Test Error

Very quick start test

twitterApi.js

import TwitterClient from "twitter-api-client";

//const TwitterClient = require("twitter-api-client");



const twitterApi = new TwitterClient({
  apiKey: "xxxx",
  apiSecret: "xxx",
  accessToken: "xxxx",
  accessTokenSecret: "xxxx",
  ttl: 120, // seconds. Defaults to 360
  disableCache: true, // Disables the caching behavior. Defaults to 'false'
  maxByteSize: 32000000, // Maximum (approximated) memory size for cache store. Defaults to 16000000.
});
const data = await twitterClient.accountsAndUsers.usersSearch({ q: 'twitterDev' });

node run command
node --experimental-modules twitterApi.js

Errors
TypeError: TwitterClient is not a constructor

const data = await twitterClient.accountsAndUsers.usersSearch({ q: 'twitterDev' });
^^^^^ SyntaxError: Unexpected reserved word

Can you please add a simple test start code?

Support for OAuth 2.0 Bearer Token

Could you consider adding support for OAuth 2.0 Bearer Token?

My use case is exactly the one presented in Twitter's doc in which I only need read-only access to pull public information.

Thank you for providing this library.

tweets.statusesHomeTimeline uses wrong StatusesHomeTimeline return type

Describe the bug
client.tweets.statusesHomeTimeline({...}) returns a list of statuses from the current user timeline. The type should be a list of tweets like Promise<StatusesHomeTimeline[]> and not Promise<StatusesHomeTimeline>. The type given currently is a single tweet even if we get an array of statuses.

To reproduce
Steps to reproduce the behavior:

  1. In a typescript project install the package
  2. call client.tweets.statusesHomeTimeline({...})
  3. the output is a list, the time is a single tweet

Expected behavior
The type should be a list if the method always returns a list of status. Promise<StatusesHomeTimeline[]>, Promise<Array <StatusesHomeTimeline>> or similar.

Package Manager:
npm

Additional context
N.A.

Split up the twitter-api-spec.yml file

Currently

The Twitter API Client is generated based on one single twitter-api-spec.yml file which is currently a whopping 3000+ lines long.
It's really cumbersome to scroll around in that file to find what you want.

Desired

The twitter-api-spec.yml file is split up into multiple .yml files.
One for each group.

AC

  • The folder src/spec/ is renamed to src/specs/ and all references in the generator files are changed.
  • The file twitter-api-spec.yml is split up into multiple files.

Additional notes

To begin with, I think it would be great to have one for each group.
A file src/specs/basics.yml, a file src/specs/accounts-and-users.yml, a file src/specs/tweets.yml, etc.
The file twitter-api-spec.yml should still be the main spec file that references these other files.

Unable To Send Direct Message.

Thanks for your awesome work.

I have been unable to send direct messages while following the reference document.

Whenever I run

let parameters ={id:"1322838158258720769", data:"helloworld"}
twitterClient.directMessages.directMessagesEventsNewMessageCreate(parameters)
.catch(err => { console.log(err) })

the library keeps returning { statusCode: 415, data: '' }.

What am I doing wrong?

My current version is "twitter-api-client": "^1.2.0"

Thank You Very Much

Getting the reply count with statusesUserTimeline

Hi,
Is it possible somehow today to get the reply count when using the method: await this.twitterClient.tweets.statusesUserTimeline();

I know in the Twitter UI it apears in .reply_count.
Or maybe another request to get this item.

Thanks

Using OAuth 2.0 as authorization to log in.

Description:
Hello, in my application I can only get access tokens (OAuth 2.0), when I set accessToken without apiKey it says that apiKey is required.

Ideal solution:
An option to set the authorization as OAuth 2.0 when creating the client or be able to only set accessToken.
const twitterClient = new TwitterClient({ accessToken: '', });
or
const twitterClient = new TwitterClient({ accessToken: '', OAuth2: true });
or
const twitterClient = new TwitterClient({ accessToken: '', auth_type: "oauth2.0" });

Describe alternatives you've considered
Official API.

Additional context
I'm trying to build an app so users if they want, go to a page, login and the app can post tweets on their behalf (with consent).

400 On twitter.accountsAndUsers.accountUpdateProfileBanner()

Describe the bug
As per the documentation of Twitter and twitter-api-client, here is the code I've written that should update an account's cover image 👇

const { default: TwitterClient } = require('twitter-api-client')
const fs = require('fs')

const twitter = new TwitterClient({
    apiKey: '[API key]',
    apiSecret: '[API secret]',
    accessToken: '[access token]',
    accessTokenSecret: '[access token secret]'
})

const set = async () => {
    try {
        const data = await twitter.accountsAndUsers.accountUpdateProfileBanner({
            banner: fs.readFileSync('cover.jpg', { encoding: 'base64' })
        })
        
        console.log(data)
    } catch (e) {
        console.log(e)
    }
}

set()

This results in 👇

{ statusCode: 400, data: '' }

and does not update the cover image of the authorized user. A quick note: The import is wrapped in a default, which requires the usage of this ☝️ ugly syntax. Tried on JavaScript CommonJS and JavaScript ECMAScript Modules 🙂

To reproduce
Steps to reproduce the behavior:

  1. Copy the above code.
  2. Install credentials
  3. Have an image on the same directory named cover.jpg
  4. Run the script.

Expected behavior
An updated cover image with a response of statusCode of 200 or 201 with data set to an empty string.

Package Manager:
Yarn: v1.22.5
Node.js: v15.0.1

Additional context
According to the documentation, on Twitter, the field banner should be sent as a URL query parameter. But since a banner is usually a big file (relatively) it's a bad practice to send it through URL query parameters.

Hence Twitter has updated to use x-www-form-urlencoded (POST body) and that isn't updated in their docs. Thanks, @silind for making this module and I am 🙂 happy to give more info.

GET lists/members need list parameters

Describe the bug

The twitter endpoint /list/members need list parameters but currently doesn't take any.

To reproduce
Steps to reproduce the behavior:

  1. Install the latest Twitter client
  2. Open a JS/TS file
  3. Create a twitter client,
  4. Call client.accountsAndUsers.listsMembers() method
  5. See the error :
     data: '{"errors":[{"code":112,"message":"You must specify either a list ID or a slug and owner."}]}' } 
    

Expected behavior

Id should take list_id and slug as parameter according to the endpoint API

Package Manager:
To install Twitter API Client, I used yarn

Installation twitter-api-client

I have installed the library in my vue 3 project, when importing it I get the following errors:

" ERROR Failed to compile with 5 errors 12:32:51

error in ./node_modules/oauth/lib/oauth.js

Module not found: Error: Can't resolve 'crypto' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }

error in ./node_modules/oauth/lib/oauth.js

Module not found: Error: Can't resolve 'http' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }

error in ./node_modules/oauth/lib/oauth.js

Module not found: Error: Can't resolve 'https' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "https": require.resolve("https-browserify") }'
- install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "https": false }

error in ./node_modules/oauth/lib/oauth.js

Module not found: Error: Can't resolve 'url' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "url": require.resolve("url/") }'
- install 'url'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "url": false }

error in ./node_modules/oauth/lib/oauth.js

Module not found: Error: Can't resolve 'querystring' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "querystring": require.resolve("querystring-es3") }'
- install 'querystring-es3'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "querystring": false }

ERROR in ./node_modules/oauth/lib/oauth.js 3:13-30
Module not found: Error: Can't resolve 'crypto' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
@ ./node_modules/oauth/index.js 1:0-44 2:0-52
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth.js 5:11-26
Module not found: Error: Can't resolve 'http' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }
@ ./node_modules/oauth/index.js 1:0-44 2:0-52
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth.js 6:12-28
Module not found: Error: Can't resolve 'https' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "https": require.resolve("https-browserify") }'
- install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "https": false }
@ ./node_modules/oauth/index.js 1:0-44 2:0-52
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth.js 7:10-24
Module not found: Error: Can't resolve 'url' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "url": require.resolve("url/") }'
- install 'url'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "url": false }
@ ./node_modules/oauth/index.js 1:0-44 2:0-52
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth.js 8:18-40
Module not found: Error: Can't resolve 'querystring' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "querystring": require.resolve("querystring-es3") }'
- install 'querystring-es3'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "querystring": false }
@ ./node_modules/oauth/index.js 1:0-44 2:0-52
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth2.js 1:18-40
Module not found: Error: Can't resolve 'querystring' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "querystring": require.resolve("querystring-es3") }'
- install 'querystring-es3'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "querystring": false }
@ ./node_modules/oauth/index.js 3:0-47
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth2.js 2:13-30
Module not found: Error: Can't resolve 'crypto' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
@ ./node_modules/oauth/index.js 3:0-47
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth2.js 3:12-28
Module not found: Error: Can't resolve 'https' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "https": require.resolve("https-browserify") }'
- install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "https": false }
@ ./node_modules/oauth/index.js 3:0-47
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth2.js 4:11-26
Module not found: Error: Can't resolve 'http' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }
@ ./node_modules/oauth/index.js 3:0-47
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

ERROR in ./node_modules/oauth/lib/oauth2.js 5:10-24
Module not found: Error: Can't resolve 'url' in 'C:\projectJorge\project-jorge\node_modules\oauth\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "url": require.resolve("url/") }'
- install 'url'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "url": false }
@ ./node_modules/oauth/index.js 3:0-47
@ ./node_modules/twitter-api-client/dist/base/Transport.js 169:30-46
@ ./node_modules/twitter-api-client/dist/index.js 16:34-61
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/HelloWorld.vue?vue&type=script&lang=js 3:0-51 41:32-45
@ ./src/components/HelloWorld.vue?vue&type=script&lang=js 1:0-202 1:0-202 1:203-394 1:203-394
@ ./src/components/HelloWorld.vue 2:0-61 3:0-56 3:0-56 8:49-55
@ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
@ ./src/App.vue?vue&type=script&lang=js 1:0-189 1:0-189 1:190-368 1:190-368
@ ./src/App.vue 2:0-54 3:0-49 3:0-49 8:49-55
@ ./src/main.js 2:0-28 5:10-13

webpack compiled with 10 errors"

I don't know exactly the reason for this error, it's driving me crazy and I don't know how to fix it.
Node V: 16.17.0
NPM 8.15.0

Access token and secret required for pre-access token OAuth 1.0 steps

Hi there,

I'm attempting to implement the standard 3-leg sign-in process using OAuth 1. After I input the consumer api key and consumer secret, the next step is to request an OAuth token which I can later exchange for an access token.

However, browsing the source code of this project, I noticed that the class constructor automatically throws an error if the access token and access token secret are not provided. This makes sense, but the code should not throw an error for values that should not exist yet. Actually, the typescript interface permits the access token and secret properties to be omitted, but the source code itself throws an error if they are.

I also tried to just enter placeholder values so the error would not occur at instantiation. But these were not accepted by Twitter:

{
statusCode: 401,
data: '{"errors":[{"code":89,"message":"Invalid or expired token."}]}'
}

I assume the client is embedding the placeholder with the request, which also makes sense but is unhelpful in this context. The whole situation is kind of a catch-22.

Support semi-required parameters

Is your feature request related to a problem? Please describe.
For multiple endpoints, there is a constraint that either user_id or screen_name should be provided.
An example can be found in this bug report.

On the Twitter Documentation, both user_id and screen_name is flagged as required, where in fact, only one of them is required.
This is also stated in the description.

I will call these types of parameters semi-required in respect to another parameter.

Describe the solution you'd like
Back in a very early version, I introduced a type UserIdOrScreenName that was able to make exactly this inference.
See the implementation here
This type got discarded due to the introduction of the generators.

I suggest that we reintroduce this type and introduce a new syntax in the twitter-api-spec.yml file, that indicates semi-required fields.

A suggestion could be the following:

parameters:
  - name: user_id
    description: ....
    required: !screen_name # <- Conditional requirement
    type: number
  - name: screen_name
    description: ....
    required: !user_id # <- Conditional requirement
    type: string

Describe alternatives you've considered
I think the above suggestion would be feasible, however, we could also implement solutions inspired by big projects, to make the syntax more familiar.

Here is a couple of examples of conditionals in YAML specifications:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html

Additional context
Let's discuss a good solution in this issue 👇

Trend functionality not working as expected

Describe the bug
When using the Trends api functions - the documentation appears to suggest that you need to pass through the WOEID, or IDs in general as integers into the functions, however if you pass in just the value, the URL is malformed:
https://api.twitter.com/1.1/trends/place.json?
instead of https://api.twitter.com/1.1/trends/place.json?id=1

To reproduce
Steps to reproduce the behavior:

  1. Run await twitterClient.trends.trendsPlace(1);
  2. You will receive a 404 error
  3. Call function again as await twitterClient.trends.trendsPlace({id: 1});
  4. Function will run successfully

Expected behavior
I would expect the documentation to clearly express what payload it was expecting, or that the function runs successfully when passing through the integer by itself

Package Manager:
To install Twitter API Client, I used npm

Need help retrieving media from DM

Hi,
I just started making a Twitter bot.

Is there any way I can automatically retrieve media from DM and tweet them using this client?
I have managed to retrieve the URL. However, I am not authorized(?) to access it and I am not sure how to exactly do that.

My understanding is that I need to have access to it in order to be able to download it, get the raw binary or base64 encoding of it, and finally upload and tweet it.
Is my understanding correct or is there a better way to do so?

Thank you.

Many methods won't work correctly without `stringify_ids` set to true

Describe the bug

Hey there, thanks for this library! Unfortunately I'm experiencing quite a few footguns while trying to use it. I understand that it's trying to be a fairly close mapping to the Twitter API, but in my opinion some parameters should be set by default, or else package consumes are going to experience strange, confusing errors.

Case in point: several methods get a list of user IDs -- for example, client.accountsAndUsers.friendsIds() and client.accountsAndUsers.friendshipsNoRetweetsIds(). If these are called without passing stringify_ids: true as a parameter, the results they return may be invalid. For example, if I do this:

const { ids: userIds } = await client.accountsAndUsers.friendsIds();

const tl = await client.tweets.statusesUserTimeline({
  user_id: userIds[0],
  count: 3,
});

I get a confusing 404 error. This is because the list of IDs is invalid (and the Twitter API can't detect it and provides a very poor error code in response). To make this code work, I have to do this:

const { ids: userIds } = (await client.accountsAndUsers.friendsIds({
  stringify_ids: true,
})) as unknown as { ids: string[] };

const tl = await client.tweets.statusesUserTimeline({
  user_id: userIds[0],
  count: 3,
});

Unfortunately, this package isn't smart enough to parametrize the return type of this endpoint based on whether stringify_ids is set, so we need to perform a double-cast to manually specify the type that's actually returned.

Expected behavior

This package should probably automatically set stringify_ids to true whenever it's available as a parameter. The Twitter API documentation prominently mentions on several pages that this parameter is strongly recommended to be set when using languages like JavaScript. While this would technically be a breaking change, I think it's worth it to help smooth over a serious footgun (and typings that are wrong to boot). Maybe it could be released as a semver-major bump?

I understand that this would deviate from providing a "clean" mapping to the Twitter API, but if this deviation were documented clearly in the readme (and if the typings accurately reflected the stringified return types for the affected calls) I think the benefit would be significant.

Package Manager:

Yarn

Any support for the streaming API.

I am wondering if there is any support yet for the streaming API. Other packages are there but they are outdated. This would be promising to get anything for that.

statuses/oembed support

Is your feature request related to a problem? Please describe.
No.

Describe the solution you'd like
I was looking for support for the statuses/oembed endpoint but didn't find it listed in the available methods. I realized I needed this for one of my projects and I'd love it if you added support for this. I could write a quick script to do the job, but i'd rather use the client. Thank you.

Describe alternatives you've considered
Haven't looked into using alternatives.

Additional context
No additional context.

`accountsAndUsers.friendshipsNoRetweetsIds()` returns Promise<unknown>

Describe the bug

Hi again, another quick bug. accountsAndUsers.friendshipsNoRetweetsIds() returns Promise<unknown>, but the actual return type appears to be Promise<number[]> (if stringify_ids is false or omitted, which as noted in #101 should not be the case IMO), or Promise<string[]> (if stringify_ids is true).

To reproduce

  1. const ids = await client.accountsAndUsers.friendshipsNoRetweetsIds().
  2. Attempt to consume ids in another method or expression.
  3. ids is of type unknown.

Expected behavior

The call is well-typed.

Package Manager:

Yarn

403 on twitter.accountsAndUsers.accountUpdateProfileBanner()

Describe the bug
I'm trying to update the Twitter banner of my user. I've created and tested with both v1 and v2 applications in the developer portal.

Here is my code:

const twitterClient = new TwitterClient({
  apiKey: process.env.API_KEY,
  apiSecret: process.env.API_SECRET,
  accessToken: process.env.CONSUMER_KEY,
  accessTokenSecret: process.env.CONSUMER_SECRET,
});


const uploadBanner = async () => {
  const base64 = fs.readFileSync('1500x500.png', { encoding: 'base64' });
  try {
    await twitterClient.accountsAndUsers.accountUpdateProfileBanner({
      banner: base64,
    });
  } catch (err) {
    console.log(err);
  }
};

To reproduce
Steps to reproduce the behaviour:

  • Create a new TwitterClient instance
  • Get the last 3 followers (just for testing the client works)
  • Read with fs an image (base64)
  • Get an error when trying to update the profile banner

The error: { statusCode: 403, data: '' }

Expected behaviour
The banner was successfully updated on Twitter

** Package Manager: **

  • nodejs: v16.13.2
  • npm: 8.1.2
  • Mac OS Monterey 12.2.1 (M1)
  • From package.json: "twitter-api-client": "^1.5.2"

Additional context
AFAIK it has to be less than 700kb. The image size I'm using is ~200kb

Edit:
I'm starting to think it's related to the app settings and permissions.
I managed to get the latest followers. So, the client connection works.

`oauth_token` is a required parameter for the access_token endpoint

Describe the bug
There's a bug in what the basics.oauthAccessToken(...) method accepts in its parameters object.

Right now, it only accepts the an object containing the field oauth_verifier.

However, in order to successfully to return a valid access token, both the oauth_verifier and oauth_token (where the request token is the value for oauth_token) need to be passed. Per the docs below, the access_token endpoint requires both parameters https://developer.twitter.com/en/docs/authentication/api-reference/access_token

To reproduce
Steps to reproduce the behavior:
Here's the workflow I'm doing to reproduce the error

const data= await TwitterClient.basics
        .oauthRequestToken({ oauth_callback: 'http://localhost:3000/twitterCallback' });

// Redirect the user to `https://api.twitter.com/oauth/authenticate?oauth_token=${data.oauth_token}`
// User goes through authorizing the app via the Twitter UI

// My callback gets hit with `http://localhost:3000/twitterCallback?oauth_token=xxx&oauth_verifier=yyy
// Extract out the oauth verifier and oauth token

// Exchange the oauth verifier for an access token
const response = await TwitterClient.basics.oauthAccessToken({ 
  oauth_verifier: oauthVerifier 
});

This request fails with

{ statusCode: 401, data: 'Request token missing' }

and there's no straightforward way to pass the request token into the call, except by annotating the basics.oauthAccessToken(...) call like this

// Exchange the oauth verifier for an access token
    const response = await TwitterClient.basics.oauthAccessToken({
        oauth_verifier: oauthVerifier,
        oauth_token: oauthToken
    } as any);

Expected behavior
This should succeed and return the user information

Package Manager:
To install Twitter API Client, I used npm

Additional context
Add any other context about the problem here.

Support DELETE verb

Currently, only GET and POST are supported.
There is one endpoint using the DELETE verb.
See here

The endpoint gets bypassed and the client is not created.
See here

AC

  • Support calling the Twitter API with the DELETE verb.
  • Create a corresponding client from the spec file.

`directMessagesEventsNewMessageCreate` is not sending the good query

This code:

await twitterClientRef.current.basics.oauthAccessToken({
        oauth_verifier: "XXXXX",
});

sends this kind of request:

fetch("https://api.twitter.com/1.1/direct_messages/events/new.json", {
  "headers": {
    "accept": "*/*",
    "accept-language": "en-US",
    "authorization": "OAuth oauth_consumer_key=\"XXXXXX\",oauth_nonce=\"XXXXXX\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"XXXXXX\",oauth_token=\"XXXXXX\",oauth_version=\"1.0A\",oauth_signature=\"XXXXXX\"",
    "content-type": "application/x-www-form-urlencoded",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "cross-site",
  },
  "referrer": "http://localhost:3000/3",
  "referrerPolicy": "no-referrer-when-downgrade",
  "body": "id=908597870&data=test",
  "method": "POST",
  "mode": "cors"
});

However, the documentation says this:

Requires a JSON POST body and Content-Type header to be set to application/json. Setting Content-Length may also be required if it is not automatically.

But also that the body should be the following object:

{"event": {"type": "message_create", "message_create": {"target": {"recipient_id": "RECIPIENT_USER_ID"}, "message_data": {"text": "Hello World!"}}}}

I think there is an issue with the lib, isn't it?

Add tweet_mode parameter

Is your feature request related to a problem? Please describe.
The statusesUserTimeline (and possibly other endpoints) supports a tweet_mode parameter. Such value can be extended which allows the full text content of the tweet, and it's hashtags, to be returned in the response.

Describe the solution you'd like
Update the typings to support the extended response structure, as well as adding tweet_mode to the supported args for tweets.statusesUserTimeline function.

Describe alternatives you've considered
For the moment, using //@ts-ignore prevents warnings about invalid parameters and response fields.

Additional context
Sample API response: https://gist.github.com/ChronSyn/f215c96aedfd56b2d7085f4b0f1f4b02

How to make calls using Bearer token?

Hi,

Thanks for great lib!

There is endpoint to obtain bearer token, however I dont see in docs / code how to use it to make requests.

Is it supported?

twitter-api-client should throw `Error`s, not objects

Describe the bug

Hi again, here's another serious issue I've encountered with this library, When I was experiencing the problem described #101 -- confusing 404 errors from the API due to non-string user IDs -- I was having a lot of trouble debugging which twitter-api-client method calls were actually failing. This is because this package appears to throw arbitrary objects rather than Errors when something goes wrong. While this is technically permitted in JavaScript -- one of the language's many quirks -- throwing objects that do not inherit from Error is strongly recommended against, since non-Error objects usually do not provide stack traces and thus make it difficult to identify where the problem originated.

Here's a simple reproduction:

const client = new TwitterClient({
  apiKey: TWITTER_CONSUMER_KEY,
  apiSecret: TWITTER_CONSUMER_SECRET,
  accessToken: TWITTER_ACCESS_KEY,
  accessTokenSecret: TWITTER_ACCESS_SECRET,
});

const tl = await client.tweets.statusesUserTimeline({
  user_id: 12892389, // some arbitrary number, not a real id
});

console.log(tl);

This yields the following console output:

{
  statusCode: 404,
  data: '{"errors":[{"code":34,"message":"Sorry, that page does not exist."}]}'
}

Now, imagine this is part of a chain of several API calls, interleaved with my own business logic. For example, I could be getting a list of user IDs a user follows (via accountsAndUsers.friendsIds()), checking whether retweets are disabled for each of the returned users (via accountsAndUsers.friendshipsNoRetweetsIds()), and then retrieving each user's timeline (via tweets.statusesUserTimeline()), setting include_rts based on whether retweets are disabled for a given user. If something goes wrong in this process and I receive an error like the above 404, how am I supposed to reason about where it originated?

Expected behavior

Method calls should throw new Error(...) or from a custom error type that inherits from Error, as per standard JavaScript best practice. This would provide stack traces to consumers, allowing them to identify where a problem arose, rather than, say, having to verbosely and hermetically seal each twitter-api-client call in a try-catch block with custom error handling to be able to debug which method exploded.

Package Manager:

Yarn

Include an example on how to upload an image with a tweet

Sorry about the noise and thank you for the library.
I need to publish tweets with images in them. The image is actually public and online -- however, my understanding is that the Twitter API requires you to upload the image with the API.
I am banging my head against the wall trying to make this happen.

Are you able to give me some guidance on how publish a tweet with a photo?

I believe this requires uploading of media first, and then posting of the twitter using the media ID.

When I post, if the image is on an URL, am I able to pass it a stream, so that I don't have to download it from the internet first? Are you able to give me some guidance/working code to do that?

Oh yes, the feature request: please add this as an example in your README!

Deno Support

Is your feature request related to a problem? Please describe.
By far this is the best API client for Twitter. It would be fantastic if it could be ported to Deno, too!

Describe the solution you'd like
To support twitter-api-client as a Deno module

Describe alternatives you've considered
n/a

Additional context
n/a

CORS Error

Describe the bug
I am following the docs step by step and just trying to use the sample query which is laid out with the docs but I am receiving a CORS error on my query.

Hope someone can point me in the right direction as to what I am doing wrong.

To reproduce
I have a plain .js file which I was hoping to use in my utils and in here I have the code from the docs

import { TwitterClient } from 'twitter-api-client';

const twitterClient = new TwitterClient({
  apiKey: process.env.TWITTER_API_KEY,
  apiSecret: process.env.TWITTER_API_SECRET,
  accessToken: process.env.TWITTER_ACCESS_TOKEN,
  accessTokenSecret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
});

// Search for a user
export const getUseData = async () => {
  const data = await twitterClient.accountsAndUsers.usersSearch({ q: 'twitterDev' });
  console.log(data);
};

I then reference the exported function in my React page's useEffect hook

useEffect(() => {
    getUseData();
  }, []);

and then when the function is triggered i get the scary cors error which says:

http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Expected behavior
I was hoping to see the data logged out not sure why it's being blocked by CORS. Do i need to make these API calls from some sort of a server repo and then pass it to my frontend repo? Or is there anyway I can get it on my client side.

Package Manager:
To install Twitter API Client, I used... (npm / yarn / something else)
npm

Additional context
Add any other context about the problem here.

Thanks Everyone.

Wrong `UsersShowParams` interface

The current UsersShowParams is wrong:

export interface UsersShowParams {
    /**
    * The ID of the user for whom to return results. Either an id or
  screen_name is required for this method.
  
    */
    user_id: string | number;
    /**
    * The screen name of the user for whom to return results. Either
  a id or screen_name is required for this method.
  
    */
    screen_name: string;
    /**
    * The entities node will not be included when set to false.
    */
    include_entities?: boolean;
}

It says user_id or screen_name is required but both are currently required.

Store credentials per instance to allow multiple clients.

Description
Currently, you can only use a single set of Twitter API Credentials.
It's possible to create multiple instances of the Twitter API Client, but every time a new client is taking credentials (and options) in the constructor, the options are stored globally and will overwrite any previously set credentials (and options).

Currently
Once a client is instantiated, the Twitter API Credentials are set globally.

Desired
Being able to instantiate multiple clients with each of their own credentials.

Unable to instantiate TwitterClient without accessToken and accessTokenSecret

Describe the bug
I wish to use the client to obtain users accessToken and accessTokenSecret, but when I attempt to instantiate the client without those values provided I receive the error "ACCESS TOKEN needs to be provided". Interface for TwitterClient options indicates that both accessToken and accessTokenSecret are optional parameters.

I'm wondering if this is expected behavior and I'm doing something wrong or is this a bug?

To reproduce
Steps to reproduce the behavior:

  1. Instantiate TwitterClient without parameters accessToken and accessTokenSecret.
  2. TypeScript does not complain as the interface indicates these are optional params
  3. Run
  4. See error "ACCESS TOKEN needs to be provided".

Expected behavior
I would expect to be able to instantiate the client and use it to obtain users accessToken and accessTokenSecret, but I'm not sure how to do that.

Package Manager:
To install Twitter API Client, I used npm

Additional context
Compiled JS code:
image

Interface:
image

Cannot use tweetsV2.searchAllTweets

Description
I see that is possible to use tweetsV2.searchAllTweets. But when I try, it gives me this error:

{
  statusCode: 403,
  data: '{\n' +
    '  "title": "Unsupported Authentication",\n' +
    '  "detail": "Authenticating with OAuth 1.0a User Context is forbidden for this endpoint.  Supported authentication types are [OAuth 2.0 Application-Only].",\n' +
    '  "type": "https://api.twitter.com/2/problems/unsupported-authentication",\n' +
    '  "status": 403\n' +
    '}'
}

To reproduce

const twitterClient = new TwitterClient({
  apiKey: "***",
  apiSecret: "***",
  accessToken: "***",
  accessTokenSecret: "***",
  disableCache: true,
  ttl: 120,
});


twitterClient.tweetsV2.searchAllTweets({
  query: "test"
}).then((response) => {
    console.log(response || "");
  })
  .catch((err) => console.error(err));

Is it possible to do it or not?

Thanks!!!

How do I get to show source labels when tweeting?

I currently see no source labels like "Twitter Web App" or "Twitter for iPhone" or "Twitter for Android". I would like to set a custom source label while tweeting, but I didn't find any docs regarding it.

After using twitter.tweets.statusesUpdate() function, I console.log() the response and see source field is set to an empty string 👇

Screenshot 2021-02-04 at 6 21 37 PM

401 On twitter.media.mediaUpload()

Describe the bug
Below are the authentication requirements by Twitter for twitter.tweets.statusesUpdate() and twitter.media.mediaUpload() endpoints respectively 👇

Screenshot 2021-02-04 at 8 01 57 PM

and

Screenshot 2021-02-04 at 8 01 14 PM

As they require same level of authentication if twitter.tweets.statusesUpdate() works then twitter.media.mediaUpload() should also work. Where twitter.tweets.statusesUpdate() works as expected, twitter.media.mediaUpload() responds with a 401. Here's the code I've used 👇

const res = await twitter.media.mediaUpload({
    media: await fs.readFile(image.path)
})

console.log('res ', res)

And here's the response I get 👇

{
    statusCode: 401,
    data: '{"errors":[{"code":32,"message":"Could not authenticate you."}]}'
}

To reproduce
Steps to reproduce the behavior:

  1. Create a new Node.js project and add twitter-api-client as dependency.
  2. Write the following code 👇 in a file named index.js
const fs = require('fs/promises')

const res = await twitter.media.mediaUpload({
    media: await fs.readFile('./image.png')
})

console.log('res ', res)
  1. Add a dummy image in the same folder as index.js
  2. Run it!

Expected behavior
I see the newly uploaded image in Twitter Media Studio.

Package Manager:
To install the Twitter API Client, I used Yarn v1.22.10

Additional context
Node.js: v15.4.0
Module System: Native ESM
Operating System: macOS Big Sur 11.1 (20C69)

Add v2 endpoints

The first set of v2 endpoints has been published for early access.
Add them to the twitter-api-spec and generate the clients.

how to only authenticate a request?

Hey how can I use this library to only generate an oauth1.0 authentication in order to perform a request using another library like 'Axios'..

for example:
I want to perform this request: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/message-attachments/guides/retrieving-media

but using 'oauth.get() doesn't work for me.

*** what do I want?/ need? ***

fetch('media_url', {headers: { client.authorize? }})

"client is the instance of the twitter-api-client"

Unable to use chucked media upload / mediaUploadAppend: "Could not authenticate you"

Describe the bug

The chunked media upload is required to upload videos, but it seems impossible to use currently due to an auth failure.

Unable to authenticate on the 2nd / APPEND endpoint of the chunked media upload.

  const mediaUploadInitResult = await twitterClient.media.mediaUploadInit({
    command: "INIT",
    media_type: "video/mp4",
    media_category: "tweet_video",
    total_bytes: 56789710,
  });
  console.log("mediaUploadInitResult", mediaUploadInitResult);

  const binary = fs.readFileSync(filePath);

  const base64 = fs.readFileSync(filePath, { encoding: "base64" });

  const mediaUploadAppend = await twitterClient.media.mediaUploadAppend({
    command: "APPEND",
    media_id: mediaUploadInitResult.media_id_string,
    media_data: base64,
    // media: binary,
    segment_index: 0,
  });
  console.log("mediaUploadAppend", mediaUploadAppend);

I tried both with binary or base64 and it does not change anything. Note non-chunked image upload works fine for me.

mediaUploadInitResult {
  media_id: 1374383257052012500,
  media_id_string: '1374383257052012546',
  expires_after_secs: 86399,
  media_key: '7_1374383257052012546'
}
Error
{
  statusCode: 401,
  data: '{"errors":[{"code":32,"message":"Could not authenticate you."}]}'
}
error Command failed.

The first INIT call works, but the 2nd APPEND call fails.

It looks like a problem related to how the OAuth signature is handled for multipart uploads, according to this blog post: https://retifrav.github.io/blog/2019/08/22/twitter-chunked-upload-video/

This page also mentions:

image

I believe there may be something wrong that prevents chunked upload in the transport layer here:
https://github.com/FeedHive/twitter-api-client/blob/master/src/base/Transport.ts

There are not many examples on the internet using NodeJS and the official doc is using twurl unfortunately.
This could be helpful: https://medium.com/ameykpatil/how-to-publish-an-external-video-to-twitter-node-js-version-89c03b5ff4fe

Would be happy to help solve this

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.