slack: github.com/ajm188/slack Index | Files | Directories

package slack

import "github.com/ajm188/slack"

Package slack provides a library for interacting with the Slack API and building custom bots.

Basics

The basic workflow for writing a bot goes as follows: first, create a new Bot object with your Slack API token; next, register any callbacks you want (outlined in further detail below); last, connect the bot to Slack and let it run forever. This looks like:

bot := slack.NewBot(myToken)
// register callbacks here
bot.Start()

A bot requires a Slack API token in order to connect to Slack, which you can find under the Custom Integrations for your Slack team. It's worth noting that a bot cannot add or remove itself from channels; this has to be done by you when you configure the bot.

When the bot connects, it will collect information about users and channels, and store this information in the Users and Channels maps. The reason for this is that Slack does not deal with channels and users in terms of their names (this is a good thing - channel names and nicks can change), but by a unique ID. The Users and Channels maps map in both directions; so given the human-readable name, they will return the ID, and given the ID they will return the human-readable name.

Slack RTM Basics

Slack provides a Real Time Messaging (RTM) API, for interacting with a Slack channel programmatically. The important thing to know is that all data is in a JSON format. See https://api.slack.com/rtm for more information.

Design

Communication with the RTM API is done via websockets. Package slack uses https://github.com/gorilla/websocket for websockets. From their documentation: "Connections support one concurrent reader and one concurrent writer. Applications are responsible for ensuring that no more than one goroutine calls the write methods (NextWriter, SetWriteDeadline, WriteMessage, WriteJSON) concurrently and that no more than one goroutine calls the read methods (NextReader, SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, SetPingHandler) concurrently."

For this reason, BotActions (the type for event handlers) do not take a reference to the websocket connection. Instead, a BotAction takes a reference to the bot and the event that caused the handler to fire, and it should return a tuple of (*Message, Status). If the reference to the message is nil, then nothing will be written into the connection. The Status indicates to the bot how it should continue to process. See the documentation on the Status values for more information.

The main loop listens for incoming events from the RTM websocket, and then calls any handlers that are registered to handle that kind of event. It then writes any non-nil responses into the websocket, and - depending on the various status values - may terminate or continue looping.

Events

The Slack RTM API defines a large number of events, which are listed at https://api.slack.com/events. Note that some events have subtypes. Thus, the bot supports two general purpose methods for registering an event handler, which look like:

bot := NewBot(myToken)
// Fires on any event with type `eventType`
bot.OnEvent(eventType, myHandler)
// Fires only on events with type `eventType` and subtype `eventSubtype'.
// Events with type `eventType` and no subtype will never cause this
// handler to fire.
bot.OnEventWithSubtype(eventType, eventSubtype, myOtherHandler)

Since messages are the most common kind of event, instances of Bot have two helper methods for registering handlers for messages: "Listen" and "Respond".

Listen takes a pattern and a BotAction, and only invokes the given handler if the message text matches the regular expression defined by the pattern. It has a variant, ListenRegexp, which does the same but takes a compiled regular expression rather than a string pattern.

Respond also takes a pattern and a BotAction, and only invokes the given handler if the message text "mentions" the bot, and the rest of the text matches the regular expression defined by the pattern. For a message to "mention" the bot, the message must begin with the bot's name. The leading "@" that is commonly used in Slack is optional, as is the trailing ": ". The text without the portion that was considered part of the "mention" is then compared against the pattern. Respond also has a variant, RespondRegexp, which does exactly what you would expect.

Common BotActions

Package slack provides a few helper functions for generating BotAction handlers for common tasks.

"Respond" creates a handler which will reply to a "message" event with the specified text. So, if a user named "@example" triggers the handler, the bot will say "@example: <text>".

"React" creates a handler which will post a Slack reaction to a "message" event with the specified emoji name. Note that you do not need to put the colons around the emoji name, unlike what you would need to manually do in Slack to produce the emoji.

Index

Package Files

api.go bot.go bot_action.go direct_message.go doc.go error.go event.go listen.go mention.go message.go plugin.go react.go respond.go status.go time.go user.go

Constants

const (
    // Version is the semantic version of this library.
    Version = "0.2.0"
)

type Bot Uses

type Bot struct {
    Token       string
    Name        string
    ID          string
    Handlers    map[string]([]BotAction)
    Subhandlers map[string](map[string]([]BotAction))
    Users       map[string]*User
    Channels    map[string]string
    // contains filtered or unexported fields
}

Bot encapsulates all the data needed to interact with Slack.

func NewBot Uses

func NewBot(token string) *Bot

NewBot constructs a new bot with the passed-in Slack API token.

func (*Bot) Call Uses

func (bot *Bot) Call(method string, data url.Values) (map[string]interface{}, error)

Call calls a Slack API method, setting the token of bot in the method call parameters.

func (*Bot) DirectMessage Uses

func (bot *Bot) DirectMessage(userID, text string) *Message

DirectMessage constructs a Message object to send to userID. The channel is obtained by opening a direct message with the given user.

func (*Bot) Listen Uses

func (bot *Bot) Listen(pattern string, handler BotAction)

Listen registers the given handler to fire on "message" events with no subtype which match the regexp specified in pattern.

