slack

package
v0.0.0-...-ba21cce Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2018 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package slack provides utilities for implementing slack bots in go.

Index

Constants

View Source
const CommandImmediateResponseTimeout = 2000 * time.Millisecond

CommandImmediateResponseTimeout is the maximum time a command invocation waits before assuming you'll reply using the ResponseURL

View Source
const InteractionImmediateResponseTimeout = 2000 * time.Millisecond

InteractionImmediateResponseTimeout is the amount of time an interaction request will wait before it returns with 200 and assumes that ResponseURL will be used to respond.

Variables

View Source
var (
	ErrInvalidClientID            = errors.New("Invalid Client ID")
	ErrInvalidClientSecret        = errors.New("Invalid Client Secret")
	ErrInvalidVerification        = errors.New("Invalid Verification Token")
	ErrInvalidConnector           = errors.New("Invalid Connector")
	ErrInvalidBotStorage          = errors.New("Invalid Bot Storage")
	ErrInvalidConversationStorage = errors.New("Invalid Conversation Storage")

	ErrConversationExists        = errors.New("Conversation Already Exists")
	ErrConversationNotFound      = errors.New("Conversation Not Found")
	ErrConversationAlreadyActive = errors.New("Conversation Already Active")
	ErrNoStartState              = errors.New("Conversation Has no start state")

	ErrInvalidMessage = errors.New("invalid message")
	ErrChannelUnset   = errors.New("channel is not set")

	ErrExceededResponseCommand = errors.New("Can only respond upto 5 times for a command")

	ErrExceededResponseInteraction = errors.New("Can only respond upto 5 times for an interaction")
	ErrEmptyResponseURLInteraction = errors.New("Empty Response URL")

	ErrStateAlreadyExists = errors.New("State Already Defined")

	ErrBotNotFound     = errors.New("Bot Not Found")
	ErrBotAlreadyAdded = errors.New("Bot Already Added")
	ErrItemNotFound    = errors.New("Item Not Found")
)

Functions

func WithBotStore

func WithBotStore(b BotStore) func(*Controller) error

WithBotStore sets a custom BotStore implementation for storing bot data.

func WithClientID

func WithClientID(id string) func(*Controller) error

WithClientID can be passed to NewController to set the Slack Client ID.

func WithClientSecret

func WithClientSecret(secret string) func(*Controller) error

WithClientSecret can be passed to NewController to set the Slack Client Secret.

func WithConnector

func WithConnector(conn Connector) func(*Controller) error

WithConnector can set a custom Connector instance to manage WebSocket connections.

func WithConversationStore

func WithConversationStore(cs ConversationStore) func(*Controller) error

WithConversationStore sets a custom ConversationStore implementation for storing conversation data.

func WithVerification

func WithVerification(secret string) func(*Controller) error

WithVerification can be passed to NewController to set the slack Verification token.

Types

type Bot

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

Bot represents a single slack bot unique to a slack team.

func (*Bot) BotUser

func (bot *Bot) BotUser() string

BotUser gets the User ID of the Bot

func (*Bot) Reply

func (bot *Bot) Reply(msg *rtm.Message, response *chat.Message) (*chat.Message, error)

Reply replies to a user message.

func (*Bot) ReplyEphemeral

func (bot *Bot) ReplyEphemeral(msg *rtm.Message, response *chat.EphemeralMessage) (string, error)

ReplyEphemeral replies to a message with an ephemeral message.

func (*Bot) ReplyInThread

func (bot *Bot) ReplyInThread(msg *rtm.Message, response *chat.Message) (*chat.Message, error)

ReplyInThread replies to a message in a thread, creates one if not in a thread.

func (*Bot) Say

func (bot *Bot) Say(msg *chat.Message) (*chat.Message, error)

Say sends a message in a channel.

func (*Bot) SayEphemeral

func (bot *Bot) SayEphemeral(msg *chat.EphemeralMessage) (string, error)

SayEphemeral sends an ephemeral message in a chat.

func (*Bot) Start

func (bot *Bot) Start() error

Start opens a WebSocket connection to slack to send and receive messages through this bot.

func (*Bot) StartConversation

func (bot *Bot) StartConversation(user, channel, name string) error

StartConversation starts the conversation with the given name for the given user in the given channel.

func (*Bot) Team

func (bot *Bot) Team() string

