Text to Gif : A Slack Bot Made With Go

Kento Murata
Level Up Coding
Published in
10 min readMar 7, 2020

--

Tumblr Gif
Tumblr Gif

As one goes about learning computer science, he or she will inevitably come across numbers of languages that may often have similarities and differences. Whether it may be how variables are used, are they object-oriented, are they capable of using concurrency within projects, there are all sorts of ways to compare computer languages to each other. It is interesting to learn new computer languages, since you can find similarities with the languages you have already learned before. I recently have been picking up on how to write code using Go, which is a coding language that seems to share a number of similarities to C++, another coding language I learned a couple years ago in community college, before coming to Make School where I began learning python.

Throughout my term creating different kinds of projects using Go, I had the opportunity to build a project that automated something I normally had to do manually. I took this chance to recreate a Slack bot that would generate a gif based on the text the user inputs. I always wondered how a bot is able to perform this action since I would usually have to look up gifs manually on the internet, copying and pasting them into the text bar for Slack.

Creating a Slack bot — Text to Gif:

Create a Slack bot app

Image from Slack API website.
Image from Slack API website (Basic Information page)

The first step I took in creating my Slack bot was to first create a Slack bot app through the Slack API website, https://api.slack.com/apps?new_classic_app=1. I specifically chose to create a legacy Slack bot app in order to avoid the scope limitations in my bot, which is basically restrictions on what my bot can and can’t do. I filled out the form with my desired app name and the Slack workspace I wanted to create my app into. After doing this I was routed to the basic information page for my newly created Slack bot. In the “Building Apps for Slack” box, there are two dropdown menus I had to go into to complete before moving on to writing actual code for my Slack bot. The first dropdown menu, labelled “Add features and functionality,” includes six properties I could edit, but I only needed to make changes to two of those properties listed.

The first box I worked on was the “Bots” property. Upon clicking the box labelled “Bots,” I scrolled down and clicked “Add Legacy Bot User” and filled out the form to name my bot.

Image from Slack API website.
Image from Slack API website (Add Legacy Bot User)
Image from Slack API website.
Image from Slack API website (Add an OAuth Scope)

Once I created the bot user, I went back to the “Basic Information” tab and this time under the “Add features and functionality” I opened the “Permissions” tab and scrolled down to the “Scopes” section. This is where I can choose what power I want my bot to have inside a slack channel. I pressed “Add an OAuth Scope” and added one scope named “Bot.” After that I scrolled up to “Redirect URLs” where I added the URL link to my Github repository for my Slack bot, https://github.com/kmurata798/goslackit. This allows users to optionally see more information on my bot if they choose to. I then click the green button at the top, “Install App to Workspace,” to add the bot to my desired Slack workspace.

Image from Slack API website.
Image from Slack API website (Install App to Workspace)

Once that has been done, I am brought to the “OAuth & Permissions” tab where I can copy the “Bot User OAuth Access Token” and paste it into my Go project. That is the last step needed to create my Slack bot app, which allows me to move onto writing code for my project.

Image from Slack API Website (Bot User OAuth Token)

Creating Slack bot Project

In order to write code for my Slack bot, I first forked this starter repository given by my Go instructor, https://github.com/droxey/goslackit, and cloned it inside my GOPATH directory. I then created a .env file by running, cp .env.sample .env within my terminal. Once the .env file was created, I pasted the “Bot User OAuth Access Token” I talked about in the previous section of this article. This will allow my code to access the Slack bot I have created through the Slack API website.

The next thing I did was change the outdated Slack import, “github.com/nlopes/slack,” located in my slack.go file, with a new import, “github.com/slack-go/slack” which provides the correct imported functionality for the updated features for Slack bots.

Snippet from top of my slack.go file
Snippet from top of my slack.go file (Fixing import statements)

After doing this, I was able to create different cases, or commands, that a Slack user would be able to type when using my Slack bot. For my bot, Text to Gif, I wanted there to be three simple commands a Slack user could type to receive a response.

Snippet from middle of my slack.go file.
Snippet from middle of my slack.go file (Commands for bot)
  1. The first case was a help command, in which my bot would display a menu of all the commands a user could use within the channel.
  2. The second case was an echo <text> command, in which the user would input text using this command, and my bot would post a message with the same text. I originally used this command to check that my bot could output given text.
  3. The last case was the gif <text> command, which is the main functionality of my bot. The user would type the word gif, followed by the word in which the bot would use to search for a gif to post to the channel.

In order for the users to run these commands within a Slack channel, the user must first type, “@Text to Gif” followed by the specific command they are trying to use. This is because I have named my bot “Text to Gif” when I added the “Legacy Bot User”, so my bot would appear in a Slack channel as Text to Gif.

I added additional cases after these bot command cases in order to help me visualize and understand what exactly my bot was doing whenever I run the program:

The bottom of my slack.go file includes functions which would execute if the commands I listed above were to be called.

Snippet from bottom of my slack.go file.
Snippet from bottom of my slack.go file (Bot Commands Functionality)
  1. When users use the help command, the sendHelp function will execute, sending the string variable I have initialized.
  2. When users use the echo command, the echoMessage function will execute, taking the text written by the user and outputting it back into the Slack channel.
  3. When users use the gif command, the returnGif function will execute, taking the text written by the user, using the Giphy API to search for a relating gif, and outputting it to the Slack channel.

