第5話 フォローしたらあいさつするBOTを作ろう
こんにちは。Kenです!
さて、前回まで以下を実施しました。
・Herokuの設定
・LINE公式アカウントの設定
・nodeライブラリExpressのインストール
さぁ今回はいよいよLINE BOTのコードを書いていきましょう!今回の目標は公式アカウントが友達登録されたら、フォローのお礼をリプライするというものです。
@line/bot-sdkのインストール
LINEBOTをnode.jsで使うには、@line/bot-sdkライブラリが必要となります。SDK とはいわゆるソフトウェア開発キットのことで、少ない労力でソフトを開発できるようにプログラムやサンプルコードなどをパッケージにしたものです。
$ npm i @line/bot-sdk
VS codeのターミナルで@line/bot-sdkをインストールしてください。あれっ、install じゃないの?iでいいの?って思われるかもしれませんが、iと省略することが可能です。はい、単なる豆知識です。
package.jsonのdependenciesに以下のように@line/bot-sdkがあれば成功です!
"dependencies": {
"@line/bot-sdk": "^7.1.0",
"express": "^4.17.1"
}
package.jsonの改造
package.jsonにnode.jsで使うための設定を書き込みましょう。
{
"name": "linebot-reservation",
"version": "1.0.0",
"description": "linebot-reservation",
"engines": {
"node": "12.x",
"npm": "6.x"
},
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "node test.js"
},
"author": "ken",
"license": "ISC",
"dependencies": {
"@line/bot-sdk": "^7.1.0",
"express": "^4.17.1"
}
}
enginesの追加とscriptsの中身を変えてます。nodeやnpmは指定のバージョンで使いますよという宣言です。バージョンの確認はVS codeターミナルで以下のように確認できます。
$ node --version
$ npm --version
私の場合は、nodeバージョンがv12.14.0、npmバージョンがv6.14.2なので、それぞれ12.x、6.xと記載してます。
いよいよコーディング
では、VS codeでフォルダ直下に作成したindex.jsを開きましょう。
const express = require('express');
const app = express();
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 5000
const config = {
channelAccessToken:process.env.ACCESS_TOKEN,
channelSecret:process.env.CHANNEL_SECRET
};
const client = new line.Client(config);
app
.post('/hook',line.middleware(config),(req,res)=> lineBot(req,res))
.listen(PORT,()=>console.log(`Listening on ${PORT}`));
解説です。まずはじめにexpressと@line/bot-sdkのライブラリを読み込んでます。expressはappという名前で使えるようにしてます。
次のconfigオブジェクトは@line/bot-sdkに渡してあげる設定値のようなものです。LINE公式アカウントを作成した時に、チャンネルアクセストークンとチャンネルシークレットをメモしておきましょうと書きましたが、ここで使うのです。ただ、コードを見るとprocess.env.xxxxと書いてあるだけ。チャンネルアクセストークンやチャンネルシークレットはアカウント固有の値なので、それをそのまま書くことはセキュリティ上よろしくありません。ですので、Herokuアプリの環境変数に2つの設定値を書き込み、そこを読みにいっていると理解いただければと思います。
では、Herokuの環境変数へ書き込みましょう。ターミナルで以下のよう入力します。
$ heroku config:set ACCESS_TOKEN=xxx --app アプリ名
$ heroku config:set CHANNEL_SECRET=xxx --app アプリ名
xxxにアクセストークン、チャンネルシークレットが入ります。アプリ名にはherokuアプリ名を入力しましょう。私の場合は、linebot-reservationですね。
その他のコードはおまじないのようなもので何回も書く必要があるものでないので、今はこんなもんか〜くらいで良いです。
expressでhttps://linebot-reservation.herokuapp.com/hookへpostされるとlineBot()という関数が実行されます。この関数は自作関数ですので、次はこの関数の中身を書いていきましょう。
関数lineBot( )のコーディング
関数の中身です。
const lineBot = (req,res) => {
res.status(200).end();
const events = req.body.events;
const promises = [];
for(let i=0;i<events.length;i++){
const ev = events[i];
switch(ev.type){
case 'follow':
promises.push(greeting_follow(ev));
break;
}
}
Promise
.all(promises)
.then(console.log('all promises passed'))
.catch(e=>console.error(e.stack));
}
コーディングは以下のサイトを参考にさせていただきました。こちらの中では非常に詳しく解説してくれているので、ぜひご覧ください。
eventsをfor文で1個ずつのevへ分解しているわけですが、実際のevの中身は以下のようになります。(const ev = ・・・の下にconsoleを入れるとわかります)
ev: {
type: 'follow',
replyToken: 'xxxxxxxxxxxxx',
source: { userId: 'yyyyyyyyyyyy', type: 'user'},
timestamp: 1601078188945,
mode: 'active'
}
evの中で注目すべきは、type、replyToken、userId、timestampです。
typeはイベントの種類を表します。今回は友達登録されたことを意味するfollowですが、他にもmessageやpostbackなどがあります。以下ご参考。
replyTokenは送られてきたイベントが持つ固有の値で、このreplyTokenを指定してあげるとそのイベントに対しピンポイントに返信できるということです。
userIdはそのイベントを送ってきた相手のLINE IDになります。つまりこの場合は、友達登録した人のLINE IDです。普段見えませんが、LINEアカウントにはこの固有のIDが割り振られており、このIDによりアカウントを特定することができます。
timestampはそのイベントの発生時刻を表します。予約アプリですので、時刻の特定は非常に重要で、timestampをすごく駆使します。それはおいおい・・・ちなみにプログラミングで用いられるtimestampの意味は、1970年1月1日00:00:00からの経過時間です。LINEのtimestampは13桁なので、ミリ秒を表してます。
関連して、2038年問題というものが存在するらしい((((;゚Д゚)))))))
さぁ、話を元に戻しまして、switch構文でev.typeの場合分けをしてあげてます。今回は、followイベントだけに対してですが、今後追加していきます。
followイベントに対しては、greeting_follow( )関数をpromiseで実行してます。なぜpromiseかというと、greeting_follow( )関数が非同期処理であるからです。非同期処理はこのプログラムの中で多用しますので、ぜひ復習しながらマスターしてください。
greeting_follow( ) のコーディング
関数の中身は以下のようになります。
const greeting_follow = async (ev) => {
const profile = await client.getProfile(ev.source.userId);
return client.replyMessage(ev.replyToken,{
"type":"text",
"text":`${profile.displayName}さん、フォローありがとうございます\uDBC0\uDC04`
});
}
非同期通信でprofileを取得するのでasync/awaitを使ってます。
ではprofileの中身がどうなっているかというと・・・
profile: {
userId: 'xxxxxxxxxxxx',
displayName: 'あなたのLINE表示名',
language: 'ja'
}
今回はdisplayNameが使いたかったため、profileを取得しました。
client.replyMessage(replyToken,{・・・});
はこのプラグラム中でよく使う構文ですので、嫌でも覚えることになるかと思います(笑)
なお、今回はreplyを使ってますが、LINE Messaging APIではpushメッセージも使えます。構文はreplyと似ていて次のようになります。
client.pushMessage(userId,{・・・})
LINE公式アカウントの料金体系で、フリープランはメッセージ通数1,000通まで無料というのを覚えておりますでしょうか。実は、この1,000通にカウントされるのがこのpushメッセージなのです。pushはユーザに対し、こちらから一方的に遅れるメッセージです(宣伝やメルマガなど)。しかし、今回はユーザのメッセージに返信するスタイルでアプリの設計をしておりますので、全てreplyで実現することができます。replyは課金対象のメッセージではないので、フリープランで使えるという訳です。私は当初、replyとpushの区別がつかず、pushメッセージを多用していたのである日突然BOTからの返事が来なくなったのです。これは重要ですので、ぜひ覚えておいてください。
最後に\uDBC0\uDC04は、遊び心の絵文字です。こちらの記事を参考にしていただければと思います。
https://www.pre-practice.net/2017/10/line-botline_21.html
いよいよHerokuへデプロイ
前回Herokuにlinebot-reservationという名前のアプリを作りました。このアプリへプログラムをデプロイするための設定を行います。
ターミナルで以下の処理を行います。
$ heroku login
herokuへのログインを行います。
$ git init
$ heroku git:remote -a アプリ名
アプリ名は私の場合は、linebot-reservationです。
では、いよいよデプロイです。
$ git add .
$ git commit -m "initial commit"
$ git push heroku master
さて、デプロイに成功するとターミナルにこんなメッセージが出てくると思います。
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote: Procfile declares types -> (none)
remote: Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote: Done: 23.1M
remote: -----> Launching...
remote: Released v8
remote: https://linebot-reservation.herokuapp.com/ deployed to Heroku
LINE公式アカウントを友達登録してみる
LINE Developersのページで作成したチャンネルのMessaging API設定の中にQRコードがあるかと思います。このQRコードを読み取り、公式アカウントを友達登録してみましょう。
なお、この時プログラムに不具合があると何も返事がありません。どんなエラーがあるのかを知るために、プログラムを試す前にターミナルで以下を実行しましょう。
$ heroku logs --tail
これを実行することにより、ターミナルでエラーのログ等を確認することができます。
以下のように返信がくれば成功です!!
今回の記事はかなりボリュームありましたね。
参考になりましたら「スキ」いただけると、今後も書くモチベーションになります!!
最後までお読みいただき、ありがとうございました。
MENTA でLINEBOT開発サポートをしております。お気軽にご相談ください。