Team gets the ID of the team the bot is in.

func (*Bot) Token

func (bot *Bot) Token() string

Token gets the access token used to create the bot.

func (*Bot) Typing

func (bot *Bot) Typing(channel string) error

Typing sends a typing indicator to this bot's connector instance.

func (*Bot) Update

func (bot *Bot) Update(ts string, msg *chat.Message) (string, error)

Update updates a message.

type BotStore

type BotStore interface {
	// AddBot adds a new bot
	AddBot(*oauth.AccessResponse) error

	// GetBot gets the bot payload for a team id
	GetBot(string) (*oauth.AccessResponse, error)

	// RemoveBot removes a bot given the team ID
	RemoveBot(string) error

	// AllBots gets all the bots stored ever
	AllBots() ([]*oauth.AccessResponse, error)
}

BotStore is an interface used to store bot data.

type ChannelJoinMessagePair

type ChannelJoinMessagePair struct {
	*rtm.ChannelJoinMessage
	*Bot
}

ChannelJoinMessagePair is sent for channel join events.

ffjson: skip

type Command

type Command struct {
	TeamID         string `json:"team_id"`
	TeamDomain     string `json:"team_domain"`
	EnterpriseID   string `json:"enterprise_id"`
	EnterpriseName string `json:"enterprise_name"`
	ChannelID      string `json:"channel_id"`
	ChannelName    string `json:"channel_name"`
	UserID         string `json:"user_id"`
	Command        string `json:"command"`
	Text           string `json:"text"`
	ResponseURL    string `json:"response_url"`
	TriggerID      string `json:"trigger_id"`
	// contains filtered or unexported fields
}

Command is the payload sent by slack for a command. ffjson: skip

func (*Command) OpenDialog

func (command *Command) OpenDialog(d *dialog.Dialog, token string) error

OpenDialog opens a dialog as a response to a command.

func (*Command) Respond

func (command *Command) Respond(msg *chat.Message, inChannel bool) error

Respond responds to a command using the response URL

func (*Command) RespondImmediately

func (command *Command) RespondImmediately(msg *chat.Message, inChannel bool) error

RespondImmediately sends an immediate response to a command

func (*Command) RespondWithEmptyBody

func (command *Command) RespondWithEmptyBody() error

RespondWithEmptyBody responds to a command with an empty response.

func (*Command) RespondWithErrors

func (command *Command) RespondWithErrors(errs []*dialog.Error) error

RespondWithErrors sends errors as a command response.

type Connector

type Connector interface {
	// add a new team and socket url to manage
	Add(team, url string) error

	// get incoming messages
	Messages() <-chan *connector.MessagePayload

	// send typing indicator for a team
	Typing(team, channel string) error

	// close the connector
	Close()
}

Connector defines the client interface to a service that manages WebSocket connections for this application.

type Controller

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

Controller is essentially a manager for a single slack App.

ffjson: skip

func NewController

func NewController(options ...func(*Controller) error) (*Controller, error)

NewController creates a new Controller using the provided functional arguments.

func (*Controller) AmbientMessages

func (c *Controller) AmbientMessages() <-chan *MessagePair

AmbientMessages are messages in conversations that the bot is in, but not mentioned in the message.

func (*Controller) BotAdded

func (c *Controller) BotAdded() <-chan *Bot

BotAdded returns a receive only channel that gets a payload each time a new bot is added.

func (*Controller) ChannelJoin

func (c *Controller) ChannelJoin() <-chan *ChannelJoinMessagePair

ChannelJoin sends a payload each time the bot is added to a new channel.

func (*Controller) CommandHandler

func (c *Controller) CommandHandler() http.HandlerFunc

CommandHandler returns a http.HandlerFunc that can handle slack Command requests.

func (*Controller) Commands

func (c *Controller) Commands() <-chan *Command

Commands returns a receive only channel that'll send a value each time a new command invocation is made.

func (*Controller) CreateAddToSlackURL

func (c *Controller) CreateAddToSlackURL(scopes []string, redirect, state string) (string, error)

CreateAddToSlackURL creates a slack OAuth authorize URL.

func (*Controller) CreateBot

func (c *Controller) CreateBot(token string) (*Bot, error)

CreateBot adds a new Bot given a slack access token.

func (*Controller) DirectMentions

func (c *Controller) DirectMentions() <-chan *MessagePair

