LoginSignup
17
14

More than 3 years have passed since last update.

Twilio Functionsのためのローカル開発環境

Last updated at Posted at 2019-01-02

はじめに

本業とは関係ないところ(父と近所の手伝い)で、Twilioを使った電話システムの開発に初めてチャレンジしてみました。

極力サーバーの構成はシンプルにしたいので、Twilio Functionsを使いました。AWS Lambdaみたいな感じでサーバーレスにTwilioのシステムを構築できるのが、とても良いですね!

Twilio Functionsの設定画面で直接Node.jsのコードを書いていけば作れるんですけど、やっぱりローカルのエディタでコード書いて、Gitにスムーズにコミットしたりしたいじゃないですか。

日本語の情報が全くなかったんですが、ちゃんと調べたらとても簡単にできたので、メモがてら残しておきます。

Functionsとローカル開発の違いで面倒臭いところ

Functionsは全体をこんな関数でくくって、終了時はcallbackを呼び出します。普通にNode.jsサーバー立てる場合はこんなことしない。

Functions
exports.handler = function(context, event, callback) {
  // ...
  callback(null, "Everything is gunna be alright");
}

そして、twimlclientオブジェクトの作り方も微妙に違います。

local
const twiml = new require('twilio').twiml.VoiceResponse();
const client = require('twilio')(ACCOUNT_SID, AUTH_TOKEN);
const callerId = process.env.CALLER_ID;
Functions
const twiml = new Twilio.twiml.VoiceResponse();
const client = context.getTwilioClient();
const callerId = context.CALLER_ID; // 環境変数はcontextに全部入る

こういうのを、「全部Functionsの仕様に寄せて書いたらローカルで動く」ようにしておきたいわけです。

twilio-runを使おう

最初は自分でcallback関数を作ったり頑張ろうとしかけたんですが、GitHubを探したらこんな素晴らしいCLIツールを見つけました!車輪の再発明せずに済んでよかった。。
https://github.com/dkundel/twilio-run

以下、twilio-runを使った構築手順です。前提条件はこんな感じ。

  • Twilio電話番号が1つ取得済み
  • 開発デバイスはMac
  • HomebrewとNode.jsがインストール済み

Twilio Functionsの設定

一番シンプルな構成として、サンプルで用意されてる「Hello Voice」を使って新規Functionを作成します。
スクリーンショット 2019-01-03 0.59.55.png

  • PATHは/hello
  • Check for valid Twilio signatureはチェック
  • EVENTはIncoming Voice Callsを選択
スクリーンショット 2019-01-03 0.59.31.png

こいつをローカルにコピペしてそのまんま動かすのが今回のゴール。

ローカルの設定

ngrokインストール

brew cask install ngrok

プロジェクト作成

mkdir hello-twilio
cd hello-twilio
npm init -y

twilio-runインストール

npm install twilio-run --save-dev

functionsディレクトリ作成
twilio-runは、実行時に./functions配下の全コードを自動的にホスティングするので、必ずこの名前で作るのがポイントです。

mkdir functions

Functionのソースコード作成
./functions配下に作成します。先ほどTwilio上で作ったHello Voiceをコピペ!1

functions/hello.js
exports.handler = function(context, event, callback) {
	let twiml = new Twilio.twiml.VoiceResponse();
	twiml.say("Hello World");
	callback(null, twiml);
};

twilio-run起動
デフォルトはポート3000番でホスティングされます。
PATHはJSのファイル名helloがそのまんま使われます。

$ npx twilio-run
┌────────────────────────────────────┐
│                                    │
│   Twilio functions available at:   │
│   => http://localhost:3000/hello   │
│                                    │
│                                    │
│   ⚠ No assets directory found      │
│                                    │
└────────────────────────────────────┘

ngrok起動
ローカルのhttpサーバーを外部公開してくれます。
Forwardingのサブドメインは毎回変わるので、固定したければ有償プランが必要です。

$ ngrok http 3000

ngrok by @inconshreveable                                            (Ctrl+C to quit)

Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://example.ngrok.io -> localhost:3000
Forwarding                    https://example.ngrok.io -> localhost:3000

ブラウザでhttpsの方にアクセスしてみましょう。
https://example.ngrok.io/hello
スクリーンショット 2019-01-03 1.52.00.png

こんなXMLが表示されたら、ローカル側は準備完了!

Twilio電話番号を開発環境に向ける

電話をかけたらローカルのプログラムが動くようにTwilio側を設定します。「通話着信時」に「Webhook」として先ほどのURLを登録すればOK。

スクリーンショット 2019-01-03 1.54.51.png

電話をかけてみよう

該当の番号に電話をかけると、英語で「Hello World」と聞こえますね!
こんな風に書き換えてtwilio-runを再起動すると、日本語でも喋ってくれますね!

functions/hello.js
exports.handler = function(context, event, callback) {
  let twiml = new Twilio.twiml.VoiceResponse();
  twiml.say("世界よこんにちは", { language: "ja-jp" });
  callback(null, twiml);
};

本番環境に反映

一通りローカルでの開発が完了したら、Functionsの設定画面で最初に作った「Hello World」コードの中身を、ローカルの「hello.js」の内容に置き換えて保存します。(何も変更しなくて良いのが最高!)

その上で、電話番号の設定画面をFunctionに向けます。

スクリーンショット 2019-01-03 2.08.02.png

ローカルでスムーズに開発し、サーバーレスなTwilio Functionsで本番運用する体制がこれで整いました!めでたしめでたし。

おわりに

kintone hack 2018の戦友、高橋さんの記事が取っ掛かりとして大変参考になりました。Twilioについてググってヒットするのは、半分以上が高橋さんの記事ですねw エバンジェリスト流石っす!
TwilioのFunctionsを使ったサーバーレス受付電話システム

実際に僕が作ったプログラムは、3つのFunctionが連携する、もう少しだけ複雑なシステムです。近々そちらのコードも公開しますねー。

2019/04/09 公開しました!
解説記事を丁寧に書く時間がなかなか取れそうにないので、ドキュメント一切無しだけど晒してしまいますw
https://github.com/the-red/twilio-neighborhood-network

田舎のガラケーしか持っていないオッチャン達が使うには、「音声電話だけで100%完結するシステム」って超便利だなーと今回思いました。Twilioの面白さに目覚めることができたので、今後も色々と作ってみたいと思います :blush:
次のステップは、モチロンkintone連携だな!

  1. 僕はセミコロン無しでJavaScript書くのが好きなんですが、Twilio Functionsに貼り付けたときセミコロンが無いと「Missing semicolon」と警告が出ちゃって気持ち悪いので、Twilio向けのコードだけはPrettierでセミコロン付ける設定にしてます。

17
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14