Slug
Slug is like Plug, but for Slack.
Your bot module defines a pipeline of functions (slugs) that receive events from Slack. Each slug can take actions in response to the events it receives, and may optionally add metadata to an event for other slugs to use downstream. This is similar to Plug and its conn
object.
Slug connects and communicates over websocket using Slack’s RTM API. A simple Slug.Slack
process also provides access to a few handy Web API calls, and maintains a cache of user and channel information for quick lookups.
Hex docs for Slug are available here.
Installation and example
Start a new project.
mix new bot_family --sup
Add Slug
to your deps, then run mix deps.get
.
def deps do
[
{:slug, "~> 0.1.0"}
]
end
Create your Bot
Create a new module for your bot, pull in Slug.Bot
, and define a simple pipeline of slugs.
# lib/bot_family/my_bot.ex
defmodule BotFamily.MyBot do
use Slug.Bot
slug(Slug.Common.MessagesOnly)
slug(Slug.Common.CheckMentioned)
slug(:simple_reply)
def simple_reply(%Slug.Event{data: event_data, metadata: %{mentioned: true}} = event) do
%{user: user_id, channel: channel_id} = event_data
Slug.Bot.send_text(__MODULE__, channel_id, "Oh hey, <@#{user_id}>!")
event
end
def simple_reply(event), do: event
end
What’s going on here? In our example bot we’re using the included Slug.Common.MessagesOnly
slug module to filter out events that are not message events.
Next we use the included Slug.Common.CheckMentioned
slug, which will check to see if our bot was mentioned in the message we just received. It will add a mentioned
key to the metadata.
Finally, we supply our own slug called simple_reply
. If it’s been mentioned, it will send a reply to the user that mentioned it in the channel using Slug.Bot.send_text/3
. If not, it will simply pass the event along.
Check out the documentation in the Slug
module for more information on creating your own slugs.
Configure your keys
Before we try out our bot, we need to configure the api keys for our bot in confix/config.exs
, and for the Slack Web API. In our case, we’ll use the same token for both.
# config/config.exs
use Mix.Config
config :slug,
keys: %{
:web_api => "xoxb-your-key",
BotFamily.MyBot => "xoxb-your-key"
}
Hello World
Now let’s boot our bot in iex
. Make sure your bot has been invited to, and joined, the channel you are using.
$ iex -S mix
iex(1)> BotFamily.MyBot.start_link()
10:52:55.558 [info] Elixir.MyBot: Initializing Websocket
{:ok, #PID<0.253.0>}
iex(1)> Slug.Bot.send_to_channel(BotFamily.MyBot, "general", "hello world")
Check out the documentation in the Slug.Bot
module for more information on sending messages from your bot.
Test your slug pipeline
You should see a “hello world” from your bot in #general
(assuming the bot is in that channel).
Let’s test our slug pipeline. Try mentioning the bot by name in your Slack channel. For example, “Hello @mybot” (use the name of the bot you specified when you created the integration in Slack). You should see a reply.
Add your bot as a worker
As a last step, you probably want to add your bot as a worker to your application.ex
instead of starting the bot explicitly.
# lib/application.ex
defmodule BotFamily.Application do
@moduledoc false
use Application
def start(_type, _args) do
children = [BotFamily.MyBot]
opts = [strategy: :one_for_one, name: BotFamily.Supervisor]
Supervisor.start_link(children, opts)
end
end