I also added additional switch cases in order to help me visualize and understand what exactly my bot was doing whenever I run the program:

Snippet from middle of my slack.go file.
Snippet from middle of my slack.go file (Print statistics/error messages in terminal)

Adding Giphy API

I decided to use the Giphy API to get my bot to search gifs on the internet and output them to a Slack channel. I used a website called RapidAPI to find this API and take the code snippet needed to implement the API into my program. Simply copying and pasting this code snippet into my program isn’t going to work, so I needed to create a new file where this code snippet would be located, and add additional helper functions to allow my bot to properly utilize this Giphy API. I made a new directory, gif, and created a new file into that directory, giphy.go, and began implementing functions.

Image of Giphy API Documentation from RapidAPI.
Image of Giphy API Documentation from RapidAPI (Taking the code snippet for Giphy)

Adding functions to make Giphy API work properly

The first function I created was made to modify the Slack user’s input so that the Giphy API can take in the input correctly. The API requires the characters, %20, to be placed in between each word in the given string. So I used the ReplaceAll function which exists in the strings Go package. Take a look at the image below.

Snippet from top of my giphy.go file.
Snippet from top of my giphy.go file (ModifyInput Function)

Now that I have this function, I can properly place the user’s modified text into the Giphy API as so:

Snippet from bottom function of my giphy.go file.
Snippet from bottom function of my giphy.go file (SearchGifs Function)

And now that the Giphy API can properly read the user input and turn it into a url, it can create a database filled with a load of information supported by the Giphy API. There are hundreds of lines of data that is given back to me, but I only really need the first line of code out of the mass amount of information. So I needed to create another function that would specifically grab a substring within the huge string of data. I decided to use the Index function which is also from the strings Go package. This function allows me to take a given string, and look for a target string within the given string to find what index the target string starts at. By utilizing this one function, I am able to initialize three variables, the first variable is the index of the first string my program is looking out for, which is acting as a beginning mark. The second variable is the index of the second string my program looks for, which acts as the ending point. The third variable is the same as the first variable, but adding the length of that first string, so the program would ideally skip the first string, which is also the start of the target string we are trying to get. Use the code snippet below to better understand what this function is doing.

Snippet from middle function of my giphy.go file.
Snippet from middle function of my giphy.go file (Between Function)

After writing out this function, I was able to implement it into the Giphy API so that I would only grab the target substring I needed, the url to the gif relating to the Slack user’s input. I decided to reuse the ReplaceAll function in order to clean up the Giphy database string, since there were backslashes, \, and double-quotes, “”, scattered throughout the massive string. The below code snippets is a comparison of what the Giphy database string would look like with and without the ReplaceAll function used in my ModifyInputs function.

First, without the function:

Unfiltered Giphy API datastring (Lack of ReplaceAll function)
Unfiltered Giphy API data string (Lack of ReplaceAll function)

And now with the function:

Filtered Giphy API datastring(Use of ReplaceAll function)
Filtered Giphy API data string (Use of ReplaceAll function)

It’s much cleaner, huh?

By first using the ReplaceAll function to filter the Giphy API data string I get, and then using my between function to grab the gif URL I want my bot to post into the Slack channel, my Text to Gif bot is now able to execute its reason of existence which is to search and post a gif into a Slack channel given user input.

Snippet of Bottom function of my giphy.go file.
Snippet of Bottom function of my giphy.go file (Updated SearchGifs Function w/ ReplaceAll implementation)

Connecting everything together

Snippet from top of my slack.go file
Snippet from top of my slack.go file (I don’t need to import my new functions, just capitalize functions I want to use elsewhere)

Now that I have finally gotten all of the functions to work with my Giphy API, I had to make sure that all of my files were importing properly so that the specific functions can be used in other files that need them. One rule about Go that had me confused for a while was the fact that in order to make a function in a file exportable, I need to make sure that the function name is capitalized. I missed this part and kept receiving an error whenever I tried importing my giphy.go file functions into my slack.go file.

Once my instructor was able to help me fix this small mistake, I was able to import my files correctly and get my Slack bot to work in the Slack channel I invited it to!

Aftermath

Although there are surely a number of bots that can already do what I coded my bot to do, plus more functionality, I felt that I was able to become more familiar with how to code projects in Go. Practicing my skills by starting from scratch for multiple Go projects has boosted my confidence in my capability in creating new projects in Go from now on. I was able to clear up more questions I had with APIs in general as well as how they can be used in Go. It is motivating being able to look back at the projects I have made and how I can reuse everything I have done and learned into my next project, if I so choose to do so. Or maybe I can push myself to learn something new, and try to see how I can implement the new topic with what I already know now. I definitely believe that the way to feel more comfortable with new coding languages is by building projects from scratch repeatedly to build muscle memory in one’s coding skills.

Dancing GOpher by Egon Elbre
Dancing GOpher by Egon Elbre

--

--

Attending Make School Product College located in San Francisco, training to be a Backend Engineer.