slack-ruby-client icon indicating copy to clipboard operation
slack-ruby-client copied to clipboard

support posting to response_url for message actions (buttons)

Open jmanian opened this issue 7 years ago • 9 comments

When creating messages with interactive buttons, one of the ways to update the message after someone hits a button is to use make a request to the response_url, which is included in the action payload. It would be very convenient if this client could make those requests.

I did some initial poking around: I tried using the response_url as the endpoint, and then put the updated message content in the body, but I got Faraday::ClientError: the server responded with status 500, so I think I don't understand Faraday.

https://api.slack.com/docs/message-buttons#how_to_respond_to_message_button_actions

jmanian avatar Oct 07 '16 22:10 jmanian

It's just an HTTP POST to that URL, no? Examine the error in the 500, you're probably not formatting the message right.

Try to build a very simple sample on top of examples and I'll try to help you out.

dblock avatar Oct 08 '16 20:10 dblock

Yes, whoops, I don't remember exactly what I was doing the other day, but I think I just needed to call to_json on the payload to get it to work. Either way, I can get it to work now like this:

connection.post do |req|
  req.url response_url
  req.body = {text: 'new message', attachments: [...]}.to_json
end

Do you think it makes sense to put a method on Slack::Web::Client that takes care of this? I'm not sure, because it's not actually part of the Web API, but it does sort of fit in there, and doesn't really fit in anywhere else.

If you think it makes sense on Slack::Web::Client then I can work on a PR.

jmanian avatar Oct 09 '16 19:10 jmanian

What's connection in this case? I totally think that making it easier would be great for the library. Can you post a little bit more code around the above and we can try and come up with a cleaner DSL?

dblock avatar Oct 09 '16 21:10 dblock

I'm using Slack::Web::Faraday::Connection#connection.

So for instance I can run it on the command line like this:

client = Slack::Web::Client.new(token: token)
client.send(:connection).post(response_url, args.to_json)

The reason I'm using Slack::Web::Faraday::Connection#connection is I wanted to inherit all the Faraday settings from there, though I honestly don't know if they're all desirable for this use case — I haven't dug in enough.

The reason I thought the new method should be an instance method on Slack::Web::Client was that I thought the request needed to include the token (and the instance contains the token). But it turns out that the request does not need the token, so the method could easily just be a class method somewhere instead.

jmanian avatar Oct 09 '16 22:10 jmanian

This is not in a realtime context, right? I mean the response URL appears as a response to what code? I think that response needs to become a class that exposes a connection method that automatically uses response_url. With Faraday I think this means adding some code that wraps the response into the class.

dblock avatar Oct 10 '16 12:10 dblock

Actually the response_url does not appear as a direct response to the app's code (for instance it does not come in a response to a Web API method call). Rather it appears in the payload of a POST to the app's API when a user clicks a button. So the URL first appears in a context completely divorced from slack-ruby-client. If I understand correctly, it sounds like your suggestion would only work if the response_url appeared within an interaction that was managed by slack-ruby-client.

jmanian avatar Oct 10 '16 15:10 jmanian

Oh I see, this is in response to a command, something that I had to do in https://github.com/dblock/slack-market/blob/master/slack-market/api/endpoints/slack_endpoint.rb for example. I guess there's nothing to do in the client indeed. If we wanted to support slash and other commands out of the box that code would belong at a higher level, ie. in slack-ruby-bot-server for example.

So you don't even need a token to POST to response_url, right? And there's really just one method on that to do POST. I think Slack::Web::Client is the wrong place to put code for it, maybe we should have a class like Slack::Web::Response that gets constructed with response_url: ... and inherits all the options?

dblock avatar Oct 10 '16 15:10 dblock

Was there any decision made with regard to how to respond to messages via response_url with the gem?

avand avatar Nov 29 '17 00:11 avand

No decision @avand, see my suggestion if you want to try to PR something.

dblock avatar Nov 29 '17 17:11 dblock