アルパカログ

カスタマーサポート (CS) とエンジニアリングを掛け算したい CRE (Customer Reliability Engineer) が気になる技術や思ったことなど。

Google Cloud Functions を使ったサーバレス LINE Bot の作り方

LINE Bot を Google Compute Engine(GCE) 無料枠で作る際の要点まとめを書いてから、別のアプリ開発で GCE が使いたくなり、GCE を節約するために LINE Bot をサーバレス化しました。

意外と簡単にできてしまった上、メンテナンス性も向上して良いことづくめということで、サーバレス LINE Bot を無料で簡単に作る方法を紹介します。

システム構成

今回はサーバレス実現のために Google Cloud Functions(GCF) を使います。

システムはいたってシンプルで、下図のように LINE Messaging API からの HTTPリクエスト(webhook) を GCF で受けて reply するだけのものです。

f:id:otoyo0122:20180127144353p:plain

サーバレスと言えば AWS Lambda が良く聞かれますが、GCF が単体でHTTPリクエストを受けられるのに対し、Lambda は AWS API Gateway を前に置いてHTTPリクエストを受ける必要があります。

Lambda も GCF も個人利用レベルでは無料になると思います*1API Gateway は有料です

動かしてみよう

サンプルコードをデプロイして実際に動かしてみましょう。

1. 前準備

前準備として下記の手順を済ませてください。1時間とかからず終わると思います。

  1. GCF の HTTP Tutorial を済ませる
  2. LINE Messaging API を開始しクイックスタートを済ませる

2. Config 配置

サンプルコード(otoyo/linebot-gcf) を任意のディレクトリに clone します。

サンプルコードの config ディレクトリに default.json を作成し、下記のように LINE Messaging API の Channel Secret とアクセストークンを記載します。

config/default.json

{
  "channelAccessToken": "xxxx",
  "channelSecret": "xxxx"
}

Channel Secret とアクセストークンは LINE Developers の Console からチャネル(Bot) を選んだ先のページに記載されています。

もしまだ発行されていなければ発行しましょう。

3. デプロイ

index.js と同じディレクトリで下記デプロイコマンドを実行します。

$ gcloud beta functions deploy webhook --trigger-http --source .

数十秒でデプロイが完了し httpsTrigger URL が表示されます(下図赤枠)。

f:id:otoyo0122:20180127155715p:plain

この URL を LINE 側コンソールの Webhook URL に設定し接続確認します。

f:id:otoyo0122:20180127160042p:plain

✅ 成功しました。と表示されれば完了です。

4. 動作確認

Bot をLINEアプリで友達追加し「ホイちゃん」と話しかけると反応します。

f:id:otoyo0122:20180128095222p:plain

リアクションさせたいキーワードは index.js 内の下記箇所で指定しています。

GCF のコード上の注意点

今回作成したコードは LINE Bot SDK / Node.jsecho-bot サンプル がベースになっていますが、サンプルを GCF で動かす上で注意すべき点が2つあります。

  • GCF のリクエストハンドラで受け取る Request Body (JSON) はパース済みであること
  • そのため署名を検証するためのメソッドを自分で呼ばなければならないこと

LINE Messaging API では、リクエストがLINEプラットフォームから送信されたことを確認する必要があります。これが署名の検証です。

echo-bot サンプルでは Express が使われており、署名はリクエストハンドラの最初のチェイン middleware() 内で検証されています (Source)。

app.post('/callback', line.middleware(config), (req, res) => {

middleware() 内で呼ばれる検証メソッド validateSignature() には生の Request Body を渡す必要があります(Source)。

if (!validateSignature(body, secret, signature)) {

GCF では req.body は既にパース済みのため、req.rawBody を引数にして直接 validateSignature() を呼び出さなければなりません。

今回作成したコードでもそのようにしています (Source)。

if (!line.validateSignature(req.rawBody, config.channelSecret, signature)) {

おわりに

Google Cloud Functions(GCF) を使って LINE Bot をサーバレスで簡単・無料で作る方法を紹介しました。

今回は LINE Bot でしたが、同じ方法で Slack Bot なども簡単に作れると思います。

チャットボットが流行している今、手軽に試せるのでみなさんもぜひ作ってみてくださいね。

そして作ったらぜひ「この記事を見て作ったよ」って教えてください😊

こちらもあわせてどうぞ

参考リンク

*1:とはいえ必ずご自身でご確認ください。 GCF 料金 / Lambda 料金