LINE Messaging API を使用して、会話の「くっころ」という言葉に反応して「くっころ」してしまうBOTを作成する方法

  • 30
    いいね
  • 0
    コメント

始めに

Node.js の勉強のために、LINE Messaging API を使用したBOTを作成しました。
Qiitaには LINE BOT API についての記事は多かったのですが、LINE Messaging API についての記事は少なかったため、共有します。

作ったもの

LINEの会話の「くっころ」という言葉に反応して、「くっころ」してしまうBOTです。
1対1の会話と、トークルームでの会話に対応しています。
ソースは以下で公開しています。
https://github.com/k-nakayama-pg/kukkoro-bot

キャプチャ.PNG

作成方法

1.LINE Messaging API の登録

Messaging APIのご紹介 | LINE Business Center から登録できるので、必要な情報を入力して登録してください。

2.LINE@ MANAGER でWebhook送信を利用するに設定

登録が終わるとLINE@ MANAGER という画面に移ると思います。
ここで [アカウント設定]>[BOT設定]>[リクエスト設定]のWebhook送信を「利用する」にチェックを入れてください。
これを忘れると、後で設定するWebhook URLを設定してもリクエストがBOTに送信されません(実体験)

キャプチャ2.PNG

3.LINE Developers でChannel SecretとChannel Access Tokenを確認

LINE@ MANAGERの[アカウント設定]>[BOT設定]>[ステータス]の「LINE Developersで設定する」というリンクからLINE Developersの画面に行きます。そこで、Messaging APIに必要な以下の2つの値を確認してください。
 - Channel Secret : リクエストがLINE Platformから送られてきたか署名検証する際に必要になります
 - Channel Access Token : Messaging APIの認証に必要になります

キャプチャ3.PNG

キャプチャ4.PNG

4.LINE Platformからリクエストを受け取って、Messaging APIに返事のテキストを送信するBOTの作成

以下がソースです。
Nodejs+LINE BOTでレストラン検索 - Qiita を参考にして作成しました。
Messaging APIから受け取るレスポンスやリクエストの方法は、LINE Developers API Document に詳しく説明されていたため、それを参考にしました。

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var request = require('request');
var crypto = require("crypto");
var async = require('async');

app.set('port', (process.env.PORT || 8000));
// JSONの送信を許可
app.use(bodyParser.urlencoded({
    extended: true
}));
// JSONのパースを楽に(受信時)
app.use(bodyParser.json());

app.post('/callback', function(req, res) {
    async.waterfall([
            function(callback) {
                // リクエストがLINE Platformから送られてきたか確認する
                if (!validate_signature(req.headers['x-line-signature'], req.body)) {
                    return;
                }
                // テキストが送られてきた場合のみ返事をする
                if ((req.body['events'][0]['type'] != 'message') || (req.body['events'][0]['message']['type'] != 'text')) {
                    return;
                }
                // 「くっころ」という単語がテキストに含まれている場合のみ返事をする
                if (req.body['events'][0]['message']['text'].indexOf('くっころ') == -1) {
                    return;
                }

                // 1対1のチャットの場合は相手のユーザ名で返事をする
                // グループチャットの場合はユーザ名が分からないので、「貴様ら」で返事をする
                if (req.body['events'][0]['source']['type'] == 'user') {
                    // ユーザIDでLINEのプロファイルを検索して、ユーザ名を取得する
                    var user_id = req.body['events'][0]['source']['userId'];
                    var get_profile_options = {
                        url: 'https://api.line.me/v2/bot/profile/' + user_id,
                        proxy: process.env.FIXIE_URL,
                        json: true,
                        headers: {
                            'Authorization': 'Bearer {' + process.env.LINE_CHANNEL_ACCESS_TOKEN + '}'
                        }
                    };
                    request.get(get_profile_options, function(error, response, body) {
                        if (!error && response.statusCode == 200) {
                            callback(body['displayName']);
                        }
                    });
                } else if ('room' == req.body['events'][0]['source']['type']) {
                    callback('貴様ら');
                }
            },
        ],
        function(displayName) {
            //ヘッダーを定義
            var headers = {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer {' + process.env.LINE_CHANNEL_ACCESS_TOKEN + '}',
            };

            // 送信データ作成
            var data = {
                'replyToken': req.body['events'][0]['replyToken'],
                "messages": [{
                    "type": "text",
                    "text": displayName + 'にこんな辱めを受けるとは...!\nくっ...殺せ!'
                }]
            };

            //オプションを定義
            var options = {
                url: 'https://api.line.me/v2/bot/message/reply',
                proxy: process.env.FIXIE_URL,
                headers: headers,
                json: true,
                body: data
            };

            request.post(options, function(error, response, body) {
                if (!error && response.statusCode == 200) {
                    console.log(body);
                } else {
                    console.log('error: ' + JSON.stringify(response));
                }
            });
        }
    );
});

app.listen(app.get('port'), function() {
    console.log('Node app is running');
});

// 署名検証
function validate_signature(signature, body) {
    return signature == crypto.createHmac('sha256', process.env.LINE_CHANNEL_SECRET).update(new Buffer(JSON.stringify(body), 'utf8')).digest('base64');
}

気をつけたところ

1.リクエストがLINE Platformから送られてきたか確認

 
LINE Developers API Document で以下のような記述がありました。

X-Line-Signature Request Headerに入っているSignatureを検証することによって、
リクエストがLINE Platformから送信されたものであることを確認する必要があります。

検証は以下の手順で行います。

  1. Channel Secretを秘密鍵として、HMAC-SHA256アルゴリズムによりRequest Bodyのダイジェスト値を得る。
  2. ダイジェスト値をBASE64エンコードした文字列が、Request Headerに付与されたSignatureと一致することを確認する。

検証には3.で確認したChannel Secretが必要になります。
ソース内の validate_signature(signature, body) メソッドが検証をしているメソッドになります。
LINE Messaging APIでX-Line-Signatureの署名検証を行う - Qiita を参考にしました。

2.Messaging API にリクエストする時のパラメータ

Messaging APIは、それまでのBOT APIと違って、リクエスト時に必要なパラメータが違いました。
BOT APIの時に必要だったMIDはなくなりました。
Messaging APIには以下のパラメータが必要です。

  • Request Headers
    • Authorization : Bearer {Channel Access Token}(3.で確認したChannel Access Token)
  • Request Body
    • replyToken : Webhookで受信したreplyToken(webhookからのリクエストのbody内に入っています)

詳しくはLINE Developers API Documentを参考にしてください。

5.herokuにソースをデプロイ

herokuへのデプロイはたくさん記事があるのでここでは書きません。
Channel SecretとChannel Access Tokenを忘れずに環境変数に追加してください。

6.Webhook URLの設定

最後の設定です。デプロイしたソースのアクセスURLをWebhook URLに設定します。
LINE BOT の参加しているトークルームや友達から会話があると、ここに設定したURLにリクエストが送られるようになります。
LINE Developersから設定できます。

キャプチャ5.PNG

7.動作確認

作成したLINE BOT を友達に追加して、話しかけることで確認できます。

キャプチャ6.PNG

まとめ

LINE Messaging APIはドキュメントが丁寧に書かれていたため、特につまづくことなく作成することができました。
特にLINE Developers API Documentには、APIの説明だけでなく、各言語別の実装サンプルコードまで書いてあったため、すごく助かりました。
皆さんも、LINE Messaging APIを使ってLINE BOTを作ってみてください。