モチベーション
Firestoreに保存してある誕生日情報をもとに、おめでとう通知をSlackにさせたかったので簡単なSlack botをfunctionsで作ってみました。
公式のnode.js用のSlackクライアントがnpmに転がっているのですが、使われている記事をみたことがなかったので試しに使ってみました。
必要なもののインストール
yarn
yarn add @slack/client
Functionsでfirebase adminを動かすために、認証情報が必要になるので、functionsの環境変数に設定しておくか、jsonファイルをfirebaseのコンソールからダウンロードしてプロジェクトに配置してください。
コード
index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as serviceAccountKey from '../serviceAccountKey.json';
import { WebClient } from '@slack/client';
admin.initializeApp({credential: admin.credential.cert(serviceAccountKey as any)});
const slack = new WebClient(functions.config().slack.api_key);
interface IUser {
birthday: Date;
name: string;
}
const notifySlack = async (users: IUser[]) => {
let names = '';
if (users.length === 1) {
users.map(user => names += user.name + ', ');
} else {
names = users[0].name;
}
const res = await slack.chat.postMessage(
{
channel: functions.config().slack.channel,
text: "今日は" + names + "が誕生日!",
}
)
console.log(res);
}
const aggregateUsers = (snapshot: FirebaseFirestore.QuerySnapshot): IUser[] => {
const today = new Date();
const users: IUser[] = new Array();
snapshot.docs.forEach(doc => {
const birthday: Date = doc.data().birthday.toDate();
if(birthday.getDate() === today.getDate() && birthday.getMonth() === today.getMonth()){
users.push(
{
birthday: doc.data().birthday,
name: doc.id,
}
);
};
});
return users;
}
export const checkBirthday = functions.https.onRequest((req, resp) => {
const ref = admin.firestore().collection('users');
ref.get()
.then(snapshot => {
const users = aggregateUsers(snapshot);
users.length === 0 ?
resp.send('ok')
:
notifySlack(users)
.then(() => resp.send('ok'))
.catch((e) => resp.send('error:' + e))
})
.catch((e) => {
resp.send('error:' + e);
});
});
上記のコードでデプロイして、関数を発火させるためのURLを発行します。
cronの設定
毎日、誕生日に該当する人がいないかチェックしたいので、cron-job.orgに発行したURLを設定してcronを回します。
ちなみに、slack通知させることは外部アクセスにあたるのでfirebaseの無料枠ではできません。
firebaseのプランはBlazeプランにしましょう。