LINE Messaging API を使ってオウム返しする Node.js 製チャットボットを作ってみる
突然だが、LINE Messaging API というモノを使って、簡単なチャットボットを作ってみる。
完成すると、LINE アプリでチャットボット用アカウントを友達登録して、トーク画面から会話できるようになる。メッセージの処理はしないので、ただユーザの発言をオウム返しする Chat Bot だが…。
目次
- LINE Developers に登録する
- プロバイダを作成する
- Messaging API チャネルを作成する
- チャネル情報を取得する
- Node.js Express サーバを実装する
- Webhook サーバを Heroku にデプロイする
- Webhook 設定を行う
- LINE アプリで実際に試してみる
- 以上
LINE Developers に登録する
まずは、「LINE Developers」という開発者用プログラムに登録する。普段 LINE アプリで使っている LINE アカウントを紐付けて登録できるようになる。
登録は上の公式サイトより。登録が完了すると、LINE Developers Console と呼ばれる管理画面に遷移する。
プロバイダを作成する
LINE Developers Console が開けたら、「新規プロバイダー作成」ボタンから、プロバイダと呼ばれる「くくり」を作る。1つのプロバイダの中に、いくつかの「チャネル」を作れるようになっている。「チャネル」というのが、チャットボットアカウント1つに相当する感じ。
Messaging API チャネルを作成する
プロバイダを登録したら、「Messaging API」用の「チャネル作成する」ボタンがあると思うので、コレを押下する。
登録時、「プラン」より「Developer Trial」プランを選ぶ。友達登録数などに制限はあるものの、無料で Push API などを利用できる。企業向けの「Phone Number Push API」や「Switcher API」なんかは「Developer Trial」プランでも試せないのであしからず。
- 参考 : LINE、「友だち」登録なしで電気料金や宅配時間をプッシュ通知へ - CNET Japan … Phone Number Push API
- 参考 : https://www.oracle.co.jp/events/platform2017/download/pdfs/ocps17_3-c.pdf … Switcher API
- LINE ってこういうエンプラ向けの情報全然公開してくれないよね…
チャネルが作成できたら、「チャネル基本設定」画面に移動する。友達登録用の QR コードが見えているので、コレを利用して友達登録をしておこう。デフォルトで自動応答メッセージ機能などが組み込まれており、一応の応答は得られるので、まずは「自分で開発用アカウントを作った感」は味わえるかと。
チャネル情報を取得する
LINE Messaging API は、ユーザからの発言をまず「LINE 社のサーバ」が受け取り、それを「自前の Webhook サーバ」で受信する。受信したメッセージに応じて応答メッセージを構築し、「LINE Messaging API サーバ」に返信すると、ユーザに応答メッセージが返される、という仕組みになっている。
これから「自前の Webhook サーバ」を作るワケだが、その際、ちゃんと LINE から送られてきたリクエストなのか、自分が作ったチャネルでのやり取りなのか、といったことを検証するために、チャネルに関する以下の情報が必要になる。
- Channel ID
- Channel Secret
- Channel Access Token
これらの文字列は、先程の「チャネル基本設定」画面で閲覧、もしくは発行できる。
「Channel ID」は最初から決まっているので控えておく。「Channel Secret」も最初から発行されているが、後から別のモノに再発行したりもできる。コレが漏洩すると不正な操作をされかねないので、厳重に管理しよう。
「Channel Access Token」は、「チャネル基本設定」画面の下部、「アクセストークン (ロングターム)」という画面から発行できる。初回であっても「再発行」ボタンだが、押下する。「失効までの時間」とやらを尋ねられるが、コレは、古いチャネルアクセストークンを失効させるまでの有効期限であり、これから発行するチャネルアクセストークンには関係ない。「0 時間」(失効しない) を選んでおけば OK。
この「アクセストークン (ロングターム)」欄から発行できるチャネルアクセストークンは、この後の「再発行」時に、時間を指定して失効させるまではずっと利用できる。開発中はコレで問題ないだろう。
新しく発行したロングタームのアクセストークンは再発行ボタンを再度押す(+指定した経過時間)まではずっと有効です。
コレとは別に、LINE API をコールしてもチャネルアクセストークンを取得できる。コチラは発行日から30日間で失効するモノで、直近に発行した30個のチャネルアクセストークンが有効となる。本番利用するモノはコチラがメインとなるだろうか。
- 参考 : Messaging APIリファレンス
Node.js Express サーバを実装する
さて、いよいよ Webhook サーバの実装だ。
ちなみに Webhook とは、POST メソッドによるリクエストを契機として何らかの処理を行うサーバの仕組みのことだ。別に特殊なツールやフレームワークを使う必要はなく、POST リクエストを受け付けて何かすれば、それはもう Webhook サーバなのである。
- 参考 : Webhookとは? - Qiita
Node.js で Webhook サーバを実装する際は、LINE 公式が提供している @line/bot-sdk
という npm パッケージを利用すると良いだろう。Express サーバ向けの専用ミドルウェアも提供されているので、Express + @line/bot-sdk
な組み合わせで実装することにしよう。
# 作業用ディレクトリの準備
$ mkdir my-line-chat-bot && cd $_
$ npm init -y
# パッケージのインストール
$ npm install -S @line/bot-sdk express
# メイン処理を書くファイルを用意
$ touch index.js
オウム返し用の実装だが、実は @line/bot-sdk
パッケージ内にサンプル実装が一式揃っているので、コレを利用してみよう。
- line-bot-sdk-nodejs/examples/echo-bot at master · line/line-bot-sdk-nodejs · GitHub
- line-bot-sdk-nodejs/index.js at master · line/line-bot-sdk-nodejs · GitHub
ただし、この公式のサンプル実装は、後述する 「Webhook 接続確認」でエラーを返してしまう作りになっているので、そこだけちょっと改善しておこう。
const line = require('@line/bot-sdk');
const express = require('express');
// 環境変数からチャネルアクセストークンとチャネルシークレットを取得する
const config = {
channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
channelSecret: process.env.CHANNEL_SECRET
};
// LINE クライアントを生成する : `channelSecret` が未定義だと例外が投げられる
const client = new line.Client(config);
// Express アプリを生成する
const app = express();
// LINE Bot SDK が提供するミドルウェアを挟み込み、リクエストヘッダの署名検証や JSON パースなどを任せてしまう
app.post('/callback', line.middleware(config), (req, res) => {
// 1回のリクエストに複数のメッセージが含まれていたりすることもあるので
// イベントの配列を1件ずつ取得して処理してやる
const events = req.body.events;
Promise.all(events.map((event) => {
// イベント1件を処理する・エラー時も例外を伝播しないようにしておく
return handleEvent(event).catch(() => { return null; });
})
.then((result) => {
// 全てのイベントの処理が終わったら LINE API サーバには 200 を返す
res.status(200).json({}).end();
});
});
/**
* イベント1件を処理する
*
* @param {*} event イベント
* @return {Promise} テキストメッセージイベントの場合は client.pushMessage() の結果、それ以外は null
*/
function handleEvent(event) {
// メッセージイベントではない場合、テキスト以外のメッセージの場合は何も処理しない
if(event.type !== 'message' || event.message.type !== 'text') {
return Promise.resolve(null);
}
// 返信用メッセージを組み立てる : ユーザからのメッセージにカギカッコを付けて返信してみる
const echoMessage = {
type: 'text',
text: `「${event.message.text}」`
};
// Reply API を利用してリプライする
return client.replyMessage(event.replyToken, echoMessage);
// Push API を利用する場合は以下のようにする
// return client.pushMessage(event.source.userId, echoMessage);
}
// サーバを起動する
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`Listening on ${port}`);
});
このように実装すると、/callback
パスに対する POST リクエストを契機に、LINE ユーザへの返信を行えるようになる。
「LINE から送られるイベント」とは何か、というのは、以下のページを見ると良いだろう。メッセージイベントの他に、フォローをしたとか、アカウント連携をしたとか、そういうユーザの操作も「イベント」として送信されてくるのだ。
- 参考 : Messaging APIリファレンス
単純に大人数が使うチャネルに成長して、複数のユーザが同時にメッセージを送ったような場合も、このイベントが複数格納される場合がある。1回のリクエストにつき、複数の返信を行わないといけない場合もあるので、Promise.all()
でイベントを分割して1件ずつ処理している。
ユーザへの返信は client.replyMessage()
関数内で行われている。/callback
パスへのレスポンスがどうであろうと、実はあまり関係ないのだ。そのため、Promise.all()
内で例外を発生させないようにし、/callback
パスのレスポンスとしては必ず 200
を返すようにした。
Webhook サーバを Heroku にデプロイする
さて、Webhook サーバを実装したはいいものの、コレを実際に LINE と連携させるには、コレを HTTPS サーバに配置しないといけない。以前はオレオレ証明書を利用したローカルサーバでも LINE からの通信を受信できたようだが、現在はできなくなっているので、今回は無料で Node.js アプリをデプロイできる Heroku を利用する。
Heroku アカウントの用意や、デプロイするための設定事項は、以下の記事を参照されたし。
主なところだと、package.json
に scripts.start
プロパティを設定してサーバが起動するように設定しておくのと、engines
プロパティを記載しておくことくらいか。
あと、Heroku の管理画面より、以下の2つの環境変数を設定しておくこと。
CHANNEL_ACCESS_TOKEN
: チャネルアクセストークン (管理画面「アクセストークン (ロングターム)」欄から発行したヤツ)CHANNEL_SECRET
: チャネルシークレット (管理画面「Channel Secret」欄の文字列)
コレで、$ git push heroku master
と Push してやろう。https://my-line-chat-bot.herokuapp.com/callback
といった URL が用意できれば OK だ。
Webhook 設定を行う
コレで、オウム返し処理を行う Webhook サーバが用意できたので、コイツを Messaging API チャネルに組み込んでやる。
「チャネル基本設定」画面に移動したら、以下のように設定を変更していく。
- 「自動応答メッセージ」 : 「利用する」から「利用しない」に変更する
- コレまで自動応答していたデフォルトメッセージを返さないようにする。Webhook サーバと併用してしまうと、「自動応答メッセージ」と「Webhook サーバからの返信」が両方届いてしまう変な Bot になってしまう
- 「Webhook 送信」 : 「利用する」に変更する
- 「Webhook URL」を設定してもコレを忘れると Webhook サーバが利用されない
- 「Webhook URL」 : Heroku にアップした Webhook サーバの
/callback
パスまでの URL を入力する- 「この URL に POST リクエストを送ってください」という設定なので、
https://my-line-chat-bot.herokuapp.com/callback
といった URL を指定してやる - 設定してから少し待つと「接続確認」ボタンが表示されるので、コレを押して疎通確認してみる。POST リクエストに対して 200 を返してくるかどうかで、上手くいっているかを教えてくれる
- 「この URL に POST リクエストを送ってください」という設定なので、
コレで設定完了。設定の反映はほとんど即時で行われるが、気になるようなら数分待ってから動作検証してみよう。
LINE アプリで実際に試してみる
コレで LINE 側の設定が終わったので、実際に LINE アプリでチャットボットに向かってトークしてみよう。Webhook サーバがリクエストを受信し、メッセージイベントを検知して Reply API をコールしてくれたら、メッセージが返信されてくるはずだ。
以上
最も簡単なサンプルはこんな感じ。
画像をやり取りするとか、Flex Message と呼ばれるリッチな応答を返すとか、複雑なことをやろうとすると、もう少し作り込みが必要になってくるが、今回はこの辺で。