func (*Bot) ListenRegexp Uses

func (bot *Bot) ListenRegexp(re *regexp.Regexp, handler BotAction)

ListenRegexp functions exactly as Listen, but instead takes a compiled regexp instead of a string.

func (*Bot) Mention Uses

func (bot *Bot) Mention(nick, text, channel string) *Message

Mention constructs a Message which mentions nick with text in channel and returns a reference to it.

func (*Bot) OnEvent Uses

func (bot *Bot) OnEvent(event string, handler BotAction)

OnEvent registers handler to fire on the given type of event.

func (*Bot) OnEventWithSubtype Uses

func (bot *Bot) OnEventWithSubtype(event, subtype string, handler BotAction)

OnEventWithSubtype registers handler to fire on the given type and subtype of event.

func (*Bot) OpenDirectMessage Uses

func (bot *Bot) OpenDirectMessage(userID string) (string, error)

OpenDirectMessage opens a direct message with the given user. The newly created channel ID is returned, or an error in the case of error. If a direct message is already open between the bot and userID, then the API call still succeeds and returns the ID for the pre-existing direct message.

func (*Bot) Respond Uses

func (bot *Bot) Respond(text string, handler BotAction)

Respond registers the given handler to fire on "message" events with no subtype, which address the bot directly and match the given text.

func (*Bot) RespondRegexp Uses

func (bot *Bot) RespondRegexp(re *regexp.Regexp, handler BotAction)

RespondRegexp functions exactly as Respond, but instead takes a compiled regexp instead of a string.

func (*Bot) Start Uses

func (bot *Bot) Start() error

Start initiates the bot's interaction with Slack. It obtains a websockect URL, connects to it, and then starts the main loop.

func (*Bot) UsePlugin Uses

func (bot *Bot) UsePlugin(pluginF PluginFunc, args ...interface{}) error

UsePlugin will load a plugin if the plugin can load. `args` is a variable-length list of arguments that will be passed to the plugin's Load function.

type BotAction Uses

type BotAction func(self *Bot, event map[string]interface{}) (*Message, Status)

BotAction represents a handler for an RTM event. A valid BotAction takes a reference to the bot, as well as the event that caused it to fire. It should then return a reference to a Message (which can be nil), and a Status, which instructs the bot's main loop in whether to continue listening and sending messages or to terminate.

func React Uses

func React(emoji string) BotAction

React creates a BotAction which reacts to the passed-in event with emoji.

func Respond Uses

func Respond(text string) BotAction

Respond creates a BotAction which responds to the passed-in event with text.

type Error Uses

type Error struct {
    Message string
}

Error is the struct used to create custom errors that occur within the slack package.

func (*Error) Error Uses

func (err *Error) Error() string

type Message Uses

type Message struct {
    // contains filtered or unexported fields
}

Message represents a message to be sent to the Slack RTM API. Messages are converted to a JSON-like map before they are written to the websocket.

func NewMessage Uses

func NewMessage(text, channel string) *Message

NewMessage constructs a new message object which will send text to channel. The Slack RTM API uses IDs to identify messages, so NewMessage uses the current time as the identifier.

func StoreReconnectURL Uses

func StoreReconnectURL(bot *Bot, event map[string]interface{}) (*Message, Status)

StoreReconnectURL takes a "url" from an event and stores it. This is done so that when Slack migrates a team to a new host, the bot can use the reconnect URL to reattach to the team.

type Plugin Uses

type Plugin interface {
    Name() string
    CanLoad() bool
    Load(*Bot, ...interface{}) error
}

The Plugin interface is used to implement a plugin for a Slack bot.

Name should return the name of the plugin. This is useful for logging.

CanLoad should return true if the plugin can be loaded without error. If CanLoad returns false, the plugin will not be loaded.

Load should contain the code necessary to actually load the plugin. It receives a reference to the bot, in order to register handlers, or anything else the plugin may need to do to load itself into the bot. It also receives a variable-length list of arbitrary arguments that the plugin may need to load correctly, such as configuration options. Load should return an error if there were any issues loading the plugin.

type PluginFunc Uses

type PluginFunc func() Plugin

PluginFunc is a function which returns a Plugin. This can be used if your plugin requires any special setup.

type Status Uses

type Status int

Status is an enumerated type used to communicate between BotActions and the bot's main loop.

const (
    // Continue indicates to keep listening and sending messages.
    Continue Status = iota
    // ShutdownNow indicates to terminate immediately and not send any messages
    // from possible downstream BotActions.
    ShutdownNow
    // Shutdown indicates to finish sending any messages from possible
    // downstream BotActions and then terminate.
    Shutdown
)

type User Uses

type User struct {
    ID        string
    Nick      string
    FirstName string
    LastName  string
}

func UserFromJSON Uses

func UserFromJSON(data map[string]interface{}) *User

func (*User) FullName Uses

func (user *User) FullName() (fullName string)

Directories

PathSynopsis
plugins/githubPackage github provides a plugin for building Github integrations into github.com/ajm188/slack.

Package slack imports 9 packages (graph) and is imported by 1 packages. Updated 2016-07-20. Refresh now. Tools for package owners.