8

I'm using Python 2.7 along with a python-slackclient. I have an attachment structure like so:

self.msg = {
    "attachments": [
        {
            "fallback": "%s, %s" % (self.jiraIssueObj.fields.summary, self.link),
            "pretext": "Detail summary for %s" % self.jiraIssueObj,
            "title": self.jiraIssueObj.fields.summary,
            "title_link": self.link,
            "text": self.jiraIssueObj.fields.description[0:self.maxSummary],
            "color": "#7CD197",
            "mrkdwn_in": ["text", "pretext", "fields"]
        }
    ]
}

then,

def Send(self):
        if (self.msg):
            slack_client.api_call("chat.postMessage", channel=self.channel, text=self.msg, as_user=True)
            self.msg = None

However, when this posts, it just posts the plaintext, with no formatting:

{"attachments": [{"title": "Upgrade Grafana to 3.0", "color": "#7CD197 ", "text": "I\u2019ve added the JIRA maillist so this email will create a ticket we can queue it up in support.\u00a0 Eric if you wouldn\u2019t mind just replying to this email with the additional info?\n\n\u00a0\n\n\u00a0\n\nSent: Thursday, August 25, 2016 11:41 AM\n", "title_link": "https://jira.jr.com/browse/ops-164", "mrkdwn_in": ["text", "pretext", "fields"], "pretext": "Detail summary for ops-164", "fallback": "Upgrade Grafana to 3.0, https://jira.jr.com/browse/ops-164"}]}

What am I doing wrong? I've tried also doing attachments=self.msg in the Send() call, but I get no output at all to my slack channel when doing that.

peterh
  • 11,875
  • 18
  • 85
  • 108
MrDuk
  • 16,578
  • 18
  • 74
  • 133

2 Answers2

6

As it turns out, the call to

slack_client.api_call("chat.postMessage", channel=self.channel, attachments=self.msg, as_user=True)

apears to add the top layer { "attachments": ... } for you. So by changing my self.msg to simply be:

self.format = [{
    "fallback": "%s, %s" % (self.jiraIssueObj.fields.summary, self.link),
    "pretext": "Detail summary for %s" % self.jiraIssueObj,
    "title": self.jiraIssueObj.fields.summary,
    "title_link": self.link,
    "text": self.jiraIssueObj.fields.description[0:self.maxSummary],
    #"color": "#7CD197",
    "mrkdwn_in": ["text", "pretext", "fields"]
}]

without this outer { "attachments": ... } wrapper, the api was able to post the message attachment as expected.

fenceop
  • 1,439
  • 3
  • 18
  • 29
MrDuk
  • 16,578
  • 18
  • 74
  • 133
1

The chat.postMessage method has a couple of quirks -- like most of Slack's web APIs, it only supports application/x-www-form-urlencoded content-types, and does not support JSON. The quirkier aspect is that the attachments parameter takes a URL-encoded array of JSON. Right now, it appears you're sending the text parameter a native Python array.

For Slack to understand that structure, you'll first need to turn it into a JSON string. The API wrapper you're using can probably handle the next step of conversion into a URL-encoded representation.

Finally, the attachment itself doesn't get placed in the text of the message -- that's a separate field. You'll want to specify something more like this, after defining your JSON string as self.attachments:

slack_client.api_call("chat.postMessage", channel=self.channel, attachments=self.attachments, as_user=True)

The text field becomes optional once you include attachments.

Taylor Singletary
  • 2,211
  • 17
  • 16
  • I tried doing `attachments=json.dumps(self.msg)`, and while this produced a JSON string (https://gist.github.com/calebtote/80a3803a717b1d908fc48986d8e876e3) it still doesn't actually post to the channel anything. – MrDuk Jan 23 '17 at 16:42