Back in my Campfire days, I remember being blown away when Github released Hubot. Our team tinkered around with our install for days – hoping to make Hubot do our bidding. It was a great little tool (and still is!), but I’ve recently fallen in love with Slack’s “Slash Commands”. They’re a handy way to send commands to a service and get a response. And the best part? You can write one in Ruby!
Slash commands work in a simple manner: you start a command with a forward slash, then the command name. For this basic example, we’ll ask for weather for a particular zip code:
The entire command, along with any additional text, is sent as a webhook to your application.
The token
is a secret setup when you configure the command inside your Slack instance. You’ll be checking this to ensure the command is actually from Slack.
The response_url
is where we’ll send our data once it’s ready.
The webhook from Slack comes as a POST
request, so we’ll create a Rails controller with a create
method:
We’re doing a few simple things here:
valid_slack_token?
which compares the token in the params with the one Slack gave us (and is stored in an ENV var)..to_h
to do this for me) We’re using a background job here since we’ll be communicating with a 3rd party API. That way, we can return a response quickly to Slack and avoid a timeout.The { response_type: "in_channel" }
JSON tells slack to leave the original command (/weather 83864
) in the Slack chat history. If you’re sending something back that only the user will see privately, you’ll want to return { response_type: "ephemeral" }
at this step.
Next, we’ll have our Sidekiq worker fetch the data and send it all back using the response_url
that Slack sent us in the params.
To fetch the Weather data, I’m using Weather Underground. I’m going to create a basic class to encapsulate some of this behavior.
And then, the Sidekiq worker which uses this class:
Here’s what’s happening:
CommandWorker
to be used in generating the text.response_url
value it sent us in the first step.To make our message a little prettier, we can send along the image URL as an “attachment” to Slack. This requires simply modifying our JSON a bit like this:
Slack provides a nice demo tool of message formatting. It’s very handy when getting your messages to look just right.
Next, we may want to send different types of commands to the same app. For instance, I could specify what I want from the weather app, like this:
To do so, you may choose to separate out pieces of the app into separate modules or sub-classes, then dispatch them from one place. In an app I’m working on at Heroku, we pass commands like this:
…where slack-app-name
is one of a few different Slash Commands apps. In order to properly parse the task, subtask, and command, we have a Processor module:
We use this to initialize the correct class to handle the command:
Now we can send something like /weather forecast:tomorrow 83864
and have a class Commands::Forecast
process it by looking at subtask
(tomorrow
) and message
(83864
). By doing so we can extend and expand our app to process multiple different tasks.
I hope this gives you a glimpse into what’s possible with Slash Commands! Happy coding, Rubyist!
Writer. Musician. Adventurer. Nerd.
Purveyor of GIFs and dad jokes.