Anderson Dias
Little programming joys
5 min readAug 18, 2017

--

Introduction

This is the last post of a series about how to write Slack Command APIs in Ruby. In the past post, we’ve finished the API by validating the input text and responding to callers with the correct outputs, based on requested actions.

In this last part of the tutorial we’re going to talk about the Chat API and how to use it to send direct messages to the congratulated user.

Sending direct messages to users

We’ve completed the application responsible for receiving, authorizing, validating and responding to an incoming Command API message.

Now, as a bonus, let’s use another API to send a direct message to the congratulated user. We’re going to use the chat.postMessage API method, but first we need to authorize it’s usage.

Authorizing the chat API

We need a new permission in order to be able to send a message as the a bot. This permission is called chat:write:bot :

Access “OAuth & Permission” menu, then “Permission”, Select the correct scope and “Save Changes”

As you hit the “Save Changes” button on the Scopes box you will be asked to reinstall the application:

Follow the “click here” link.

You’ll be redirected to the application authorization page. Authorize the new permission and we’re done here:

Click “Authorize”

Testing the API via curl

Now we’ve authorized the new permissions to our application, we are able to test it via curl. Before that, we need the application’s OAuth Token to send the commands:

Copy the value of the “OAuth Access Token” field

Replace the TOKEN with the value recently copied uppon and JOHN with a valid username in your team (perhaps yours):

curl --data "token=TOKEN&channel=%40JOHN&text=%40andersondias%20has%20congratulated%20you.&as_user=false&link_names=true" https://slack.com/api/chat.postMessage

And you should see a return like this:

{"ok":true,"channel":"D6543210","ts":"1503010047.000183","message":{"text":"@andersondias has congratulated you.","username":"command-app","bot_id":"B12345678","type":"message","subtype":"bot_message","ts":"1503010047.000183"}}

Access the Slack application with the channel username given upon and you will find a new message from @slackbot that should look like this:

The message sent via curl as expected.

Let’s dig in the params we’ve used in the curl call:

  • token: it’s the OAuth Token from our Slack Application;
  • channel: who is going to receive the message; it’s the encoded version of @JOHN;
  • text: the encoded text to be sent; in this case “@andersondias has congratulated you.”;
  • as_user: when true it sends the message as the caller user; when false sends as the bot;
  • link_names: links user and channel names within text.

There are many other params that enables us to customize the chat messages as you can find in the chat.postMessage method documentation.

Now we know everything is working, let’s send direct messages from within our application.

Calling the API in our application via HTTPClient

Let’s begin by creating a new class that will deliver the messages. We will be using the most basic HTTP client in Ruby and we need to import it in the Gemfile:

# Gemfile
source 'https://rubygems.org'
ruby '2.4.1'
gem 'sinatra'
gem 'httpclient'

Run bundle install in the terminal to update the Gemfile.lock file.

Now, create a new file:

# app/slack_messenger.rbrequire 'httpclient'class SlackMessenger
SLACK_API_ENDPOINT = 'https://slack.com/api/chat.postMessage'.freeze
def self.deliver(from, to, message)
new(from, to, message).deliver
end
def initialize(from, to, message)
@from, @to, @message = from, to, message
end
def deliver
client = HTTPClient.new
client.post(SLACK_API_ENDPOINT, params)
end
def params
{
token: ENV['SLACK_OAUTH'],
channel: @to,
text: "@#{@from} has congratulated you: \"#{@message}\".",
as_user: false,
link_names: true
}
end
end

As you may notice, the OAuth token is now encapsulated in the SLACK_OAUTH env var.

Next, we need to import this class and use it:

# app.rbrequire 'sinatra'
require_relative 'app/slack_authorizer'
require_relative 'app/slack_messenger'
...post '/slack/command' do
case params['text'].to_s.strip
when VALID_CONGRATULATE_EXPRESSION
from, message = $1, $2
SlackMessenger.deliver(params['user_name'], from, message)
OK_RESPONSE % from

end
end

Note: I’ve removed all the unrelated code here and highlighted the code I’ve introduced inside the case statement. See the GitHub repository at the end of the post for more detailed codes.

We’re fetching the from and message variables from the regex captured results.

Before deploying it, we must setup the new environment variable:

Add the SLACK_OAUTH config variable to Heroku.

Deploy and test it

Finally, we are able to deploy the new application version:

$ git add .
$ git commit -m 'Sending direct messages to users'
$ git push heroku master

Test it by sending this a new command:

/congratulate @andersondias you did a great job!

And you may see something like this:

The direct message sent by the application.

Conclusion

We have come to the end of this series of posts on how to write Slack Command APIs in Ruby. Our application now receives the command message and sends a reply to the congratulated user.

There are many improvements to be made in a real world application:

  • Do not allow users to send congratulations to themselves;
  • Validates if the congratulated username is valid;
  • Send the direct message asynchronously to prevent slow response times.

Probably, I’ll tackle each of these changes in the GitHub repository. Feel free to open pull requests with any improvements you may find useful.

Happy hacking!

--

--