LINE Bot のカルーセルテンプレートを Firebase Functions で実装する方法について


## 概要

3~4年も前に[公式のスタートガイド](https://firebase.google.com/docs/functions/get-started?hl=ja)ぐらいしか使ったことがなかったため、Firebase Functionsをちゃんと触るのは今回が初めてで、LINE Botも簡単なメッセージ返答ぐらいまでしか触ったことがなかったことと、FirebaseとLINE Botの組み合わせも初めてだったので色々とハマったことをまとめようかと。

## やったこと

　　　<img width="100" alt="29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png" src="https://user-images.githubusercontent.com/10379601/29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png">

最初は、FirebaseとLINE Botの組み合わせで定期的に何かをつぶやくBotを作りたいなと思い、つぶやく内容をスクレイピングで取得するために参考記事をもとに `Puppeteer` を使っていたところFirebase Functionsとの相性が悪く、 [Puppeteer slow execution on Cloud Functions · Issue #3120 · puppeteer/puppeteer](https://github.com/puppeteer/puppeteer/issues/3120)で議論されている内容が手元でも起きて解決できませんでした。

　　　<img width="200" alt="carousel.d89a53f5.png" src="https://developers.line.biz/assets/img/carousel.d89a53f5.png">

最終的にはFirebaseとLINE Botの組み合わせてカルーセルテンプレートを使えるようになるところを目指しました。

## セットアップ

Firebase FunctionsのセットアップおよびLINE Botのセットアップはそれぞれ他の記事を参考にしてもらえたらなと。
`@line/bot-sdk`をFirebase Functionsで使う設定は特別何かすることはなく、他のライブラリ同様に`$npm install @line/bot-sdk`で取り込んで`$firebase deploy --only functions`でアップできたらローカル同様にFirebase Functions上でも動いてくれます。

もし、本記事をきっかけにFirebase FunctionsもLINE Botも初めて触る人は、Firebase Functions関連でNodeのバージョンや有料プラン設定とGCPのCloud Functions設定などでハマる可能性が高いと思います。
そこは、LINE Botとの組み合わせだからといって「Firebase Function LINE Bot 【エラー内容】」みたいにググるとややこしくLINE Botは一旦関係なかったりするので、Firebase Functionsを軸にググるように。

参考記事をまとめておくのでググる前に参考にして、もう少し詳細知りたい場合は各自ググってくださいmm

### 補足

LINE Botのシークレットキーとアクセストークンをハードコーディングするのは、セキュリティ的に危ないので`$firebase functions:config:set`で設定して、コード上では`functions.config()`で呼び出すようにすることでセキュアなアプリが作れます。

- [環境の構成 | Firebase Documentation](https://firebase.google.com/docs/functions/config-env?hl=ja)


## 参考記事

- [【Firebase+Node.js+LINE SDK】230行でコロナ通知サービスを開発した話 (ソース付) #27](https://www.bravesoft.co.jp/seblog/archives/2213)
- [Firebase FunctionsとPuppeteerでスクレイピングの定期実行するのを作ってみた](https://blog.nismit.me/post/2020/02/firebase-functions-scraping)
- [LINE botの返事をカルーセル形式にしてみました](https://techblog.lclco.com/entry/2017/03/29/175710)
- [Node.js + HerokuでLINE Messaging APIを叩いてみる](https://puyobyee18.hatenablog.com/entry/2018/10/28/171941)
- [Promiseについて0から勉強してみた](https://qiita.com/toshihirock/items/e49b66f8685a8510bd76)
- [FirebaseでNode.jsを動かしてLINE BOTを作る](https://qiita.com/n0bisuke/items/909881c8866e3f2ca642)
- [超絶簡単！LINE bot開発](https://qiita.com/ufoo68/items/f0ba45347b226c8afcd8)
- [
jirawatee/CarouselTemplate.js | GitHub Gist](https://gist.github.com/jirawatee/49d33653f51841f2fa84469b546da4bd)
- [（チュートリアル）Node.jsを使ってサンプル応答ボットを作る | LINE Developers](https://developers.line.biz/ja/docs/messaging-api/nodejs-sample/)
- [Webhook | line-bot-sdk-nodejs](https://line.github.io/line-bot-sdk-nodejs/guide/webhook.html)


## できたもの

　　<img width="200" alt="IMG_5127.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/d3d351db-e555-f62a-a5f0-abd124424b13.png">　<img width="200" alt="IMG_5128.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/7a876c49-e365-221f-b125-fd6249004dbb.png">

## 準備

カルーセルテンプレートは、[LCL Engineers' Blogさんの参考](https://techblog.lclco.com/entry/2017/03/29/175710)をモロパクリしたので、まずYoutubeAPIのAPIキーを取得しておく必要があります。
今回、[YouTube APIキーの取得 (2020/03/25時点)](https://qiita.com/iroiro_bot/items/1016a6a439dfb8d21eca)の記事を参考にセットアップしたFirebaseプロジェクトを指定した[GCPコンソールのライブラリー画面](https://console.cloud.google.com/apis/library)に入ってAPIキーを取得しました。

取得したAPIキーは、LINE Botのシークレットキーとアクセストークンの同様に`$firebase functions:config:set`からYouTubeAPIキーも設定しておきましょう！

```bash
$ firebase functions:config:set gcp:api_key="取得したYouTubeAPIキー"

$ firebase functions:config:get 
{
  "line": {
    "secret": "LINE Botのシークレットキー",
    "accesstoken": "LINE Botのアクセストークン"
  },
  "gcp": {
    "api_key": "YouTubeAPIキー"
  }
}
```


## ソースコード

GitHub Gistにアップしています。
[gremito/line_webhook.js](https://gist.github.com/gremito/2fe56252c260a0e5fc7bf6e998330c2e)

ファイル名は、`line_webhook.js`ではなく実際に配置しているパスは`firebase/functions/line/webhook.js`で次のようにFirebase Functionsを設定しています。

- [複数の関数を整理する | Firebase Documentation](https://firebase.google.com/docs/functions/organize-functions?hl=ja)

```javascript:firebase/functions/index.js
exports.line = require('./line/webhook')
```


## まとめ

とりあえず動くところまでできたわけですが、まだFirebase FunctionsとLINE Botが理解できているわけでもなく、最初は`Promise`を使って`async function`で非同期関数にしてたんですが、カルーセルテンプレートの実装で上手いやり方がわからず、通常のやり方で`request`ライブラリ実装でなんとか動くところまでできた現状です笑汗

当初の目的としてFirebase FunctionsとLINE Botの組み合わせでどこまでできるのか実際触って知見を得られたので、次に`Puppeteer`を再挑戦するのか一旦Node.jsのキャッチアップをやってからFirebase Functionsの理解を深めるかどうするかはまた改めて。

## 注意

Firebase Functionsは有料プランの設定でないと使えないサービスなので、もし悪意あるハッカーが攻撃してきて知らぬ間に請求額がすごいことになっているという可能性もあるので作ったまま放置するのは危険です。

幸いなことにLINE Botの方は、公開設定にしていなければID検索したとしても作ったボットは見つからないと思うので、LINE Botの方でこのような危険はほぼないと思います。

使わない場合は、Firebase Functionsのダッシュボードから**デプロイした関数を削除**しておくことをお勧めします。
また、何か問題が起きたとしても自己責任でご対応のほどよろしくお願いいたしますmm