Actions SDKだけで始める、Google Home超入門（日本語対応も）

# はじめに
こんばんは！ Advent Calendar12日目担当で、今年初参加の新人のODAです。
最近スマートスピーカー、流行ってますよね。
Google Homeに続きAmazon Alexaも日本に上陸したのをはじめとして、様々なスマートスピーカーが世に出ています。
私自身、スマートスピーカーの有用性については結構懐疑的だったのですが、いざ使ってみると便利！
そして便利と言う点以上に、会話してる感じがなんか使ってて楽しいです！一人でも寂しくない！
今ではGoogle Homeは手放せません。

でもせっかくエンジニアなのに、使っているだけじゃもったいないですよね。
自分でオリジナルの会話ができるアプリ(Google Action)を作ってみたいと思います。
私自身はgoogleのクラウドサービスや、他のグーグル製品向けのアプリはあまり作ったことがないので、初めてActionを作ってみようと思う人の助けに慣れたらと思い記事を書きます。
あと、公式のページが軒並み英語なので、挫折しそうな人も参考にしていただけると嬉しいです。（私自身何度も挫折しそうになりました）

# 前提
* Google Homeのセットアップは終わっていて、アカウントと紐付いている

# プロジェクトの作成
https://console.actions.google.com/ に繋いで、プロジェクトを作成します。
すると以下のような選択肢が出てくると思います。
<img width="600" alt="Screen Shot 2017-12-12 at 23.38.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/69504/e9050e6f-f5ff-d4be-004e-be01012625b9.png">
上３つが1から自分のActoinを作るもので、下３つはあらかじめ決められた入力フォームに従って入力すると自動的にサンプルが作れるというものです。
ここは入門だからサンプルから... と行きたいところですが、残念ながら**日本語に対応していません**...

と言うわけで選択肢が３つになったわけですが、ここでは基本となるActions SDKのみを用いた方法について書きたいと思います。
他の方法での入門は良い記事がたくさんあるので、Qiitaで探すと良いと思います。

Actions SDKをクリックすると、以下のようなダイアログが出てきます。

<img width="600" alt="Screen Shot 2017-12-12 at 23.43.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/69504/92b2e329-eb22-69d3-ad8e-30a2fe215534.png">

Update appの下にコマンドが出ていて目が惹かれますが、これを使うのは最後です。まずは、Setupのリンクに飛びます。
このリンク先ですが、全部英語な上に結構不親切なドキュメントなので、読むのに結構忍耐が必要です。
最初の方に出てくる、gactionsのインストールは必須なので、それだけは行う必要があります。
なので、読み解いた結果を簡単に書きます。

# Action本体のプログラム作成方法
Action作成には大きく分けて
* Action本体の定義
* Actionでユーザーに応答するためのFunction
の二つが必要です。この二つについて説明します。

### Action定義
以下のコマンドで、初期設定のactions定義のファイルを生成します。
```$ gactions init```

今回は、デフォルトから変更して、以下のようなaction.jsonを作成しました。

```json:actoin.json
{
  "locale": "ja",
  "actions": [
    {
     "name": "MAIN",
     "intent": {
       "name": "actions.intent.MAIN"
     },
     "fulfillment": {
       "conversationName": "myFulfillmentFunction"
     }
    }
  ],
  "conversations": {
    "myFulfillmentFunction": {
      "name": "myFulfillmentFunction",
      "url": "<エンドポイントURL>"
    }
  }
}

```

重要なのがconversationsの部分と、最初のlocaleの部分です。
conversationsの部分で、対話に用いるサーバーのエンドポイントを指定しています。サーバーのエンドポイントは後ほど作成したものを入れます。
localeの指定はチュートリアルページや初期設定では行われていないのですが、日本語対応する場合やっておかないと、後々日本語を追加する時に意味のわからないエラーメッセージに遭遇するので必ず追加しましょう。
これで私は1時間以上持っていかれました...

