Skip to content

Fix interactive payload parsing#148

Open
MaxGabriel wants to merge 2 commits intomasterfrom
fixInteractivePayloadParsing
Open

Fix interactive payload parsing#148
MaxGabriel wants to merge 2 commits intomasterfrom
fixInteractivePayloadParsing

Conversation

@MaxGabriel
Copy link

@MaxGabriel MaxGabriel commented Apr 15, 2025

I was parsing interactive commands from Slack sent via websocket and realized the parsing of SlackInteractivePayload wasn't working. The JSON it was expecting was actually all under a "payload" key. This seems to match the docs:

The payload will be sent to your configured Request URL in an HTTP POST. The body of that request will contain a payload parameter. Your app should parse this payload parameter as JSON.

https://api.slack.com/messaging/interactivity#understanding_payloads

Here's an example of the JSON I received:

{
  "envelope_id": "4c5b7ddd-93e4-4100-bd31-469dc0da2a74",
  "payload": {
    "type": "block_actions",
    "user": {
      "id": "U6TF7D36Y",
      "username": "max",
      "name": "max",
      "team_id": "T6TBZABPW"
    },
    "api_app_id": "A02JS09R199",
    "token": "at9L8bAfkSgMXMcCXYnEx7W4",
    "container": {
      "type": "message",
      "message_ts": "1744643896.565239",
      "channel_id": "D03HC9XKZBK",
      "is_ephemeral": false
    },
    "trigger_id": "8762673254145.231407351812.1081a4547c3eef355373a7b1c4d3cc55",
    "team": {
      "id": "T6TBZABPW",
      "domain": "mercurytechnologies",
      "enterprise_id": "E088T4586SY",
      "enterprise_name": "Mercury"
    },
    "enterprise": {
      "id": "E088T4586SY",
      "name": "Mercury"
    },
    "is_enterprise_install": false,
    "channel": {
      "id": "D03HC9XKZBK",
      "name": "directmessage"
    },
    "message": {
      "user": "U02JBAN4TMM",
      "type": "message",
      "ts": "1744643896.565239",
      "bot_id": "B02JS1B80JW",
      "app_id": "A02JS09R199",
      "text": "Mark Read button",
      "team": "T6TBZABPW",
      "blocks": [
        {
          "type": "actions",
          "block_id": "Da20m",
          "elements": [
            {
              "type": "button",
              "action_id": "button1",
              "text": {
                "type": "plain_text",
                "text": "Mark Read",
                "emoji": true
              }
            }
          ]
        }
      ]
    },
    "state": {
      "values": {}
    },
    "response_url": "https://hooks.slack.com/actions/T6TBZABPW/8762673200785/jUHi85fRbVeX5XHtgG6qyVP4",
    "actions": [
      {
        "action_id": "button1",
        "block_id": "Da20m",
        "text": {
          "type": "plain_text",
          "text": "Mark Read",
          "emoji": true
        },
        "type": "button",
        "action_ts": "1744643994.442584"
      }
    ]
  },
  "type": "interactive",
  "accepts_response_payload": false
}

I have not actually built slack-web and confirmed this works, but I did modify my own code like so:

newtype InteractiveRequest = InteractiveRequest 
  { payload :: SlackInteractivePayload 
  } deriving stock (Show)

instance FromJSON InteractiveRequest where
  parseJSON = withObject "InteractiveRequest" $ \o -> do
    payload <- o .: "payload"
    pure $ InteractiveRequest payload

and that seems to have worked correctly

Before submitting your PR, check that you've:

n/a

n/a

After submitting your PR:

  • Update the Changelog.md file with a link to your PR
  • Bumped the version number if there isn't an (unreleased) on the Changelog
  • Check that CI passes (or if it fails, for reasons unrelated to your change, like CI timeouts)

@MaxGabriel MaxGabriel requested a review from lf- April 15, 2025 13:01
Copy link
Contributor

@lf- lf- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heya, thanks for the contribution! Can you please add that JSON as a golden test so that we can make sure it doesn't regress?

Otherwise lgtm.

@lf-
Copy link
Contributor

lf- commented Apr 15, 2025

Actually wait a minute.... Are we sure this isn't a SlackWebhookEvent?

instance FromJSON SlackWebhookEvent where
parseJSON = withObject "SlackWebhookEvent" \obj -> do
tag :: Text <- obj .: "type"
case tag of
"url_verification" -> EventUrlVerification <$> parseJSON (Object obj)
"event_callback" -> EventEventCallback <$> parseJSON (Object obj)
_ -> pure $ EventUnknownWebhook (Object obj)

The thing that's weird here is that those docs could also be read as "it's x-form-urlencoded with a payload parameter containing JSON". And the second weirdness is that this is using websocket mode, so it could be an artifact of websocket mode.

I am a little bit confused as to what context you got that data in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants