そのたおおぜい

研究とか英語とかプログラミングとか

SlackAPIでattachmentsが表示されなかった時

GoogleAppScript経由でSlackのAPIchat.postMessageを叩いて投稿するみたいなことがしたかったんだけど,その時に結構な時間ハマったので,今日はそんな話です.参考文献はこちら.

stackoverflow.com

attachments field actually does get sent as a string of JSON, but URL-encoded into a parameter.

要するに,Attachment部分は文字列で渡してあげる必要があるらしい.さすがにこれだけだとわかりづらすぎるので,ちょっと例を挙げる.世間一般でGAS経由でSlackのAPIを叩く場合,大抵の場合こんな感じで叩いている.

  var url = "https://slack.com/api/chat.postMessage";
  
  var payload = {
    "token" : "トークン",
    "channel" : "チャンネル名",
    "as_users" : true,
    "text" : "なんかテキスト",

   // ここにattachmentsを書く
  };
  
  
  var params = {
    "method" : "post",
    "payload" : payload
  };
  
  var response = UrlFetchApp.fetch(url, params)
  Logger.log(response);

要するに,URLのパラメータは関数側に放り投げて作ってもらっているってことです.挙動が見たい人は以下のページ参照.

Class UrlFetchApp  |  Apps Script  |  Google Developers

ハマったのはこのpayloadattachmentsを書くところ.これ,変数をそのまんま書いちゃうと,JSON形式であっても文字列じゃないので展開されないらしい.と言ってもわかりづらいと思うので,負例を挙げる.

    // NG
    "attachments" : [
        {
          "color": "#FFD700",
          "title": "ナンタラカンタラ",
          "fields": fieldsList
        }
    ]

このままだとJSON形式にはなっているらしいが,文字列にはなっていない.ので,APIを叩いてもattachmentsが表示されない.らしい.

f:id:hagyou:20170718094445p:plain

chat.postMessage method | Slack

これ,APIのドキュメントからスクショ取ってきたやつなんですけど,これで,文字列でほしいってことらしいです.わかんねーよ.でも,文字列で欲しがっているものは欲しがっているので,JSON.stringify()で文字列にしてあげる必要がある.

    // OK!
    "attachments" : JSON.stringify([
        {
          "color": "#FFD700",
          "title": "ナンタラカンタラ",
          "fields": fieldsList
        }
    ])

こんな感じ.これで後は表示されます.

これ,何がハマるって,文字列にしないでAPI叩いてもAPI側からエラーも警告も返ってこないんですよ.ひどくない?

あと,これは完全に愚痴ですけど,関数自体の呼び方も人によって異なっていたり,そもそも全部JSON.stringfy()で文字列にして送っていたりする人もいて,結局どこからどこまでを文字列にしなければいけないのかが全然わからなかったんですよね.あとSlackのAPI DocmentにあるTesterを使っても普通に表示されます.故にハマったハマった.同じような苦しみを生じさせないためにも記事にしました.参考になった人がいたら幸い.