Google Chatにスレッドを指定してポストする

Google Apps Script(GAS)からGoogle ChatのWebhookでポストする際、普通にポストすると毎回新規スレッドになってしまいます。
スレッドを使わずに運用しているチャットルームや、Botがポストした投稿にBotが自ら追記したい時に困ります。
この記事ではスレッドを指定してポストする方法について説明します。

#どうやってやるの
ポストした際、ポスト成功のレスポンスにthreadのnameが入っているので
2回目のポストからはthread nameを指定する事で同一スレッドにポストする事が出来ます。

**※2020/1/10追記**
　チャットルームのソースコードからthread nameを取れることに気が付きました…。
　チャットルームのURL`https://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

```javascript
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でレスポンスの中身を見られます。
##レスポンスの中身
```json
{
  "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

今回重要なのはここ

```json
"thread": {
    "name": "spaces/AAAAAAAAAAA/threads/aaaaa_aaaaa"
  }
```
これがthread nameなので、2回目の投稿からこのnameを指定してポストします。

#thread nameを指定してポスト
先ほどのコードで変数`payload`にthread nameを追加します。
実行すると最初のメッセージと同一のスレッドにポストされる筈。

```javascript
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^￣

と通知が出るようにしています。
その時はスレッドをレスポンスから取得して追記します。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514873/1e80ec6d-3673-c9ab-d186-8e6cb3f13d40.png">

レスポンスをjsonにして、thread nameを取得します。

```javascript
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先生がんばって！