Building a Slackbot with Ruby and Sinatra

Share this article

slackbot

This article was peer reviewed by Thom Parkin. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Slack seems to be everywhere these days. It is enjoying the kind of success and adoption that other services can only dream about. Part of the reason for its success is how easy it is to integrate Slack with other services. There are tons of integrations out-of-the-box, along with web hooks and other integration methods that make using Slack with your favorite service a breeze.

Another way Slack offers extensibility is “Slackbots”. Slackbots are items that can be configured to fire based on a keyword typed into Slack.

Today we’re going to see how to build a custom Slackbot that triggers on a keyword, performs some action, and responds back to Slack. We’re gonna build it using Ruby and the Sinatra web framework. There’s no database involved in this tutorial, but you could extend it and add one if you so desire. This is a basic tutorial that gives you a taste of building a Slack extension. We’re making a brick here with which you can build other things.

Let’s get started.

Our bot, let’s call it giubot, will provide a set of commands to get details from GitHub. We’ll make the trigger word as giubot: so an example would be,

Message:-
    giubot: issues _ twbs/bootstrap

Response:-
    There are currently 433 open issues on twbs/bootstrap.

We’re going to use the official GitHub API. Documentation for the API is available here.

Let’s setup the project files first.

Project Setup

Create a folder for the project and create the below files into like so:

giubot
|
|---- app.rb
|---- Gemfile

That’s it. It’s a simple app where all the functionality goes inside app.rb. The Gemfile is where we’ll specify the dependencies for our project. Let’s also add the gem dependencies before initializing and committing the changes in git. Add the following to the Gemfile:

source 'https://rubygems.org'

gem 'sinatra'
gem 'httparty'

and run

bundle install

A new Gemfile.lock file is created inside the project directory. Regarding our dependencies, all we need is these two gems: Sinatra and httparty. httpparty is a gem that lets handle HTTP requests easily.

Once you’ve created the files, it’s time to commit the changes into git. All the steps in this tutorial regarding git are optional, but encouraged. Git is also required if you want to host the app on Heroku. Let’s initialize our repository and commit all the changes. Type the following commands from inside the project directory:

git init
git add -A
git commit -m "Add project files and gem dependencies"

While we are at it, let’s also push our repository to GitHub. It is free for public repositories, but paid for private ones. Let’s quickly create our repository using this link. Once the repository is created, Github will supply the URL which can be located on the repository page. Copy that URL and add it as a remote:

git add remote origin https://github.com/avinoth/giubot.git

We’re adding the remote URL and aliasing it as origin. Once it’s done, push the changes to GitHub:

git push origin master

After it successfully pushes, you should see your code on GitHub. We’re done with bootstrapping, let’s go ahead and write some code.

Create API endpoint

Here’s how the communication between Slack and our web app will work: Whenever the word giubot: is mentioned in a message, Slack will send the details of the message, along with a couple of details about the Slack account, to the URL provided when the extension is configured (More on that later). The request method is a POST with data in the body.

We’ll fetch the full message, getting the repository name and the command requested in the message, then respond with the necessary data. For this app’s purposes, all we need is a single API endpoint which Slack will call if the trigger word is mentioned, generating the response we want to be posted back into Slack. Let’s add the below lines to our app.rb file:

