DialogflowのWebhookでGoogle AssistantにBasic Cardのレスポンスを返す

Google Assistantでは応答メッセージだけを返すSimple Responses以外に、スマホの画面向けに画像やURLのリンクを付けた応答メッセージ返すRich Responsesという種類のレスポンスがあります。

詳細は公式ドキュメントを参照。
[Responses  |  Actions on Google  |  Google Developers](https://developers.google.com/actions/assistant/responses)

Basic Cardの場合、このように応答メッセージに加えてサイトの情報を表示してリンク先に誘導することができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/3324/c9cfc62b-340f-2915-5a1b-9c2f82033d9b.png)

DialogflowのWebhookでこのような応答を作る場合、大きく２種類の手段があります。

- Firebaseで用意されているNodeのライブラリを使う
- 自前でJsonのレスポンスを作って返す

今回は（Firebaseを使わなかったので）後者の手段を選びたかったのですが、Dialogflowのドキュメントにはあまり説明が書かれておらず少し苦労したのでまとめます。

[Fulfillment  |  Dialogflow](https://dialogflow.com/docs/fulfillment)

Simple Responsesの場合は以下のように `speech` と `displayText` にメッセージを入れて返すだけです。

```js
response.setHeader("Content-Type", "application/json")
response.send(JSON.stringify({'speech':"これはテストです",'displayText':"これはテストです"})
```

しかし、Rich Responsesのほうは上記Dialogflowのドキュメントによると書式付きメッセージということになるのでおそらく `data` にJsonオブジェクトを作って返してやる必要がありますが、あまり説明がありません。DialogflowはSlackやFaebookとも連携できる仕組みなのでそれぞれのサービスに合わせるということだとは思いますが、フォーラムでもうまくいかないということで議論されているようです。

[Google Assistant rich message responses - Integrations - Dialogflow (API.AI) Forums](https://discuss.api.ai/t/google-assistant-rich-message-responses/5134/19)

このフォーラムの内容を参考に以下の記述でBasic Cardを作ることができました。上記で紹介した [Action on Googleの公式ドキュメント](https://developers.google.com/actions/assistant/responses) のBasic Cardのところで書かれているサンプルコードを当てはめると以下のようになります。

```js
 response.setHeader("Content-Type", "application/json")
  response.send(
    JSON.stringify({
      "speech": "This is a simple response for a carousel",
      "data": {
        "google": {
          "expectUserResponse": true,
          "richResponse": {
            "items": [
              {
                "simpleResponse": {
                  "textToSpeech": "This is a simple response for a carousel"
                }
              },
              {
                "basicCard": {
                  "title": "Math & prime numbers",
                  "formattedText": "42 is an even composite number. It\n    is composed of three distinct prime numbers multiplied together. It\n    has a total of eight divisors. 42 is an abundant number, because the\n    sum of its proper divisors 54 is greater than itself. To count from\n    1 to 42 would take you about twenty-one…",
                  "image": {
                    "url": "https://example.google.com/42.png",
                    "accessibilityText": "Image alternate text"
                  },
                  "buttons": [
                    {
                      "title": "Read more",
                      "openUrlAction": {
                        "url": "https://example.google.com/mathandprimes"
                      }
                    }
                  ]
                }
              }
            ],
            "suggestions": []
          }
        },
        "possibleIntents": [
          {
            "intent": "actions.intent.TEXT"
          }
        ]
      }
    })
  );
```

Simple Responsesの場合とは違い、 `displayText` は指定せず、 `data` の中に `google.richResponse.items` という配列を作り、その中に `displayText` 相当の
 `simpleResponse` を作り、 `basicCard` を追加します。 `List Selector` などの他の種類のレスポンスも同じように実現できると思われます（試してませんが）。

<img width="410" alt="スクリーンショット 2017-11-13 0.40.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/3324/a242d975-5223-b458-7a23-a63814d8ac1f.png">

フォーラムに書かれている [このコメント](https://discuss.api.ai/t/google-assistant-rich-message-responses/5134/19) を参考にしました。