Creating a Slack Emoji Auto-Generator Bot with Golang, chromedp, and Slack Bot

Overview

I created a Slack bot that automatically generates emoji images using Golang, chromedp, and Slack Bot.

What I Made

This bot generates an image when you mention it in Slack with specific parameters. Internally, it creates an image using a canvas based on the parameters, takes a screenshot with a headless browser, saves the image, and posts it to Slack.

github.com - emoji-generator-slack-app

You can get a rough idea of how to use it by checking the README...

Since I made this over a weekend hackathon-style, there are still some bugs left... https://github.com/bmf-san/emoji-generator-slack-app/issues/1

Image Generation in Golang

Golang has a standard package called image that provides a full range of image processing features.

You can easily perform tasks like applying mosaic effects, combining images, cropping, and drawing text (at least from what I’ve seen).

While it’s not very practical, for example, you can create a solid-colored image with just a few lines of code:

If you want to make it more interesting by drawing text on the image, you can use the following code:

By carefully adjusting the drawing parameters as shown in the code above, you can generate custom images. If you want to create complex geometric patterns, you’ll need to adjust more parameters, which can be quite a challenge.

While it seems possible to create Slack emojis using the image package, I found adjusting the parameters to be tedious. So, I looked for a simpler solution and came across an article introducing image generation using a headless browser. I decided to use a headless browser for this project.

cf. note.com - Dynamic Image Generation Using Headless Browser in Go

From the article above, I learned that the image package only supports the TrueType font format. While I wasn’t too concerned about this since I wasn’t aiming for a highly designed output, it’s something to keep in mind if you want to customize fonts for your service.

Image Generation Using a Headless Browser

The idea is to use a headless browser to take a screenshot and generate an image.

Compared to using the image package, this method allows you to adjust the image on the frontend rather than the server-side. This provides greater design flexibility, such as adjusting the image with CSS or using any font supported by the browser.

Additionally, this method is highly versatile as it can also be used for web scraping or generating Open Graph Protocol (OGP) images.

To use a headless browser (Chrome) with Golang, I used the chromedp package. github.com - chromedp

chromedp supports the Chrome DevTools Protocol, allowing you to control Chrome with or without a UI, without relying on external tools like Selenium or PhantomJS. chrome devtools protocol

Here’s an example of how to take a screenshot using chromedp in headless mode:

After taking the screenshot with chromedp, you can save it to a file and post it to Slack to complete the bot’s workflow.

Creating the Slack Emoji Auto-Generator Bot

I’ll skip the details of Slack bot development.

This article explains it well: cf. qiita.com - Creating a Slack Bot with Go (March 2020 Edition)

For this project, I created a bot that responds to mentions with parameters, generates an image based on the parameters, and posts the image. I didn’t use features like dialogs or slash commands, only event subscriptions.

Using dialogs might improve the user experience, but it seemed complicated and there weren’t many examples available, so I implemented a bot that simply responds to mentions.

Here’s the final result before diving into the implementation:

Screen Shot 2020-08-11 at 14 49 46 Screen Shot 2020-08-11 at 14 49 40

When you mention the bot like this, it generates a Slack emoji image (128px × 128px) with one or two lines of text and responds.

The bot takes the following input: @botname [color] [bgColor] [line1] [line2(optional)]

The input data is used to generate the image. I used a canvas for the image generation. Initially, I wanted to achieve this with just CSS, but I couldn’t figure out how to take a screenshot without including extra margins. Using a canvas worked as expected, so I decided to go with it.

The input data is passed into a template file (tpl), which the canvas uses to generate the image:

There’s no specific limit on the number of characters, so I adjusted the x-axis to fit the width nicely. For the y-axis, I found a suitable value and set it (I should probably think about how to calculate it properly, but I didn’t bother...).

Even though I ended up dealing with x and y axes using the canvas, which made me think I could have just used the image package, I still feel this method was relatively easier to implement.

Once the template for image generation is ready, I set up an API endpoint that generates images using query strings. For example: http://localhost:9999/generator?color=red&bgColor=green&line1=foo&line2=bar

Finally, I wrote the code to respond to bot mentions, extract parameters from the mention, launch a headless browser with chromedp, hit the image generation endpoint, create the image, and post it to Slack.

Here’s an excerpt of the code:

With this, I was able to create a bot that responds to mentions and generates images. However, unfortunately, there are still some bugs left...

https://github.com/bmf-san/emoji-generator-slack-app/issues/1

Thoughts

I feel like I didn’t really need to use chromedp. Now I’m wondering how to fix the bugs...

References