位置情報からお店を教えてくれるLINEbot

post-cover

作ったもの

位置情報を送るとそこから半径500m以内のテイクアウトやっているお店を最大10件、近い順にカルーセル表示するLINEのbotです。

linebot

ソースコードは下記リポジトリにあります。 TakaShinoda/linebot-takeout-nodejs

主に使用した技術

  • node.js (v12.14.0で動作確認済み)
  • yelp API
  • LINE Messaging API
  • vercel
  • いらすとや

やったこと

オウム返しbotを作成

yelpに登録

  • yelpに登録してAPI Keyを取得します。 yelp
  • .envファイルにyelpのAPI Keyを追加します。 .envファイルをまだ作ってない場合は下記コマンドで作成
npm install dotenv
touch .env
  • .env

    # LINEのチャネルシークレットとチャネルアクセストークン
    CHANNEL_SECRET = "XXXXXXXXXXXX"
    CHANNEL_ACCESS_TOKEN = "XXXXXXXXXXXX"
    # 今回取得したyelpのAPI Keyを追記
    YELP_API_KEY = "XXXXXXXXXXXX"
    

テイクアウトbot作成

  • .envから値を読み込むためオウム返しbotのserver.jsに下記を追加

    // server.js
    require('dotenv').config();
    

axiosをインストール

yelp APIを用いて通信を行うためaxiosをインストールします。

npm install axios

「位置情報を送信してね!」と返す

今回はユーザから位置情報が欲しいので、位置情報以外が送られた場合は「位置情報を送信してね!」と返します。

// server.js
if (event.type !== 'message' || event.message.type !== 'location') {
      return client.replyMessage(event.replyToken, {
          type: 'text',
          text: '位置情報を送信してね!'
      })
 }

緯度・経度を取得

送られたきた位置情報から緯度・経度を取得します。

// server.js
// 緯度
const lat = event.message.latitude
// 経度
const lng = event.message.longitude

店舗情報を取得

axiosを使って通信を行い店舗情報を取得します。

let yelpREST = axios.create({
    baseURL: "https://api.yelp.com/v3/",
    headers: {
      Authorization: `Bearer ${process.env.YELP_API_KEY}`,
      "Content-type": "application/json",
    },
  })

  await yelpREST.get("/businesses/search", {
    params: {
      latitude: lat, // 取得した緯度
      longitude: lng, // 取得した経度
      radius: 500, // 今回は半径500m
      term: "takeout", // テイクアウト
      sort_by: "distance", // 距離でソート
      limit: 10, // 最大10件
    },
  })

(略)

その他パラメータはyelpのサイトを参照してください。 /businesses/search

レスポンスは下記のようになりました。(例)

{
  businesses: [
    {
      id: '12-34xx56xx78xx90xxxxxx',
      alias: 'XXXXXX-渋谷区',
      name: 'Shibuya XXXXXX',
      image_url: 'https://sample.jpg',
      is_closed: false,
      url: 'https://www.yelp.com/biz/xxxxxxxxxxxxxx',
      review_count: 5,
      categories: [Array],
      rating: 4.5,
      coordinates: [Object],
      transactions: [],
      price: '¥¥¥',
      location: [Object],
      phone: '+0123456789',
      display_phone: '+81 0-1234-5678',
      distance: 30.987654321
    },
(略)
}

店舗情報をカルーセル表示する

上記通信成功後レスポンスから欲しいものを選択して、カルーセル表示します。詳しくは公式ドキュメントを参照ください。

Messaging APIリファレンス | LINE Developers

// server.js
(略)
.then(function (response) {
        // handle success
        // データがない場合は「近くにお店はありません!」と表示する
        if(response.data.total === 0) {
            return client.replyMessage(event.replyToken, {
                type: 'text',
                text: '近くにお店はありません!'
            })
        }
          // carouselは最大10
          // colums配列にデータを入れていく
          let columns = [];
          for (let item of response.data.businesses) {
            columns.push({
              "thumbnailImageUrl": item.image_url,
              "title": item.alias,
              "text": '⭐️' + item.rating,
              "actions": [{
                "type": "uri",
                "label": "yelpでみる",
                "uri": item.url
              }]
            });
          }
          // replyMessageの第二引数を配列にすることで複数メッセージを送信できる
        return client.replyMessage(event.replyToken, [
          {
            type: 'text',
            text: 'おいしそうだね!'
          },
          {
            type: 'template',
            altText: '店舗情報を送信しました!',
            template: {
                type: 'carousel',
                columns: columns
            }
        }]);
    })

デプロイ

下記記事を参考にさせていただき、vercelでデプロイを行いました。

VercelでLINE BOTを動かす 2020年5月版 - Qiita

// vercel.json
{
    "routes": [
        { "src": "/", "dest": "api/server.js" },
        { "src": "/webhook", "dest": "api/server.js" }
    ]
}

まとめ

yelpのAPIを使ってテイクアウトできるお店を教えてくれるLINEbotを作成しました。

今回作成したLINEbotは下記を読み込む事でお友達に追加できますのでよかったら追加してみてください。

qr

©︎ 2021 ts621-blog