In Scalac we use Slack for communication and more. We decided to create a framework for our custom Slack integrations, so we transform it into a living heart of our company. Here are some details on how and why we did that
In Scalac we believe that communication is essential in IT and that projects with inefficient information sharing are doomed to fail. Fortunately for us it doesn’t always mean that putting people in one place is the only way. More often it’s about creating the right spirit for exchanging knowledge and providing ways to do so. As in Scalac we are very often working remotely, we had to come up with a tool to help us communicate. We tried few different products for communication, but in the end we switched to Slack. We are using it for around a year now and are pleased with the rich experience it offers.
But our ambitions don’t stop here. As we are a medium size company we strive for maximum efficiency. We are eager to automate as much of the process as possible, so our employees can spend their time focusing on tasks requiring creativity and accountability. As we are hiring the best people, we don’t want them to do boring and repeatable busywork.
It’s not always an easy process. You have to face technical difficulties and convince people to trust the new tools.
How is Slack helping us automate? It’s done via Integrations. Slack Integrations contain apps for many useful services as Google Hangouts, Github, Crashlytics or Google Docs. Unfortunately for us it’s not enough … we would like to have a central hub with all our tools, so they have a common interface and are easily accessible. This is where Real Time Messaging API (provided by Slack) and Scala Slack Bot (hacked together by us) come in.
The following sections are a step by step guide on how to setup a custom integration for Slack using Scala Slack Bot.
First, let’s start with configuring the integration in Slack. First go to
https://XXX.slack.com/services/new (where XXX is the name of your organization). There you can browse all the existing integrations. Search for “Bots” option and click “View” button. Give the new bot a name and click “Add Bot Integration”. After that you will be taken to a page with a detailed view of your new bot. The most important thing is to generate and save the API Token. We will need it for later!
You should see something like this
Now let’s start with the Scala side of things. Create a new Scala application using sbt. Having this in place open your
build.sbt and add
Also open your
src/main/resources/application.conf file and add the API token we got from Slack as follows
The value of
websocket.key can be any Base64 encoded value. It will be used by the bot to identify websocket connection.
Having the needed libs in place we can create a starting point for our app.
As Scala Slack Bot is written on top of Akka, we need to create an
ActorSystem in which the bots will run first. Also we shouldn’t forget to close them properly using
sys.addShutdownHook(shutdown()). Now we can start tinkering with our bots. The heart of the bot system is the ScalaBotActor class that takes few parameters:
BotModules instance, a
MessageEventBus for communication, reference to master class and an
ActorRef pointing to
UserStorage actor. You don’t have to worry about all of that now. Just concentrate on BotBundle.
A note on architecture. As Slack limit the amount of integrations you can use, we decided on the following approach. We integrate a single application with Slack, so only one slot is used and you are free to add third-party integrations. On the other hand this application may hold multiple bot modules, each providing a distinct feature. Those modules are created by instances of
The body of a
BotModules instance is very simple. It defines one function
registerModules which is responsible for initializing actor instances. One thing to notice here is that the actors share the same instance of
MessageEventBus (passed as a parameter for easier testing) and all have readable actor names.
In our example we start three modules. The
CommandsRecognizerBot is a handy utility actor, invisible from the outside, that will translate raw Slack messages for us into a more useful
HelpBot is the Slack’s counterpart of Linux
man command - it presents users with options and descriptions for commands. The
CalculatorBot is a dummy bot, that we will write on our own.
OK, let’s create our first bot. This one will be a simple Clojure-style calculator.
Let’s elaborate on this a little. The
AbstractBot class is a thin wrapper around Akka’s
Actor class providing few useful utility methods for bot authors and constraints a Bot should meet. There are three things a bot should do:
helpmethod for maintainers and user
actmethod, which behaves roughly the same way as
receivein an ordinary actor
The first thing you might notice in this draft is
help being a
OutboundMessage represents a message that will be sent back to Slack. It takes two parameters: on what channel to send and what to send. Having this basic understanding we can move to implementing the
act method. We can do that as follows.
As you can see this is not far from Akka. The only difference is that we match on
Command instances provided to us by
CommandsRecognizerBot. This class carries three values. The first is the command name without the leading ‘command’ character ($ be default), and
List[String] of the arguments (without the leading command) and the raw message (so we can, for instance, extract the channel id). After matching a request we perform some computations, form an
OutboundMessage and pass it to
publish for sending. Simple as that.
There are few things to consider when writing a new bot. We find it useful to communicate with end users as much as possible about the failures and when a command can’t be matched (for instance it’s lacking params). You don’t have to extend
AbstractBot, but it’s recommended in most cases. If you are in need for creating an internal bot able to communicate with Slack consider using
IncomingMessageListener directly, but proceed with caution.
For more examples you can check the bots we are using. The source is available here.
The command above should start the bot. After all components start successfully, the bot will get online as on the screen.
Now we can send a few Direct Messages to the bot:
The bot will also listen on all channels that he has been invited to. If you think that this “console command” style of communication is not for you, you can also mention the bot and pass the command without the leading character.
In Scalac we have a strong belief that in the future all redundant tasks will be automated and the done by efficient, specialized robots working on behalf of humans. So people will be able to focus on creative tasks and those tasks that require taking responsibility. We are far from there, yet I’m in the opinion that Slack Bot presented to you above is a step into the future.