Skip to content

Receiving no payload on websocket based events #1272

@talaniz

Description

@talaniz

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

  • Go: 1.21.0
  • slack-go/slack: v0.12.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions