Documentation ¶
Overview ¶
Package slack provides sarah.Adapter implementation for Slack.
Index ¶
- Constants
- Variables
- func DefaultEventsPayloadHandler(_ context.Context, config *Config, payload *eventsapi.EventWrapper, ...)
- func DefaultRTMPayloadHandler(_ context.Context, config *Config, payload rtmapi.DecodedPayload, ...)
- func EventToInput(e interface{}) (sarah.Input, error)
- func IsThreadMessage(input *Input) bool
- func NewResponse(input sarah.Input, msg string, options ...RespOption) (*sarah.CommandResponse, error)
- type Adapter
- type AdapterOption
- type Config
- type Input
- type RespOption
- func RespAsThreadReply(asReply bool) RespOption
- func RespReplyBroadcast(broadcast bool) RespOption
- func RespWithAttachments(attachments []*webapi.MessageAttachment) RespOption
- func RespWithLinkNames(linkNames int) RespOption
- func RespWithNext(fnc sarah.ContextualFunc) RespOption
- func RespWithNextSerializable(arg *sarah.SerializableArgument) RespOption
- func RespWithParse(mode webapi.ParseMode) RespOption
- func RespWithUnfurlLinks(unfurl bool) RespOption
- func RespWithUnfurlMedia(unfurl bool) RespOption
- type SlackClient
Constants ¶
const (
// SLACK is a designated sara.BotType for Slack.
SLACK sarah.BotType = "slack"
)
Variables ¶
var ErrNonSupportedEvent = xerrors.New("event not supported")
Functions ¶
func DefaultEventsPayloadHandler ¶
func DefaultEventsPayloadHandler(_ context.Context, config *Config, payload *eventsapi.EventWrapper, enqueueInput func(input sarah.Input) error)
DefaultEventsPayloadHandler receives incoming events, convert them to sarah.Input and then pass them to enqueueInput. To replace this default behavior, define a function with the same signature and replace this.
myHandler := func(_ context.Context, _ config *Config, _ *eventsapi.EventWrapper, _ func(sarah.Input) error) slackAdapter, _ := slack.NewAdapter(slackConfig, slack.WithEventsPayloadHandler(myHandler))
func DefaultRTMPayloadHandler ¶
func DefaultRTMPayloadHandler(_ context.Context, config *Config, payload rtmapi.DecodedPayload, enqueueInput func(sarah.Input) error)
DefaultRTMPayloadHandler receives incoming events, convert them to sarah.Input and then pass them to enqueueInput. To replace this default behavior, define a function with the same signature and replace this.
myHandler := func(_ context.Context, config *Config, _ rtmapi.DecodedPayload, _ func(sarah.Input) error) slackAdapter, _ := slack.NewAdapter(slackConfig, slack.WithRTMPayloadHandler(myHandler))
func EventToInput ¶
func EventToInput(e interface{}) (sarah.Input, error)
EventToInput converts given event payload to *Input.
func IsThreadMessage ¶
IsThreadMessage tells if the given message is sent in a thread. If the message is sent in a thread, this is encouraged to reply in a thread.
NewResponse defaults to send a response as a thread reply if the input is sent in a thread. Use RespAsThreadReply to specifically switch the behavior.
func NewResponse ¶
func NewResponse(input sarah.Input, msg string, options ...RespOption) (*sarah.CommandResponse, error)
NewResponse creates *sarah.CommandResponse with given arguments. Simply pass a given sarah.Input instance and a text string to send a string message as a reply. To send a more complicated reply message, pass as many options created by ResponseWith* function as required.
When an input is sent in a thread, this function defaults to send a response as a thread reply. To explicitly change such behavior, use RespAsThreadReply() and RespReplyBroadcast().
Types ¶
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter internally calls Slack Rest API and Real Time Messaging API to offer Bot developers easy way to communicate with Slack.
This implements sarah.Adapter interface, so this instance can be fed to sarah.RegisterBot() as below.
slackConfig := slack.NewConfig() slackConfig.Token = "XXXXXXXXXXXX" // Set token manually or feed slackConfig to json.Unmarshal or yaml.Unmarshal slackAdapter, _ := slack.NewAdapter(slackConfig) slackBot, _ := sarah.NewBot(slackAdapter) sarah.RegisterBot(slackBot) sarah.Run(context.TODO(), sarah.NewConfig())
func NewAdapter ¶
func NewAdapter(config *Config, options ...AdapterOption) (*Adapter, error)
NewAdapter creates new Adapter with given *Config and zero or more AdapterOption.
func (*Adapter) BotType ¶
func (adapter *Adapter) BotType() sarah.BotType
BotType returns BotType of this particular instance.
func (*Adapter) Run ¶
func (adapter *Adapter) Run(ctx context.Context, enqueueInput func(sarah.Input) error, notifyErr func(error))
Run establishes connection with Slack, supervise it, and tries to reconnect when current connection is gone. Connection will be
When message is sent from slack server, the payload is passed to go-sarah's core via the function given as 2nd argument, enqueueInput. This function simply wraps a channel to prevent blocking situation. When workers are too busy and channel blocks, this function returns BlockedInputError.
When critical situation such as reconnection trial fails for specified times, this critical situation is notified to go-sarah's core via 3rd argument function, notifyErr. go-sarah cancels this Bot/Adapter and related resources when BotNonContinuableError is given to this function.
func (*Adapter) SendMessage ¶
SendMessage let Bot send message to Slack.
type AdapterOption ¶
type AdapterOption func(adapter *Adapter)
AdapterOption defines function signature that Adapter's functional option must satisfy.
func WithEventsPayloadHandler ¶
func WithEventsPayloadHandler(fnc func(context.Context, *Config, *eventsapi.EventWrapper, func(sarah.Input) error)) AdapterOption
WithEventsPayloadHandler creates an AdapterOption with the given function to handle incoming Events API payloads. The simplest example to receive message payload is to use a default payload handler as below:
slackAdapter, _ := slack.NewAdapter(slackConfig, slack.WithEventsPayloadHandler(DefaultEventsPayloadHandler))
See WithRTMPayloadHandler for detailed usage. WithEventsPayloadHandler is just another form of payload handler to work with Events API.
func WithRTMPayloadHandler ¶
func WithRTMPayloadHandler(fnc func(context.Context, *Config, rtmapi.DecodedPayload, func(sarah.Input) error)) AdapterOption
WithRTMPayloadHandler creates an AdapterOption with the given function to handle incoming RTM payloads. The simplest example to receive message payload is to use a default payload handler as below:
slackAdapter, _ := slack.NewAdapter(slackConfig, slack.WithRTMPayloadHandler(DefaultRTMPayloadHandler))
However, Slack's RTM API defines relatively large amount of payload types. To have better user experience, developers may provide customized callback function to handle different types of received payload. In that case, one may implement an original payload handler and replace DefaultRTMPayloadHandler. Inside the customized payload handler, a developer may wish to have direct access to SlackClient to post some sort of message to Slack via Web API. To support such scenario, wrap this function like below so the SlackClient can be accessed within its scope.
// Setup golack instance, which implements SlackClient interface. golackConfig := golack.NewConfig() golackConfig.Token = "XXXXXXX" slackClient := golack.New(golackConfig) slackConfig := slack.NewConfig() rtmPayloadHandler := func(connCtx context.Context, config *Config, paylad rtmapi.DecodedPayload, enqueueInput func(sarah.Input) error) { switch p := payload.(type) { case *event.PinAdded: // Do something with pre-defined SlackClient // slackClient.PostMessage(connCtx, ...) default: input, err := EventToInput(p) if err == ErrNonSupportedEvent { log.Debugf("Event given, but no corresponding action is defined. %#v", payload) return } if err != nil { log.Errorf("Failed to convert %T event: %s", p, err.Error()) return } trimmed := strings.TrimSpace(input.Message()) if config.HelpCommand != "" && trimmed == config.HelpCommand { // Help command help := sarah.NewHelpInput(input) _ = enqueueInput(help) } else if config.AbortCommand != "" && trimmed == config.AbortCommand { // Abort command abort := sarah.NewAbortInput(input) _ = enqueueInput(abort) } else { // Regular input _ = enqueueInput(input) } } } slackAdapter, _ := slack.NewAdapter(slackConfig, slack.WithSlackClient(slackClient), slack.WithRTMPayloadHandler(rtmPayloadHandler)) slackBot, _ := sarah.NewBot(slackAdapter)
func WithSlackClient ¶
func WithSlackClient(client SlackClient) AdapterOption
WithSlackClient creates AdapterOption with given SlackClient implementation. If this option is not given, NewAdapter() tries to create golack instance with given Config.
type Config ¶
type Config struct { Token string `json:"token" yaml:"token"` AppSecret string `json:"app_secret" yaml:"app_secret"` ListenPort int `json:"listen_port" yaml:"listen_port"` HelpCommand string `json:"help_command" yaml:"help_command"` AbortCommand string `json:"abort_command" yaml:"abort_command"` SendingQueueSize uint `json:"sending_queue_size" yaml:"sending_queue_size"` RequestTimeout time.Duration `json:"request_timeout" yaml:"request_timeout"` PingInterval time.Duration `json:"ping_interval" yaml:"ping_interval"` RetryPolicy *retry.Policy `json:"retry_policy" yaml:"retry_policy"` }
Config contains some configuration variables for slack Adapter.
type Input ¶
type Input struct {
// contains filtered or unexported fields
}
Input represents a Slack-specific implementation of sarah.Input. Pass incoming payload to EventToInput for conversion.
func (*Input) ReplyTo ¶
func (i *Input) ReplyTo() sarah.OutputDestination
ReplyTo returns slack channel to send reply to.
type RespOption ¶
type RespOption func(*respOptions)
RespOption defines function signature that NewResponse's functional option must satisfy.
func RespAsThreadReply ¶
func RespAsThreadReply(asReply bool) RespOption
RespAsThreadReply indicates that this response is sent as a thread reply.
func RespReplyBroadcast ¶
func RespReplyBroadcast(broadcast bool) RespOption
RespReplyBroadcast decides if the thread reply should be broadcasted. To activate this option, RespAsThreadReply() must be set to true.
func RespWithAttachments ¶
func RespWithAttachments(attachments []*webapi.MessageAttachment) RespOption
RespWithAttachments adds given attachments to the response.
func RespWithLinkNames ¶
func RespWithLinkNames(linkNames int) RespOption
RespWithLinkNames sets given linkNames to the response. Set 1 to linkify channel names and usernames in the response. The default value in this apiSpecificAdapter is 1.
func RespWithNext ¶
func RespWithNext(fnc sarah.ContextualFunc) RespOption
RespWithNext sets given fnc as part of the response's *sarah.UserContext. The next input from the same user will be passed to this fnc. See sarah.UserContextStorage must be present or otherwise, fnc will be ignored.
func RespWithNextSerializable ¶
func RespWithNextSerializable(arg *sarah.SerializableArgument) RespOption
RespWithNextSerializable sets given arg as part of the response's *sarah.UserContext. The next input from the same user will be passed to the function defined in the arg. See sarah.UserContextStorage must be present or otherwise, arg will be ignored.
func RespWithParse ¶
func RespWithParse(mode webapi.ParseMode) RespOption
RespWithParse sets given mode to the response. The default value in this apiSpecificAdapter is webapi.ParseModeFull.
func RespWithUnfurlLinks ¶
func RespWithUnfurlLinks(unfurl bool) RespOption
RespWithUnfurlLinks sets given unfurl value to the response. The default value is this apiSpecificAdapter is true.
func RespWithUnfurlMedia ¶
func RespWithUnfurlMedia(unfurl bool) RespOption
RespWithUnfurlMedia sets given unfurl value ot the response. The default value is this apiSpecificAdapter is true.
type SlackClient ¶
type SlackClient interface { ConnectRTM(ctx context.Context) (rtmapi.Connection, error) PostMessage(ctx context.Context, message *webapi.PostMessage) (*webapi.APIResponse, error) RunServer(ctx context.Context, receiver eventsapi.EventReceiver) <-chan error }
SlackClient is an interface that covers golack's public methods.