Zoom Team Chat の Incoming Webhook 応用編

## Incoming Webhook 第2弾（応用編）
前回の記事（下記）では、Google Form から通知を受け取るために GAS(Google Apps Script) を活用、という形でご紹介しました。

https://qiita.com/michitakasugi/items/edfad8d8fe033e79922e

ただ、Webhookを使うサービスによっては Zoom Team Chat が用意しているセキュリティの仕組み（POSTするデータのヘッダーにAuthorizationを含める必要があります）やデータフォーマット（クエリパラメータとして format の種類を設定することができます）に対応できないものもあるかと思います。

https://support.zoom.us/hc/en-us/articles/4418193782029

そんな時のために、またもや GAS を使って橋渡しをする方法をご紹介します。

## 下準備
前回の記事ですでに Incoming  Webhook の導入方法はご紹介していますので、こちらは割愛します。まだの方は、前回の記事を参照していただきつつ、導入をしてみてください。

導入済みの方は、今回もお好きな Zoom Team Chat チャンネルにて

```bash
/inc connect WEBHOOKNAME
```
と入力して新規Webhook接続を作成します。[^1]

[^1]: WEBHOOKNAME の部分は任意で指定してください。

次に、出力されたURLと Verification Token を控えつつ、GASのスクリプト画面を立ち上げます。

https://script.google.com/u/0/home

今回はスタンドアロン型で実行するため、新しいプロジェクトを作成します。

![p1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442226/e25fa839-98ec-7337-52ea-784bc052b310.png)

## 処理の概要
外部サービスから受け取る Webhook、つまり POST されるデータを受け取って処理するには、GAS側でデータを受け取る「Webアプリ」の仕組みを利用します。基本的には `doPost` を使って受け取る形になります。

その後、受け取ったデータを必要に応じて加工し、 `UrlFetchApp.fetch` で今度は Zoom Team Chat の Incoming Webhook に POST します。

![p2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442226/ef28aec5-0bee-00bd-9a78-02b295c61cbc.png)


##  受け取る仕組み
今回は参考として、 fluxguard から Web ページの更新通知を受け取る、というシナリオで考えてみます。

https://fluxguard.com/

Fluxguard は無料で Web ページをクロールしつつ、変化点があったら diff 付きで教えてくれる、便利なサービスです。他に Distill.io などもありますね。

Fluxguard のサイトでサインアップしたら、ADD SITE から通知してほしいページの URL を指定します。ちなみにですが Fluxguard の Webhook のリファレンスページやサンプルでは BBC News を使っているんですが、実際にこれやると多分秒で更新かかり続けるのでワケワカメになる気がします。なので登録するオススメはやっぱり [Zoom Releases](https://support.zoom.us/hc/ja/sections/360008531132) とかですかねー。（棒読み）

![p3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442226/342a20eb-ddc8-0c54-1cc5-491fd747d907.png)


Webhookの仕組みについては、このページに記載があり

https://fluxguard.com/how-to-guides/use-webhooks-to-integrate-web-change-notifications

データフォーマットを読み解いていくと、diffUrl という差分をまとめたページと、タイトルや対象URLが含まれているようです。

![p4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442226/575eb8b1-4952-ed37-205c-16016218c212.png)


これを踏まえつつ GAS に戻り、POST データの受け取りとデータの処理の仕組みを書いていきます。

```javascript
// fluxguard からの Webhook を doPost で受け付けます
function doPost(e) {
  if (e == null || e.postData == null || e.postData.contents == null) return; 
  //リクエストデータがnullの場合、処理をスキップ
  var jsonData = e.postData.contents;
  var objectData = JSON.parse(jsonData);
  // fluxguardから受け取ったリクエストデータのJSONをパースして、 objectData の配列に格納します

  // 配列内の title url diffUrl だけ取得します
  var title = objectData["title"];
  var url = objectData["url"];
  var diffUrl = objectData["diffUrl"];
  var message = "Webページが更新されました！";
  pushUpdates(title,url,diffUrl);
}
```

こんな感じで受け止められるようにします。

## GAS の Webアプリ公開
さて、POST データを受け取るには、作成したスクリプトが外部から叩けるようにしておく必要があります。やり方は比較的簡単で、スクリプトエディタ画面の右上にある「新しいデプロイ」をクリックし、Webアプリとしてデプロイします。

![p5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442226/0d80bf15-59f6-287d-057f-07f4dcbf4c52.png)


種類の選択の隣にある歯車マークから、**ウェブアプリ**を選択し説明を入力します。**次のユーザーとして実行**を「**自分**」、**アクセスできるユーザー**を「**全員**」として**デプロイ**します。

デプロイが完了すると、URL が発行されますのでこのアドレスを控えてください。ここに POST されると、GAS に書かれた doPost 以降の処理が実行されます。

この辺りについてはすでにさまざまな記事がありますので、詳しくはググってみてください。以下、参考まで。

https://auto-worker.com/blog/?p=3565

https://www.shanaidx.com/webapp_deploy/

## Webhook を使った Zoom Team Chat への投稿
前半で受け取ったデータをもとに、実際に Zoom Team Chat へ投稿します。この部分は前述の記事と同様になりますが、あらためて載せておきます。

```javascript
function pushUpdates(title,url,diffUrl){
  // 取得した WebhookURL と Verification Token
  var urlEndpoint = "https://WEBHOOKURL?format=fields";
  var token = "TOKEN";
  // Body
    let body = {
    "Title": title,
    "URL": url,
    "Diff" : diffUrl,
    }
  // リクエストヘッダー
  let requestOption = {
    "method" : "POST",
    "headers" : {
      "Content-Type" : "application/json",
      "Authorization" : token,
    },
    "payload" : JSON.stringify(body),
    "muteHttpExceptions" : false
  }
  // UrlFetchApp.fetch で投稿
  var response = UrlFetchApp.fetch(urlEndpoint,requestOption)
  var errorCode = response.getResponseCode()
  var errorText = response.getContentText()
  // エラーが起きたらGASのコンソールで確認できるようにしておきます
  Logger.log("Code: " + errorCode + " Message: " + errorText)
}
```
以上でGASを経由した Webhook 投稿が完了しました。

ちなみに、Zoom Team Chat 側で先に専用のチャンネルを作成しておき、そこで `/inc connect WEBHOOKNAME` を実行しておくと、今回のような Web ページ更新の通知専用チャンネルのようにチャンネルを使い分けることができます。

## (おまけ) Zoom Team Chat のチャンネル設定
ちなみに Zoom Team Chat のチャンネル作成においても、他のチャットアプリと同様公開チャンネル・非公開チャンネルの設定だけでなく、

- メンバー追加権限
- アカウント外メンバーの追加可否
- 投稿可能なメンバーの指定
	- チャンネル内の全員
	- オーナーと管理者のみ
	- オーナー、管理者プラス指定されたメンバー

をチャンネル作成時に指定することができます。[^2]
とても安全かつ便利に使うことができますので、是非一度使ってみてください。

[チャットの管理者設定：チャンネルの管理](https://support.zoom.us/hc/ja/articles/360048757952)

[^2]: 管理者による設定に依存します。あらかじめ**管理者＞アカウント管理＞アカウント設定＞チームチャット**にて設定を行なってください。