### Function
GoogleのサービスであるFirebaseを用いて、自分でサーバーを立てなくても応答を返すことができます。
npmでfirebase-toolsをインストールし、以下のコマンドを打ちます。

```bash
$ firebase init functions
```
コマンド途中でプロジェクトと紐付けるか聞かれると思うので、Google Home用のプロジェクトと紐づけます。
生成されたディレクトリの、functions/index.jsをいじります。

```javascript:functions/index.js
const functions = require('firebase-functions');
const ActionsSdkApp = require('actions-on-google').ActionsSdkApp;

exports.testFunc = functions.https.onRequest((req, res) => {
  const app = new ActionsSdkApp({request: req, response: res});

  function mainIntent (app) {
    const inputPrompt = app.buildInputPrompt(true, '<speak>こんにちは<break time="1"/> ' +
          '数をこんな風によみあげます ' +
          '<say-as interpret-as="ordinal">123</say-as>. 数を言ってください.</speak>',
          ['聞こえませんでした']);
    app.ask(inputPrompt);
  }

  function rawInput (app) {
    if (app.getRawInput() === 'bye') {
      app.tell('Goodbye!');
    } else {
      const inputPrompt = app.buildInputPrompt(true, '<speak>あなたは, <say-as interpret-as="ordinal">' +
        app.getRawInput() + '</say-as>と言いましたね</speak>',
          ['聞こえませんでした']);
      app.ask(inputPrompt);
    }
  }

  const actionMap = new Map();
  actionMap.set(app.StandardIntents.MAIN, mainIntent);
  actionMap.set(app.StandardIntents.TEXT, rawInput);

  app.handleRequest(actionMap);

});

```
これはgoogleのページから持ってきたサンプルをちょっと変更したものです。
プログラムの詳細は、ドキュメントを読んで解読してください。（すいません）
変更したあと、このnodeをデプロイします。

```bash
$ cd functions
$ npm install
$ npm install acions-on-google
$ firebase deploy --only functions
```
うまくいくと、以下のようなメッセージが出るはずです。

```bash
Function URL (testFunc): https://us-central1-xxxxxxxx.cloudfunctions.net/testFunc
```
これが会話のために使う、エンドポイントのURLになります。これを上で書いた<エンドポイントURL>に入れます。

# Actionのデプロイ
いよいよ準備が整ったので、デプロイします。

```bash
$ gactions update --action_package action.json --project <プロジェクト名>
```
プロジェクト名は、firebase listコマンドをうち、でてきた中から今回作成したプロジェクト名から始まるものを選びます。
一回認証が必要になりますが、もう一回コマンドを打てば、無事デプロイできるはずです。
最後に画面に戻り、日本語の追加を行います。以下のEDITから、飛んだ先の画面で日本語を追加します。
<img width="560" alt="Screen Shot 2017-12-13 at 00.15.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/69504/ad4e67e7-1f7f-7f16-6d0e-e18b0dce8326.png">
設定項目が足りないとエラーと表示されますが、テストをする分には問題ありません。
ただ、設定項目はなくても日本語を選択だけしておかないと日本語で使えないので注意が必要です。


# テスト
ついにテストを行います。画面下のTEST DRAFTをクリックすると、テストを行うことができます。
画面左から、PCでテストを行うことができます。
<img width="250" alt="Screen Shot 2017-12-13 at 00.18.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/69504/cfda60a5-d935-584f-d19b-102ab83d3070.png">
ついに会話することができました！（色々おかしいのは気にしないでください。）
さらにGoogle Homeに向かって話せば、この時点で既に実機テスト出来るようになっています！素晴らしい！

# 終わりに
会話できるまでが結構大変ですね。
Amazon Echoみたいに、Lambdaテンプレートみたいなの用意してくれたらいいんじゃないかと思うのですが...
何はともあれ、これで好きな会話をgoogle homeと出来るようになりました。
話し方や声質も自在に変えられるので、自分だけのアシスタントを作るのも楽しいのではないでしょうか。