Friday, July 31, 2015

Make Memes via API Calls

In today's comic the frogs are recycling pictures into memes, and by clicking on the meme in the last frame you can create your own frog meme. You just type in your own text and your personalized meme appears. You can even share it.

I don't want to get into a debate about how the sharing of memes has destroyed what remains of our humanity - it's just a comic about frogs. The interesting thing is how I was able to find a meme generation API that I could work with to make this comic possible.

My first attempt at this used memegenerator.net. It's a very popular meme site. They have a JSON API and there are even some modules for Node.js that interface with it. That all sounded good. I tried out the node-meme module and it worked - for all the read methods. Once I tried to create a meme with it I was informed by an error code that I needed valid login credentials.

No problem! I'll just register for an account.

Nope.
Or not. Apparently, account registration has been unavailable for quite some time. All attempts at it result in a rather unintelligible error message. There goes that plan!

After some more searching I found Imgflip.com. They have both a meme-generation API and functioning account registration! Yeah!

To make the comic work the way I intended, I needed to make all the memes from my server and then just update the browser with the Imgflip URL. This prevents everyone who uses the comic from having to get their own account, but it makes things a little more complicated for me. I essentially had to set up a meme-generation proxy. Your browser POSTs data to my server, my server POSTs data to Imgflip, Imgflip generates a meme and tells my server the URL, and finally my server tells your browser the URL.

This also required me to do something I haven't done a lot of before - use the Node http client. Sure, I've done simple things with it in the past, but the out-of-the-box features make it a bit difficult to use when you want to access a REST web service.


So I also started using the request module. It greatly simplifies working with HTTP(S) requests in Node. Here is an example of how I use it to interact with Imgflip's API:

var request = require("request");

var formData = {
    template_id : "41754803",
    username : "user",
    password : "passwd",
    text0 : "i look displeased...",
    text1 : "but i have no idea what's going on"
};

request.post("https://api.imgflip.com/caption_image", {
    form : formData
}, function(error, response, body) {

    var meme = JSON.parse(body);

    if (!error && response.statusCode == 200) {
        console.log(meme.data.url);
    }

});

Simple, right? The first parameter to request.post is the URL.

The second is what to POST. In this case, I want to POST a form, specifying the form data as an object. Imgflip only accepts form data as input, and every POST must include your username and password. You get those by registering on their site. The template_id form field is the id number for the meme image you want to use. If you upload your own meme template images, you can find the id numbers on template details page linked from your account. The text0 field is the text for the top of the image, and text1 is for the bottom.

The third parameter is the callback function for when the POST completes. This function gets an error (if there was one), the response object for checking the status code (and other stuff if you want), and the body of the response. In the case of the Imgflip web service, I know the body will be JSON. In this example I just log the meme image URL.

That is much simpler than doing it the purely native way. I recommend the request module if you need to do any kind of REST API access and there's no custom client available.

Now the fun begins: frog memes for everyone!

Amphibian.com comic for 31 July 2015