【LINE Messaging API＆Custom Search API】LINEでGoogle検索してみた

# はじめに
興味本位でLINEBOTを作成してみました。
既に多くの方が解説してくださっていますが自身の備忘録として一通りやったことを残します。

# 目的
LINEBOTを作ってみたかったので遊びで実装しました。

# アウトプット
このようになります。
![1980.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465078/6a1c970d-6371-4ec4-e977-308e25990d6d.jpeg)

# 目次
[・LINE Developersの登録とチャンネル作成](#line-developersの登録とチャンネル作成)
[・Google APIの登録とCustom Search APIの登録](#google-apiの登録とcustom-search-apiの登録)
[・githubの登録とコード管理](#githubの登録とコード管理)
[・サンプルBOT作成](#herokuの登録とデプロイ)
[・Herokuの登録とデプロイ](#herokuの登録とデプロイ)
[・動作検証 その1](#動作検証-その1)
[・Custom Search APIコール準備](#custom-search-apiコール準備)
[・カルーセル表示](#カルーセル表示)
[・検索結果のマッピング](#検索結果のマッピング)
[・デプロイと動作検証 その2](#デプロイと動作検証-その2)

# 開発環境
Node.js：v14.16.1
yarn：1.15.2

# LINE Developersの登録とチャンネル作成
[こちら](https://account.line.biz/login?redirectUri=https%3A%2F%2Fdevelopers.line.biz%2Fconsole%2F)にアクセスしてログインします。
LINEアカウントを持っていてば特に問題なくログインできます。

[LINE Developers公式ドキュメント](https://developers.line.biz/ja/docs/messaging-api/getting-started/)に記載されている通りに作業します。

# Google APIの登録とCustom Search APIの登録
Google検索を行うためにCustom Search APIを使いました。
[こちら](https://qiita.com/zak_y/items/42ca0f1ea14f7046108c)で解説してくださっています。手順通りに作業します。

# githubの登録とコード管理
説明は不要だと思うので割愛します。

# サンプルBOT作成
右も左もわからなかったので、まず[チュートリアル](https://developers.line.biz/ja/docs/messaging-api/nodejs-sample/)でサンプルBOTを作成しました。
これをベースとして実装を行いました。
デプロイと動作検証が完了したら検索部分の実装を行います。

# Herokuの登録とデプロイ
デプロイには[Heroku](https://jp.heroku.com/home)を使用します。
アカウント作成後にアプリケーションを作成します。
デプロイはコマンドラインからではなくgithubを連携させて手動で行いました。
[こちら](https://qiita.com/sho7650/items/ebd87c5dc2c4c7abb8f0)で解説してくださっているので手順通りの作業でgithubからデプロイできるようになります。

私の場合エラーなくデプロイできていると、真っ白な背景の左上にOKとだけ表示されます。

# 動作検証 その1
テキトーにメッセージを投げてみたところLINEBOTからメッセージが返ってきました。
※SSを添付したかったのですが1か月近く前なのでLINEの履歴から消えてしまっていました…

もしうまくデプロイできていなかったり、メッセージを投げて結果が返ってこなかった場合には
ログを確認することになります。
まずコマンドラインからherokuにログインします。

```Bash
heroku login
```

何かボタンを押せと言われるので押します。

```Bash
heroku: Press any key to open up the browser to login or q to exit:
```

ブラウザが立ち上がるorタブが追加されてログイン画面が表示されるのでログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465078/c0d72c3c-2f76-f892-66f7-411e7319703e.png)

その後以下コマンドでログを確認できます。

```Bash
heroku logs --tail --app アプリ名
```

# Custom Search APIコール準備
APIに設定することができるパラメータは結構ありましたが、
検索ができればよかったので必要最低限のパラメータで実装しました。
以下サンプルです。

```Javascript
customSearch.cse.list({
  // APIキー
  auth: "AIzaSyD~~~~~~~~~~",
  // カスタムエンジンID
  cx: "2ab139~~~~~~~~~",
  // クエリ
  q: query
});
```

APIキーとカスタムエンジンIDはそれぞれ以下から取得します。

APIキー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465078/84790143-5751-18b8-d8ef-b304c12d8b56.png)

カスタムエンジンID
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465078/f77f2375-1075-d78f-2403-955bc8bd2093.png)


また、より高度な検索を行う場合は[パラメータ一覧](https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list#request)をご参照ください。

# カルーセル表示
LINEBOTからの返信では検索結果をカルーセル表示させます。
[カルーセルテンプレート](https://developers.line.biz/ja/reference/messaging-api/#carousel)に記載されている通りに検索結果を加工することになります。

注意点として
・`imageSize`：`contain`に設定しなければサムネイルが見切れてしまいます。
・`defaultAction`：設定すると画像部分をタップしてもリンクが開けるようになります。
・`action`：[URIアクション](https://developers.line.biz/ja/reference/messaging-api/#uri-action)の`lebel`はただのカルーセルの場合必須です。また20文字制限があります。

# 検索結果のマッピング
マッピングの前に[レスポンスの形式](https://developers.google.com/custom-search/v1/reference/rest/v1/Search)を確認します。
この中の`items`に検索結果が入っています。

・`items[i].link`：検索結果のリンクが入っています。
・`items[i].title`：タイトルが入っています。
・`items[i].pagemap`：サムネイルのURLが取得できるのですが、下記注意が必要です。

注意の前にまず「焼き肉」で検索したときの検索結果のうち1つのpagemapを見てみます。

```Javascript
{
  "cse_thumbnail": [
    {
      "src": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQJ9azqHAYG_X-xfzPIZ8quePzAOXoQd_9L-UJB0iFfyZsPgboeSKg3whGw",
      "width": "225",
      "height": "225"
    }
  ],
  "metatags": [
    {
      "og:image": "https://www.yakiniku-king.jp/wp-content/uploads/2020/10/og.png",
      "og:type": "website",
      "twitter:card": "summary",
      "twitter:title": "焼肉きんぐ｜お席で注文　焼肉食べ放題！",
      "og:site_name": "焼肉きんぐ",
      "viewport": "width=device-width, initial-scale=1.0, minimum-scale=1.0",
      "twitter:description": "焼肉きんぐはおいしい焼肉が食べ放題のお店です。テー ブルバイキングだからお席まで出来たての商品をお持ちします。焼肉満腹保証つき！食べ放題コース：幼児無料、小学生半額、60歳以上500円引き。WEBから受付予約できます。",
      "og:title": "焼肉きんぐ｜お席で注文　焼肉食べ放題！",
      "og:url": "https://www.yakiniku-king.jp/",
      "og:description": "焼肉きんぐはおいしい焼肉が食べ放題のお店です。テーブルバイキングだからお席まで出来たての商品をお持ちします。焼肉満腹保証つき！食べ放題コース：幼児無料、小学生半額、60歳以上500 円引き。WEBから受付予約できます。",
      "og:image:secure_url": "https://www.yakiniku-king.jp/wp-content/uploads/2020/10/og.png",
      "twitter:image": "https://www.yakiniku-king.jp/wp-content/uploads/2020/10/og.png"
    }
  ],
  "cse_image": [
    {
      "src": "https://www.yakiniku-king.jp/wp-content/uploads/2020/10/og.png"
    }
  ]
}
```

`items[i].pagemap`の中には`cse_thumbnail`や`metatags`、`cse_image`があります。
サムネイルと書かれているので`cse_thumbnail`を使用するのですが、データによっては`cse_thumbnail`が存在しない場合がありました。
そもそも`pagemap`が存在しない場合もありました。
(`metatags`と`cse_image`も存在しない場合がありました。)

以下カルーセルのmessages部分のの実装例です。

```Javascript
messages: [
  {
    "type": "template",
    "altText": req.body.events[0].message.text + "の検索結果",
    "template": {
      "type": "carousel",
      "imageSize": "contain",
      "columns": commonFunction.createCarouselColumns(formattedResult)
    }
  }
]
```

以下マッピング部分の実装例です。

```Javascript
createCarouselColumns(response) {
  // サムネイルが存在しないサイトはのぞく
  return response.items.filter(item => item.pagemap !== undefined && item.pagemap !== null && item.pagemap.cse_thumbnail !== undefined).map(item => ({
    "thumbnailImageUrl": item.pagemap.cse_thumbnail[0].src,
    "text": item.title,
    "defaultAction": {
      "type": "uri",
      "label": item.title.substr(0,20),
      "uri": item.link
    },
    "actions": [
      {
        "type": "uri",
        "label": item.title.substr(0,20),
        "uri": item.link
      }
    ]
  }));
}
```

# デプロイと動作検証 その2
コードをpushしてHerokuからデプロイします。
**焼き肉**で検索をしてみると…想定通り検索結果を取得することができました！！！
![1980.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465078/6a1c970d-6371-4ec4-e977-308e25990d6d.jpeg)



# 最後に
遊びで作っていたのでテキトーな実装かつ簡単な機能ですが、楽しんで作ることができました。
何か思いついたらまた作ってみたいです。

この備忘録がどなたかの参考になりましたら幸いです。

# 参考
[Messaging APIを始めよう](https://developers.line.biz/ja/docs/messaging-api/getting-started/)
[Custom Search APIを使ってGoogle検索結果を取得する](https://qiita.com/zak_y/items/42ca0f1ea14f7046108c)
[（チュートリアル）Node.jsを使ってサンプル応答ボットを作る](https://developers.line.biz/ja/docs/messaging-api/nodejs-sample/)
[heroku 初級編 - GitHub から deploy してみよう -](https://qiita.com/sho7650/items/ebd87c5dc2c4c7abb8f0)
[URIアクション](https://developers.line.biz/ja/reference/messaging-api/#uri-action)