Slack (SlackKit v1.0.0-alpha.0)

View Source

Defines the behaviour for a Slack Real Time Messaging (RTM) bot.

use Slack injects four overridable callbacks — handle_connect/2,
handle_event/3, handle_close/3, handle_info/3 — plus a default
child_spec/1 so the module can be supervised, and imports the helper
functions in Slack.Lookups and Slack.Sends. Slack.Bot.start_link/4
takes the resulting module, opens the WebSocket, and dispatches incoming
events to it.

Quick start

Define your bot:

defmodule MyBot do
  use Slack

  def handle_connect(slack, state) do
    IO.puts("Connected as @#{slack.me.name} to #{slack.team.name}")
    {:ok, state}
  end

  # Greet anyone who says "hi" in any channel the bot can see.
  def handle_event(%{type: "message", text: "hi"} = msg, slack, state) do
    send_message("Hello to you too!", msg.channel, slack)
    {:ok, state}
  end

  # Catch-all — Slack sends many event types; ignoring unknown ones keeps
  # the bot from crashing on each new flavour.
  def handle_event(_event, _slack, state), do: {:ok, state}
end

Start it under your supervision tree:

children = [
  {MyBot, []}
]

Supervisor.start_link(children, strategy: :one_for_one)

Or, for ad-hoc use:

{:ok, _pid} = Slack.Bot.start_link(MyBot, [], "xoxb-…")

See Token Generation Instructions for
obtaining a token.

Callbacks

All four callbacks are optional; the default implementations ignore their
input and return the unchanged state.

CallbackWhen it fires
handle_connect(slack, state)The WebSocket has connected and the bot identity is known.
handle_event(event, slack, state)An RTM event arrived from Slack. event is an atom-keyed map.
handle_close(reason, slack, state)The WebSocket closed — return :close to stop, or {:reconnect, state}.
handle_info(msg, slack, state)An arbitrary Erlang message arrived in the bot's mailbox.

Each callback returns {:ok, state} (with the exception of handle_close/3
which may also return :close). The returned state is threaded into the
next callback invocation, so you can carry arbitrary bot state across events.

The slack argument

Every callback receives a Slack.State struct that tracks the live view of
the workspace. SlackKit folds each incoming RTM event into it before invoking
your callback, so slack.channels, slack.users, and friends always reflect
the latest known state. See Slack.State for the field layout.

Sending messages

Inside a callback, send_message/3 (imported from Slack.Sends) writes a
text message back through the WebSocket:

send_message("Hello!", "C123ABC", slack)

For richer messages — attachments, blocks, threads, ephemeral posts — use
the corresponding Web API function under Slack.Web.Chat.

Driving the bot from outside

Anything sent to the bot's process arrives in handle_info/3, which is the
natural entry point for "send this message from elsewhere in my app":

def handle_info({:say, text, channel}, slack, state) do
  send_message(text, channel, slack)
  {:ok, state}
end

# …then, from a controller, a job, IEx, etc.
send(bot_pid, {:say, "External hello", "#general"})