BluemixでぐるなびAPIを呼び出すLINE BOTを作成してみた


はじめに
---
自己学習のためにBluemixでLINE Messaging APIを使用してぐるなびAPIを呼び出すBOTを作成しました。
今回、Bluemix、LINE Message API、ぐるなびAPIの使い方等、多数のQiitaの記事(コードも含めて)を参考にさせていただきました。
この場を借りてお礼申し上げます。

用意するもの
---
Bluemixのアカウント
LINEビジネスアカウント
ぐるなびWebサービスのアクセスキー

BluemixでBOT用のサーバーを準備する
---
今回はNode.jsで実装するため、ダッシュボードから「アプリ作成」ボタンをクリックしカタログ画面に遷移し、「SDK for Node.js」を選択する
![Kobito.flL10s.png](https://qiita-image-store.s3.amazonaws.com/0/60232/483cd7ca-0436-ff90-7e35-f07779471f3f.png "Kobito.flL10s.png")

Cloud Foundryアプリの作成画面にて「アプリ名」を入力して「作成」ボタンをクリックする
![Kobito.wINH12.png](https://qiita-image-store.s3.amazonaws.com/0/60232/79bdfddc-ff7c-b60b-0060-c228a6bba5f6.png "Kobito.wINH12.png")


LINE BOTを準備する
---
webhook URLにbluemix側でリクエストを受け付けるURLを指定し、Channel Access Tokenをメモしておく
![スクリーンショット 2017-05-05 0.16.08.png](https://qiita-image-store.s3.amazonaws.com/0/60232/0b981370-ead8-86c2-df4c-a24f15f25758.png "スクリーンショット 2017-05-05 0.16.08.png")

LINE@MANAGERのBot設定を下記のように変更する。
　Webhook送信　→　利用する
　自動応答メッセージ →　利用しない
![image](https://qiita-image-store.s3.amazonaws.com/0/60232/9f8ba755-82ed-7459-eef1-bb27b3ab3378.png)


DevOppsServiceにてソースを編集する
---
概要ページの継続的デリバリーの「hub.jazz.net でプロジェクトをセットアップするために「Git の追加」ボタンをお探しですか? ここをクリックしてください」の「ここを」をクリックする
![Kobito.bQQX6P.png](https://qiita-image-store.s3.amazonaws.com/0/60232/1c89acfe-1c41-0016-5f1b-cf83cdb9256b.png "Kobito.bQQX6P.png")

「コードの編集」をクリック
![Kobito.K8h87P.png](https://qiita-image-store.s3.amazonaws.com/0/60232/0484c2ad-2a72-a156-9127-5707ac6d49fd.png "Kobito.K8h87P.png")

package.jsonのdependenciesを下記のように書き換える

```package.json
	"dependencies": {
		"express": "4.13.x",
		"cfenv": "1.0.x",
		"body-parser": "1.15.2",
		 "request": "2.75.0",
		 "async":"*"
	},
```

app.jsを下記のように更新する

```app.js

// This application uses express as its web server
// for more info, see: http://expressjs.com
var express = require("express");

// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require("cfenv");

// create a new express server
var app = express();

// ---- 追加　ここから -------//
var async = require("async");

var bodyParser = require("body-parser");

var request = require("request");

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

app.post("/api", function(req, res) {
	// 検索結果をオブジェクト化
	var search_result = {};
	
	var err = null;             
	
    async.waterfall([
    
        function (callback) {            
            var json = req.body;              
            // 受信テキスト
            var search_place = json["events"][0]["message"]["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();
            }
            
            var gnavi_url = "http://api.gnavi.co.jp/RestSearchAPI/20150630/";
            
            // ぐるなび リクエストパラメータの設定
            var gnavi_query = {
                "keyid":"<ぐるなびWebサービスのアクセスキー>",
                "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
            };

            request.get(gnavi_options, function (error, response, body) {
                if (!error && response.statusCode === 200) {
                	
                    if("error" in body){
						err = body.error.message;
                        console.log("検索エラー" + JSON.stringify(body));				
						callback(err);
                        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(err,json, search_result );
                } else {
                    console.log("error: "+ response.statusCode);
                }
            });
        }

    ],

    
    function(err,json,search_result){
	var options = {};
	
		if (err === null ){		
			options = {
				method: "POST",
				uri: "https://api.line.me/v2/bot/message/reply",
				body: {
					replyToken: req.body.events[0].replyToken,
					messageNotified: 0,	
					messages: [
						// 基本情報
						{
							contentType: 1,
							type: "text",
							text: "こちらはいかがですか？\n【お店】" + search_result["name"] + "\n【営業時間】" + search_result["opentime"],
						}
						,
						// 写真
						{
							contentType: 2,
							type: "image",
							originalContentUrl: search_result["shop_image1"],
							previewImageUrl: search_result["shop_image1"]
	                    }
	                    ,
	                    // 位置情報
	                    {
	                        contentType:7,
	                        type: "location",
	                        title: search_result["name"],
	                        address: search_result["address"],
	                        latitude: Number(search_result["latitude"]),
	                        longitude: Number(search_result["longitude"])
	                    }
					]
				},
				auth: {
					bearer : "<自分のToken>"
				},
				json: true
			};
			

		}else{
			options = {
				method: "POST",
				uri: "https://api.line.me/v2/bot/message/reply",
				body: {
					replyToken: req.body.events[0].replyToken,
					messageNotified: 0,	
					messages: [
						// 基本情報
						{
							contentType: 1,
							type: "text",
							text: "検索エラーです。下記の例の様に入力してください。\n例：\n東京都中央区\n蕎麦",
						}
					]
				},
				auth: {
					bearer : "<自分のToken>"
				},
				json: true
			};
			
		}

		request(options, function(err, res, body) {
				console.log(JSON.stringify(res));
		});
		res.send("OK");
	});
    
});
    
// ---- 追加　ここまで -------

// serve the files out of ./public as our main files
app.use(express.static(__dirname + "/public"));

// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();

// start server on the specified port and binding host
app.listen(appEnv.port, "0.0.0.0", function() {
  // print a message when the server starts listening
  console.log("server starting on " + appEnv.url);
});
```

ソースの修正が完了したらコミット＆プッシュする
---
左側のメニューからGitをクリックする
![Kobito.juhO30.png](https://qiita-image-store.s3.amazonaws.com/0/60232/a37ea543-ee6f-5dd1-dfc2-bbcbbdcfce7b.png "Kobito.juhO30.png")

コメントを入力してコミットをクリックする
![Kobito.CYuZX1.png](https://qiita-image-store.s3.amazonaws.com/0/60232/c59b1471-c8e9-097c-d68d-d06a50bf03a1.png "Kobito.CYuZX1.png")


発信の右側のPushボタンを押す
![Kobito.wCgA6Q.png](https://qiita-image-store.s3.amazonaws.com/0/60232/d4c00113-2f10-e7a8-eb57-ece92aa66bb9.png "Kobito.wCgA6Q.png")

右上のBUILD＆DEPLOYボタンを押す
![Kobito.meaLYL.png](https://qiita-image-store.s3.amazonaws.com/0/60232/d47e02f7-62d8-1703-536e-320f161550ef.png "Kobito.meaLYL.png")

Delopy Stageが「ステージの成功」となることを確認する
![Kobito.WqgxwU.png](https://qiita-image-store.s3.amazonaws.com/0/60232/45a7e648-2033-3184-b068-8bb024463631.png "Kobito.WqgxwU.png")

動作確認
---
下記の組み合わせで送信する
都道府県名＋市区町村名
レストランのカテゴリ

例：
東京都中央区
蕎麦

<img src=https://qiita-image-store.s3.amazonaws.com/0/60232/2ce4c240-565e-5b4b-145a-4e167f55e82a.png width=400px>