Debugging Slack Web Requests


#1

1) Give a description of the problem
I’m trying to replace all my IFTTT applets that update my Slack status with a single piston to update Slack, since now I have to be on multiple Slack instances at work, and IFTTT can only manage connections to one Slack instance per account. Piston debug shows that the web requests in this piston appear to be made successfully, but my Slack status is not changing. However, if I use an external tool like a browser plugin to issue a POST request with content-type application/x-www-form-encoded to these Slack URLs using the variables in the script as defined, it works as expected. Not sure what the issue is here or even how to see the response in piston debug?

Additional details: I’ve replaced my Slack tokens for posting, but the originals are valid from https://api.slack.com/custom-integrations/legacy-tokens, and the Contact Sensors are GCal Smart App calendar event triggers.

2) What is the expected behavior?
URLs and data are submitted to Slack successfully, status and visibility updates in Slack.

3) What is happening/not happening?
I see the web requests being made in debug, but Slack status is not updated as expected. Not sure what the error is.

4) Post a Green Snapshot of the pistonimage

5) Attach any logs (From ST IDE and by turning logging level to Full)
+1ms ╔Received event [zoom Events].contact = open with a delay of 87ms +179ms ║RunTime Analysis CS > 13ms > PS > 52ms > PE > 114ms > CE +190ms ║Runtime (72105 bytes) successfully initialized in 52ms (v0.2.0fe.20171109) (188ms) +191ms ║╔Execution stage started +209ms ║║Comparison (enum) open changes_to (string) open = true (0ms) +210ms ║║Cancelling condition #10's schedules... +211ms ║║Condition #10 evaluated true (12ms) +228ms ║║Comparison (enum) present is (string) present = true (2ms) +230ms ║║Condition #11 evaluated true (18ms) +231ms ║║Cancelling condition #2's schedules... +232ms ║║Condition group #2 evaluated true (state changed) (33ms) +235ms ║║Cancelling statement #4's schedules... +241ms ║║Executed virtual command setVariable (2ms) +246ms ║║Executed virtual command setVariable (2ms) +252ms ║║Sending external web request to: slack.com/api/users.profile.set +416ms ║║Executed virtual command httpRequest (165ms) +422ms ║║Executed virtual command setVariable (2ms) +430ms ║║Sending external web request to: slack.com/api/users.profile.set +546ms ║║Executed virtual command httpRequest (118ms) +557ms ║║Cancelling statement #57's schedules... +561ms ║║Calculating (string) Last run: + (string) Fri, Nov 17 2017 @ 12:00:00 PM MST >> (string) Last run: Fri, Nov 17 2017 @ 12:00:00 PM MST +563ms ║║Executed virtual command setState (1ms) +565ms ║╚Execution stage complete. (374ms) +567ms ║Setting up scheduled job for Fri, Nov 17 2017 @ 5:30:00 PM MST (in 19799.097s) +583ms ╚Event processed successfully (583ms)

UPDATE: See a working example of a Slack request piston here:


#2

It seems like there are a few things going on here. First, webCoRE encode the parameters for HTTP requests. Since you have encoded them manually they will end up double-encoded. Instead of %7B%22status_text%22%3A%20%22In%20a%20meeting%22%2C%22status_emoji%22%3A%20%22%3Acalendar%3A%22%7D you would set the value to {"status_text": "In a meeting","status_emoji": ":calendar:"}.

However, according to the Slack API docs this endpoint only accepts JSON data. So rather than FORM you would need to select JSON for the request type.

Now we get to the nonstarter. There is currently no way to just type in the entire JSON request body, you have to assign values to variables that will become the top-level keys in the json request object. Your token is fine since it is just a string, but the profile data has to be an actual object with the keys and values that you specified.

