Dialogflow Messengerで用意されているレスポンスをDenoで返してみた

Dialogflow Messengerとは、あなたが運営しているWebサイトに対して、簡単にQ&Aのようなチャット機能を組み込むことができます。
ドキュメントは下記URLをご確認ください。

https://cloud.google.com/dialogflow/docs/integrations/dialogflow-messenger

## ハンズオン資料URL
Katacodaを使って簡単に試せる環境を用意しました。こちらの資料に沿って行えばあっという間に確認できます。

https://katacoda.com/gaomar/scenarios/deno-dialogflowmessenger-playground

## リッチレスポンス
普通にテキストを返すことはもちろんですが、リッチなレスポンスを返すことができます。

<img width="1290" alt="スクリーンショット 2020-06-23 14.40.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/54cae175-0b87-c323-df89-6c071d9f38bc.png">

## DenoでAPI作成
今回はそのレスポンスを今流行のDenoで返してみたいと思います。サーバー部分は `abc` を使いました。

https://deno.land/x/abc

`start` メソッドでポートを指定してサーバーを起動しています。あとは指定されたJsonをレスポンスとして返しています。



```typescript:hello.ts
import { Application, Context } from "https://deno.land/x/abc@v1.0.0-rc10/mod.ts"

const app = new Application()

app.static('/', './public')

app.get('/', async (ctx: Context) => {
    await ctx.file('./public/index.html')
})

app.post('/', async (ctx: Context) => {
    let js = {}

    js = {
        "fulfillmentMessages": [
            {
                "payload": {
                    "richContent": [
                        [
                          {
                            "type": "info",
                            "title": "情報レスポンス",
                            "subtitle": "サブタイトル\nクリックすると別のページに飛ぶよ",
                            "image": {
                              "src": {
                                "rawUrl": "https://www.i-enter.co.jp/images/favicon.ico"
                              }
                            },
                            "actionLink": "https://www.i-enter.co.jp"
                          }
                        ]
                    ]
                }
            }
        ]
    }

    await ctx.json(js)
})
app.start({port: 3000})
```

これを実行すると、Dialogflow Messengerのレスポンスは下記のようになります。
ちょっとオシャレでリッチなデザインが返ってきます。

<img width="397" alt="スクリーンショット 2020-06-23 14.27.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/13014831-d908-b5cb-a0d8-2869dab23d39.png">

## 各レスポンス種類

### 説明レスポンス
一般的なタイトルと内容を明記するものです。

```javascript
js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "description",
                            "title": "説明レスポンス",
                            "text": [
                                "説明1行目",
                                "説明2行目"
                            ]
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="393" alt="s200.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/22e3e735-5cd2-eff5-0b88-ab733fffb734.png">


### 画像レスポンス
画像を返してくれます。svgファイル以外にもjpeg、png画像なども可能です。

```javascript
js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "image",
                            "rawUrl": "https://deno.land/logo.svg",
                            "accessibilityText": "Deno logo"
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="394" alt="s201.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/6e2c5e46-3b23-0845-b613-8f4b29549fc9.png">

### ボタンレスポンス
クリックすると、別のWebページに遷移させることができます。また `event` を使うことで、別途パラメータを渡すこともできます。
アイコンは[マテリアルアイコンライブラリ](https://material.io/resources/icons/?style=baseline)のIDを指定することができます。

```javascript

js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "button",
                            "icon": {
                                "type": "sentiment_satisfied_alt", // 何も指定しなければ矢印アイコン
                                "color": "#FF9800"
                            },
                            "text": "クリックすると別のページに飛ぶよ",
                            "link": "https://www.i-enter.co.jp",
                            "event": {
                                "name": "RESULT",
                                "languageCode": "ja-JP",
                                "parameters": {
                                    "hoge": "ボタンクリック"
                                }
                            }
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="401" alt="s202.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/e9398040-1c46-841a-1b0f-2a773f128205.png">

### リストレスポンス
検索結果などを表示するのに適しているものです。 `divider` を使うことで区切り線をつけることができます。クリックで反応することができます。 `event` にも対応しています。

```javascript

js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "list",
                            "title": "リスト1タイトル",
                            "subtitle": "リスト1 - クリックしてみてね",
                            "event": {
                                "name": "RESULT",
                                "languageCode": "ja-JP",
                                "parameters": {
                                    "hoge": "リスト1をクリック"
                                }
                            }
                        },
                        {
                            "type": "divider"
                        },
                        {
                            "type": "list",
                            "title": "リスト2タイトル",
                            "subtitle": "リスト2 - クリックしてみてね",
                            "event": {
                                "name": "RESULT",
                                "languageCode": "ja-JP",
                                "parameters": {
                                    "hoge": "リスト2をクリック"
                                }
                            }
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="389" alt="s203.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/797218a7-8376-37bc-4c71-49059f39e319.png">

### アコーディオン
クリックすると、メニューが展開されます。

```javascript
js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "accordion",
                            "title": "アコーディオンレスポンス",
                            "subtitle": "サブタイトル",
                            "text": "アコーディオンテキスト"
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="943" alt="s204.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/959826b6-c57f-2850-a778-ade231e62be4.png">

### 候補ワードレスポンス
押してほしい候補をボタンで返してくれます。 `image` を指定するとボタンアイコンを設定することができます。

```javascript

js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "chips",
                            "options": [
                                {
                                    "text": "はい",
                                    "image": {
                                        "src": {
                                            "rawUrl": "https://www.i-enter.co.jp/images/favicon.ico"
                                        }
                                    }
                                },
                                {
                                    "text": "いいえ"
                                }
                            ],
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="398" alt="s205.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/238ef268-bbe7-7791-b420-69aa48d52187.png">

### 組み合わせレスポンス
これまでに紹介したものを組み合わせることができます。

```javascript
js = {
    "fulfillmentMessages": [
        {
            "payload": {
                "richContent": [
                    [
                        {
                            "type": "image",
                            "rawUrl": "https://deno.land/logo.svg",
                            "accessibilityText": "Denoイメージ"
                        },
                        {
                            "type": "info",
                            "title": "組み合わせレスポンス",
                            "subtitle": "今まで紹介したのを組み合わせられるよ",
                            "actionLink": "https://cloud.google.com/dialogflow/docs/integrations/dialogflow-messenger#info_response_type"
                        }
                    ]
                ]
            }
        }
    ]
}
```

<img width="398" alt="s206.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/c96ed285-9a33-58c4-bf52-41fcdc0d9038.png">

## まとめ
いかがでしたでしょうか？リッチなレスポンスを返すことができたでしょうか？
ドキュメントには外部APIを使ったレスポンスに関する情報が一切無かったので、誰かの為になれば幸いです。

システム化のご検討やご相談は弊社までお問い合わせください。
https://i-enter.co.jp/contact/