DirectMentions returns messages which are sent by mentioning the bot as the first term.

func (*Controller) DirectMessages

func (c *Controller) DirectMessages() <-chan *MessagePair

DirectMessages returns a receive only channel to get direct messages.

func (*Controller) EventHandler

func (c *Controller) EventHandler() http.HandlerFunc

EventHandler returns a http.HandlerFunc that can listen to slack events.

func (*Controller) GroupJoin

func (c *Controller) GroupJoin() <-chan *GroupJoinMessagePair

GroupJoin sends a payload each time a user joins a group chat.

func (*Controller) InteractionHandler

func (c *Controller) InteractionHandler() http.HandlerFunc

InteractionHandler returns a http.HandlerFunc that can be used to handle interactions from slack.

func (*Controller) InteractionOptions

func (c *Controller) InteractionOptions() <-chan *InteractionOptionsPair

InteractionOptions returns a payload each time a new option is added.

func (*Controller) InteractionOptionsHandler

func (c *Controller) InteractionOptionsHandler() http.HandlerFunc

InteractionOptionsHandler returns a http.HandlerFunc that can handle options requests. NOTE: this blocks calling thread

func (*Controller) Interactions

func (c *Controller) Interactions() <-chan *InteractionPair

Interactions returns a payload for each new interaction

func (*Controller) Mentions

func (c *Controller) Mentions() <-chan *MessagePair

Mentions are messages where the bot is mentioned somewhere in the middle.

func (*Controller) OAuthHandler

func (c *Controller) OAuthHandler(redirect, expectedState string, onSuccess func(*oauth.AccessResponse, http.ResponseWriter, *http.Request)) http.HandlerFunc

OAuthHandler returns a http.HandlerFunc that can complete OAuth handshake with slack, creating new Bots.

func (*Controller) RegisterConversation

func (c *Controller) RegisterConversation(name string, conv *Conversation) error

RegisterConversation registers a new conversation with the bot.

func (*Controller) UserChannelJoin

func (c *Controller) UserChannelJoin() <-chan *UserChannelJoinMessagePair

UserChannelJoin sends a payload each time a user joins a new channel.

type Controls

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

Controls is an object passed to conversation handlers and allows setting, getting conversation state and data.

func (*Controls) Bot

func (c *Controls) Bot() *Bot

Bot gets the bot associated with the current conversation.

func (*Controls) End

func (c *Controls) End() error

End ends the conversation.

func (*Controls) Get

func (c *Controls) Get(key string) (string, error)

Get gets a value for a key in the current conversation state.

func (*Controls) Set

func (c *Controls) Set(key string, value string) error

Set sets the value for a key.

func (*Controls) To

func (c *Controls) To(state string) error

To makes a state transition.

type Conversation

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

Conversation is a mapping of states to ConversationHandler functions.

ffjson: skip

func NewConversation

func NewConversation() *Conversation

NewConversation creates a new conversation.

func (*Conversation) On

func (s *Conversation) On(state string, handler ConversationHandler) error

On adds a new handler for a particular state.

type ConversationHandler

type ConversationHandler func(msg *chat.Message, controls *Controls)

ConversationHandler is a handler for a conversation state.

type ConversationRegistry

type ConversationRegistry map[string]*Conversation

ConversationRegistry is a mapping of conversation names to implementations.

func NewConversationRegistry

func NewConversationRegistry() ConversationRegistry

NewConversationRegistry creates a ConversationRegistry object.

func (ConversationRegistry) Add

func (c ConversationRegistry) Add(name string, conv *Conversation) error

Add adds a new name -> Conversation mapping.

func (ConversationRegistry) Get

Get gets the conversation associated with a particular name.

type ConversationStore

type ConversationStore interface {
	// Start starts a new conversation given a user, channel and team
	Start(user, channel, team, id string) error

	// IsActive checks if a conversation is active
	IsActive(user, channel, team string) bool

	// Active returns the active conversation id and state
	Active(user, channel, team string) (id, state string, err error)

	// SetState sets the state for the current conversation
	SetState(user, channel, team, state string) error

	// SetData sets a key-value pair for the current conversation
	SetData(user, channel, team, key, value string) error

	// GetData gets the value stored for a key for the current conversation
	GetData(user, channel, team, key string) (string, error)

	// End ends the current conversation.
	End(user, channel, team string) error
}

