How to create a Twitter Bot using Node.js and Heroku
Tags: node, datascience, twitter, javascript
Published: 2020-07-25 14:39:49

Making a twitter bot is one of the many use cases of using the Twitter API. A bot can be used to enhance your business, assist customers through automated replies, automate retweets for specific terms, and a lot more. 
This article is about how I created [`The Data Science Bot`](https://twitter.com/datasciencebot_) using Node.js.

# Table Of Contents
1. [Apply for Twitter developer account](#apply)
2. [Create app on twitter](#create-app)
3. [Setup dev environment](#setup)
4. [Write code in nodejs](#code)
5. [Deploy to heroku](#deploy)
6. [How to avoid duplication of retweets](#avoid-duplication)

![Let's start](https://dev-to-uploads.s3.amazonaws.com/i/vqmfaofwi3rqvcvenkcw.gif)

<a name="apply"></a>    

## **Step 1: Apply for Twitter Developer Account**

This is the most important and perhaps the most difficult step according to me.

- Login into [Twitter](https://twitter.com)
- Go to [developers.twitter.com](https://developer.twitter.com/en/apply-for-access) and click on 'Apply for a Developer account'
- Select the type of application i.e. student/business/hobbyist, etc.
- Mention the purpose of your application.
Be as specific as you can over here.  

> Make sure you have read the [Developer Agreement and Policy](https://developer.twitter.com/en/developer-terms/agreement-and-policy), [Automation rules](https://help.twitter.com/en/rules-and-policies/twitter-automation) and [The Twitter Rules](https://help.twitter.com/en/rules-and-policies/twitter-rules) thoroughly before applying.

>  Failing to meet these conditions will cause your application to be rejected

**Read the full article** on [How to apply for a twitter developer Account](https://dev.to/sumedhpatkar/beginners-guide-how-to-apply-for-a-twitter-developer-account-1kh7)

<a name="create-app"></a>    

## **Step 2: Create app on twitter**
Once your twitter developer account access has been approved.
- Create an APP on [apps.twitter.com](https://developer.twitter.com/en/apps).
  Fill in the required details.

- Generate API keys. Click on your apps details and navigate to `Keys and tokens`
![Generate Keys](https://dev-to-uploads.s3.amazonaws.com/i/jqg8e9bg11aj5mbjh8q2.png)

> ⚠️ **Warning** (Don't reveal the API keys in any case).

<a name="setup"></a>    

## **Step 3: Setup Development Environment**

Make sure you have Node.js and npm installed on your PC.

For Ubuntu, install using the following commands
```sh
sudo apt install nodejs
sudo apt install npm
```

For other distributions, click [here](https://nodejs.org/en/) for installation instructions.


Create a directory named `your-botname`.
In my case, I have named it `the-datascience-bot`.

To initialize the git environment and install the package `twit` using `npm`, enter the following commands *inside* the `your-botname` directory: 

![init env](https://dev-to-uploads.s3.amazonaws.com/i/piar6f0axdautjbthjjc.png)

Congratulations! You have successfully set up your Node.js DEV environment 🎉🎉

<a name="code"></a>    

## **Step 4: Code**

- Firstly, we have to authenticate `twit`.
To do this, we will link our twitter app and code using the generated *API keys*.  

Create a file named `config.js`.
Put the following code in your `config.js` file

#### config.js
![config.js](https://dev-to-uploads.s3.amazonaws.com/i/gfhcsvimg5o28ctkpr61.png)

Put your keys copied from your twitter apps dashboard.

- Next, we write the code for the bot in a file `bot.js`.

Here is the code.  

#### bot.js  

```javascript
const config = require('./config')
const twit =  require('twit')

const T = new twit(config)

function retweet(searchText) {
    // Params to be passed to the 'search/tweets' API endpoint
    let params = {
        q : searchText + '',
        result_type : 'mixed',
        count : 25,
    }

    T.get('search/tweets', params, function(err_search, data_search, response_search){

        let tweets = data_search.statuses
        if (!err_search)
        {
            let tweetIDList = []
            for(let tweet of tweets) {
                tweetIDList.push(tweet.id_str);

                //more code here later...
            }

            // Call the 'statuses/retweet/:id' API endpoint for retweeting EACH of the tweetID
            for (let tweetID of tweetIDList) {
                T.post('statuses/retweet/:id', {id : tweetID}, function(err_rt, data_rt, response_rt){
                    if(!err_rt){
                        console.log("\n\nRetweeted! ID - " + tweetID)
                    }
                    else {
                        console.log("\nError... Duplication maybe... " + tweetID)
                        console.log("Error = " + err_rt)
                    }
                })
            }
        }
        else {
            console.log("Error while searching" + err_search)
            process.exit(1)
        }
    })
}

// Run every 60 seconds
setInterval(function() { retweet('#DataScience OR #DataVisualization'); }, 60000)

```

Let's break it down.

- We initialize the twit object using our configuration details from `config.js`
- The retweet function first calls the `search/tweets` API endpoint for the given search query.
  In my case, it is ***'#DataScience OR #DataVisualization'***
- We pass the following parameters to search API
  - `q`: The search query
  - `result_type`: *'mixed'* for latest as well as popular older tweets
  - `count`: number of tweets to retrieve at once
- The retrieved [JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON) object has the list of tweets having either #DataScience or #DataVisualization in it.

-We then pass each of the tweet IDs to the `statuses/retweet/:id` API endpoint, which retweets the tweet.

> Detailed API reference guides for [Search](https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets) and [Retweet](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id).

Test the bot locally using the following command:

```sh
node bot.js
```

Your Twitter timeline should show the retweets.

Try debugging on the console if it doesn't work.

<a name="deploy"></a>    

## **Step 5: Deploy to Heroku**

- Create an account on [Heroku](https://www.heroku.com/)
- Create an app named 'your-botname' on Heroku


![Create new app button](https://dev-to-uploads.s3.amazonaws.com/i/dvovig9254f7gue1g5wk.png)

![Heroku New App](https://dev-to-uploads.s3.amazonaws.com/i/i4p8r8uxmkywrnhnfwfm.png)

> Make sure the name of your local project directory is exactly the same as your Heroku project name.

- Install **heroku-cli** on your pc

If you have an *Ubuntu/Debian* based distribution, then use the following command to install `heroku-cli`
```
curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
```

For other environments, the installation instructions can be found [here](https://devcenter.heroku.com/articles/heroku-cli)

- Create a file named 'Procfile' having the following code

#### Procfile
```
worker: node bot.js
```

- Login to heroku CLI 
```
$ heroku login
```
This will open a login link on heroku, where you have to enter your password.
 
- Deploy to Heroku using these commands
![Deploy Heroku commands](https://dev-to-uploads.s3.amazonaws.com/i/2km8dhr85p97fjg7ohqj.png)

#### **One last step**
*Start the `worker` dyno on Heroku.*
Go to [dashboard.heroku.com/apps](https://dashboard.heroku.com/apps) and click on your bot app.

Then, click on configure Dynos
![Configure Dynos](https://dev-to-uploads.s3.amazonaws.com/i/zms7x1rku1b0yv2ibotg.png)

Start the `worker` dyno and click on confirm
![Start worker dyno](https://dev-to-uploads.s3.amazonaws.com/i/oyofou2peuwfggw0ui1y.png)


### And your bot is Ready! 🎉🎉
![bot_dancing](https://dev-to-uploads.s3.amazonaws.com/i/xted0ahf6jgg2jexdcj7.gif)

<a name="avoid-duplication"></a>    

## **Step 6: How to avoid duplication of retweets**

Add the following code in the for loop where we wrote 
`//more code here later..`

#### Check duplication
![Check Duplication](https://dev-to-uploads.s3.amazonaws.com/i/lsewjukfk6qa920ffm4m.png)

Then outside the loop - 
```javascript
// Utility function - Gives unique elements from an array
function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}

// Get only unique entries
tweetIDList = tweetIDList.filter( onlyUnique )
```

The utility function `onlyUnique` can be written outside the retweet function as well.

This will let our bot avoid duplicate retweets.

***Short explanation of the above code***
- Each tweet has a unique property `id_str`.
If you retweet someone's tweet, it has a different `id_str`.

- The search API finds both the original tweet and the retweeted ones.

- When we call the `statuses/retweet/:id` API endpoint, it retweets all of them.

- To a novice Twitter user, it looks like your bot has retweeted the same stuff two or more times.

#### Something like this 👇
![Duplicate retweets](https://dev-to-uploads.s3.amazonaws.com/i/tiq4m0fe2mlakuptralq.png)

- If tweet text starts with "RT @" then it is a retweeted tweet, with a different `id_str` than the original.  
  We take the `id_str` of the **original tweet** and filter duplicates using the `onlyUnique` function

There are a lot more things you can do with the API. Check out the API reference(https://developer.twitter.com/en/docs/api-reference-index) for more details.

#### Source Code - 
The full source code can be accessed here  

{% github Sumedh-Patkar/the-datascience-bot %} 

### **The Data Science Bot** 🤖

The bot retweets tweets having hashtags [#DataScience](https://twitter.com/search?q=%23DataScience) and [#DataVisualization](https://twitter.com/search?q=%23DataVisualization)

Here is the link to my bot https://twitter.com/datasciencebot_

{% twitter 1280069048202477568 %}


Alright, that's it!

This was my first tech article on the Developer community.
Any feedback would be greatly appreciated!

Thanks for reading! 😊