Documentation ¶
Overview ¶
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 ¶
- Constants
- func StoreReconnectURL(bot *Bot, event map[string]interface{}) (*Message, Status)
- type Bot
- func (bot *Bot) Call(method string, data url.Values) (map[string]interface{}, error)
- func (bot *Bot) DirectMessage(userID, text string) *Message
- func (bot *Bot) Listen(pattern string, handler BotAction)
- func (bot *Bot) ListenRegexp(re *regexp.Regexp, handler BotAction)
- func (bot *Bot) Mention(nick, text, channel string) *Message
- func (bot *Bot) OnEvent(event string, handler BotAction)
- func (bot *Bot) OnEventWithSubtype(event, subtype string, handler BotAction)
- func (bot *Bot) OpenDirectMessage(userID string) (string, error)
- func (bot *Bot) Respond(text string, handler BotAction)
- func (bot *Bot) RespondRegexp(re *regexp.Regexp, handler BotAction)
- func (bot *Bot) Start() error
- type BotAction
- type Error
- type Message
- type Status
- type User
Constants ¶
const (
// Version is the semantic version of this library.
Version = "0.2.0"
)
Variables ¶
This section is empty.
Functions ¶
func StoreReconnectURL ¶ added in v0.1.5
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.
Types ¶
type Bot ¶
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 (*Bot) Call ¶
Call calls a Slack API method, setting the token of bot in the method call parameters.
func (*Bot) DirectMessage ¶
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 ¶
Listen registers the given handler to fire on "message" events with no subtype which match the regexp specified in pattern.
func (*Bot) ListenRegexp ¶
ListenRegexp functions exactly as Listen, but instead takes a compiled regexp instead of a string.
func (*Bot) Mention ¶
Mention constructs a Message which mentions nick with text in channel and returns a reference to it.
func (*Bot) OnEventWithSubtype ¶
OnEventWithSubtype registers handler to fire on the given type and subtype of event.
func (*Bot) OpenDirectMessage ¶
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 ¶
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 ¶
RespondRegexp functions exactly as Respond, but instead takes a compiled regexp instead of a string.
type BotAction ¶
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.
type Error ¶ added in v0.1.1
type Error struct {
Message string
}
Error is the struct used to create custom errors that occur within the slack package.
type Message ¶
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 ¶
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.
type Status ¶
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 )