Lambdaで作ってみよう
AWS Lambdaはサーバーレスのスクリプトなので、サーバーを立ち上げる手間なく動作の確認ができるので、手始めにはオススメです。
流れは大体こんな感じです。
- AWS Lambdaで実装
- AWS API Gatewayの設定
- LINE BotアカウントにWebhookを設定
AWS Lambdaで実装
ランタイムはNode.js 10.xを使用しています。
@line/bot-sdkを使用して受信メッセージを読み込み、返信までを行なっています。
'use strict';
const line = require('@line/bot-sdk');
const crypto = require('crypto');
// 環境変数の読み込み
const channelSecret = process.env.CHANNELSECRET;
const channelAccessToken = process.env.ACCESSTOKEN;
// LINE Clientオブジェクトの作成
const client = new line.Client({channelAccessToken: channelAccessToken});
exports.handler = function (event, context) {
const body = JSON.parse(event.body);
console.log(event);
// (1)HMACを用いて正規のLINEサーバからのリクエストであることを確認
const signature = crypto.createHmac('SHA256', channelSecret).update(event.body).digest('base64');
const xLineSignature = (event.headers || {})['X-Line-Signature'];
let verified = false;
if (signature === xLineSignature) {
verified = true;
}
if(!verified){
// 正規のLINEサーバからのリクエストでない場合
console.log("Signature verify error.");
}
else{
// 正規のLINEサーバの場合
console.log("Signature verify succeed.");
let replyToken = body.events[0].replyToken;
// リクエストの内容を確認
if(replyToken === '00000000000000000000000000000000'){
// 接続確認の場合
console.log("Connection check.");
let response = {
statusCode: 200,
headers: { "X-Line-Status" : "OK" },
body: '{"result":"connect check"}'
}
context.succeed(response);
}
else{
// 通常メッセージの場合
console.log("Message received.");
let message = body.events[0].message;
// (2)メッセージのTypeから返答を設定する
console.log("Message type :" + JSON.stringify(message.type));
let reply_text = null;
if(JSON.stringify(message.type) == "\"text\""){
// テキストの場合
let text = body.events[0].message.text;
switch (text) {
case "グー":
reply_text = "パー"
break;
case "チョキ":
reply_text = "グー"
break;
case "パー":
reply_text = "チョキ"
break;
default:
reply_text = "興味ないね"
break;
}
}
else{
// テキスト以外の場合
reply_text = "...";
}
// 返信メッセージの作成
let res_message = {
"type": "text",
"text": reply_text
};
// (3)メッセージの返信
client.replyMessage(replyToken, res_message)
.then((res) => {
let response = {
statusCode: 200,
headers: { "X-Line-Status" : "OK"},
body: '{"result":"reply completed"}'
};
context.succeed(response);
}).catch((err) => console.log(err));
}
}
};
何をやっているのかは、LINEのドキュメントを確認すれば丁寧に書いてありますが、一部抜粋して解説します。
(1) HMACを用いて正規のLINEサーバからのリクエストであることを確認
LINE Botアカウントに”Channel Secret”という文字列が設定されています。
下記の処理は、これを使ってメッセージ全体をハッシュ化し、BASE64エンコードした文字列を作成し、リクエストヘッダーに含まれる”X-Line-Signature”というパラメータと値を比較しています。
const signature = crypto.createHmac('SHA256', channelSecret).update(event.body).digest('base64');
const xLineSignature = (event.headers || {})['X-Line-Signature'];
let verified = false;
if (signature === xLineSignature) {
verified = true;
}
LINEサーバーは、”X-Line-Signature”に同じようにして生成した文字列を入れて送ってくるわけです。
これは"Channel Secret"を知らない他人にはできないため、この照合によって、正規のLINEサーバーから送られてきたかどうかを確認できるわけです。
※注意:Channel Secretをプログラムにベタ書きしてGithubでばらまいてしまっては話は別です。他人に知られないように。
(2) メッセージのTypeから返答を設定する
正規のLINEサーバからのリクエストだとわかったら、メッセージの中身を確認します。
let message = body.events[0].message;
if(JSON.stringify(message.type) == "\"text\""){
// テキストメッセージの場合
}else{
// それ以外の場合
}
本来は、メッセージよりも前に"event"という要素を確認すべきですが、割愛します。
"message"要素の"type"には、"text","sticker","image"...など、どんなメッセージが来たかが書いてあります。
それを元に分岐を作って、返答を作っていくことになります。
(3) メッセージの返信
メッセージを返信するには、受信したメッセージに含まれる"replyToken"を使います。
合わせてメッセージを詰めて返信し、通信のステータスが"200"なら返信成功、失敗したらログを残す、といった内容です。
client.replyMessage(replyToken, res_message)
.then((res) => {
let response = {
statusCode: 200,
headers: { "X-Line-Status" : "OK"},
body: '{"result":"reply completed"}'
};
context.succeed(response);
}).catch((err) => console.log(err));
まずは全てコピペで良いと思います。
あと、プログラムの上部で環境変数を読み込んでいますが、Lambdaには環境変数を設定することができます。
下記のようにLINE Botアカウントの画面から、該当項目を確認して値を設定しておきましょう。
チャンネルアクセストークンはWebhook送信を「利用する」に設定して、「再発行」ボタンを押せば発行できます。
AWS API Gatewayの設定
次にAPI Gatewayを設定します。
まずは「+APIの作成」ボタンからこんな感じで作成します。
次に「アクション」からPOSTメソッドを作成します。
- 統合タイプ:Lambda関数
- Lambdaプロキシ統合の使用:✔︎
- Lambda関数:先ほど作成した関数名
- デフォルトタイムアウトの使用:一応3秒くらい待つようにしました
最後に、「アクション」から「APIのデプロイ」を行います。
ステージ名はこだわらなければ適当で構いません。
そうすると、URLが発行されます。
LINE BotアカウントにWebhookを設定
発行されたURLをLINE Botのアカウントにある「WebhookURL」へ設定します。
で、「接続確認」ボタンを押して、成功しましたと出ればOK!
あとは、Webhookでアプリケーションで応答をする場合、デフォルトの応答設定が邪魔になるので、下記のように「挨拶メッセージ」「応答メッセージ」はオフにしてWebhookをオンにしましょう。
あとはLINE BotをQRコードで友達登録して、メッセージを送ってみると・・・
応答が返ってきました!くだらないですね!
終わりに
ここまでできれば、あとはプログラムの中身を工夫するだけで、ちょっとしたボットは作れちゃいます!
AWS API Gatewayは無料利用枠があり、月間のメッセージ数 100 万件 (送信または受信) および接続時間 750,000 分以内は無料です。
Lambdaもリージョンによりますが、東京は1 か月に 1,000,000 件のリクエストおよび 400,000 GB-秒のコンピューティング時間は無料のようなので、ちょっと試しに作る分には無料で実現できそうですね。
小一時間あればできるので、ぜひやってみてください!