コメントが投稿されたらslackに通知する
create: 2019-11-14
Nuxt.js firebase functions firestore Slack API

ブログのコメントはfirebaseに登録しています。
firestoreに登録されたタイミングで、slackのチャネルに投稿する処理を作りたいと思います。

firestore の登録トリガ

firebase functionsでは、接続されているfirestoreの登録・更新・削除のイベントトリガで処理を実行することができます。

ブログ記事にコメントが投稿されたらSlackに通知されるような関数を登録したいと思います。

ライブラリに axios を追加

functionsで通信を行うので、使い慣れたaxiosを依存関係に追加します。

cd functions
yarn add axios

トリガの設定

トリガのウォッチ方法については、firebaseの公式ドキュメントに詳しく書いてありました。
Cloud Firestore トリガー

ブログのコメントは posts/postId/comments/commentIdという構造で保存しているので、このパスに書き込まれたらトリガされるようにします。
postIdは記事の ID、commentIdfirestoreの自動採番のため、動的な値となります。
このpostIdcommentIdをパラメータとして受け取ることができます。

postIdがわかれば記事もわかるので、Slackへの投稿時に記事へのリンクが表示されるようにしました。

const axios = require('axios')
const functions = require('firebase-functions')

exports.commentPost = functions.firestore
  .document('posts/{postId}/{comments}/{commentId}')
  .onCreate(async (snap, context) => {
    // change内に登録されたデータ内容が入る
    const commentData = snap.data()

    // 投稿文字列の作成。`\n`を挟むことで改行ができるので、配列を作成しておく。
    const array = [
      `新しいコメントが届きました!`,
      `<https://bitto.jp/jump?id=${context.params.postId}|${
        context.params.postId
      }> @${new Date(changeData.timestamp)}`,
      `名前: ${commentData.name}`,
      changeData.text
    ]

    // slack APIが受け取れるオブジェクトを作成する
    const data = {
      text: array.join('\n'), // 配列を`\n`で結合、改行する
      icon_emoji: ':ghost:',
      username: 'BLOG-BOT',
      channel: '#comments'
    }

    // slack APIに送信する
    await axios.post('https://hooks.slack.com/services/xxx/xxx/xxx', data)
  })

Slack APIに投稿するデータはJSONで送ります。
デフォルトでアイコンやユーザ名、投稿チャネルが決まっていますが自由に書き換えられます。
ひとつの API でチャネルやユーザを使い分けても問題ないようです。

  • text: 投稿する文章です。リンクなどいろいろかけます
  • icon_emoji: 投稿者のアイコンを絵文字で指定できます
  • username: 表示されるユーザ名です
  • channel: 投稿先のチャネルを設定します

Firebase から外部サービスに送信するには有料プランに変更する必要がある

Slackの API に向かって通信したいのですが、無料の spark プランでは外部ネットワークを参照できません。
そのため、Blazeプランにアップグレードする必要があります。

無料で使っていた Spark プランから有料プランへの移行です。
が、Spark プランの無料枠に収まっているくらいなので、しばらくは課金が発生することもなさそうです。

2019/12/20 追記
Cloud Functions の料金の詳細によると、アウトバウンドネットワーキングについては無料枠がなく、課金対象となります。
本日時点で $0.12/GB となっているので、1GB に収まっていればだいたい 25 円くらいでしょうか。
このくらいならラズパイの 20 ~ 30 円/月と言われている電気代くらいなので OK とします。

2020/01/10 追記
そういえば料金請求こないな?と思っていたら、アウトバウンドにも無料枠があるようです。
「使用量と請求額 ベータ版」によると、月 5GB も無料枠が!

Cloud Functions の料金の詳細を確認したら、無料枠の説明がありました。
前はなかったような気が。。。

プランアップグレードをする

Firebaseコンソールの左下から、アップグレードをクリック。

プランの選択

Firebaseの料金プランというダイアログが表示されるので、右側のBlazeからプランを選択をクリック

購入を確定

次の画面では購入の最終確認が行われます。
クレジットカードを登録していない場合は登録ステップへ進みます。
(登録が終わっただけでは購入が完了しないので、再度プランアップグレードの手順をします)

アップグレード完了

有効なクレジットカードで購入を決定するとアップグレード完了画面が表示されます。
数分以内にプラン変更完了のメールが送信されると、firebase functionsから外部ネットワークのリクエストが可能になります。

なお、アップグレード後も同じ手順でダウングレードすることでSparkプランに変更できます。

動作確認

ブログからコメントを投稿すると、#commentsチャネルに通知が飛ぶようになりました。
感動!

リアルタイムに飛んでくるからタイムスタンプは不要かな。。。