PHP
api
bot
linebot

【LINE BOT API】位置情報を送ると近くのラーメン屋さんを教えてくれるBOTを作ってみました

More than 1 year has passed since last update.

[追記 5/24]
位置情報以外を送ると近辺以外のラーメン屋さんが10件でたらめに返ってきたので、ユーザが送信したコンテンツタイプを取得して、コンテンツタイプが位置情報以外の場合は使い方を返すようにコードを修正しました。

[追記 5/25]
・検索結果に、「Powered by ぐるなび」のテキスト表示を追加しました。
ぐるなびAPI - クレジット表示について
・BOT追加時にメッセージが表示されるようにコードを修正しましたが、表示されません。本当に最初の1回のみしかopTypeは取得できないのだろうか?ただいま、調査中です。
・一部重複しているコードをリファクタリングしました。
・Qiitaのタイトル変更しました。
(修正前)
LINE BOT APIを利用してXSERVER + PHP + ぐるなびAPIでラーメン屋BOTを作ってみました
(修正後)
【LINE BOT API】位置情報を送ると近くのラーメン屋さんを教えてくれるBOTを作ってみました

概要

酔っ払った後、無性にラーメンが食べたくなります。しかし、そんな時はスマホを使って手入力によるラーメン屋さんの検索が危うい程酔っ払っているものです(笑)

ラーメン屋BOTは、そんな酔っ払いに優しいBOTでして、LINEで位置情報を送ると近辺のラーメン屋さんが最大10件リストになって返ってきます。

ただし、ぐるなびAPIを利用しているので、ぐるなびに登録されていないラーメン屋さんは返ってきません(笑)

当初は食べログAPIを使ってランキング順に表示したかったのですが、なんと食べログAPIはサービス終了!!

RettyのAPIが公開されないかなあ(笑)

環境と使った技術など

XSERVER
PHP5.6.18
SSLはXSERVERの共有SSLを利用
ぐるなびAPI

はまった点

私が利用しているXSERVERのPHPのバージョンが、5.3.3だったため他の方のサンプルコードに書いてあった配列の初期化array = []が使えなくエラーとなっていたが見つけるまでに時間がかかりました。(私の知識不足)

PHPのバージョンは、XSERVERのサーバーパネルからPHPのバージョン切り替えで5.6.18にバージョンアップすることによりサンプルコードが動きました。

最初Lineにcallbackで指定したurlがまだ反映されるのは時間がかかるということが書いてある記事が複数あったため、それがエラーの原因と勘違いしていましたが、数日待ってもエラーが解消されないので、問題はコードのどこかに原因があるのではと思い原因調査。

PHPの知識もあまり無く、原因が判明するのに時間がかかってしまいました。

使い方

ただ位置情報を送るだけです。
LINEから送った位置情報から現在地の緯度と経度取得し、緯度と経度をぐるなびAPIに送り、APIより近くのラーメン屋を最大10件返してもらっています。

Screenshot_2016-05-21-21-08-22.jpg

実装

実装に当たって以下の記事が大変参考になりました。ありがとうございました(^_^)

Line bot trial アカウントの取得方法は以下の記事をご参考に。

LINE BOT API Trialでできる全ての事を試してみた
LINE BOT APIを利用した地獄のミサワBOTの作り方
【LINE Bot】Heroku+PHP+ぐるなびAPIで蕎麦探しBot作ってみた
エックスサーバーとPHPを使ってLINE BOTを作る方法。プログラミングの練習に最適だぞ!

line_callback.php
<?php
// ぐるなびアクセスキー
const GNAVI_ACCESS_KEY = "input your gnavi access key";
const LINE_CHANNEL_ID = "input your channel id";
const LINE_CHANNEL_SECRET = "input your channel secret";
const LINE_MID = "input your mid";

$request = file_get_contents('php://input');
$jsonObj = json_decode($request);
$to = $jsonObj->{"result"}[0]->{"content"}->{"from"};
$contentType = $jsonObj->{"result"}[0]->{"content"}->{"contentType"};
$opType = $jsonObj->{"result"}[0]->{"content"}->{"opType"};

// 友達追加時に送信するメッセージ
if ($opType !== null && $opType === 4) {
    $response_format_text = ['contentType'=>1,"toType"=>1,"text"=>"ご登録ありがとうございます!"];
    send_message_to_user($to,$response_format_text);
    return;
}

