위치 정보를 보내면 인근 숙박 시설을 반환하는 LINEBot 만들기

처음에



LINEmessagingAPI + WebAPI에서 위치 정보를 보내면 근처의 숙박 시설을 반환하는 LINEBot을 만들었습니다.
다음에 가장 가까운 역도 반환합니다.

사용한 API
■라쿠텐 여행 시설 검색 API(숙박 시설의 검색)
ぇtps://우ぇbせrゔぃせ. 라쿠텐. 이. jp/아피/시mpぇ호테l세아rch/

■HeartRails Geo API(가장 가까운 역의 검색)
h tp // 게오아피. 헤어 rt 같다 ls. 코m/

코드


'use strict'; // おまじない

// ########################################
//               初期設定など
// ########################################

// パッケージを使用します
const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');

// ローカル(自分のPC)でサーバーを公開するときのポート番号です
const PORT = process.env.PORT || 10000;

// Messaging APIで利用するクレデンシャル(秘匿情報)です。
const config = {
    channelSecret: '作成したBotのチャネルシークレット',
    channelAccessToken: '作成したBotのチャネルアクセストーク'
};



// ########## ▼▼▼ サンプル関数 ▼▼▼ ##########
const sampleFunction = async (event) => {
    // ユーザーメッセージが位置情報かどうか
    if (event.message.type == 'location') {
        let pushText = '';
        const latitude = event.message.latitude;
        const longitude = event.message.longitude;
        const postNumber = event.message.address.split('')[1].split(' ')[0].replace('-','');

        //楽天トラベル施設検索APIで、指定された位置情報から半径1km以内の宿を検索(おすすめ順・5件)
        client.pushMessage(event.source.userId, {
            type: 'text',
            text: '1km以内の宿泊施設を検索します。',
        });
        try {
            const rakuten = await axios.get('https://app.rakuten.co.jp/services/api/Travel/SimpleHotelSearch/20170426?applicationId=アプリID&format=json&latitude=' + latitude + '&longitude=' + longitude + '&searchRadius=1&datumType=1&hits=5');
            for(let i in rakuten.data.hotels){
                client.pushMessage(event.source.userId, {
                    type: 'text',
                    text: rakuten.data.hotels[i]['hotel'][0]['hotelBasicInfo']['hotelInformationUrl'],
                });
            }
        } catch (error) {
            pushText = '楽天検索中にエラーが発生しました。ごめんね。';
            // APIからエラーが返ってきたらターミナルに表示する
            console.error(error);
            client.pushMessage(event.source.userId, {
                type: 'text',
                text: pushText,
            });
        }

        //郵便番号から最寄駅を検索
        try {
            const station = await axios.get('http://geoapi.heartrails.com/api/json?method=getStations&postal=' + postNumber);
            client.pushMessage(event.source.userId, {
                type: 'text',
                text: '最寄り駅は' + station.data['response']['station'][0].name + '駅です。',
            });
        } catch (error) {
            pushText = '最寄り駅検索中にエラーが発生しました。ごめんね。';
            // APIからエラーが返ってきたらターミナルに表示する
            console.error(error);
            client.pushMessage(event.source.userId, {
                type: 'text',
                text: pushText,
            });
        }
        return await client.pushMessage(event.source.userId, {
            type: 'text',
            text: '良い旅を。',
        });
    }
};
// ########## ▲▲▲ サンプル関数 ▲▲▲ ##########



// ########################################
//  LINEサーバーからのWebhookデータを処理する部分
// ########################################

// LINE SDKを初期化します
const client = new line.Client(config);

// LINEサーバーからWebhookがあると「サーバー部分」から以下の "handleEvent" という関数が呼び出されます
async function handleEvent(event) {
    // 受信したWebhookが「テキストメッセージ以外」であればnullを返すことで無視します
    //if (event.type !== 'message' || event.message.type !== 'text') {
    //    return Promise.resolve(null);
    //}
    // サンプル関数を実行します
    return sampleFunction(event);
}



// ########################################
//          Expressによるサーバー部分
// ########################################

// expressを初期化します
const app = express();

// HTTP POSTによって '/webhook' のパスにアクセスがあったら、POSTされた内容に応じて様々な処理をします
app.post('/webhook', line.middleware(config), (req, res) => {
    // Webhookの中身を確認用にターミナルに表示します
    console.log(req.body.events);

    // 検証ボタンをクリックしたときに飛んできたWebhookを受信したときのみ以下のif文内を実行
    if (req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff') {
        res.send('Hello LINE BOT! (HTTP POST)'); // LINEサーバーに返答します
        console.log('検証イベントを受信しました!'); // ターミナルに表示します
        return; // これより下は実行されません
    }

    // あらかじめ宣言しておいた "handleEvent" 関数にWebhookの中身を渡して処理してもらい、
    // 関数から戻ってきたデータをそのままLINEサーバーに「レスポンス」として返します
    Promise.all(req.body.events.map(handleEvent)).then((result) => res.json(result));
});

// 最初に決めたポート番号でサーバーをPC内だけに公開します
// (環境によってはローカルネットワーク内にも公開されます)
app.listen(PORT);
console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);

결과



실행 결과입니다.



과제·고찰



・가까운 역의 취득을 할 수 없는 경우가 있다
원인 : LINE에서 위치 정보를 보낼 때 시설을 지정하면 우편 번호를 보낼 수 없습니다.
대책:주소 정보→우편번호 변환→가까운 역 검색 처리로 변경

· 대화식으로 검색 조건을보다 유연하게 만들고 싶습니다.
라쿠텐 여행 시설 검색 API를 이용할 때, 검색 조건은 「추천 순서」로 5건 표시로 하고 있습니다만,
Bot과의 대화에서 「가격이 싼 순서」등을 설정해 검색할 수 있으면 보다 사용하기 쉽다고 느꼈습니다.

위치 정보를 이용한 API는 그 밖에도 몇 가지가 있으므로, 더욱 조합하면 보다 편리한 Bot가 될 것 같다.
숙소 검색하고 그대로 예약까지 할 수 있지 않을까.

좋은 웹페이지 즐겨찾기