Google Apps Script(GAS)からGoogle ChatのWebhookでポストする際、普通にポストすると毎回新規スレッドになってしまいます。
スレッドを使わずに運用しているチャットルームや、Botがポストした投稿にBotが自ら追記したい時に困ります。
この記事ではスレッドを指定してポストする方法について説明します。
#どうやってやるの
ポストした際、ポスト成功のレスポンスにthreadのnameが入っているので
2回目のポストからはthread nameを指定する事で同一スレッドにポストする事が出来ます。
※2020/1/10追記
チャットルームのソースコードからthread nameを取れることに気が付きました…。
チャットルームのURLhttps://chat.google.com/room/AAAAAAAAAAA
の末尾の文字列と
ソースコード中のdata-topic-id="aaaaa_aaaaa"
の部分を組み合わせて
spaces/AAAAAAAAAAA/threads/aaaaa_aaaaa
とする事でthread nameになります。
手動でやるならわざわざポスト成功レスポンスを取得しなくても良さそうです。
#ポスト成功レスポンスの中身を取得する
GASからWebhookでポストするコードは下記の記事のものを使わせて頂いています。
http://20november.hatenablog.com/entry/2018/06/14/235352
function myFunction() {
var url = "WebhookのURL";
var text = "thread name確認投稿"
var payload = {
"text" : text
}
}
var json = JSON.stringify(payload); //エンコード
// ポストするためにヘッダーとかボディをまとめて入力する
var options = {
"method" : "POST",
"contentType" : 'application/json; charset=utf-8',
"payload" : json
}
var response = UrlFetchApp.fetch(url, options); //XMLHttpRequestが使えないのでこっちでポスト
Logger.log(response);
}
実行するとチャットルームにメッセージが届き、Logger.logでレスポンスの中身を見られます。
##レスポンスの中身
{
"name": "spaces/AAAAAAAAAAA/messages/aaaaa_aaaaa.aaaaa_aaaaa",
"sender": {
"name": "users/0000000000000000000",
"displayName": "test-bot",
"avatarUrl": "",
"email": "",
"domainId": "",
"type": "BOT"
},
"text": "thread name確認投稿",
"cards": [],
"previewText": "",
"annotations": [],
"thread": {
"name": "spaces/AAAAAAAAAAA/threads/aaaaa_aaaaa"
},
"space": {
"name": "spaces/AAAAAAAAAAA",
"type": "ROOM",
"displayName": "Sandbox"
},
"fallbackText": "",
"argumentText": "thread name確認投稿",
"createTime": "2019-10-16T05:47:19.557647Z"
}
各要素が何を意味しているかは下記記事を参照してください。
https://qiita.com/Shota_Fukuda/items/7cd94126b578fad81d27
今回重要なのはここ
"thread": {
"name": "spaces/AAAAAAAAAAA/threads/aaaaa_aaaaa"
}
これがthread nameなので、2回目の投稿からこのnameを指定してポストします。
#thread nameを指定してポスト
先ほどのコードで変数payload
にthread nameを追加します。
実行すると最初のメッセージと同一のスレッドにポストされる筈。
var thread = "spaces/AAAAAAAAAAA/threads/aaaaa_aaaaa"
var text = "同一スレッドに投稿"
var payload = {
"text" : text,
"thread": {
"name": thread
}
}
#Botでやる例
社食のメニューを通知するBotを運用しているのですが
「天ぷら盛り合わせ」が出た時は蕎麦と合わせて天蕎麦にする文化があるので
通知内容に「天ぷら盛り合わせ」が含まれる時に
_人人人人人人人人人_
> 天そばチャンス <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
と通知が出るようにしています。
その時はスレッドをレスポンスから取得して追記します。
レスポンスをjsonにして、thread nameを取得します。
var response = UrlFetchApp.fetch(url, options); //XMLHttpRequestが使えないのでこっちでポスト
var json = JSON.parse(response.getContentText());
var thread = json["thread"]["name"];
//天そばチャンス判定
if(sentence.match(/天ぷら盛り合わせ/)){
sentence = '\n_人人人人人人人人人_\n> 天そばチャンス <\n ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄';
var payload = {
'text' : sentence,
"thread": {
"name": thread
}
};
var options = {
'method' : 'post' ,
'contentType' : 'application/json' ,
'payload' : JSON.stringify(payload),
};
UrlFetchApp.fetch(url, options)
}
#スレッド指定について参考にした記事
Google Hangouts ChatでAPIからスレッドを指定して書き込む
https://uyamazak.hatenablog.com/entry/2018/10/01/121552
残念ながらGASじゃなかったのでコードは全然流用出来ず、
「レスポンスにthread.nameが入っているって言われてもどうやって取得すえばええの???」
から始まり、なんとか思惑通り動くコードになりました。レスポンス見るのめっちゃ簡単だったね。
#Google Chatって情報少なくない?
GASでスレッド指定する方法なんか偉大なる先人達の知恵が当然あるはず!と調べたらGASでやってる情報がない。
そもそもGoogle Chatを具体的に解説してる記事が少ない…?
やっぱりChat botならSlackが鉄板なんですかね。
うちの職場はSlack?なにそれ?状態で導入出来ずG Suite一択なんで、Google先生がんばって!