Edited at
TwilioDay 1

Twilio FunctionsとStudioを使って連続架電を行う


はじめに

Twilioを使うと連続架電が簡単にできます。

詳細は過去のこちらの記事を御覧ください。

今回は、Twilio FunctionsとStudioを使って、条件が満たされるまで連続で架電する仕組みを作ってみましょう。

シナリオとしては、サーバー障害などをトリガーとして、担当者が応答するまで複数の担当者に架電をしていくようなものを想定しています。

なお、留守番電話が応答してしまうことを想定して、相手が応答したら対応可能かを問い合わせるようにしています。


手順

今回の記事の手順は大きく次の5つになります。


  1. 電話番号を購入します(この記事では割愛します)。

  2. Flowを呼び出すFunctionsを作成します。

  3. 架電するFlowを作成します。

  4. 環境変数を設定します。

  5. テスト


手順1. 電話番号を購入します

今回の記事を実行するためには、アップグレード済みのTwilioアカウントが必要になります。

詳しい手順については、以下の動画を参考にしてください。

ここでは、050番号を一つ購入したものとして先に進めます。


手順2. Flowを呼び出すFunctionsを作成します


  • 管理コンソールの左側のスライドメニューからRuntime > Functions > Manageを選択します。


  • Create a new Functionボタンを押すか、赤いプラスアイコンを押してFunctionsを新規作成していきます。

  • Function名は、「SerialCallStudio」とします。

  • PATH名は、「/serial-call-studio」とします。PATH欄の右側にあるコピーアイコンを押して、このFunctionのPathをメモ帳などに記録しておきます。後ほどテストのときに使用します。

    SerialCallStudio_Function.png


  • CODE欄に書かれているコードをすべて削除して、以下のコードを貼り付けます。架電先リストの内容をご自分の環境(かけたい相手の番号)に変更してください。なお、リストの登録数には制限はありませんので、必要に応じて増やしたり減らしたりしてください。


/**

* Studioを連携させた連続架電 - serialCallStudio
*
* @param idx リストインデックス
* @param loop ループ回数
*/

// 架電先リスト(発信したい電話番号のリストをE.164形式で記述します)
const callList = {
"携帯1": "+818012345678",
"携帯2": "+819012345678",
"携帯3": "+819011111111",
"携帯4": "+819022222222",
};
// ループ回数(1以上の整数、1ならループしない)
const maxLoop = 2;

exports.handler = function(context, event, callback) {
// カウンター関連
let idx = event.idx || 0; // インデックスパラメータを取得
let loop = event.loop || 1; // ループパラメータを取得
if (idx >= Object.keys(callList).length) { // リストの最後まで到達
idx = 0; // インデックスは0に戻す
if (loop >= maxLoop) { // ループ回数が最大値を超えたので終了
callback(null, "Call count was expired.");
} else {
loop++; // ループ回数をインクリメント
}
}

// 架電先電話番号
let number = callList[Object.keys(callList)[idx]];
idx++; // インデックスをインクリメント

// 架電するStudioフローを呼び出す
const client = context.getTwilioClient();
client.studio.flows(context.FLOW_SID).engagements.create({
to: number,
from: context.FROM_NUMBER,
parameters: JSON.stringify({
idx: idx,
loop: loop,
})
})
.then((call) => {
callback(null, "OK");
})
.catch((error) => {
callback(error);
});
};



  • Saveボタンを押して、設定を保存します。しばらくするとデプロイ完了のメッセージが表示されれば完了です。