if ($contentType !== 7) {
    $response_format_text = ['contentType'=>1,"toType"=>1,"text"=>"位置情報を送って下さいね〜"];
    send_message_to_user($to,$response_format_text);
} else {
    $ramen_info = get_ramen_info($jsonObj);
    $response_format_text = ['contentType'=>1,"toType"=>1,"text"=>$ramen_info];
    send_message_to_user($to,$response_format_text);    
}

function send_message_to_user($to,$response_format_text){
    $post_data = ["to"=>[$to],"toChannel"=>"1383378250","eventType"=>"138311608800106203","content"=>$response_format_text];
    $ch = curl_init("https://trialbot-api.line.me/v1/events");
    curl_setopt($ch, CURLOPT_POST,true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, create_http_header());
    $result = curl_exec($ch);
    curl_close($ch);
}

function create_http_header(){
    $content_type = 'Content-Type: application/json; charser=UTF-8';
    $channel_id = 'X-Line-ChannelID: '.LINE_CHANNEL_ID;
    $channel_secret = 'X-Line-ChannelSecret: '.LINE_CHANNEL_SECRET;
    $mid = 'X-Line-Trusted-User-With-ACL: '.LINE_MID;
    return array($content_type,$channel_id,$channel_secret,$mid);
}

// ぐるなびWebサービスを利用した検索
function get_ramen_info($jsonObj){
    // ぐるなびWebサービス利用するためのURLの組み立て
    $url = build_url($jsonObj);
    // API実行
    $json = file_get_contents($url);
    return parse($json);
}


function build_url($jsonObj){

    //エンドポイント
    $uri = "http://api.gnavi.co.jp/RestSearchAPI/20150630/";

    //APIアクセスキーは、ぐるなびで取得して設定します。
    $acckey = GNAVI_ACCESS_KEY;

    //返却値のフォーマットを変数に入れる
    $format= "json";

    //緯度・経度、範囲、及びカテゴリーにラーメンを設定
    $location = $jsonObj->{"result"}[0]->{"content"}->{"location"};
    $lat   = $location->latitude;
    $lon   = $location->longitude;
    $range = 3;
    // 業態がラーメン屋さんを意味するぐるなびのコード(大業態マスタ取得APIをコールして調査)
    $category_s = "RSFST08008";

    //URL組み立て
    $url  = sprintf("%s%s%s%s%s%s%s%s%s%s%s%s%s", $uri, "?format=", $format, "&keyid=", $acckey, "&latitude=", $lat,"&longitude=",$lon,"&range=",$range,"&category_s=",$category_s);

    return $url;
}

function parse($json){

    $obj  = json_decode($json);

    $result = "";

    $total_hit_count = $obj->{'total_hit_count'};

    if ($total_hit_count === null) {
        $result .= "近くにラーメン屋さんはありません。";
    }else{
        $result .= "近くにあるラーメン屋さんです。\n\n";
        foreach($obj->{'rest'} as $val){

            if (checkString($val->{'name'})) {
                $result .= $val->{'name'}."\n";
            }

            if (checkString($val->{'address'})) {
                $address = get_address_without_postal_code($val->{'address'});
                $result .= $address."\n";
            }

            if (checkString($val->{'url'})) {
                $result .= $val->{'url'}."\n";
            }

            $result.="\n"."\n";
        }
        $result.="Powered by ぐるなび";
    }
    return $result;
}

function get_address_without_postal_code($address){
    return mb_substr($address,11);
}

//文字列であるかをチェック
function checkString($input)
{
    if(isset($input) && is_string($input)) {
        return true;
    }else{
        return false;
    }
}

今後追加したい機能

1.現時点でぐるなびから返ってきたラーメン屋リストをそのまま表示しているので、位置情報から一番近い順に並び替えて表示とかさせたいです。
2.お店のURLが長いのでショートURLにしようかなと。

感想

作っているうちに他にも色々アイデアが浮かんできましたが、現時点で1アカウント1ボットなのが悲しい!

早く複数ボットを使えるようになりたいです。

そして、単純に作っていて楽しかったです!!

最後に

宜しければお使い下さい。
ただしトライアルアカウントなので50人までしか使えないみたいです。
また裏で色々とソースをいじっているので使えない時があるかもです(笑)
13249521_965957006833237_1020733240_n (1).png