使用Node.js和LINE BOT进行餐厅搜索

首先

2016年4月7日,LINE推出了“BOT API试用账户”的免费提供(仅限前1万名)。虽然已经有各种各样的文章出现了,但我没有找到使用Express的内容,所以我决定试试,自己制作了一款餐厅BOT,正如服务开启时的新闻所述。

当我写这篇文章的时候,我发现了一篇非常相似的文章,但对此毫不在意。真的。

这次我们正在将应用部署到Heroku上,但如果你搜索一下,会找到很多先人们的经验记录,所以这方面的话题我们就不谈了。
参考:使用Node.js+Express+EJS+Heroku进行Web应用开发 第1篇

环境

    • OS X El Capitan 10.11.3

 

    • node v5.4.1

 

    npm 3.5.3

准备好了

    • Herokuを使えるようにしておく

BOT API Trial Accountに登録して次の3つを取得

Channel ID
Channel Secret
MID

Herokuのアドオン(Fixie)用にクレジットカード ※無料

ぐるなび Webサービスからアクセスキーを取得

马上开始吧

暂时先运作起来的东西。

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

app.set('port', (process.env.PORT || 5000));
app.use(bodyParser.urlencoded({extended: true}));  // JSONの送信を許可
app.use(bodyParser.json());                        // JSONのパースを楽に(受信時)
// app.get('/', function(request, response) {
//     response.send('Hello World!');
// });

app.post('/callback', function(req, res){

    async.waterfall([
        // ぐるなびAPI
        function(callback) {

            var json = req.body;

            // 受信テキスト
            var search_place = json['result'][0]['content']['text'];
            var search_place_array = search_place.split("\n");

            //検索キーワード
            var gnavi_keyword = "";
            if(search_place_array.length == 2){
                var keyword_array = search_place_array[1].split("");
                gnavi_keyword = keyword_array.join();
            }

            // ぐるなびAPI レストラン検索API
            var gnavi_url = 'http://api.gnavi.co.jp/RestSearchAPI/20150630/';
            // ぐるなび リクエストパラメータの設定
            var gnavi_query = {
                "keyid":"<ぐるなびのアクセスキー>",
                "format": "json",
                "address": search_place_array[0],
                "hit_per_page": 1,
                "freeword": gnavi_keyword,
                "freeword_condition": 2
            };
            var gnavi_options = {
                url: gnavi_url,
                headers : {'Content-Type' : 'application/json; charset=UTF-8'},
                qs: gnavi_query,
                json: true
            };

            // 検索結果をオブジェクト化
            var search_result = {};

            request.get(gnavi_options, function (error, response, body) {
                if (!error && response.statusCode == 200) {
                    if('error' in body){
                        console.log("検索エラー" + JSON.stringify(body));
                        return;
                    }

                    // 店名
                    if('name' in body.rest){
                        search_result['name'] = body.rest.name;
                    }
                    // 画像
                    if('image_url' in body.rest){
                        search_result['shop_image1'] = body.rest.image_url.shop_image1;
                    }
                    // 住所
                    if('address' in body.rest){
                        search_result['address'] = body.rest.address;
                    }
                    // 緯度
                    if('latitude' in body.rest){
                        search_result['latitude'] = body.rest.latitude;
                    }
                    // 経度
                    if('longitude' in body.rest){
                        search_result['longitude'] = body.rest.longitude;
                    }
                    // 営業時間
                    if('opentime' in body.rest){
                        search_result['opentime'] = body.rest.opentime;
                    }

                    callback(null, json, search_result);

                } else {
                    console.log('error: '+ response.statusCode);
                }
            });

        },
    ],

    // LINE BOT
    function(err, json, search_result) {
        if(err){
            return;
        }

        //ヘッダーを定義
        var headers = {
            'Content-Type' : 'application/json; charset=UTF-8',
            'X-Line-ChannelID' : '<Your Channel ID>',
            'X-Line-ChannelSecret' : '<Your Channel Secret>',
            'X-Line-Trusted-User-With-ACL' : '<Your MID>'
        };

        // 送信相手の設定(配列)
        var to_array = [];
        to_array.push(json['result'][0]['content']['from']);


        // 送信データ作成
        var data = {
            'to': to_array,
            'toChannel': 1383378250, //固定
            'eventType':'140177271400161403', //固定
            "content": {
                "messageNotified": 0,
                "messages": [
                    // テキスト
                    {
                        "contentType": 1,
                        "text": 'こちらはいかがですか?\n【お店】' + search_result['name'] + '\n【営業時間】' + search_result['opentime'],
                    },
                    // 画像
                    {
                        "contentType": 2,
                        "originalContentUrl": search_result['shop_image1'],
                        "previewImageUrl": search_result['shop_image1']
                    },
                    // 位置情報
                    {
                        "contentType":7,
                        "text": search_result['name'],
                        "location":{
                            "title": search_result['address'],
                            "latitude": Number(search_result['latitude']),
                            "longitude": Number(search_result['longitude'])
                        }
                    }
                ]
            }
        };

        //オプションを定義
        var options = {
            url: 'https://trialbot-api.line.me/v1/events',
            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');
});

你在做什么?

当收到回调请求(用户发送的消息)时,

    • 一行目:住所 例)岩手県盛岡市

 

    二行目:検索キーワード 例)焼き肉、冷麺…

将其提取出来,然后向ぐるなび的API发送。
从搜索结果中筛选,

    • お店の名前

 

    • 画像

 

    • 住所

 

    • 緯度・経度

 

    営業時間

从中取出信息并在此处设置要从LINE BOT发送的信息,然后进行POST操作。
如果要发送的内容只有一个,则使用“发送消息”;如果有多个,则使用“发送多个消息”。

绊倒的地方

当我看到如何在Heroku上免费运行LINE BOT时,我决定先试一试。

使用 Fixie 的 Heroku 插件可以解决 LINE BOT API 调用需要指定连接源 IP 的问题,这让我觉得在 Heroku 上变得更容易了。

哇!太感激了。
在使用Fixie时,连免费的情况下都需要注册信用卡,所以我勉强输入了必要的信息。
然后,由于忘记了下一步的操作,耽误了很多时间。

在 Heroku 的管理界面中,点击 Resources > Fixie > account,然后将 Proxy URL 提交给 LINE BOT 所需。

然后,终于做出了一个像样的东西。

IMG_9307.PNG

总结

如果有任何建议请随时提出!(BOT API试用账户,好像还没达到1万名用户呢。。。)

广告
将在 10 秒后关闭
bannerAds