坂本研のゼミ室

位置情報からテイクアウトやってるお店を教えてくれるLINEbot

作ったもの

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

f:id:TakaShinoda:20210129112906p:plain

ソースコードは下記リポジトリにあります。

github.com

主に使用した技術

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

やったこと

オウム返しbotを作成

  • LINEbotは初めてだったので、ますは下記を参考にしてオウム返しをするbotを作成しました。

1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest - Qiita

yelpに登録

  • yelpに登録してAPI Keyを取得します。

f:id:TakaShinoda:20210129204939p:plain

  • .envファイルにyelpのAPI Keyを追加します。 .envファイルをまだ作ってない場合は下記コマンドで作成
npm install dotenv
touch .env
# LINEのチャネルシークレットとチャネルアクセストークン
CHANNEL_SECRET = "XXXXXXXXXXXX"
CHANNEL_ACCESS_TOKEN = "XXXXXXXXXXXX"

# 今回取得したyelpのAPI Keyを追記
YELP_API_KEY = "XXXXXXXXXXXX"

テイクアウトbot作成

  • .envから値を読み込むためオウム返しbotのserver.jsに下記を追加
require('dotenv').config();
axiosをインストール

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

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

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

if (event.type !== 'message' || event.message.type !== 'location') {
      return client.replyMessage(event.replyToken, {
          type: 'text',
          text: '位置情報を送信してね!'
      })
 }
緯度・経度を取得

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

// 緯度
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のサイトを参照してください。

Business Search Endpoint - Yelp Fusion

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

{
  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

(略)
.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 "version": 2 は現在はなくても大丈夫そうでした。

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

まとめ

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

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

f:id:TakaShinoda:20210131183025p:plain