kintone と Google Apps Script で 簡単おうむ返しチャットBotを作って見た

ちょっと前から自分の中で Webサービスとか、Botの関心度が高くなってまして。LINE Botもチュートリアルを見ながら作って見たものの、いまいちLINEの設定の辺りとか訳が分からないので、kintoneでBotを作ったら理解が進むのではと思って、簡単なおうむ返しチャットBotを作って見ました。フロントのデザインはkintoneのアレなままなので、これをチャットBotというのは無理な感じですが、その辺りはご容赦ください。

# 前提条件や知識など

* kintoneアプリが作れる
* JavaScriptが書ける
* Google Apps Scriptが書ける

# 動作イメージ
雑ですみません。私の中のイメージです。LINEとの対比ですが、LINEはBotを作るのにLINE Messaging APIを利用します。LINE Platform という基盤の上で Bot用のチャネルを作り、そのBotチャネルを通して外部のBotサーバーと接続する感じです。（多分）

![IMG_1114.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/d2362b55-2a74-49f7-b4a7-962d4b28e8b6.jpeg)

kintoneは、Botアプリを作って、アプリの Webhook を通して外部のサーバーと接続すれば、Botができるという具合です。今回BotサーバーにはGoogle Apps ScriptをWebアプリモードで動作させる感じです。

新規レコードを作成して
<img width="426" alt="スクリーンショット 2020-06-07 21.57.32-04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/e66548cc-fcc8-a52e-51f4-36e2b175a014.png">

一覧に戻ると、Botサーバーからおうむ返しが返ってきます
<img width="518" alt="スクリーンショット 2020-06-07 21.58.05-05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/88b438f8-7000-bf22-ea85-31932a7eac51.png">



# 概要
kintoneにはWebhookという、アプリの入力をトリガーとして外部のサーバー（例えばBotサーバー）にデータを送信する仕組みがあります。Botの作成にはこの仕組みを利用します。
作り方は下記の通りです。

1. kintoneで Botアプリを作ります。
2. Google Apps Script でWebアプリを作成します。
3. Google Apps Script の公開URLをkintoneのBotアプリのWebhookに設定します。

# 1. kintoneで Botアプリを作ります。
メッセージ入力用のフィールドとBotサーバーの応答用のフィールドを用意します。
<img width="721" alt="スクリーンショット 2020-06-07 21.58.23-01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/8a132b87-437e-c14d-b6a2-6332b550cacb.png">

サーバー応答用のフィールドには、Botサーバーからの応答時の際に、メッセージと一緒に何かしらのフラグをセットします。
これにより、新規のメッセージ投稿とサーバーからの応答なのかを判別しています。
これがないと無限ループしますので注意してください。

# 2. Google Apps Script でWebアプリを作成します。
一応コードを載せておきますが、基本はkintoneからのレコードを取得して、メッセージフィールドの内容を返しているだけです。
デバッグの為に、Spreadsheetにログを吐いていますがその処理は外してOKです。

```javascript
function doPost(e) {

  // 環境変数のセット
  const scriptProperties = PropertiesService.getScriptProperties();
  const DOMAIN = scriptProperties.getProperty('DOMAIN'); // kintone ドメイン名
  const APP_ID = scriptProperties.getProperty('APP_ID'); // kintone アプリID
  const API_TOKEN = scriptProperties.getProperty('API_TOKEN'); // kintone APIトークン
  const SHEET_ID = scriptProperties.getProperty('SHEET_ID'); // デバッグ用 Spreadsheet ID

  appendLogToSpreadsheet('--- debug start', SHEET_ID)
  appendLogToSpreadsheet(JSON.stringify(e), SHEET_ID)
  appendLogToSpreadsheet(JSON.stringify(JSON.parse(e.postData.contents)), SHEET_ID)

  const contents = JSON.parse(e.postData.contents)
  const record = contents.record
  // BOTサーバーからの返信の時は何もしない
  if (record.botServerReplyMessage.value) {
    appendLogToSpreadsheet('BOTサーバーからの返信の時', SHEET_ID)
    return
  } else {
    appendLogToSpreadsheet('新規メッセージの時', SHEET_ID)
  }

  const payload = {
    app: APP_ID,
    record: { 'message': 
              {'value': record.message.value},
              'botServerReplyMessage':
              {'value': contents.id},
            }
  }
  const option = {
    method: "post",
    contentType: "application/json",
    headers: { "X-Cybozu-API-Token": API_TOKEN },
    muteHttpExceptions: true,
    payload: JSON.stringify(payload)
  };
  appendLogToSpreadsheet('option', SHEET_ID)
  appendLogToSpreadsheet(option, SHEET_ID)

  let response = ''
  // kintoneにレコード追加
  response = UrlFetchApp.fetch(
    `https://${DOMAIN}/k/v1/record.json`,
    option
  )
  appendLogToSpreadsheet('response', SHEET_ID)
  appendLogToSpreadsheet(response, SHEET_ID)

  // Spreadsheetにログを書き出す
  function appendLogToSpreadsheet(log, sheetId, sheetName = 'sheet1') {
    const spreadSheet = SpreadsheetApp.openById(sheetId)
    spreadSheet.getSheetByName(sheetName).appendRow(
      [new Date(), log]
    );
    SpreadsheetApp.flush()
  }

  return response
}
```

kintoneのAPIトークンなどの環境変数はプロジェクトのプロパティにセットしています。
<img width="700" alt="スクリーンショット 2020-06-07 23.18.04-03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/5319cd3c-4ad0-6453-2afc-76fe15642641.png">

コードを作成後に、Webアプリとして公開する設定をします。
<img width="476" alt="スクリーンショット 2020-06-07 23.08.42-02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/46cd0c4d-45a8-237d-3953-e324677d861d.png">


# 3. Google Apps Script の公開URLをkintoneのBotアプリのWebhookに設定します。
<img width="714" alt="スクリーンショット 2020-06-07 22.01.16-06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/8e700940-3022-17ab-96bb-b852f622765e.png">

# 今後の展開

* LINEのMessaging APIの設定の辺りを整理する
* LINEのLIFFを使ってkintoneとやりとりする

あと、もう少しチャットBotのイメージのUIは用意したいですね。

# 参考
後ほど。

* Google Spreadsheet https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app
* Simple Triggers https://developers.google.com/apps-script/guides/triggers
* UrlFetchApp https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)
* V8 Runtime Overview https://developers.google.com/apps-script/guides/v8-runtime#v8_syntax_examples
* kintone レコード取得 https://developer.cybozu.io/hc/ja/articles/202331474
* kintone レコード登録 https://developer.cybozu.io/hc/ja/articles/202166160
* LINE Messaging API https://developers.line.biz/ja/services/messaging-api/