今回は、apigatewayを利用したnode.js@Lambdaでじゃんけんゲームを作ってみた。
環境構築やプログラムなどは、全て以下の参考①~④を参考に進めた。
だいたい、最初の①と②でLinebotが動く。そして③と④でLambda版のLinebotが動いた。筆者も言っているように感動ものである。
ちなみに、ほぼ1日でLinebotが動くようになった。
したがって、コードのほとんどは参考のまんまであることをお断りしておきます。
【参考】
①LINEBotをみんなで作ろう〜環境構築編〜【GWアドベントカレンダー1日目】
②LINEBotをみんなで作ろう〜おうむ返しbotを作ろう編〜【GWアドベントカレンダー3日目】
③LINEBotをみんなで作ろう〜レイヤーとAPIgateway設定編〜【GWアドベントカレンダー7日目】
④LINEBotをみんなで作ろう〜コードを実装編〜【GWアドベントカレンダー最終日】
ということで、この先のことも考えてじゃんけんゲームを作ってみた。
やったこと
・環境構築(Line)
・環境構築(Lambda@AWS)
・じゃんけんボット
・環境構築(Line)
参考①の解説のとおりで環境が構築出来ました。
LINE Developerのサイトにログインできるようにする。
- ログイン→開発者名、メール入力
- プロバイダーを作成→プロバイダー名;この下にボットを構築
- 新規チャネルを作成→Messaging APIを選択
- Messaging APIのチャンル作成する→ボット名、その他
- Botの設定→
- channel secret(短い方)とChannel access token (long-lived)(長い方)をアプリ側に設定、
- アプリの公開アドレスからWebhook URLを設定、
- BotのLINE Official Account featuresのeditから
- アカウント設定で応答設定;bot オン、
- あいさつ オフ、
- 応答メッセージ オフ、
- Webhook オン
おうむ返しボット
まず、自PC、Windows10でNode.jsを利用しておうむ返しボットを作ります。
ngrokをインストールする
Download & setup ngrokから自PCのOsにあったものをダウンロードして、解凍するとngrok.exeが入っているのでこれを実行すれば(ダブルクリックで)コンソールが動きました。そこで以下を実行すると実行できます。
※ちなみに、専用コンソールで実行してください。WindowsPromptだと動きませんでしたngrok -v
ngrok version 2.3.35
node.js(v10以上推奨)をインストールする
node.js(v10以上推奨)ダウンロードからWindowsInstaller;node-v12.18.1-x64.msiをダウンロードして、インストール。
通常のコマンドラインで以下のように確認できる。>node -v
v12.18.1
エディタ
使い慣れたjupyter notebookを使いました。
おうむ返しボットのnode.jsコード
以下のようにdesktop配下にDirを作って、そこで環境構築して作業します。参考にいろいろな拡張があって凄い記事になっていました。
【参考】
⑤1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest
cd deskTop
mkdir test-linebot
cd test-linebot
npm init -y
npm i @line/bot-sdk express
次にプログラムのメインとなるindex.jsをtest-linebotフォルダ内に作成します。
エディタで以下をコピペします。
上記のとおり、短い方と長い方をBotのBasic settingsとMessaging API settingsからコピペして設定します。
"use strict";constexpress=require("express");constline=require("@line/bot-sdk");constPORT=process.env.PORT||5000;constconfig={channelSecret:"短い方",channelAccessToken:"長い方"};constapp=express();app.post("/webhook",line.middleware(config),(req,res)=>{console.log(req.body.events);Promise.all(req.body.events.map(handleEvent)).then((result)=>res.json(result));});constclient=newline.Client(config);asyncfunctionhandleEvent(event){if(event.type!=="message"||event.message.type!=="text"){returnPromise.resolve(null);};letmes={type:"text",text:event.message.text};returnclient.replyMessage(event.replyToken,mes);}app.listen(PORT);console.log(`Server running at ${PORT}`);
ここで、肝心な部分として、返信している文字列は
eventが以下のようなものなので、event.message.text='動くかな😅'
となります。
{
type: 'message',
replyToken: '*******************************',
source: { userId: '*****************', type: '***' },
timestamp: **************,
mode: 'active',
message: { type: 'text', id: '*************', text: '動くかな😅' }
}
これで、Linebotを動かしてみます。\Desktop\test-linebot>node index.js
Server running at 5000
この状態で、もう一個ターミナルを起動して、ngrok http 5000
これで上記のindex.jsを公開します。
以下のような表示が出現します。以下は1時間37分ほど経過するとexpireするものになっています。
以下の表示からhttps://73e6916ab721.ngrok.io
というサイトからフォワードしていることが分かるので、ボットのWebhook URLとして、https://73e6916ab721.ngrok.io/webhook
とします。
※因みにこのサーバーは一意だと思いますが、毎回起動の度に変化します。また、Session Expiresの時間も長いとき(約7時間半)も短いとき(約1時間半)もバラバラです。
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Session Expires 1 hour, 37 minutes
Version 2.3.35
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://73e6916ab721.ngrok.io -> http://localhost:5000
Forwarding https://73e6916ab721.ngrok.io -> http://localhost:5000
これで動くと思います。動かなかったら、参考②や参考⑤を見てください。どちらもとても丁寧に書かれています。
出来ると、単なるおうむ返しですが、なんとなくうれしいです。
・環境構築(Lambda@AWS)
今度は、上記のindex.jsをLambdaで動作させApiGatewayを利用して、Linebotと連携します。
これも、参考③のとおりです。
・AWSアカウントでログイン;コンソールへ行く
・Lambdaを開く
・Lambda関数を作成・関数名(lamdbaTst)、ランタイムNode.Node.js 12js 12.x、ロール(基本的な...)等の設定
・コンソールに戻って、(検索して)API Gatewayを選択
・RestAPI 構築・REST・新しいAPI・API名;linebotAPI・エンドポイントタイプ;リージョン・APIの作成
・アクション・メソッドの作成・Post設定
・アクション;POSTセットアップ・Lambda関数・Lambdaプロキシ統合の使用;チェック・Lambda関数;lambdaTst・保存
・Lambda関数に権限を追加するダイアログ;OK
・アクション;POSTメソッドの実行・メソッドリクエスト・HTTPリクエストヘッダー・ヘッダー追加・名前欄にX-Line-Signatureと入力、必須にチェック
・アクション・APIのデプロイ・レイヤーの作成
・デプロイされるステージ;新しいステージ・ステージ名;test1・デプロイ
・Lambdaの関数の画面へ行き、関数にAPIGatewayが連携(追加)されていれば成功
・利用するNode.js環境をzipファイルにまとめて、レイヤーとして登録する・参考③はMac環境ですが、全く同じように作成します。
・cd Desktop・mkdir nodejs・npm init -y・npm i @line/bot-sdk・nodejsディレクトリをzip圧縮
・Lambda関数ページのレイヤーを開く・レイヤーの作成でnodejs.zipをアップロード。名前はそれらしい名前;linebot-SDK。・互換性のあるランタイムオプション;node.js 12,x node.js 10.x・作成
・Lambda関数ページのレイヤーを連携・レイヤーの追加・ランタイムと互換性のあるレイヤーのリストから選択・名前;linebot-SDK
・バージョン;1・追加
・関数画面でレイヤーで読み込めていたら(下に表示されたら)成功
・関数名をクリックして下へスクロール、環境変数の項目を探す、編集をクリック・編集・ACCESSTOKEN;長い方・CHANNELSECRET;短い方・保存
・Lambda関数をクリックして、関数を以下のコードをコピペして張り付ける。・右上の保存
・WEBhookURLを設定する・API Gatewayを押下・APIエンドポイントをコピペ・LinebotのWEBhookURLに張り付ける
これで、動きました。
さて、張り付けるコードは以下のじゃんけんゲームです。
じゃんけんゲームのコード
"use strict";// モジュール呼び出しconstcrypto=require("crypto");constline=require("@line/bot-sdk");// インスタンス生成constclient=newline.Client({channelAccessToken:process.env.ACCESSTOKEN});exports.handler=(event,context,callback)=>{// 署名検証constsignature=crypto.createHmac("sha256",process.env.CHANNELSECRET).update(event.body).digest("base64");constcheckHeader=(event.headers||{})["X-Line-Signature"];constbody=JSON.parse(event.body);constevents=body.events;console.log(events);// 署名検証が成功した場合if(signature===checkHeader){events.forEach(async(event)=>{letmessage;// イベントタイプごとに関数を分けるswitch(event.type){// メッセージイベントcase"message":message=awaitmessageFunc(event);break;// フォローイベントcase"follow":message={type:"text",text:"追加ありがとうございます!"};break;// ポストバックイベントcase"postback":message=awaitpostbackFunc(event);break;}// メッセージを返信if(message!=undefined){client.replyMessage(body.events[0].replyToken,message).then((response)=>{constlambdaResponse={statusCode:200,headers:{"X-Line-Status":"OK"},body:'{"result":"completed"}',};context.succeed(lambdaResponse);}).catch((err)=>console.log(err));}});}// 署名検証に失敗した場合else{console.log("署名認証エラー");}};constmessageFunc=asyncfunction(event){varmes=awaitmesmakeFunc(event);letmessage;switch(event.message.type){case"text":message={type:"text",text:mes};break;case"image":message={type:"text",text:"がぞうを受け取ったよ!"};break;case"sticker":message={type:"text",text:"ステッカーを送ってくれたんだね!"};break;}if(message!==undefined){returnclient.replyMessage(event.replyToken,message);}returnmessage;};constmesmakeFunc=asyncfunction(event){console.log('event.text:',event.message.text);varmes=['グー','チョキ','パー',event.message.text];varr=Math.floor(Math.random()*4);varmes0=mes[r];console.log('message:',mes0);returnmes0;};constpostbackFunc=asyncfunction(event){letmessage;message={type:"text",text:"ポストバックイベントを受け付けました!"};returnmessage;};
自PCでのじゃんけんゲームのコード
"use strict";constexpress=require("express");constline=require("@line/bot-sdk");constPORT=process.env.PORT||5000;constconfig={channelSecret:"短い方",channelAccessToken:"長い方"};constapp=express();app.post("/webhook",line.middleware(config),(req,res)=>{console.log(req.body.events);Promise.all(req.body.events.map(handleEvent)).then((result)=>res.json(result));});constclient=newline.Client(config);asyncfunctionhandleEvent(event){if(event.type!=="message"){returnPromise.resolve(null);};letmes=awaitmessageFunc(event);console.log('mes_message:',mes);returnclient.replyMessage(event.replyToken,mes);};constmessageFunc=asyncfunction(event){varmes=awaitmesmakeFunc(event);letmessage;console.log('message_message:',event.message.type);switch(event.message.type){case"text":message={type:"text",text:mes};break;case"image":message={type:"text",text:"がぞうを受け取ったよ!"};console.log('image_message:',message);break;case"sticker":message={type:"text",text:"ステッカーを送ってくれたんだね!"};console.log('sticker_message:',message);break;}returnmessage;};constmesmakeFunc=asyncfunction(event){console.log('event.text:',event.message.text);varmes=['グー','チョキ','パー',event.message.text];varr=Math.floor(Math.random()*4);varmes0=mes[r];console.log('message:',mes0);returnmes0;};app.listen(PORT);console.log(`Server running at ${PORT}`);
まとめ
・Linebotを自PCとLambdaで連携して遊んでみた
・ちょっとした拡張として、じゃんけんゲームを作成してみた
・利用性の高いアプリを作ってみようと思う