mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-24 07:45:15 +00:00
165 lines
3.8 KiB
Go
165 lines
3.8 KiB
Go
|
package interact
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"os"
|
||
|
|
||
|
"github.com/sirupsen/logrus"
|
||
|
"github.com/slack-go/slack"
|
||
|
"github.com/slack-go/slack/slackevents"
|
||
|
"github.com/slack-go/slack/socketmode"
|
||
|
)
|
||
|
|
||
|
type SlackSession struct {
|
||
|
BaseSession
|
||
|
}
|
||
|
|
||
|
type SlackSessionMap map[int64]*SlackSession
|
||
|
|
||
|
//go:generate callbackgen -type Slack
|
||
|
type Slack struct {
|
||
|
client *slack.Client
|
||
|
socket *socketmode.Client
|
||
|
|
||
|
sessions SlackSessionMap
|
||
|
|
||
|
commands []*Command
|
||
|
|
||
|
// textMessageResponder is used for interact to register its message handler
|
||
|
textMessageResponder Responder
|
||
|
|
||
|
authorizedCallbacks []func(userSession *SlackSession)
|
||
|
}
|
||
|
|
||
|
func NewSlack(client *slack.Client) *Slack {
|
||
|
socket := socketmode.New(
|
||
|
client,
|
||
|
socketmode.OptionDebug(true),
|
||
|
socketmode.OptionLog(
|
||
|
log.New(os.Stdout, "socketmode: ",
|
||
|
log.Lshortfile|log.LstdFlags)),
|
||
|
)
|
||
|
|
||
|
return &Slack{
|
||
|
client: client,
|
||
|
socket: socket,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Slack) SetTextMessageResponder(responder Responder) {
|
||
|
s.textMessageResponder = responder
|
||
|
}
|
||
|
|
||
|
func (s *Slack) AddCommand(command *Command, responder Responder) {
|
||
|
s.commands = append(s.commands, command)
|
||
|
}
|
||
|
|
||
|
func (s *Slack) listen() {
|
||
|
for evt := range s.socket.Events {
|
||
|
switch evt.Type {
|
||
|
case socketmode.EventTypeConnecting:
|
||
|
fmt.Println("Connecting to Slack with Socket Mode...")
|
||
|
case socketmode.EventTypeConnectionError:
|
||
|
fmt.Println("Connection failed. Retrying later...")
|
||
|
case socketmode.EventTypeConnected:
|
||
|
fmt.Println("Connected to Slack with Socket Mode.")
|
||
|
case socketmode.EventTypeEventsAPI:
|
||
|
eventsAPIEvent, ok := evt.Data.(slackevents.EventsAPIEvent)
|
||
|
if !ok {
|
||
|
fmt.Printf("Ignored %+v\n", evt)
|
||
|
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
fmt.Printf("Event received: %+v\n", eventsAPIEvent)
|
||
|
|
||
|
s.socket.Ack(*evt.Request)
|
||
|
|
||
|
switch eventsAPIEvent.Type {
|
||
|
case slackevents.CallbackEvent:
|
||
|
innerEvent := eventsAPIEvent.InnerEvent
|
||
|
switch ev := innerEvent.Data.(type) {
|
||
|
case *slackevents.AppMentionEvent:
|
||
|
_, _, err := s.client.PostMessage(ev.Channel, slack.MsgOptionText("Yes, hello.", false))
|
||
|
if err != nil {
|
||
|
fmt.Printf("failed posting message: %v", err)
|
||
|
}
|
||
|
case *slackevents.MemberJoinedChannelEvent:
|
||
|
fmt.Printf("user %q joined to channel %q", ev.User, ev.Channel)
|
||
|
}
|
||
|
default:
|
||
|
s.socket.Debugf("unsupported Events API event received")
|
||
|
}
|
||
|
case socketmode.EventTypeInteractive:
|
||
|
callback, ok := evt.Data.(slack.InteractionCallback)
|
||
|
if !ok {
|
||
|
fmt.Printf("Ignored %+v\n", evt)
|
||
|
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
fmt.Printf("Interaction received: %+v\n", callback)
|
||
|
|
||
|
var payload interface{}
|
||
|
|
||
|
switch callback.Type {
|
||
|
case slack.InteractionTypeBlockActions:
|
||
|
// See https://api.slack.com/apis/connections/socket-implement#button
|
||
|
|
||
|
s.socket.Debugf("button clicked!")
|
||
|
case slack.InteractionTypeShortcut:
|
||
|
case slack.InteractionTypeViewSubmission:
|
||
|
// See https://api.slack.com/apis/connections/socket-implement#modal
|
||
|
case slack.InteractionTypeDialogSubmission:
|
||
|
default:
|
||
|
|
||
|
}
|
||
|
|
||
|
s.socket.Ack(*evt.Request, payload)
|
||
|
case socketmode.EventTypeSlashCommand:
|
||
|
cmd, ok := evt.Data.(slack.SlashCommand)
|
||
|
if !ok {
|
||
|
fmt.Printf("Ignored %+v\n", evt)
|
||
|
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
s.socket.Debugf("Slash command received: %+v", cmd)
|
||
|
|
||
|
payload := map[string]interface{}{
|
||
|
"blocks": []slack.Block{
|
||
|
slack.NewSectionBlock(
|
||
|
&slack.TextBlockObject{
|
||
|
Type: slack.MarkdownType,
|
||
|
Text: "foo",
|
||
|
},
|
||
|
nil,
|
||
|
slack.NewAccessory(
|
||
|
slack.NewButtonBlockElement(
|
||
|
"",
|
||
|
"somevalue",
|
||
|
&slack.TextBlockObject{
|
||
|
Type: slack.PlainTextType,
|
||
|
Text: "bar",
|
||
|
},
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
}}
|
||
|
|
||
|
s.socket.Ack(*evt.Request, payload)
|
||
|
default:
|
||
|
fmt.Fprintf(os.Stderr, "Unexpected event type received: %s\n", evt.Type)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Slack) Start(ctx context.Context) {
|
||
|
go s.listen()
|
||
|
if err := s.socket.Run() ; err != nil {
|
||
|
logrus.WithError(err).Errorf("slack socketmode error")
|
||
|
}
|
||
|
}
|