Cloud Functions for Firebase ～Firestore をトリガーとし、LINE に通知～

～ 追記 ～
どうやらFirebaseとGoogole以外のサービスとの連携にはクレジットカード情報を登録しないといけない模様。ご注意を。
@atomyah さん、ありがとうございました。
～～～～～


Firebase を使う機会があった為、検証がてら
Cloud Functions for Firebase を使って、他サービス（LINE Notify）へ連携してみました。

ここでは非常に簡単な LINE Notify を使っていますが、APIを提供しているサービスなら何でも対応できるはず！

[言語]
- TypeScript: 2.8.3

[ライブラリ]
- firebase-admin: 6.0.0
- firebase-functions: 2.1.0
- request: 2.88.0
- request-promise: 4.2.2

## Cloud Functions 導入
以下の公式ガイドを参照してください。
https://firebase.google.com/docs/functions/get-started?hl=ja

[補足]
firebase の初期化後にできる`firebase.json`に以下の記述があると思います。

```json
{
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  }
}
```

`$RESOURCE_DIR` を定義するか、パスを直接書くかしないと、デプロイ時にコけました。
インストール時から階層を変えてなければ、$RESOURCE_DIRを「functions」に置き換えるだけでOKです。


## LINE Notify 

LINE さんが準備している API に文字列を送信すると、"LINE Notify" から自分宛に通知することができます。
とにかく簡単に通知できるので、個人的には重宝しています。

詳細は下記を参照ください。

- 公式ページ
https://notify-bot.line.me/ja/

- 参考ページ
https://qiita.com/iitenkida7/items/576a8226ba6584864d95


## ライブラリのインストール
１．コマンドプロンプトを起動し、プロジェクトのリソースディレクトリへ移動
`$ cd <firebase を初期化したフォルダ>/functions`

２．request-promise をインストール
`$ npm install --save request`
`$ npm install --save request-promise`

（参考）https://www.npmjs.com/package/request-promise


## ソースコード

※<生成したLINE Notifyのアクセストークン> の箇所だけ置き換えてください。※

```typescript
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as rp from 'request-promise';

// firebase の初期化
admin.initializeApp();
const db = admin.firestore();

// MEMO: simple が true の場合、 3XX のステータスコードを返却された時でもエラーとなる模様
const request = rp.defaults({simple: false});

const FIRESTORE_COLLECTION = 'test';
const LINE_ACCESS_TOKEN = '<生成したLINE Notifyのアクセストークン>';

// functions にデプロイする関数
// とあるコレクションにドキュメントを作成すると、LINEに通知します。
// MEMO: ドキュメントに対し、「作成」「更新」「削除」を取得することができます。詳細は下記参照
//       https://firebase.google.com/docs/functions/firestore-events?hl=ja
export const lineNotify = functions.firestore
  .document(FIRESTORE_COLLECTION + '/{doc}')
  .onCreate((snap, context) => {

  // line へ通知
  request({
    uri : 'https://notify-api.line.me/api/notify',
    method: 'POST',
    headers: {
      'Content-Type' : 'application/x-www-form-urlencoded',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN
    },
    form: {
      'message': 'Success!!!\r\n' + FIRESTORE_COLLECTION + 'にドキュメントが作成されました。'
    }
  }).then(function(response) { // 成功時 (3XX)
    // LINE Notify からのレスポンスを Functions のログに出力
    console.log('User has %d repos', response.length);
    console.log('response :' + response);
    return null;
  }).catch(function (err) { // 失敗時 (4XX or 5XX)
    Error(err);
   });
  return null;
});
```

#### lineNotify 関数をデプロイ
１．firebase を初期化したディレクトリへ移動

２．下記コマンドを実行
`$ firebase deploy --only functions:lineNotify`

[補足] `--only` オプションを付けることで、該当するFunctionのみデプロイすることが可能です。


#### 動作確認
デプロイしたプロジェクトの Functions を開くと`lineNotify`関数が追加されています。
![Firebase_Functions.png](https://qiita-image-store.s3.amazonaws.com/0/315833/34b6575f-baae-12c1-15c6-6e5a698ec754.png)

次に、Databaseを開き、`test` という名称のコレクションを生成し、ドキュメントも作成してみてください。
以下の画像のように通知が来るはずです。
![Screenshot_20181211-130842.png](https://qiita-image-store.s3.amazonaws.com/0/315833/d5fce5e3-413c-c08e-dfe7-1e1d8c9f2b6f.png)

ログも確認してみます。
![Firebase_Functions_log.png](https://qiita-image-store.s3.amazonaws.com/0/315833/0d6ea4d1-67af-0237-06b5-23d6ade2bdf8.png)

問題なさそうですね！

※コマンドプロンプト上でデプロイ成功していても、反映されるのに時間がかかるケースがあります。2-3分経っても通知が来ない場合は Functions のログを確認してみてください。

## おわり
今後、使いどころも増えそうなので、自分の備忘録にもなるよう、投稿してみました。

初投稿のため、至らないところ等あるかと思いますので、不明点・補足等ございましたらコメント頂けたらと思います。