For my final post of the year, I wanted to do something fun and decided to create a chatbot that creates memes. You’ve probably seen them before in the form of image macro’s with the typical top text and bottom text. This chatbot (called the MemeBot) is built with the Bot Framework and a fun way to see what the framework can do.
MemeBot can simply create images like these:
In this post, you’ll learn:
- How to consume the RapidAPI, which is used to generate the images.
- How to send embedded images through the Bot Framework.
Dive directly in the code on Github or learn step-by-step by reading on!
Setup
The idea is simple: Let the user select a meme, set some top text and bottom text and let the bot generate the image. Before we continue, make sure you have an account on RapidAPI to make use of the Meme Generator. I selected the BASIC-pricing tier which is free.
This bot doesn’t make use of LUIS, but does use Prompt Dialogs.
The meme API
To generate the memes, we’ll be using the APIMeme through RapidAPI. Although this API supports many memes, for this sample I made a small preselection. RapidAPI recommends the use of Unirest, a Lightweight HTTP Request Client Library, so we’ll use it here as well. Simply add the Nuget-package to your project.
I’ve wrapped the call to RapidAPI in a separate class. A part of the most important method, GenerateMeme
, is highlighted below.
public async Task<string> GenerateMeme(Meme meme, string topText, string bottomText)
{
var response = await Unirest.get($"https://ronreiter-meme-generator.p.mashape.com/meme?" +
$"bottom={ HttpUtility.HtmlEncode(bottomText) }" +
$"&font=Impact" +
$"&font_size=50" +
$"&meme={ ConvertMemeToURL(meme) }" +
$"&top={ HttpUtility.HtmlEncode(topText) }")
.header("X-Mashape-Key", RAPID_API_KEY )
.header("X-Mashape-Host", "ronreiter-meme-generator.p.mashape.com")
.asJsonAsync<MemoryStream>();
return Convert.ToBase64String(response.Body.ToArray());
}
Some important things to point out:
- The
RAPID_API_KEY
is the key that can be retrieved from RapidAPI. - Since the API returns a stream, we’ll convert the result to a
MemoryStream
. - To enable image embedding in the bot later one, we’ll need to convert the result to a
Base64
-encoded string.
The dialog
The dialog is pretty straight forward: We’ll simply ask the user to make a Choice
and enter Text
. I’ve added it to the RootDialog and after all the input is requested, we’ll send the generated image to the user.
private async Task ResumeAfterBottomTextClarification(IDialogContext context, IAwaitable<string> result)
{
// setup a message that can hold the generated image
var replyMessage = context.MakeMessage();
var image = new Attachment();
image.ContentType = "image/jpeg";
image.ContentUrl = $"data:image/jpeg;base64," +
$"{ await _api.GenerateMeme(_meme, _topText, _bottomText) }";
replyMessage.Attachments = new List<Attachment> { image };
// return our reply to the user
await context.PostAsync(replyMessage);
}
Over here, we see:
- Create an
Attachment
that will hold the image data. - Use the
ContentUrl
to pass along the image data inBase64
format to embed it in the message.
Conclusion & Download
Now that we have all the pieces of the puzzle, we can simply ask the bot to generate the memes that we want!
There you have it: A simple bot that generates memes! Grab the code to learn even more, make adjustments or improve it on Github. I’d personally like to add some improvements to the selection of the meme, but that might be a next post. What do you think? Tell me in the comments or through Twitter!