DEV Community

Cover image for How to build a Twitter Bot that recommends movies
Tom
Tom

Posted on

How to build a Twitter Bot that recommends movies

I love films. I love recommending films to watch. I also love when people ask for my recommendations on what to watch. But sometimes this can become a little tedious, so a couple of months ago I started building a bot that recommends random (and good) movies when you mention it on Twitter. That's how @nosequever was born.

This is a simple guide on how to do it:

First let's install all the dependencies we'll use to build our bot. These are:

  • Twit: it's a Twitter API client for Node.js. We'll use this client to "listen" for mentions in our account, and to tweet a response with our recommendation.
  • Axios: an HTTP client for Node.js. This client will allow us to do a GET request to the TMDb API to get our random movie to recommend.

To install these dependencies, run inside your project's directory:

    $ npm install --save twit axios

Once you've all our dependencies installed, we need to get all the credentials for the API's we'll be using: the Twitter API and the TMDb API. Let's create a config.js file and paste those credentials:

    module.exports = {
      // Add your Twitter API Credentials
      twitter_api: {
        consumer_key: '',
        consumer_secret: '',
        access_token: '',
        access_token_secret: ''
      },
      // Add the ID of the user you want to track
      // You can find the ID of a twitter user in http://gettwitterid.com/
      twitter_user_id: '',
      // Add your TMBb API Credentials
      movies_database_api_key: ''
    }

Now we're ready to start building our bot! First, let's create an asynchronous function that returns the movie we'll recommend. This function will make a GET request to the TMDb API to retrieve a movie based in certain search parameters: a minimum number of votes and a minimum average score. In theory this will allow us to recommend only "good" movies, but it can fail (yes, we're talking to you Green Book). This request will return an array with different movies, and our recommendation we'll be a random index of that array.

    const config = require('./config')
    const Twit = require('twit')
    const axios = require('axios')

    // This will return the string with
    // the recommended movie. If something
    // goes wrong, returns an error message to tweet.
    const getRecommendedMovie = async () => {
      const tmdbApiKey = config.movies_database_api_key 
      const listPage = Math.floor(Math.random() * 234) + 1
      const minimumVotes = 50
      const minimumScore = 7
      const requestURL =
        'https://api.themoviedb.org/3/discover/movie?api_key=' +
        tmdbApiKey +
        '&language=en-US&sort_by=vote_average.desc&include_adult=false&include_video=false&page=' +
        listPage +
        '&vote_count.gte=' +
        minimumVotes +
        '&vote_average.gte=' +
        minimumScore

      // Stores the GET request into a variable
        // that we'll return
      const recommendedMovie = await axios
        .get(requestURL)
        .then((response) => {
          if (response.status === 200) {
            const moviesList = response.data.results
            const listLength = moviesList.length
            const randomIndex = Math.floor(Math.random() * listLength) + 1

            // Yayy! We've our random movie to recommend!
            const recommendedMovie = moviesList[randomIndex]

            // Now, let's start putting together
            // the string to tweet to the user
            const movieID = recommendedMovie.id
            const movieTitle = recommendedMovie.title
            const movieReleaseYear = recommendedMovie.release_date.split('-')[0] // We just want the year
            const movieURL = 'https://www.themoviedb.org/movie/' + movieID

            // We'll tweet this to the user
            const tweet =
              ' today you could watch ' +
              movieTitle +
              ' (' +
              movieReleaseYear +
              '). More info: ' +
              movieURL
            return tweet
          }
        })
        .catch(() => {
          return ' seems like something went wrong πŸ’”. Try again in a few minutes!'
        })

      return recommendedMovie
    }

Alright! We've our movie recommendation. That was easy, wasn't it?

Now we need to initialize a Twit instance to "listen" for mentions in our account. If we're mentioned, we'll post a tweet in reply with our recommendation.

If you check Twit's documentation, in order to initialize an instance of it we need to pass our Twitter API credentials as a parameter. Once it's initialized we'll use the stream() method to filter Twitter's public stream to search for mentions in our account, by using our Twitter account ID. Then, we can finally reply to that mention with our recommendation ❀️.

    const config = require('./config')
    const Twit = require('twit')
    const axios = require('axios')

    // This will return the string with
    // the recommended movie. If something
    // goes wrong, returns an error message to tweet.
    const getRecommendedMovie = async () => {
      const tmdbApiKey = config.movies_database_api_key // Your TMDb api key goes here
      const listPage = Math.floor(Math.random() * 234) + 1
      const minimumVotes = 50
      const minimumScore = 7
      const requestURL =
        'https://api.themoviedb.org/3/discover/movie?api_key=' +
        tmdbApiKey +
        '&language=en-US&sort_by=vote_average.desc&include_adult=false&include_video=false&page=' +
        listPage +
        '&vote_count.gte=' +
        minimumVotes +
        '&vote_average.gte=' +
        minimumScore

      // Does a GET request to the TMDb API
      // to get the random movie data
      const recommendedMovie = await axios
        .get(requestURL)
        .then((response) => {
          if (response.status === 200) {
            const moviesList = response.data.results
            const listLength = moviesList.length
            const randomIndex = Math.floor(Math.random() * listLength) + 1

            // Yayy! We've our random movie to recommend!
            const recommendedMovie = moviesList[randomIndex]

            // Now, let's start putting together
            // the string to tweet to the user
            const movieID = recommendedMovie.id
            const movieTitle = recommendedMovie.title
            const movieReleaseYear = recommendedMovie.release_date.split('-')[0] // We just want the year
            const movieURL = 'https://www.themoviedb.org/movie/' + movieID

            // We'll tweet this to the user
            const tweet =
              ' today you could watch ' +
              movieTitle +
              ' (' +
              movieReleaseYear +
              '). More info: ' +
              movieURL
            return tweet
          }
        })
        .catch(() => {
          return ' seems like something went wrong πŸ’”. Try again in a few minutes!'
        })

      return recommendedMovie
    }

    // Our bot object
    const bot = new Twit(config.twitter_api)
    const myAccountId = config.twitter_user_id

    // Twitter's public stream
    const stream = bot.stream('statuses/filter', { follow: myAccountId })

    // Every time our account receives a tweet,
    // the `stream` object will run a function
    // to verify if the tweet it's a mention
    stream.on('tweet', async (eventMsg) => {
      if (eventMsg.in_reply_to_screen_name === 'nosequever') {
        const userToMention = eventMsg.user.screen_name
        const toTweet = '@' + userToMention + ' ' + (await getRecommendedMovie()) // Remember getRecommendedMovie() it's asynchronous
        const tweetParams = {
          status: toTweet,
          in_reply_to_status_id: eventMsg.id_str,
        }

        // πŸŽ‰πŸŽ‰ Tweets the recommendation πŸŽ‰πŸŽ‰
        bot.post('statuses/update', tweetParams)
      }
    })

πŸŽ‰ IT'S ALIVE πŸŽ‰

You can test it by running node app.js and then mentioning your bot account on Twitter. If you want it to run forever (wink, wink) you'll need to start a forever process in your app.js. You can do this by installing forever like this:

    $ npm install --save forever

And then running

    $ forever start app.js

✨ That's it! You've successfully created a bot on Twitter ✨

Feel free to clone this project and make any improvements you want. You can even make a pull-request to add some features!

Hope you liked it. If you have any questions, you can ask me for help on Twitter at any time :)

Stay home, stay safe!

Top comments (0)