1
votes

I've looked everywhere and can't find this issue. I've come over from PeopleSoft to .NET and have only recently began learning JavaScript and I'm attempting to use Google Apps Script to send email notification messages to Slack.

It appears to me that GAS's UrlFetchApp isn't handling an array correctly. Below I didn't include all the Slack API options for clarity. Here how I constructed the payload, where 'attachments' contains the array in question:

var payload = 
      {
       // ...
        "username": "Test webhook Bot", 
        "attachments": [
          {
            "pretext": "pre-hello1", 
            "text": "text-world1"
          },
          {
            "pretext": "pre-hello2", 
            "text": "text-world2"
          }
        ]        
        //  ...        
      };


 var options = 
      {
        "method" : "post",
        "payload" : payload,
        "contentType":"application/json"
      };

var response = UrlFetchApp.fetch(requestURL, options); 

When testing I found that the post was occuring but Slack was ignoring the attachments portion of the message. I used the following to examine the outgoing POST:

    var response = UrlFetchApp.getRequest(requestURL, options);

And what I found looking at the execution transcript I find that the JSON array in my payload isn't being encoded the way I expected. Before execution, I clearly see the properly formatted array.

[16-01-26 07:26:39:050 MST] UrlFetchApp.getRequest([https://slack.com/api/chat.postMessage?, {method=post, payload={attachments=[{pretext=pre-hello1, text=text-world1}, {pretext=pre-hello2, text=text-world2}], username=Test webhook Bot}, contentType=application/json}]) [0 seconds]

But what is actually sent, in place of the attachments array is: %5BLjava.lang.Object;@37f01fb3

[16-01-26 07:26:39:051 MST] Logger.log([Test:https://slack.com/api/chat.postMessage?attachments=%5BLjava.lang.Object;@37f01fb3&username=Test+webhook+Bot, []]) [0 seconds]

I tried searching this out as much as I could before asking for help, but I'm not sure if I'm either loss. Does anyone know where I may look to find out what I'm missing? Thanks.

2
I found that if I used JSON.stringify(payload) in the construction of my options object that the array was intact for the POST.Kevin Stokes
Did you find a solution?Alan Wells
@SandyGood: I did get an answer. I just posted it along with additional information I learned based on my previous comment. Thanks for checking.Kevin Stokes

2 Answers

3
votes

To the extent that this information is helpful almost 4 years out, I've been running into the same problem and here's the solution I came up with: - I will be including all relevant information encoded in the URL JSON structure - The "options" portion of the UrlFetchApp is then just specifying the method and contentType

An example would look like this:

var url = "https://slack.com/api/chat.postMessage?token=the-token-here&channel=channel_id_here&text=hello%20world";

  var options = {
    "method": "post",
    "contentType": "application/json",
  };


  return UrlFetchApp.fetch(url,options);
}

I also got some more helpful information at this Stack Overflow thread. I think this is the Slack API documentation that helps explain the constraints:

JSON-encoded bodies

For these write methods, you may alternatively send your HTTP POST data as Content-type: application/json.

There are some ground rules:

You must explicitly set the Content-type HTTP header to application/json. We won't interpret your POST body as such without it. You must transmit your token as a bearer token in the Authorization HTTP header. You cannot send your token as part of the query string or as an attribute in your posted JSON. Do not mix arguments between query string, URL-encoded POST body, and JSON attributes. Choose one approach per request. Providing an explicitly null value for an attribute will result in whichever default behavior is assigned to it.

1
votes

Based on a comment I received from a Google Drive Help Forum discussion , I wanted to pass on more information on what I found regarding the use of JSON.stringify() in creating my Slack request. I modified my options JSON

var options = {
    'method': 'post',
    'payload': JSON.stringify(payload)
  };

Google then interprets the 'attachments' array correctly when constructing the request and I no longer see the java.lang.Object error.

Additional lessons learned: prior to using JSON.stringify() Slack would let me post using my personal developer token as part of the payload. Once I began using JSON.stringify() Slack would not accept my personal token nor could I pass a channel parameter. This resulted in me creating a Slack Incoming Webhook direct to the channel I wanted. I haven't tracked down why that would be the case. It may be in Slack's documentation somewhere, I just haven't had time to look yet.