Dialogflow(旧:API.AI) のイベントをCloud functionsで受け取りユーザーにテキストを返してみる #dialogflow

#API.AIのイベントを受け取る
API.AIではWebhookを設定することが出来ます。これによりユーザーから届いたリクエストを外部のサーバーで処理することができます。今回は[Actions on Google](https://developers.google.com/actions/)のイベントをCloud functionsで受取り、テキストをユーザーに返してみます。

###今回使用するサービス
- [API.AI](https://api.ai/)
- [Actions on Google](https://developers.google.com/actions/)
- [CLOUD FUNCTIONS](https://cloud.google.com/functions/)

##API.AIのプロジェクトを用意
今回は[Google I/O 2017 API.AIのセッションのベーグル注文を日本風で試してみる](http://qiita.com/flatfisher/items/797c304f2013dce48e87)で作成したプロジェクトをそのまま使用したいと思います。

###Actions on Gooleの有効化
IntegrationsのActions on Gooleのチェックを入れ有効化し、Settingからプロジェクトを作成します。Add actions to your appで「USE API.AI」か「Use Actions SDK」のどちらかを選択する画面に来たら「USE API.AI」を選択し画面の内容を確認したら「OK」で戻ります。
***※日本語非対応のためのシュミレーターは試せません***

##Cloud functionsの準備
- [Node.JSの導入](https://nodejs.org/en/)
- [最新のCloud SDKを導入](https://cloud.google.com/sdk/docs/)
- [Google Developer console](https://console.cloud.google.com/project)でプロジェクトを選択
- [課金を有効にする](https://support.google.com/cloud/answer/6293499#enable-billing)
- [Cloud functionsを有効化する](https://console.cloud.google.com/apis/api/cloudfunctions.googleapis.com/overview) 
- [Cloud storageのバケットを用意する](https://cloud.google.com/storage/docs/cloud-console#_creatingbuckets)
    - バケット名を控えておいてください
    - このバケットにfunctionsのコードをアップロードします
    - 私は「order-sushi」というバケットを作成しました
- プロジェクト用のディレクトリを作成する
- プロジェクトのディレクトリ内で``` gcloud init ```を実行しGCPプロジェクトを選択する

##index.jsとpackage.jsonを用意
プロジェクト用のディレクトリに ```index.js```と```package.json```を作成します。

```js:index.js
'use strict';

process.env.DEBUG = 'actions-on-google:*';
const App = require('actions-on-google').ApiAiApp;

//API.AI actions
const ORDER_SUSHI = 'order.sushi';

exports.ordersushi = (request, response) => {
  const app = new App({request, response});
  console.log('Request headers: ' + JSON.stringify(request.headers));
  console.log('Request body: ' + JSON.stringify(request.body));

  // Fulfill action business logic
  function orderSushiHandler (app) {
    // Complete your fulfillment logic and send a response
    console.log('Requested ' + ORDER_SUSHI);
    app.ask('Sushi requested!!');
  }

  const actionMap = new Map();
  actionMap.set(ORDER_SUSHI, orderSushiHandler);

  app.handleRequest(actionMap);
};
```
**ORDER_SUSHI には Intentsのアクション名を入れます**

<img width="500" alt="Screen Shot 0029-05-30 at 7.55.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/2ae25812-b1b1-4f49-5a41-63a7ad41d143.png">

```json:package.json
{
  "name": "sushi-order-demo",
  "description": "This is your Action's webhook",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "~6.0"
  },
  "scripts": {
    "lint": "semistandard --fix \"**/*.js\"",
    "start": "functions deploy ordersushi --trigger-http",
    "deploy": "gcloud beta functions deploy ordersushi --trigger-http --stage-bucket order-sushi"
  },
  "dependencies": {
    "actions-on-google": "^1.0.0"
  },
  "devDependencies": {
    "semistandard": "^9.1.0"
  }
}
```

##プロジェクトをアップロードする
以下のコマンドでプロジェクトをCloud Storageにアップロードします。

```text:terminal
gcloud beta functions deploy ordersushi --trigger-http --stage-bucket order-sushi
```

アップロードが終わるとURLが返ってくると思います。そのURLを控えておいてください。

```
httpsTrigger:
url: https://us-central1-yourproject.cloudfunctions.net/ordersushi
```

##API.AIにWebhookを設定する
###Webhookの有効化
横のメニューから「Fulfillment」を選択し、Webhookを有効化します。
そして先ほどのURLを入れます。

<img width="500" alt="Screen Shot 0029-05-30 at 8.07.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/9b3a0494-3e69-67dc-8b61-51ad12eb42df.png">

###Webhookの設定
Intents の Sushi OrderのUse webhookにチェックを入れます。

<img width="500" alt="Screen Shot 0029-05-30 at 8.11.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/13ba8ae5-f5f1-81e8-3baf-54541260899c.png">

##テストしてみよう
Actions on Gooleでテストしたいところですが、まだシュミレーターが日本語非対応なのでAPI.AIのシュミレーターでテストしてみましょう。

###Text Responseの削除
テスト前にText Responseの「へい、かしこまりました！」は削除します。代わりにfunctionsで「Sushi requested!!」を返します。

###実行
右のシュミレータで実行します。「寿司食べたい、さび有り、まぐろ」と入力し、注文が確定すると。。。

<img width="337" alt="Screen Shot 0029-05-30 at 8.19.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/114922/8b0f2a75-8918-855e-0063-b51c82c8c1c4.png">

ちゃんと「Sushi requested!!」が返されましたね！

###ログの確認
以下のコマンドでfunctionsのログを見る

```text:terminal
gcloud beta functions logs read ordersushi
```
**Requested order.sushi**が確認できました！

```text:terminal
I ordersushi  xxxxxxxx  2017-05-29 23:15:38.465  Requested order.sushi
````