slack-go / slack

Slack API in Go, originally by @nlopes; Maintainers needed, contact @parsley42
https://pkg.go.dev/github.com/slack-go/slack
BSD 2-Clause "Simplified" License
4.6k stars 1.11k forks source link

Receiving no payload on websocket based events #1272

Open talaniz opened 4 months ago

talaniz commented 4 months ago

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

main.go

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

talaniz commented 4 months ago

I suspect that it might be because of the Slack client I used looking at the example vs the tutorial I used. I'll try an example with the RTM client and follow up on this ticket.

tylerhammer commented 2 months ago

Were you able to resolve this? I'm running into the same issue.