require 'sinatra'
require 'httparty'`
require 'json'

post '/gateway' do
  message = params[:text].gsub(params[:trigger_word], '').strip

  action, repo = message.split('_').map {|c| c.strip.downcase }
  repo_url = "https://api.github.com/repos/#{repo}"

  case action
    when 'issues'
      resp = HTTParty.get(repo_url)
      resp = JSON.parse resp.body
      respond_message "There are #{resp['open_issues_count']} open issues on #{repo}"
  end
end

def respond_message message
  content_type :json
  {:text => message}.to_json
end

Let’s see what’s happening here. We’re requiring the only three modules we need for the app. There is a POST request hander called /gateway, which is going to serve all the requests from Slack. Then get the message, stripping out the trigger word. As you can see, we are making the trigger word independent of the app and making use of the one that comes along with the request, so not only giubot but any keywords will work.

After that, take the text parameter and split it by _, which is the separator to split the various components of the message. Having a standard separator will be helpful when you want to have more than one command, which might require more keywords.

There’s a case statement that performs the necessary action based on the incoming command. Currently it only supports an issues command, which fetches the current open issues count in a repository. Writing another command is just a case statement away, so that’s nice. Inside the case statement, make the API call to GitHub which returns the open issue count and we can build the response to post back to Slack.

Also, if you notice we’re not validating the token from Slack and simply ignoring the parameter altogether. This is not recommended, but since this is account-specific, we’re keeping it open. If you want you can validate the token by having this as the first line of the handler action:

return if params[:token] != ENV['SLACK_TOKEN']

That’s it. Our app’s functionality is done, it’s time to commit and push the changes:

git add -A
git commit -m "Add app logic"
git push origin master

Deploying the app

We will have to deploy the app to configure it in Slack and start using it. Let’s deploy it to Heroku[https://heroku.com], which is a PaaS provider for hosting web apps. Create a file called config.ru inside the project directory and add the below lines to it:

require './app'
run Sinatra::Application

This file is required by Heroku to recognize and start the app. Add the file to git and commit it:

git add config.ru
git commit -m "Add config.ru"

Install the heroku gem in your local system if you haven’t already:

gem install heroku

and type in the following commands from inside the project directory:

heroku create <APP-NAME>
heroku deploy

<APP_NAME> can be whatever you like, or you can leave it off and Heroku will assign a name to the app. Sign in with your Heroku credentials when it asks for them. Heroku will recognize it’s a Rack application by the config file we created and build the code. We have now deployed our app to Heroku.

Configuring Slack

We’re all set from the application side, let’s configure Slack with the URL of the app we just created. Go to the Outgoing Webhook URL on Slack’s website and click on Add Outgoing Webhooks Integration. In the Add new page, give all the details however you wish, including the app name and trigger word. In the URL box add the below URL:

http://<APP-NAME>.herokuapp.com/gateway

where <APP-NAME> is the Heroku name for your deployed application. Save the integration.

We have successfully created our extension and configured it. Test it out by typing messages in the channels with the trigger word we’ve configured at the time of configuring the extension, and see it in action.

slackbot

Please note, the message is a normal message, so it’s visible to everyone in the channel, as is the response.

Conclusion

Thusly, you now have taste of writing a Slackbot in Ruby. I hope this has your mind swimming in ideas of other Slackbots and extensiosn. The code used in this tutorial is hosted in GitHub. Feel free to fork and poke around. If you have created your own Slack extension, tell me about it in the comments below.

Frequently Asked Questions (FAQs) about Building a Slackbot with Ruby and Sinatra

How can I integrate my Slackbot with other applications?

Integrating your Slackbot with other applications can enhance its functionality and make it more useful. For instance, you can integrate it with Google Calendar to schedule meetings, or with Trello for project management. To do this, you’ll need to use APIs (Application Programming Interfaces) provided by these applications. You’ll need to send HTTP requests from your Slackbot to these APIs, and handle the responses. This can be done using the ‘net/http’ library in Ruby.

Can I use other programming languages to build a Slackbot?

Yes, you can use other programming languages to build a Slackbot. While this article focuses on using Ruby and Sinatra, Slackbots can also be built using languages like Python, JavaScript (Node.js), and PHP. The choice of language depends on your comfort level and the specific requirements of your bot. Regardless of the language you choose, the basic principles of building a bot – such as setting up webhooks, handling events, and sending messages – remain the same.

How can I test my Slackbot during development?

Testing your Slackbot during development is crucial to ensure it works as expected. You can use tools like Postman to send HTTP requests to your bot and check the responses. You can also use unit testing frameworks like RSpec (for Ruby) to write automated tests for your bot’s functionality. Additionally, you can use logging to track your bot’s activity and debug any issues.

How can I make my Slackbot interact with users in a more human-like way?

To make your Slackbot interact with users in a more human-like way, you can use Natural Language Processing (NLP) libraries like Wit.ai or Dialogflow. These libraries can help your bot understand user intent, manage conversations, and respond in a more natural and conversational manner.

How can I deploy my Slackbot?

Once you’ve built and tested your Slackbot, you can deploy it on a server so that it can be used by others. You can use cloud platforms like Heroku, AWS, or Google Cloud for deployment. These platforms provide detailed documentation on how to deploy your bot, and also offer features like scaling, monitoring, and logging.

How can I secure my Slackbot?

Securing your Slackbot is important to protect it from malicious attacks and to ensure the privacy of your users’ data. You can secure your bot by using HTTPS for all communication, validating all incoming requests, and storing sensitive data (like API keys) securely.

Can I build a Slackbot without coding?

Yes, there are platforms like Zapier and IFTTT that allow you to build simple Slackbots without coding. These platforms provide a user-friendly interface where you can set up triggers and actions for your bot. However, for more complex bots, coding is usually required.

How can I add custom commands to my Slackbot?

You can add custom commands to your Slackbot by using Slack’s slash commands feature. Slash commands allow users to interact with your bot by typing commands in the chat. You can set up slash commands in your bot’s settings on the Slack API website.

How can I make my Slackbot respond to specific events?

You can make your Slackbot respond to specific events by using Slack’s Events API. The Events API sends your bot a HTTP request whenever a specified event occurs. Your bot can then respond to this request as needed.

Can I use my Slackbot to send automated messages?

Yes, you can use your Slackbot to send automated messages. This can be done by setting up a cron job or a similar scheduling mechanism in your bot’s code. The bot can then send messages at the specified times without any manual intervention.

Vinoth is a Server Administrator turned Full stack web developer. He loves to try his hands on multiple programming languages but his primary programming language of choice is Ruby. He is currently a Software Engineer @ Intelllex building the server side of things. You can find more about him at avinoth.com.

botschatbotsEmerging TechGlennGrubysinatraslackslackbots
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week