ConversationStore defines the interface for storing conversation data.

type Event

type Event struct {
	*rtm.Message
	Type    string `json:"type"`
	EventTs string `json:"event_ts"`
}

Event is a placeholder for event key payload in the Event payload

ffjson: noencoder

func (*Event) UnmarshalJSON

func (j *Event) UnmarshalJSON(input []byte) error

UnmarshalJSON umarshall json - template of ffjson

func (*Event) UnmarshalJSONFFLexer

func (j *Event) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error

UnmarshalJSONFFLexer fast json unmarshall - template ffjson

type EventPayload

type EventPayload struct {
	Token       string   `json:"token"`
	TeamID      string   `json:"team_id"`
	APIAppID    string   `json:"api_app_id"`
	Event       *Event   `json:"event"`
	Type        string   `json:"type"`
	EventID     string   `json:"event_id"`
	EventTime   int      `json:"event_time"`
	AuthedUsers []string `json:"authed_users"`
}

EventPayload represents the entire payload received for a slack event.

ffjson: noencoder

func (*EventPayload) UnmarshalJSON

func (j *EventPayload) UnmarshalJSON(input []byte) error

UnmarshalJSON umarshall json - template of ffjson

func (*EventPayload) UnmarshalJSONFFLexer

func (j *EventPayload) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error

UnmarshalJSONFFLexer fast json unmarshall - template ffjson

type GroupJoinMessagePair

type GroupJoinMessagePair struct {
	*rtm.GroupJoinMessage
	*Bot
}

GroupJoinMessagePair is sent for group join events.

ffjson: skip

type Interaction

type Interaction struct {
	Actions []*struct {
		Name            string `json:"name"`
		Value           string `json:"value,omitempty"`
		Text            string `json:"text,omitempty"`
		Type            string `json:"type"`
		SelectedOptions []struct {
			Value string `json:"value"`
		} `json:"selected_options,omitempty"`
	} `json:"actions"`
	Team *struct {
		ID     string `json:"id"`
		Domain string `json:"domain"`
	} `json:"team"`
	Channel *struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	} `json:"channel"`
	User *struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	} `json:"user"`
	ActionTs        string          `json:"action_ts"`
	MessageTs       string          `json:"message_ts"`
	AttachmentID    string          `json:"attachment_id"`
	CallbackID      string          `json:"callback_id"`
	IsAppUnfurl     bool            `json:"is_app_unfurl"`
	OriginalMessage *chat.Message   `json:"original_message"`
	ResponseURL     string          `json:"response_url"`
	TriggerID       string          `json:"trigger_id"`
	Type            string          `json:"type"`
	Submission      json.RawMessage `json:"submission"`
	// contains filtered or unexported fields
}

Interaction represents the payload received for an interaction.

ffjson: skip

func (*Interaction) OpenDialog

func (iact *Interaction) OpenDialog(d *dialog.Dialog) error

OpenDialog opens a dialog for the current interaction.

func (*Interaction) Respond

func (iact *Interaction) Respond(msg *chat.Message) error

Respond responds to an interaction using the ResponseURL.

func (*Interaction) RespondImmediately

func (iact *Interaction) RespondImmediately(msg *chat.Message) error

RespondImmediately responds immediately to an interaction.

TODO: the channel is closed after the first time, what then?

func (*Interaction) RespondWithEmptyBody

func (iact *Interaction) RespondWithEmptyBody() error

RespondWithEmptyBody responds with an empty body.

func (*Interaction) RespondWithErrors

func (iact *Interaction) RespondWithErrors(errs []*dialog.Error) error

RespondWithErrors responds with an error payload.

type InteractionOptions

type InteractionOptions struct {
	Name       string `json:"name"`
	Value      string `json:"value"`
	CallbackID string `json:"callback_id"`
	Team       struct {
		ID     string `json:"id"`
		Domain string `json:"domain"`
	} `json:"team"`
	Channel struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	} `json:"channel"`
	User struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	} `json:"user"`
	ActionTs     string `json:"action_ts"`
	MessageTs    string `json:"message_ts"`
	AttachmentID string `json:"attachment_id"`
	// contains filtered or unexported fields
}

InteractionOptions is the payload received for an Interaction Options Request.

ffjson: skip

func (*InteractionOptions) Respond

