29
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

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

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先生がんばって!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
29
Help us understand the problem. What are the problem?