Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Building a Twitter Bot to Display Random Comic Book Covers

DZone's Guide to

Building a Twitter Bot to Display Random Comic Book Covers

This weekend I was thinking about a few Twitter accounts I follow that just post random pictures and thought it might be kind of fun to build a similar mechanism for comic books. Recycling an old experimental web app that randomly-generated a Marvel comic book cover every minute, I was able to create something new. Check it out.

· Web Dev Zone
Free Resource

Get deep insight into Node.js applications with real-time metrics, CPU profiling, and heap snapshots with N|Solid from NodeSource. Learn more.

A bit over two years ago I played around with the (then) recently released Marvel API to build some cool demos. The end result of that experiment was a simple web app that randomly displayed a Marvel comic book cover every minute: http://marvel.raymondcamden.com/.

This weekend I was thinking about a few Twitter accounts I follow that just post random pictures. (I’ll share a list of them at the end.) I like these accounts because they’re easy to ignore, provide something simple and cool to my feed, and are just a random piece of coolness during the day. I thought it might be kind of fun to build a similar mechanism for comic books (well, Marvel comics, I need to see if DC has an API.)

In theory, all I needed to do was:

  • Create a way to select a random cover (which was already done - by me)
  • Create a way to Tweet (there’s probably a npm library for that - yep - there is)
  • Create a schedule (there’s probably a npm library for that too - yep - there is)

It ended up being very quick to develop - maybe two hours total. Here is the complete source of the main script file. (Note, the entire thing is up on GitHub - the link will be at the bottom.


/*eslint-env node*/

var request = require('request');

var express = require('express');

var credentials = require('./credentials.json');

var Twitter = require('twitter');
var client = new Twitter(credentials.twitter);

var marvel = require('./marvel');
marvel.setCredentials(credentials.marvel.private_key, credentials.marvel.api_key);

// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');

var app = express();

app.use(express.static(__dirname + '/public'));

// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();

// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {

    // print a message when the server starts listening
    console.log("server starting on " + appEnv.url);
});

var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

function tweetRandomCover() {
    console.log('First, we get a random cover.');

    marvel.getCover(function(res) {
        console.log('back from mavel');
        console.dir(res);
        var tweet = res.title + ' published '+(MONTHS[res.date.getMonth()])+' '+res.date.getFullYear() +'\n'+res.link;

        console.log('Now going to fetch the image link.');

        request.get({url:res.url,encoding:null}, function(err, response, body) {
            if(!err && response.statusCode === 200) {
                console.log('Image copied to RAM');

                client.post('media/upload', {media: body}, function(error, media, response) {

                    if(error) {
                        console.error('Error from media/upload: '+error);
                        return; 
                    }

                    // If successful, a media object will be returned.
                    console.log('Image uploaded to Twitter');

                    var status = {
                        status: tweet,
                        media_ids: media.media_id_string 
                    }

                    client.post('statuses/update', status, function(error, tweet, response){
                        if (!error) {
                            console.log('Tweeted ok');
                        }
                    });

                });

            }
        });
    }); 
}

app.get('/forceTweet', function(req, res) {
    tweetRandomCover();
    res.end('Done (not really)');
});

var cron = require('cron');
var cronJob = cron.job('0 6,12,18 * * *', function() {
    console.log('do the cover');
    tweetRandomCover(); 
    console.log('cron job complete');
});
cronJob.start();

Let’s break it down bit by bit, focusing on the important parts. To handle the Twitter API, I used the twitter Node library. As you will see a bit later in the code, it is incredibly trivial to use, even when creating Tweets with media attached.

The Marvel API is just a copy of the code I used before, although I’ve modified it a bit so I can pass in my credentials.

The real meat of the code is in tweetRandomCover. We begin by asking the Marvel API for a random cover. If you read my post from two years ago you’ll note that I have to fake that a bit. I essentially select a random month+year and grab everything I can from there - then select an item.

Once I have the random issue, I use the request library to suck down the binary of the image into a variable. I’ve heard of this library quite a bit, but I’ve never actually used it. Big mistake on my part.

Finally, I have to create the tweet. Twitter requires you to upload the media first so it is a two step process. First the image is posted and then the actual Tweet is created. I’ve got a bit of “Callback Hell” going on here and if this app did anything else I’d abstract this logic out of the main script, but since this isn’t a web app people will hit, I’m not going to worry about it.

The final aspect is scheduling - which you can see is done via node-cron. Easy to use - it took me longer to figure out the right cron syntax than it did to implement the code. As you can see, I’ve selected a schedule that should post tweets three times a day which “feels” right for this kind of account. I may tweak that later.

You can find the complete code (although there’s not much else) up on GitHub: https://github.com/cfjedimaster/randomcomicbook. I’m hosting the app up on IBM Bluemix.

And of course, you can (and should!) follow the Twitter acount: https://twitter.com/randomcomicbook

Image title

Random Comic Book @randomcomicbook
Incredible Hulk (1962) #146 published December 1971 http://marvel.com/comics/issue/8957/incredible_hulk_1962_146?utm_campaign=apiRef&utm_source=fe877c0bf61f995fc8540d9eac4704f1 …

PS…

So yeah, about those random Twitter accounts I follow for pictures? Here they are:

I used to follow some related to historical pictures, but they either turned to spam or shared pictures unrelated to history, which to me is a cardinal sin of these types of accounts. (Another example - news organizations that will RT their sports or entertainment accounts. I freaking hate that.)

Node.js application metrics sent directly to any statsd-compliant system. Get N|Solid

Topics:
twitter ,api

Published at DZone with permission of Raymond Camden, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}