ja ja en nb ja es ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja uk ja ja ja ja ja ja ja ja ja ja ja en ja ja en ja en ja ja ja ja en ja ja ja ja ja en ja ja ja en ja es ja ja ja ja ja en ja ja ja ja ja ja ja ja ja ja ja pl nl ja ru ja ja nb ja ja pl en ja nb ja ja nb ja ja ja ja ja en ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja jbo en en ja nl nb en ko it en it it it en fr it ja ja en la fi ja it it it pt it de en ja en en it fr it en it nb it ja ja ja ja en ja ja ja ja ja ja ja ja ja
Twilioを使ってWeb API経由で電話をかける(前編) - Sanwa Systems Tech Blog
読み上げの前後に、予め準備した音声ファイル(mp3など)を再生してくれます。
を使って、《CloudWatchでアラートが発生した際、電話でアラートを通知する》仕組みをサーバーなしで構築することにしました。前編ではこの手順のための下準備としてTwilioの使い方を説明します。
まずいつもの通りCloudWatchで監視内容を設定します。
監視でエラーが発生すると、AWS SNSにアラートが飛ぶようにします。
そのSNSをトリガーとしてAWS Lambdaが起動するようにします。
LambdaはDynamoDBを参照し、エラー通知先の電話番号と通知内容を取得し、Twilio APIを叩いて電話をかけて担当者を叩き起こします。
担当者は頑張って対応します。
なお、Twilioの全ての機能は有料です。まずクレジットカード(Visa/Masterのみ)を使って事前にいくらか*1料金をチャージしておき、サービスを利用するたびにそこから残高が引き落とされていく仕組みになっています。残高がゼロになるとサービスが利用できなくなりますので適宜追加してください。自動チャージも可能です。
まずはTwilioのトップページより「サインアップ」へ移動してアカウントを作成します。
twilio.kddi-web.com
注意点としては、ここで作ったアカウントは米Twilioのアカウントとは別になるため、サインインする際は https://jp.twilio.com/login/kddi-web (末尾に"kddi-web"がある)を経由する必要があるということです。サインアウトした状態でサービスを使おうとすると https://jp.twilio.com/login にリダイレクトされるのですが、こちらではサインインができません。パスワードのリセットを行おうとしても「このメールアドレスに紐付いたアカウントは存在しない」と言われてしまって混乱することになります。というか、実際に混乱して1時間無駄にしました。
アカウントができたら、クレジットカードで適当にチャージします(どうせ使うので)。お試しでもサービスは利用できますが、任意の番号に任意の内容で電話をかけることはできません。
APIクレデンシャルを取得
アカウント取得後、 アカウントページ を見ると、APIを叩くのに必要なキーが表示されています。キーには2種類あり、右側の「テスト」はAPIのテストのために利用できます(これを使ってAPIを叩いても実際に電話をかけるなどの操作は行われません。料金もかかりません)。
発信元電話番号を確認する
電話番号画面を見ると、電話番号が一つ表示されているはずです。この電話番号は自分だけのもので、電話をかける・受けるときに使われます。(有料で)別に新規取得することもできます。最初に確認しておきましょう。
この情報をもとにエンドポイントにHTTP POSTを送ると電話をかけられます。
ドキュメントの REST API: 通話を開始する を見ると、curlでテスト実行を行うためのサンプルコードが見つかるはずです(「XML」に切り替えるのを忘れないでください)。
既にAPIキーは埋め込まれていますので、{AuthToken}を本物の値に書き換え、Fromを自分の電話番号(上記)に書き換え、さらにToを自分の好きな番号に変更して実行すればいいです。
curl -XPOST https://api.twilio.com/2010-04-01/Accounts/AC92555d**************************/Calls \ -d "Url=http://demo.twilio.com/docs/voice.xml" \ -d "To=%2B81311112222" \ -d "From=%2B8199998888" \ -u 'AC92555d**************************:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
発信先電話番号は国番号(日本なら"+81")から指定します。たとえば03-1111-2222にかけるのであれば、先頭のゼロを取り、"+81"を付加して"+81311112222"になります。さらにcurlの仕様により+は%2Bにエスケープする必要があるので、パラメーターはTo=%2B81311112222と書くことになります。FromはTwilioから発行された電話番号を指定しますが、同様に修正してください。
--data-urlencodeを使えばこの手間は省けますし見やすくなります。
curl -XPOST https://api.twilio.com/2010-04-01/Accounts/AC92555d**************************/Calls \ --data-urlencode "Url=http://demo.twilio.com/docs/voice.xml" \ --data-urlencode "To=+81311112222" \ --data-urlencode "From=+8199998888" \ -u 'AC92555d**************************:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
ただのBASIC認証つきのHTTP(S) POSTなので、もちろんPowerShellでも同じように書けます(若干面倒です)。こちらでもエスケープは必要ありません。
$key = "AC92555d**************************" $secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" $uri = "https://api.twilio.com/2010-04-01/Accounts/$key/Calls" $xml = "http://demo.twilio.com/docs/voice.xml" $parameters = @{Url=$xml; To="+81311112222"; From="+8199998888"; } # BASIC認証 $auth = "${key}:${secret}" $base64 = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($auth)) $header = @{Authorization = "Basic $base64"} Invoke-WebRequest -Uri $uri -Method POST -Body $parameters -Headers $header
うまく行けば電話がかかってきて「Enjoy!」と言ってくれるはずです。
喋る内容をカスタマイズする
電話で喋る内容は、上記のパラメーターの中で指定した http://demo.twilio.com/docs/voice.xml の中で指定しています。
Thanks for trying our documentation. Enjoy!   http://demo.twilio.com/docs/classic.mp3
これはTwiMLと呼ばれるXMLで、文法は TwiMLTM: Twilio マークアップ言語 で解説されています。これと同じようなXMLファイルを自分で用意してWebサーバーでホストし、そのURLを指定すれば任意の文章を読み上げさせることができます。日本語にも対応していて、単にlanguage属性で言語に日本語を指定すればいいだけです。
大切なサーバーが停止しました。   http://s3-ap-northeast-1.amazonaws.com/YOUR-BUCKET-NAME/very-very-horrible-music.mp3
思わず心臓が躍り出すような通告が3回繰り返された後、S3に置いた*2mp3ファイルが再生されます。
TwiMLをS3に配置するときの注意点
TwiMLをS3にホストすればWebサーバーは必要ありませんが、TwilioはデフォルトでこのTwiMLにPOSTでアクセスしに行くため、S3ではエラーになってしまいます*3。パラメーターに Method=GET を追加してこの動作をオーバーライドできます。curlの例であれば--data-urlencode "Method=GET" \を、PowerShellであれば
$xml = "https://s3-ap-northeast-1.amazonaws.com/YOUR-BUCKET-NAME/voice.xml" $parameters = @{Url=$xml; To="+814155551212"; From="+81012345678"; Method="GET"}
のように書いてください。
Twimletsを使う
いくらサーバーが必要ないとはいえ、あらかじめファイルを作成してアップロードしておくのは面倒なものです。Twilioから提供されているWebサービス「Twimlets」を使うと、上述のTwiMLを動的に生成することができます。
Twilio Labs
パラメーターにXMLの中身を丸ごと渡してあげると、そのままのXMLを出力してくれます。*4
http://twimlets.com/echo?Twiml=%3CResponse%3E%0A%20%20%20%20...
このURLを生成するためのPowerShellのコードを示します。
Add-Type -AssemblyName System.Web $raw = '  大切なサーバーが停止しました。  http://s3-ap-northeast-1.amazonaws.com/YOUR-BUCKET-NAME/very-very-horrible-sound.mp3  ' $encoded = [System.Web.HttpUtility]::UrlEncode($raw, [System.Text.Encoding]::UTF8) $xml = "http://twimlets.com/echo?Twiml=" + $encoded
Linuxであればnkfか何かを使ってください。あらかじめ用意することができる固定メッセージであれば上述のURLからブラウザで作ることもできます。このURLさえ準備できれば、Twilioにリクエストを送る際にUrlオプションにこのURLを渡してあげればいいわけです。なお、curlでリクエストを送る場合は-dではなく--data-urlencodeオプションを使ってください。
Lambda(Node.js)から呼ぶ
ライブラリも提供されているのですが、この程度であれば直接リクエストを送ってしまった方が早いでしょう。次のコードはLambdaで実行すると電話をかけて処理を終了します。
var https = require('https'); exports.handler = function(event, context) { var key = "AC92555d**************************" var secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" var options = { hostname: "api.twilio.com", port: 443, path: "/2010-04-01/Accounts/" + key + "/Calls", method: 'POST', auth: key + ":" + secret, headers : { "Content-Type" : "application/x-www-form-urlencoded" } }; var req = https.request(options, function(res) { if (200  ' + ' ' + '  大切なサーバーが停止しました。 ' + '  http://s3-ap-northeast-1.amazonaws.com/YOUR-BUCKET-NAME/very-very-horrible-music.mp3 ' + ' '; var urlParam = encodeURIComponent('http://twimlets.com/echo?Twiml=' + encodeURIComponent(rawXml)); req.write("To=+81311112222&"); req.write("From=+8199998888&"); req.write("Method=GET&"); req.write("Url=" + urlParam); req.end(); };
HTTP POSTでパラメーターを送信するので、ヘッダにContent-Type : application/x-www-form-urlencodedを指定する
XMLの中身はencodeURIComponentでURLエンコードしてTwimletsに渡す
そのURL自体をまとめて再度encodeURIComponentでURLエンコードしてTwilioに渡す
bashやPowerShellのコンソールと、電話という子供の頃から慣れ親しんできたデバイスとが繋がるのはなんだか不思議な感じがします。次回はこちらを使い、CloudWatch+Lambdaから呼び出して実際に電話をかけることにします。
*1:2,000円以上、1,000円単位になります
*2:Twilioのサーバーが取得できるように外部からアクセス可能でないといけません
*3:S3はHTTP POSTを受け取ると無条件でエラーを返す仕様となっています
*4:メッセージ内容だけを渡すバージョンもあるのですが、language属性の指定ができないため日本語では使えませんでした
nurenezumi 2016-01-28 21:14
Node.jsからmultipart/form-dataでデータをPOSTする
お久しぶりです。最近Node.jsばかり書いているwakです。 さて、…
API Key認証付きのAPI GatewayからS3へリダイレクトしたい(できない)
こんにちは、AWS担当のwakです。 概要 表題の通りです。できな…
API Gateway + LambdaでSlackのCustom Commandを作る
こんにちは、AWS担当のwakです。先日このような記事を書いたの…
AWS LambdaからGoogle APIを呼び出す
こんにちは、AWS担当のwakです。間が空いてしまったので、今回…
Google Chromeアプリ[Postman]の使い方メモ
井上です。WEB API作成時にとても便利なPostman。その使い方に…
« Slackのリマインダー機能まとめ Google Chromeアプリ[Postman]の使い方メモ »