手順3. 架電するFlowを作成します


  • 管理コンソールの左側のスライドメニューから、Studioを選択します。

  • 赤いプラスアイコンをクリックするか、「Create a new flow」を選択して、新しいフローを作成します。


  • FLOW NAMEに「SerialCallStudio」と入力して、NEXTボタンを押します。

  • キャンパスが表示されたら、WIDGET LIBRARYからMake Outgoing Callをキャンパス上にドラッグアンドドロップします。Make Outgoing Callは、Twilioから発信をするためのウィジェットです。

  • TriggerボックスのREST APIと、今配置した「call_1」ボックスを結合します。

    スクリーンショット 2018-05-29 12.05.51.png


  • call_1ウィジェットを選択して、WIDGET NAMEを「Call」に変更します。これ以外の項目は変更する必要はありません。


  • SAVEボタンを押します。


  • 続いて、WIDGET LIBRARYからGather Input on Callをキャンバス上にドロップします。


  • CallウィジェットのAnsweredと、今ドロップした「gather_1」を結合します。Answeredは、相手が応答したときのイベントとなります。


  • gather_1ウィジェットを選択して、WIDGET NAMEを「Gather」に変更します。


  • TEXT TO SAY欄に応答した相手に伝えたいメッセージを記述します。今回は「異常が発生しました。対応は可能でしょうか?「はい」か、「いいえ」で応答してください。」と入力しておきます。


  • LANGUAGEのプルダウンから「Japanese」を選択し、MESSAGE VOICEのプルダウンリストからお好きな声を選択します。


  • SPEECH RECOGNITION LANGUAGEのプルダウンリストから「Japanese (Japan)」を選択します。似たような言語が他にもあるので、間違えないようにしてください。ここの選択を間違えると音声認識がうまく動作しません。


  • SPEECH RECOGNITION HINTS欄には、「はい, いいえ」と入力しておきます。SPEECH RECOGNITION HINTSは、音声認識に関するヒントを指定する項目で、発話する内容が予め決まっているような場合は音声認識の精度が向上します。

    スクリーンショット 2018-11-29 12.38.40.pngスクリーンショット 2018-11-30 17.04.43.png


  • ここまで設定ができたら、SAVEボタンを押して設定を保存します。


  • 続いて、WIDGET LIBRARYからSplit Based On...をキャンバス上にドロップします。Split Based On...ウィジェットは、条件分岐を設定するためのものです。今回は、直前のGatherウィジェットで発話された内容(「はい」か「いいえ」)を判定するために使用します。


  • GatherウィジェットのUser Said Somethingと、今ドロップしたsplit_1ウィジェットを結合します。


  • split_1ウィジェットを選択して、WIDGET NAMEを「YesOrNo」に変更します。


  • VARIABLE TO TEST欄をクリックして、表示されたリストの中からGatherSpeechResultを選択します。

    スクリーンショット 2018-11-29 12.47.48.png


  • 続いて、同じウェジェットのTransitionsタブに移動し、NEW CONDITIONの右側に表示されている赤いプラスアイコンを押します。

    スクリーンショット 2018-11-29 12.51.02.png


  • 比較条件のプルダウンリストは「Equal to」、比較対象欄に「はい」と入力してSet conditionと書かれた赤いリンクをクリックして設定を保存します。

    スクリーンショット 2018-11-29 14.15.41.png


  • ウィジェットのプロパティページを上にスクロールして、先ほどと同じくNEW CONDITIONの右側に表示されている赤いプラスアイコンを押します。


  • 比較条件のプルダウンリストは「Equal to」、比較対象欄に「いいえ」と入力してSet conditionと書かれた赤いリンクをクリックして設定を保存します。この作業によりYesOrNoウィジェットに「はい」と「いいえ」の接続ポイントが追加されたことがわかります。

    スクリーンショット 2018-11-29 14.21.30.png


  • 続いて、WIDGET LIBRARYからSay/Playをキャンバス上にドロップします。


  • YesOrNoウィジェットのIf value equal_to はいと、今ドロップしたsay_play_1ウィジェットを結合します。


  • say_play_1ウィジェットを選択して、WIDGET NAMEを「SayYes」に変更します。


  • TEXT TO SAY欄に、「ありがとうございます。よろしくお願いいたします。」と入力します。


  • LANGUAGEのプルダウンリストから「Japanese」を選択し、MESSAGE VOICEはお好きな音声を選択します。


  • Saveボタンを押して、設定を保存します。


  • 続いて、WIDGET LIBRARYからRun Functionをキャンバス上にドロップします。


  • YesOrNoウィジェットのIf value equal_to いいえと、今ドロップしたrun_function_1ウィジェットを結合します。


  • run_function_1ウィジェットを選択して、WIDGET NAMEを「CallNext」に変更します。


  • FUNCTION URLのプルダウンリストから、先程作成した「SerialCallStudio」を選択します。


  • Function Parametersの右側にあるAddをクリックし、以下の2つの値を設定します。


KEY
VALUE

idx
{{flow.data.idx}}

loop
{{flow.data.loop}}

スクリーンショット 2018-11-30 17.20.08.png


  • Saveボタンを押して、設定を保存します。


  • YesOrNoウィジェットのNo Condition Matchesと、Gatherウィジェットも結合します。これにより、「はい」や「いいえ」以外を回答されたときに、再度応答を促すことができます。


  • GatherウィジェットのNo Inputと、CallNextウィジェットを結合します。


  • CallウィジェットのBusyと、No AnswerCall Failedを、すべてCallNextウィジェットに結合します。これにより、架電先が電話に出ない場合や話し中の場合には、次の人に架電されるようになります。


ここまで作成すると、次のようなフローが出来上がります。

スクリーンショット 2018-11-30 17.29.45.png


  • 最後に画面上部にある赤いPublishのボタンを押します。

  • 確認のダイアログが表示されるので、Publishボタンを押します。

スクリーンショット 2018-07-26 10.28.37.png


手順4. 環境変数を設定します


  • 管理コンソールのスライドメニューからRuntime > Functions > Configureを選択します。


  • Environment Variablesの赤いプラスアイコンを2回押して、以下の2つの変数を追加してください。

Key
Value

FROM_NUMBER
購入した050番号(E.164形式)

FLOW_SID
先程作成したStudioフローのSID(FWから始める文字列)



  • Saveボタンを押して、設定を保存します。


手順5. テスト


  • 手順2で作成したFunctionのPathをブラウザで開きます。

  • Function内で指定した電話番号に対して電話がかかることを確認します。


まとめ

実際の利用シーンでは、テストで使用したURLを起動するようにすればOKです。

ただし、このままではURLがバレてしまうと、他の人が電話をできるようになってしまいますので、以下の記事を参考にセキュリティ対策をされることをおすすめします。

Twilio Functionを外部からセキュアに呼び出す

StudioをFunctionsから呼び出すことで、相手が応答した場合やしない場合などをわかりやすく管理することができます。

CallNextウィジェットにわたす変数などを間違えてしまうと、思わぬループに入ってしまうこともありますので、実際に利用する場合には十分注意をしてください。なお、予期せぬループが発生してしまった場合は、Functionsを削除するか、Path名を一時的に変更するなどしてループを止めてください。