The first thing I tried since it is fairly easy is using the Parse JSON data task to convert the JSON string into an object that could be stored to a variable then mapped back to JSON. However, the web request seems to be unable to serialize this data back to JSON. Rather than {"profile":{"status_text":"In a meeting", "status_emoji":":calendar:"}"} it makes a request with the body {"profile":"[status_text:In a meeting, status_emoji::calendar:]"}.

My next thought would be to use a string[] profile list variable and set values for the status_text and status_emoji keys. However, the dropdown for web requests filters out list variables so there is no way to add it to the request.

As you can see, the web request functionality in webCoRE needs a lot of work. I have worked around this type of problem in the past by sending request data to (you guessed it) IFTTT which has more flexibility in defining the request body. Pass arguments to IFTTT (probably the url, token, and JSON that you already have just as an unencoded string) then IFTTT compiles it into a proper request.


#3

Sorry, details were pretty thin on how to do this in IFTTT, here is a similar case of a web request that was not possible in webCoRE and a few replies down how it was set up in IFTTT.


#4

Thank you for the awesome help @ipaterson! I didn’t realize params were automatically urlencoded, so I’ve switched that and am trying this piston again shortly with my next calendar meeting. If that doesn’t work I will try your IFTTT workaround as referenced in the other thread. My whole goal is to get away from IFTTT, but if IFTTT required then I will use it. =) At least it’s one dynamic IFTTT applet instead of 12! And for reference in case anybody else is looking to do the same thing, this users.profile.set endpoint in the Slack API can use application/x-www-form-urlencoded, see, https://www.hitchhq.com/slack/activities/591b07659659a6263d0ccd49 - my previous IFTTT applets I was using before this piston worked with application/x-www-form-urlencoded.


#5

Yeah! In this case the approach also benefits from avoiding that 1-to-1 connection between IFTTT and Slack since as far as IFTTT is concerned it is just doing a random web request. I’m not so sure it will support form data though, that link was referring to users.profile.get rather than set.


#6

@ipaterson Good news! By removing the urlencoding and taking a cue from the other piston you pasted here by escaping the curly brackets, this works as-is, including keeping the FORM type as application/-www-form-urlencoded. Thx for all your help!


LaMetric Time Notifications
#7

OK people! Right now I’ve been using HA to send messages through a Slack bot… I’d LOVE to be able to do this through webcore. But I cannot get it working. First question, is this even possible? Second… what do I need to do with my POST JSON request to get this to work?

Note: the happens daily at TIME is simple for testing purposes :slight_smile:

13 AM


#8

When you see that error you likely just need to escape the curly brackets on your request. See the previous post in this thread for an example with the ‘statusXYZ’ variables. You can also see a working example of a Slack request piston here:


#9

@andyhawks thanks for the post! So I’ve managed to get status updates working in Slack via webCoRE at this point. What I can’t manage to do is get it to send a message via a bot that I set up. It appears the request is being sent succesfully, but not coming out the other side. Thoughts?

19 PM


#10

@acd37 Alec, I see a few things that may need to change with this snippet to be able to post a message to a channel:

  1. Change the Content Type of the web request to JSON instead of FORM. Most of the Slack API uses JSON, the profile endpoint is an exception that uses application/x-www-form-urlencoded, but the postMessage endpoint uses JSON.
  2. In your profileStatus, change ‘type’ to ‘text’.
  3. By setting the ‘profile’ value to the value of ‘profileStatus’ and then sending that ‘profile’ variable in the payload, webCoRE is going to add a ‘profile’ object into the JSON paylod (e.g. {"profile": {"channel" "....", "text": "Hello}} ) and you don’t want that extra ‘profile’ object in there. I’m not 100% sure, but I think you want to send 3 separate variables into the data of the web request: token, channel, and text (e.g. Make a POST request to {jsonUrl} with type JSON and data {token,channel,text}). So try changing your variables around to match that. You may run into issues @ipaterson pointed out with JSON objects in this post earlier in this thread:

Some extra variable logging can help debug what’s going on by adding these underneath the web request:
Log info "{$json}" Log info "{$response}"

BTW, not sure of your use case here, but if you simply want to post the same message to the same channel every Wed @ 11:40 AM, I’d use Slack’s built-in /reminder functionality instead of webCoRE.


#11

So after much trial and error with the variables, it ended up being much easier to create a Slack app with a bot, and send in a simple webhook. The use-case, in response to your post, is to actually use Slack to send notifications over using push/text notifications.


#12

Integrating this into an arrival piston looks like so:

with following result:

49 PM