func (iactopt *InteractionOptions) Respond(msg *InteractionOptionsResponse) error

Respond responds to an interaction options request.

type InteractionOptionsPair

type InteractionOptionsPair struct {
	*InteractionOptions
	*Bot
}

InteractionOptionsPair is sent for interaction options.

ffjson: skip

type InteractionOptionsResponse

type InteractionOptionsResponse struct {
	Options      []*chat.Option      `json:"options,omitempty"`
	OptionGroups []*chat.OptionGroup `json:"option_groups,omitempty"`
}

InteractionOptionsResponse is the response payload sent as a response to an interaction options request.

ffjson: nodecoder

func (*InteractionOptionsResponse) MarshalJSON

func (j *InteractionOptionsResponse) MarshalJSON() ([]byte, error)

MarshalJSON marshal bytes to json - template

func (*InteractionOptionsResponse) MarshalJSONBuf

func (j *InteractionOptionsResponse) MarshalJSONBuf(buf fflib.EncodingBuffer) error

MarshalJSONBuf marshal buff to json - template

type InteractionPair

type InteractionPair struct {
	*Interaction
	*Bot
}

InteractionPair is sent for interactions

ffjson: skip

type MemoryBotStore

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

MemoryBotStore is an in-memory BotStore implementation.

ffjson: skip

func NewMemoryBotStore

func NewMemoryBotStore() *MemoryBotStore

NewMemoryBotStore creates a new MemoryBotStore object.

func (*MemoryBotStore) AddBot

func (bs *MemoryBotStore) AddBot(p *oauth.AccessResponse) error

AddBot adds a new paylaod to the store.

func (*MemoryBotStore) AllBots

func (bs *MemoryBotStore) AllBots() ([]*oauth.AccessResponse, error)

AllBots gets all stored payloads.

func (*MemoryBotStore) GetBot

func (bs *MemoryBotStore) GetBot(team string) (*oauth.AccessResponse, error)

GetBot gets a stored payload given a team.

func (*MemoryBotStore) RemoveBot

func (bs *MemoryBotStore) RemoveBot(team string) error

RemoveBot removes a stored payload given the team.

type MemoryConversationStore

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

MemoryConversationStore is an in-memory implementation of ConversationStore.

ffjson: skip

func NewMemoryConversationStore

func NewMemoryConversationStore() *MemoryConversationStore

NewMemoryConversationStore creates a new MemoryConversationStore object.

func (*MemoryConversationStore) Active

func (s *MemoryConversationStore) Active(user, channel, team string) (id, state string, err error)

Active gets the active conversation.

func (*MemoryConversationStore) End

func (s *MemoryConversationStore) End(user, channel, team string) error

End ends the conversation.

func (*MemoryConversationStore) GetData

func (s *MemoryConversationStore) GetData(user, channel, team, key string) (string, error)

GetData gets the stored value for a key for a conversation.

func (*MemoryConversationStore) IsActive

func (s *MemoryConversationStore) IsActive(user, channel, team string) bool

IsActive checks if a conversation is active.

func (*MemoryConversationStore) SetData

func (s *MemoryConversationStore) SetData(user, channel, team, key, value string) error

SetData sets the value for a key in the current conversation.

func (*MemoryConversationStore) SetState

func (s *MemoryConversationStore) SetState(user, channel, team, state string) error

SetState sets the state for the active conversation.

func (*MemoryConversationStore) Start

func (s *MemoryConversationStore) Start(user, channel, team, id string) error

Start starts a conversation

type MessagePair

type MessagePair struct {
	*rtm.Message
	*Bot
}

MessagePair is sent as the payload when a new message is received. ffjson: skip

func (*MessagePair) Reply

func (mp *MessagePair) Reply(msg *chat.Message) (*chat.Message, error)

Reply replies with the passed message to the original message with the pair's bot.

func (*MessagePair) StartConversation

func (mp *MessagePair) StartConversation(name string) error

StartConversation starts a conversation with the pair's bot.

func (*MessagePair) Typing

func (mp *MessagePair) Typing() error

Typing sends a typing indicator.

type UserChannelJoinMessagePair

type UserChannelJoinMessagePair struct {
	*rtm.UserChannelJoinMessage
	*Bot
}

UserChannelJoinMessagePair is sent for user channel join events.

ffjson: skip

Directories

Path Synopsis
api
im
rtm
contrib

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL