slack
slack copied to clipboard
Receiving no payload on websocket based events
I'm not certain this is a bug, it seems more like maybe I'm not implementing something correctly. But I've been through the documentation and have been unable to find anything that directly talks about handling a slack interactive event over a websocket.
What happened
When I use websockets, I'm not receiving any data in response, just a slack.InteractionCallback
with only the type populated.
Expected behavior
I would expect to receive a payload with the ActionID, Name, Value and Type messages populated. This is what I receive from the print statements in the code below:
2024/03/05 17:04:20 ******** Name:
2024/03/05 17:04:20 The action called is
2024/03/05 17:04:20 The response was of type: interactive_message
2024/03/05 17:04:20 ******** Channel Name:
2024/03/05 17:04:20 ******** ResponseURL: https://hooks.slack.com/actions/T015M2ZDW58/6774396088240/b19qOY06tSeqf0LL5BisCkTZ
2024/03/05 17:04:20 ******** Value:
2024/03/05 17:04:20 ******** Type: interactive_message
2024/03/05 17:04:20 ************{{ %!s(bool=false) [] [] %!s(*slack.Edited=<nil>) %!s(bool=false) %!s(int=0) %!s(bool=false) %!s(*slack.Icon=<nil>) %!s(*slack.BotProfile=<nil>) [] %!s(int=0) [] [] [] %!s(bool=false) %!s(*slack.Comment=<nil>) %!s(int=0) [] %!s(bool=false) %!s(bool=false) { map[]} {[]} } %!s(*slack.Msg=<nil>) %!s(*slack.Msg=<nil>)}
{"replace_original":false,"delete_original":false,"metadata":{"event_type":"","event_payload":null},"blocks":null}
**** {"replace_original":false,"delete_original":false,"metadata":{"event_type":"","event_payload":null},"blocks":null}socketmode: 2024/03/05 17:04:20 socket_mode_managed_conn.go:483: Scheduling Socket Mode response (error: <nil>) for envelope ID e436eaa0-4f17-41b3-bbb7-b22bf12baa97: {"envelope_id":"e436eaa0-4f17-41b3-bbb7-b22bf12baa97"}
Steps to reproduce
If I run a switch statement on the incoming socketClient.Events
and print the various attributes, they should be populated. I'll include the code in the next section.
reproducible code
go func(ctx context.Context, client *slack.Client, socketClient *socketmode.Client) {
for {
select {
case <-ctx.Done():
log.Println("Shutting down socketmode listener")
return
case event := <-socketClient.Events:
switch event.Type {
// Slack events
case socketmode.EventTypeEventsAPI:
eventsApiEvent, ok := event.Data.(slackevents.EventsAPIEvent)
if !ok {
log.Printf("Could not type case the event to the EventsAPIEvent: %v\n", event)
continue
}
log.Println("Received API event: ", event.Type)
socketClient.Ack(*event.Request)
err := handlers.HandleEventMessage(eventsApiEvent, client)
if err != nil {
log.Fatal(err)
}
// Slash command
case socketmode.EventTypeSlashCommand:
command, ok := event.Data.(slack.SlashCommand)
if !ok {
log.Printf("Could not type case the message to a SlashCommand: %v\n", command)
continue
}
// consider removing the client parameter as it's unused
payload, err := handlers.HandleSlashCommand(command, client)
if err != nil {
log.Fatal(err)
}
socketClient.Ack(*event.Request, payload)
case socketmode.EventTypeInteractive:
interaction, ok := event.Data.(slack.InteractionCallback)
if !ok {
log.Printf("Could not type cast the message to an Interaction callback: %v\n", interaction)
continue
}
err := handlers.HandleInteractionEvent(interaction, client)
if err != nil {
log.Fatal(err)
}
socketClient.Ack(*event.Request)
default:
log.Println("****** Received Event: ", event)
}
}
}
handlers.go
func handleIsArticleGood(command slack.SlashCommand, client *slack.Client) error {
attachment := slack.Attachment{
Pretext: "pretext",
Fallback: "We don't currently support your client",
CallbackID: "accept_or_reject",
Color: "#3AA3E3",
Actions: []slack.AttachmentAction{
slack.AttachmentAction{
Name: "accept",
Text: "Accept",
Type: "button",
Value: "accept",
},
slack.AttachmentAction{
Name: "reject",
Text: "Reject",
Type: slack.ActionType("button"),
Value: "reject",
Style: "danger",
},
},
}
_, _, err := client.PostMessage(command.ChannelID, slack.MsgOptionAttachments(attachment))
if err != nil {
return fmt.Errorf("failed to post message: %w", err)
}
return nil
}
// HandleInteractionEvent determines actions for interactive event types
func HandleInteractionEvent(interaction slack.InteractionCallback, client *slack.Client) error {
log.Printf("******** Name: %s\n", interaction.Name)
log.Printf("The action called is %s\n", interaction.ActionID)
log.Printf("The response was of type: %s\n", interaction.Type)
log.Printf("******** Channel Name: %s\n", interaction.Message.Channel)
log.Printf("******** ResponseURL: %s\n", interaction.ResponseURL)
log.Printf("******** Value: %s\n", interaction.Value)
log.Printf("******** Type: %s\n", interaction.Type)
switch interaction.Type {
case slack.InteractionTypeBlockActions:
for _, action := range interaction.ActionCallback.BlockActions {
log.Printf("%+v", action)
log.Println("Selected option: ", action.SelectedOptions)
}
case slack.InteractionTypeInteractionMessage:
log.Printf("************%s\n", interaction.Message)
d, _ := json.Marshal(interaction.Message)
fmt.Println(string(d))
var payload slack.InteractionCallback
err := json.Unmarshal([]byte(d), &payload)
if err != nil {
fmt.Printf("Could not parse action response JSON: %v", err)
}
fmt.Printf("**** %s", d)
default:
}
return nil
}
Versions
- Go: 1.21.0
- slack-go/slack: v0.12.5