電話でテイクアウト可能なお店を聞ける電話

#なぜ作ったか
##ハッカソンのサンプルに作りました。以下のストーリーは妄想です
今の世の中、安心して外を出歩くこともできず、Uber Eatsなどで出前を取る方も多かったのではないかと思います。
そして、テイクアウトのお店も増えてきました。スマートフォンがあれば、注文も調べることもできて、とても便利な世の中になりました。
しかし、スマートフォンを持っていないお年寄りはどうだったでしょうか？
調べることもできず、スーパーに買い出しをしにいかなければならなかったのではないでしょうか

#こんなアプローチ

すごくシンプルに、電話かけて、市区町村と料理ジャンルをしゃべれば、テイクアウトできるオススメの１件の住所を教えてくれる。というもの。

<img width="467" alt="ソリューション.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/f6c7b3ad-f09d-788e-48d2-6de624e1e8b5.png">

#準備物
- ぐるなびのAPIキー
    - [こちら](https://api.gnavi.co.jp/api/tools/)から申し込みできます

- Twilioのアカウント
    - [こちら](https://twilio.kddi-web.com/signup/)で作成できます
    - 執筆時点(2020年5月22日)では、[Twilioオンラインコンテスト](https://cloudapi.kddi-web.com/twilio-online-contest-vol1/)が行われており、初めてアカウントを作り、オンラインコンテストに参加する条件でポイントをもらうことができます
- Google Cloud Platformのアカウント（手順は結構省きます）
    - [こちら](https://cloud.google.com/) にアクセスしてください
    - プロジェクトを作成して、Cloud Natural Language APIを有効にする必要があります
    - APIキーの生成を行なってください
#全体の流れ

<img width="588" alt="TwilioStudioFlow.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/f70e08cc-cc17-af04-a915-de3ac0b2365e.png">

1. 電話を着信します。
2. 応答メッセージが流れ、市区町村、料理のジャンルを言います(今回は広島県限定)
3. 音声認識した結果を、Googleの自然言語分析にかけて、市区町村、料理のジャンルの固有名詞を抜き出します
4. ぐるなびのレストラン検索APIを利用して、対象のお店1件を取得します(テイクアウトでき、クレジットカードが使えるお店で検索します）
5. 取得できたお店の名前を音声で読み上げます（一応、住所とTELも取得しています）

#Twilioの基本的な使い方
- 電話番号の取得については、[こちら](https://jp.twilio.com/docs/usage/tutorials/how-to-use-your-free-trial-account) をご確認ください

#自然言語解析で、ぐるなびを検索するためのワードを抽出するためのファンクションを作成する
Google Cloud PlatformのNatural Languageを利用するにあたり、[こちら](https://cloud.google.com/natural-language/docs/quickstart-client-libraries) を見ていただくとよいと思います。

#Twilio「Function」を設定する
Twilioの左側のメニューに「RUNTIME」**Functions**というメニューがあります。
**Functions**を選択してください。
<img width="221" alt="TwilioFunctionNEW.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/a5eb48fe-e071-3863-5ffc-1495372ad605.png">
そうすると、**Functions**の詳細メニューが開きます。~~ベータってなんだろ・・・~~
<img width="220" alt="TwilioFunctionConfigNew.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/17208c29-840d-7a4a-0081-aa3b5a0cd0ff.png">

**設定**をクリックしてください

そうすると、以下の画面が表示されます。

<img width="1059" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/c69047de-dea3-2af5-6cef-a33943ff07db.png">

まず、**Enable ACCOUNT_SID and AUTH_TOKEN**のチェックをONにしてください
<img width="331" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/a171884f-e4e1-0785-75de-9008d4203974.png">

次に、**Functions**で利用する定数を入力します。

<img width="20" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/22b24fa1-15d4-a5d5-919f-9d836e990bcf.png">ボタンを押すことにより、キーを追加できますので、以下を設定してください

- ぐるなびAPIキー
    - Key
        - GNAVI_API_KEY
    - Value 値
        - ぐるなびさんから付与されたAPIキーを入力
- ぐるなびAPIの都市コード（広島県決めうちしてます）
    - Key
        - GNAVI_PREF
    - Value 値
        - PREF34
- Google Cloud Platformのnatural-languageのAPIキー
    - Key
        - GOOGLE_API_KEY
    - Value 値
        - Googleで取得したAPIキー

次に**Functions**で利用する追加のライブラリーの設定です。
**Functions**でHTTPリクエストを使いたい為、request-promiseを活用しています。

<img width="712" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/1a733193-1a5f-e0ea-f40b-82a9562dbdce.png">

<img width="20" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/22b24fa1-15d4-a5d5-919f-9d836e990bcf.png">ボタンを押すことにより、追加できますので、以下を設定してください

- NAME
    - request-promise 
- VERSION
    - 4.2.2

最後に<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/335e1d61-489d-e25b-0267-db926ba5140b.png">ボタンを押せば、設定は完了です
##Twilio「Function」を作成する
次に**管理**をクリックします

<img width="220" alt="TwilioFunctionConfigNew.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/17208c29-840d-7a4a-0081-aa3b5a0cd0ff.png">

以下の画面が表示されますので、

<img width="1056" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/cc7ae14a-1f3b-0bd9-7b7e-e3e7a59bff48.png">

<img width="20" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/22b24fa1-15d4-a5d5-919f-9d836e990bcf.png">をクリックしてください。
 
以下のウィンドウが上がるので、**+Blank**を選択して、<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/5a05abc3-5c49-5eec-37b5-7c9fd315e406.png">をクリックしてください。

<img width="808" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/b68065eb-17ce-d461-f8ea-b695c474ad39.png">

こんなBlankな画面が表示されます。

<img width="1040" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/904fe777-8ffa-c8ed-ebb6-1c2c9033f309.png">

##自然言語解析処理のFunctionを作成する

- FUNCTION NAME
    - NLS
- PATH
    - /nls
- ACCESS CONTROL
    - チェックを外す
- EVENT
    - 何も指定しない

<img width="788" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/4f4d1d98-5cf0-cdcd-c681-0d881f5f9a3b.png">

CODE部分には以下を貼り付けます。

```javascript

const request = require('request-promise');
exports.handler = function(context, event, callback) {
    var options = { 
        method: 'POST',
        url: 'https://language.googleapis.com/v1/documents:analyzeEntities',
        qs: { key: context.GOOGLE_API_KEY },
        headers: { 
            'cache-control': 'no-cache',
            'content-type': 'application/json' 
        },
        json: { 
            document: { 
                type: 'PLAIN_TEXT', 
                content: event.text || '', 
                language: 'ja-JP' },
            encodingType: 'UTF8' },
    };

    request(options)
    .then((parsedBody) => {
        console.log(parsedBody);
        for (const entity in parsedBody.entities) {
            console.log(`${parsedBody.entities[entity].name}`);
        }
        //期待値としては、市区町村名、お店か料理のジャンルの順番でくる
        //エンティティが１つの場合、お店の名前か料理のジャンルの名前しかないという想定
        if (parsedBody.entities.length == 1) {
            callback(null, {freeword:parsedBody.entities[0].name});
        }else if (parsedBody.entities.length > 1){
            var freeword = '';
            var count = 0;
            for (const entity in parsedBody.entities) {
                if(count == 0){
                    freeword = `${parsedBody.entities[entity].name}`;
                }else{
                    freeword = freeword + ',' + `${parsedBody.entities[entity].name}`;
                }
                count++;
            }
            console.log(freeword);
            callback(null, {freeword: freeword});
        }
    })
    .catch((err) => {
        console.error(`problem with request: ${err.message}`);
        callback(err.message);
    });
};
```

最後に<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/335e1d61-489d-e25b-0267-db926ba5140b.png">ボタンを押せば、設定は完了です

##ぐるなびAPIのFunctionを作成する

以下のファンクションを新規で作成する

- FUNCTION NAME
    - GNavi
- PATH
    - /gnavi
- ACCESS CONTROL
    - チェックを外す
- EVENT
    - 何も指定しない
   
<img width="886" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/9e36cb02-7c24-45da-9698-6f6370625158.png">
CODE部分には以下を貼り付けます。

```javascript
const request = require('request-promise');
exports.handler = function(context, event, callback) {
    //console.log(`text: ${event.text} `);
    var options = { 
        method: 'GET',
        url: 'https://api.gnavi.co.jp/RestSearchAPI/v3',
        qs: { keyid: context.GNAVI_API_KEY,takeout: '1', pref: context.GNAVI_PREF,hit_per_page: '1',card:'1',freeword: event.text},
        headers: { 
            'cache-control': 'no-cache',
            'content-type': 'application/json' 
        }
    };

    request(options)
    .then((parsedBody) => {
        console.log(`name: ${JSON.parse(parsedBody).rest[0].name},address: ${JSON.parse(parsedBody).rest[0].address},tel: ${JSON.parse(parsedBody).rest[0].tel}`);
        callback(null, {name:JSON.parse(parsedBody).rest[0].name, address:JSON.parse(parsedBody).rest[0].address, tel:JSON.parse(parsedBody).rest[0].tel});
       
    })
    .catch((err) => {
        console.error(`problem with request: ${err.message}`);
        callback(err.message);
    });

};
```
#電話を受けて、自然言語解析、ぐるなび検索の一連の動作を作る

左側のメニューの「RUNTIME」にある**Studio**をクリックします。
<img width="220" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/8731763e-620b-bef4-a042-06e6a8fea7e8.png">

以下の画面が表示されるので、<img width="20" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/22b24fa1-15d4-a5d5-919f-9d836e990bcf.png">ボタンを押します。

<img width="1042" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/96c9c3fd-79c4-5a10-a169-7623ff6f34e7.png">

以下のウィンドウが表示されるので、好きな名前をつけて<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/b48f8e29-674a-8072-965a-7cc51fbe19c6.png">ボタンを押します。

<img width="602" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/916a8ace-4fc9-aed0-bce2-861c862f714b.png">

以下の画面が表示されるので、**Start from scratch**を選択して、<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/b48f8e29-674a-8072-965a-7cc51fbe19c6.png">ボタンを押します。

<img width="602" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/05988422-0fd0-cd54-b397-50f4a15d2948.png">

そうすると、まっさらなフローが立ち上がります。

<img width="1222" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/a709f430-8c31-251b-81d1-a7feebde4da0.png">

右にあるメニューの中に**VOICE** **Say/Play**をクリックドラックしましょう

<img width="302" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/e4e810a4-af1c-2358-ddbf-4471f4fc9826.png">

フローに以下のように表示されたと思います。

<img width="480" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/9ee22b1a-ee38-0c8f-2a01-ec6b05fb1299.png">

say_play_1と表示されているボックスをクリックし、以下の表示を確認してください。
<img width="333" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/0b5d6575-05ef-c760-b1dd-03ca11b484de.png">
WIDGET NAMEはお好みでいいですが、以下のように設定してください

- WIDGET NAME
    - SayWelcome
- TEXT TO SAY(自動音声で喋らせるワードです）
    - いらっしゃいませ、テイクアウトができるお店をお教えするサービスです

そのほかは以下のように設定しています。
<img width="281" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/6f50bcf0-379b-6dd2-4504-8d364c24b492.png">

<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/4c9bdd54-d4c3-1332-7d6b-f340813bfad0.png">ボタンを押して忘れずに保存してください。

そして、**Trigger**にある**Incoming Call**を**SayWelcome**とクリックドラッグで線を繋げます。以下の感じになるはずです。
<img width="344" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/816bedcf-6bbe-3e79-4971-e47dc5649bcc.png">


次に電話から音声入力してもらい、テキストに変換する部分です。
右にあるメニューの中に**VOICE** **Gather Input on Call**をクリックドラックしましょう

<img width="316" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/667ea22c-3d57-43c7-bdd7-30b7754f055b.png">

これも同様に設定していきます。

<img width="657" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/00c9eb0e-cd83-f7cc-7a41-42fd5d853045.png">

WIDGET NAMEはお好みでいいですが、以下のように設定してください

- WIDGET NAME
    - WhatAreYouLookingFor
- TEXT TO SAY(自動音声で喋らせるワードです）
    - 市区町村、料理のジャンルを言ってください。

その他の設定は以下のようにしています。
<img width="277" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/085f6ea8-7a27-ccd1-8bed-7e72898e78de.png">
<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/4c9bdd54-d4c3-1332-7d6b-f340813bfad0.png">ボタンを押して忘れずに保存してください。

**SayWelcome**の**Audio Complete**から** WhatAreYouLookingFor**に接続します。

<img width="666" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/e74226b1-a09a-c621-d793-93f4b8dc5710.png">

次に、Functionの呼び出しを設定します。右側メニュー**TOOLS & EXECUTE CODE**から**Run Function**をクリックドラックしてください

<img width="326" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/68e2879b-2c21-3dcf-e2fd-f8adef804c0f.png">

フローに**function_1**が配置されました。

<img width="692" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/7bc1986e-ad25-bd96-9985-c02bd66ba764.png">

**function_1**を選択して以下のように設定します。

- WIDGET NAME
    - NLS
- FUNCTION URL(Functionsで作成したFunction名を指定)
    - NLS
    
**FunctionsParameters**の<img width="44" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/d2d89a7b-a0d2-af40-2b37-17d3a2d3c322.png">
をクリックして、以下のKey,Valueを入力します
<img width="278" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/af078054-2ecd-4fc4-ebb2-4d98b36691b8.png">

- Key
    - text
- Value(** WhatAreYouLookingFor**で音声入力されたテキストデータを設定)
    - {{widgets.WhatAreYouLookingFor.SpeechResult}}

以下のように** WhatAreYouLookingFor**の**User Said Something**と**NLS**を接続します。
<img width="439" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/f25f8f13-4cbe-c700-2cb1-0d937c1609b4.png">
<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/4c9bdd54-d4c3-1332-7d6b-f340813bfad0.png">ボタンを押して忘れずに保存してください。

もう一つFunctionの呼び出しを設定します。右側メニュー**TOOLS & EXECUTE CODE**から**Run Function**をクリックドラックしてください

<img width="663" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/72e9ac72-7382-f7f5-35b2-262b345a7231.png">

**function_2**を選択して以下のように設定します。

- WIDGET NAME
    - CallGNavi
- FUNCTION URL(Functionsで作成したFunction名を指定)
    - GNavi
- Key
    - text
- Value(** NLS**で自然言語解析されたテキストデータを設定)
    - {{widgets.NLS.parsed.freeword}}

<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/4c9bdd54-d4c3-1332-7d6b-f340813bfad0.png">ボタンを押して忘れずに保存してください。

**NLS**の**Success**と** CallGNavi**を以下の図のように線を繋ぎます。

<img width="736" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/6cda4d63-f6e2-f026-0275-350cad2e15bf.png">

右にあるメニューの中に**VOICE** **Say/Play**をクリックドラックしましょう

<img width="302" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/e4e810a4-af1c-2358-ddbf-4471f4fc9826.png">
say_play_2と表示されているボックスをクリックし、以下の表示を確認してください。
<img width="333" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/0b5d6575-05ef-c760-b1dd-03ca11b484de.png">
WIDGET NAMEはお好みでいいですが、以下のように設定してください

- WIDGET NAME
    - END
- TEXT TO SAY(自動音声で喋らせるワードです）
    - お店は{{widgets.CallGNavi.parsed.name}}でいかがでしょうか？

<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/4c9bdd54-d4c3-1332-7d6b-f340813bfad0.png">ボタンを押して忘れずに保存してください。

** CallGNavi**の**Success**と** END**を以下の図のように線を繋ぎます。

<img width="587" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/9e6986bc-a374-e174-41a6-4ffdd5127338.png">

これで完成したので、上部にある<img width="70" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/34f358af-c142-c9dd-1d31-dff116961d2b.png">を押せば作業完了です。

#電話番号とFlowを紐づける

右のメニューにある**#Phone Numbers**を選択します

<img width="233" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/a9bfd8a2-043a-9990-e6e1-1e9ef3ab9612.png">

保有している電話番号をクリックすると、以下の表示が出てきます。
**A CALL COMES IN**を***Studio Flow**に変更し、左のプルダウンのところを作成したFlowを設定します。

<img width="702" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/ec6f40e5-dabd-9b56-96cd-b8818dfb498b.png">

最後に<img width="50" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123800/afebbc0d-4deb-9a02-2502-235b7f43bf73.png">を押せば完成です。

あとは電話をかければ、自動的に作成したフローに接続されますので、試してみてください。