Lambda不要！電話を発信するAlexaスキルを作る

## はじめに
Alexaは『声』という直感的なインターフェイスを使って様々なサービスを利用することができます。
自分で『スキル』を構築することで拡張でき、オリジナルのサービスをAlexaを通して利用することができます。

Twilioは電話、SMS、FAX、LINE、チャットなどのコミュニケーション用APIを提供するサービスです。

ここではTwilioを使って電話するAlexaスキルの作り方を紹介します。Lambdaを使わないのでAWSアカウントは必要ありません。

## 前提
この記事では以下を前提としています。

- [Alexa開発者アカウント](https://developer.amazon.com/ja/alexa)を持っている
- [Twilioアカウント](https://jp.twilio.com/try-twilio/kddi-web)を持っている

## 1. 電話番号取得
電話発信するにはTwilioで電話番号を購入する必要があります。[Twilioコンソール](https://jp.twilio.com/console)にログインします。

左のメニューから[『Phone Numbers』を選択し、『番号の管理』から『番号を購入』（+ボタン）](https://jp.twilio.com/console/phone-numbers/incoming)を選択します。

<img width="776" alt="phone_number_menu.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/3f83d783-99c0-46ae-bcd1-b58d0ea8e135.png">

Twilioは100カ国以上の電話番号を購入できます。ここでは日本の電話番号を購入しましょう。
COUNTRYがJapanであることを確認し検索ボタンを押します。

<img width="1035" alt="buy-phone-number.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/d1c63691-ff3c-95d3-0e40-efb2a19b43e3.png">

購入できる電話番号のTYPEはトールフリー(いわゆるフリーダイヤル)とローカルがあります。ローカルを購入しましょう。

<img width="1361" alt="phone-numbers.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/9751da52-91d6-4001-eb43-a79f7db6e8c7.png">

## 2. Alexaスキルを作る
[Alexaデベロッパーコンソール](https://developer.amazon.com/ja/alexa)にサインインします。
『スキルを作成』ボタンをクリックし、スキル作成画面に遷移します。

<img width="1336" alt="skill_create.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/01e82ef3-b26f-e3c0-edfa-61cf4acf61ce.png">

スキル名、デフォルトの言語（日本語）、スキルに追加するモデル（カスタム）を選択し、『スキルを作成』ボタンをクリックすると、新しいスキルが作成できます。

<img width="975" alt="alexa-new-skill.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/a988a753-2f7f-e1cf-07fe-c8cfbff744ca.png">

スキル名に「MakingCalls」と入力して「スキルを作成」ボタンを押してください。

## 3. スキルの呼び出し名、インテントを設定
### 3-1. 呼び出し名
スキルの管理画面で左のメニューから『呼び出し名』を選択します。

<img width="1340" alt="skill_call_name.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/93a4fabf-17d1-df83-2551-454e7f6ec558.png">

呼び出し名は、『アレクサ、〇〇で■■して』とAlexaに話しかけたときの『〇〇』にあたる部分です。
好きな名前を入力してください（今回は『かけるくん』とします）。入力したら、『モデルを保存』ボタンで入力値を保存します。

### 3-2. インテント
左メニューのインテントで『追加』をクリックします。

インテントは『アレクサ、〇〇で■■して』とユーザーからリクエストを受けたあと、そのリクエストに対応して行われる処理のことを指します（詳細については、[ユーザーによるカスタムスキルの呼び出し](https://developer.amazon.com/ja/docs/custom-skills/understanding-how-users-invoke-custom-skills.html)をご参照ください）。

『追加』をクリックするとインテントの名前入力欄が表示されます。
インテントの名前はこの後作成するTwilio Functionのコードでも使用しますので、アルファベットの大文字、小文字、アンダースコアのみを使い、わかりやすい名前をつけてください（今回は『MakingCalls』とします）。
名前の入力後、『カスタムインテントを作成』をクリックします。

### 3-3. サンプル発話
カスタムインテントの作成後、そのインテントの詳細設定画面に遷移します。ここでは『サンプル発話』を入力します。
サンプル発話は『アレクサ、〇〇で■■して』の『■■して』の部分にあたります。サンプル発話に登録した内容がAlexaにリクエストされると登録されているインテントが実行されます。

ここではサンプル発話として下記を入力します。

- 電話して
- 電話をして
- 電話かけて
- 電話をかけて

登録後、『モデルを保存』ボタンで入力値を保存します。

## 4. Twilio Functionで電話発信

Twilioコンソールで左メニューから[『Runtime』>『Functions』](https://jp.twilio.com/console/runtime/functions/manage)を選択します。
[Functionsの『Configure』メニュー](https://jp.twilio.com/console/runtime/functions/configure)を選び『Enable ACCOUNT_SID and AUTH_TOKEN』にチェックを入れます。

<img src="https://vigorous-crush-3355.twil.io/assets/function_configure_enable.png">

### 4-1. Environmental Variables

『Environmental Variables』に＋をクリックしてALEXA_APP_ID_FOR_CALL、TWILIO_CALL_FROM_NUMBER、TWILIO_CALL_TO_NUMBERの3つの値を登録します。

<img src="https://vigorous-crush-3355.twil.io/assets/function_conficure_env.png">

#### 4-1-1. ALEXA_APP_ID_FOR_CALL

AlexaのスキルIDを入力します。スキルIDはAlexaデベロッパーコンソールのAlexaスキル一覧画面で『スキルIDの表示』から取得できます。

※下記画像はサンプルです。MakingCallsのスキルIDを取得してください。
<img src="https://vigorous-crush-3355.twil.io/assets/skill_list.png">

#### 4-1-2. TWILIO_CALL_FROM_NUMBER

手順1で取得したTwilioの発信用電話番号を入力します。
なお、このとき電話番号は+81からはじまる[E.164形式](https://ja.wikipedia.org/wiki/E.164)で入力します。E.164形式の電話番号は、Twilioコンソールで『Phone Numbers』>『番号の管理』で該当番号をクリックし、表示される詳細画面の『電話番号』で確認できます。

#### 4-1-3. TWILIO_CALL_TO_NUMBER

発信先の電話番号です。同じくE.164形式で入力します。例えば080-1234-5678なら+818012345678と入力します。
自分の電話番号を登録してみましょう。

### 4-2. Dependencies

DependenciesはFunctionのnpmです。Nameに『alexa-sdk』、バージョンに『1.0.25』と入力します。
バージョンはコマンドラインからnpm view alexa-sdk versionで調べることができます。

```shell
$ npm view alexa-sdk version
1.0.25
```
<img src="https://vigorous-crush-3355.twil.io/assets/function_configure_dependency.png">

入力が終わったら『Save』ボタンをクリックして入力値を保存します。

### 4-3. 電話するコード

Functionコンソールで『+』ボタンをクリックしFunctionを作成します。タイプは『Blank』を選び『Create』をクリックします。

<img src="https://vigorous-crush-3355.twil.io/assets/function_create.png">

『FUNCTION NAME』に「MakingCalls」、『PATH』に「/MakingCalls」を入力します。

<img width="891" alt="function-name-and-path.png" src="https://qiita-image-store.s3.amazonaws.com/0/268190/fbe1be07-9f75-732e-37e8-c20a1c98ec35.png">

『ACCESS CONTROL』と『EVENT』は特に入力する必要はありません。
『CODE』の部分には以下のコードを貼り付けます。

```javascript
const Alexa = require('alexa-sdk');

const HELP_MESSAGE = '電話を発信できます。かけるくんで電話してと言ってみてください';
const HELP_REPROMPT = '何ができますか?';
const MESSAGE_BODY = 'こんにちは！ Alexaから電話です';
const SENT_MESSAGE = '電話しました。';
const STOP_MESSAGE = 'さようなら';

const handlers = {
    'LaunchRequest': function() {
        this.emit(':ask', HELP_MESSAGE, HELP_MESSAGE);
    },
    'MakingCalls': function() {
        // 電話発信
        // https://jp.twilio.com/docs/voice/make-calls
        const client = this.context.getTwilioClient();
        client.calls.create({
                url: 'https://' + this.context.DOMAIN_NAME + '/MakingCalls?message=' + encodeURIComponent(MESSAGE_BODY),
                from: this.context.TWILIO_CALL_FROM_NUMBER,
                to: this.context.TWILIO_CALL_TO_NUMBER
            })
            .then(call => {
                this.response.speak(SENT_MESSAGE);
                this.emit(':responseReady');
            })
    },
    'AMAZON.HelpIntent': function() {
        const speechOutput = HELP_MESSAGE;
        const reprompt = HELP_REPROMPT;

        this.response.speak(speechOutput).listen(reprompt);
        this.emit(':responseReady');
    },
    'AMAZON.CancelIntent': function() {
        this.response.speak(STOP_MESSAGE);
        this.emit(':responseReady');
    },
    'AMAZON.StopIntent': function() {
        this.response.speak(STOP_MESSAGE);
        this.emit(':responseReady');
    },
    'Unhandled': function() {
        this.response.speak(HELP_MESSAGE);
        this.emit(':responseReady');
    },
};

exports.handler = function(context, event, callback) {
    if (event.message) {
        // event.messageをTwilioが発声
        // https://jp.twilio.com/docs/voice/twiml/say
        let sayParams = {};
        sayParams.language = 'ja-JP';
        sayParams.voice = 'alice';

        const twiml = new Twilio.twiml.VoiceResponse();
        twiml.say(sayParams, event.message);
        callback(null, twiml);
    } else {
        const alexa = Alexa.handler(event, context, callback);
        alexa.appId = context.ALEXA_APP_ID_FOR_CALL;
        alexa.registerHandlers(handlers);
        alexa.execute();
    }
};
```

コード内の'MakingCalls'が手順3で作成したインテントに対応する処理です。

終わったら『Save』ボタンをクリックしてFunctionを保存します。デプロイ開始メッセージの数秒後にデプロイ完了メッセージが表示されます。保存してもすぐに反映されないことにご注意ください。

『PATH』のURLをコピーしてメモしておきます。このURLは手順5で使用します。

## 5. AlexaスキルとTwilio Functionをつなぐ
Alexaデベロッパーコンソールで左メニューの『エンドポイント』を選択します。

『サービスのエンドポイントの種類』から『HTTPS』を選択し、『デフォルトの地域』に手順4で作成したFunctionのURLを入力します。
証明書は『開発用のエンドポイントは、証明機関が発行したワイルドカード証明書を持つドメインのサブドメインです』を選択します。

<img src="https://vigorous-crush-3355.twil.io/assets/function_endpoint.png">

入力が終わったら『エンドポイントを保存』ボタンで入力値を保存します。

## 6. テスト
Alexaデベロッパーコンソールの上部メニューで『ビルド』を選択し『モデルをビルド』をクリックします。

<img src="https://vigorous-crush-3355.twil.io/assets/alexa_skill_build.png">

ビルド完了までには数分かかり、完了したらメッセージが表示されます。
ビルドが完了したら『テスト』を選択します。もしスキルのテストが無効になっていた場合は有効化します。
入力欄に『アレクサ、{呼び出し名}で{サンプル発話}』と入力します。例えば、『呼び出し名』に『かけるくん』、『サンプル発話』に『電話して』と入力していたら、『アレクサ、かけるくんで電話をして』と入力します。

電話が掛かってきましたか？

これで電話するAlexaスキルの作成は完了です。

## おわりに
Alexaスキル開発にTwilioを利用し、さまざまなコミュニケーション機能を是非組み込んでみてください。

ほかにもいくつかの例を用意しました。参考になれば幸いです。

[AlexaにTwilioを使用してコミュニケーション機能を組み込む](https://qiita.com/twilioforkwc/private/2e31347acda73e4ba1a8)