SendGrid + Cloud Functionsで毎朝お天気通知してみよう

### 概要
Firebase Cloud Functionsと、SendGridによって毎朝お天気と祝日を通知してくれるアプリをさくっと作成してみました。

### アーキテクチャ図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/ec435369-44c7-7d76-76c0-0a99f2a90234.png)

**Firebase Cloud Functions**
Firebaseによる、サーバレスにプログラムを実行してくれるサービス。今回はnode.jsで記述します。

https://cloud.google.com/functions

**SendGrid**
クラウドベースのメール配信サービス

https://sendgrid.kke.co.jp/

### 拝借したAPI

https://weather.tsukumijima.net/

https://holidays-jp.github.io/


### Firebase - プロジェクトの作成
自分のGoogleアカウントで、[Firebaseコンソール](https://console.firebase.google.com/)から、Firebaseのプロジェクトを作成します。
今回は、設定などはデフォルトで大丈夫です。
![スクリーンショット 2021-12-11 13.07.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/c2f0d534-21ba-9294-82be-8619893964e7.png)
![スクリーンショット 2021-12-11 13.08.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/8b27e702-c684-af9e-396e-3a19f01c15ab.png)

Cloud Functionsを使用するためには、プロジェクトの料金プランをSpark(無料)からBlaze（従量課金制）に変更する必要があります。
![スクリーンショット 2021-12-11 16.12.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/4bc7d6b1-0126-0a9d-c542-cf1dc525585f.png)



### SendGridのアカウントの作成
[SendGrid](https://sendgrid.kke.co.jp/)からアカウントを作成します。
![スクリーンショット 2021-12-11 15.49.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/4c4989db-6456-a6e8-1b1e-9c6fa5cf488b.png)
アカウントを使用できるようになるまでは審査が必要で、使用目的や用途を書く必要があります。
自分の場合は、金曜日に登録をして月曜日に審査が通りました。

### ローカルファイルとFirebaseの接続
VSCode内で空のディレクトリを開き、Firebaseの初期化を行います。
以下の公式ドキュメントの**Firebase CLI をインストールする**〜**Firebase プロジェクトを初期化する**を実行します。

https://firebase.google.com/docs/cli?hl=ja#install_the_firebase_cli

**Firebase プロジェクトを初期化する**に記載のある、`firebase init`を実行する。
今回はCloud Functionsのみ使用するので、Cloud Functionsをセットアップする。
![スクリーンショット 2021-12-11 15.59.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/744a3431-ea29-d69c-3742-0da5b83142d3.png)

プロジェクトのセットアップで、先ほど作成したプロジェクトを選択する。

```
? Please select an option: Use an existing project
? Select a default Firebase project for this directory: //先ほど作成したプロジェクトを選択
i  Using project //先ほど作成したプロジェクト
```

Firebaseのプロジェクトのセットアップが完了すると、ディレクトリ内に各フォルダが作成されます。
![スクリーンショット 2021-12-11 16.06.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/9ccc7ccc-2204-09e6-749b-cba9897238b7.png)

### SendGridのAPIキー取得
SendGridにログインし、Dashboard > Settings > API Keysから、Create API KeyでAPIキーを作成する。
作成した直後にAPIキーは表示されるが、その時からAPIキーは表示されないので注意。

### Cloud Functionsの環境変数の設定
Cloud Functionsはターミナルから環境変数を自由に設定することができます。
後にコード内でSendGridのAPIキーを使用するために、Cloud Functionsの環境変数にSendGridのAPIキーを設定します。

```bash
firebase functions:config:set sendGrid.apikey="YOUR API KEY"
```

### コーディング

```javascript:index.js
const functions = require("firebase-functions");
const sgMail = require('@sendgrid/mail');
const admin = require('firebase-admin');
const axios = require('axios');
require('date-utils');

admin.initializeApp();

exports.sendEmailScheduler = functions
    .region('asia-northeast1')
    .pubsub
    // 毎日8時に実行
    .schedule('0 8 * * *')
    .timeZone('Asia/Tokyo')
    .onRun(async (context) => {
        try {

            // 環境変数の呼び出し
            const config = functions.config();
            // APIキーの設定
            sgMail.setApiKey(config.sendgrid.apikey);
            fromTo = "YOUR EMAIL ADREESS"

            // お天気APIの取得
            const weatherRes = await axios.get('https://weather.tsukumijima.net/api/forecast/city/130010');

            // 祝日APIの取得
            const holidayRes = await axios.get('https://holidays-jp.github.io/api/v1/2022/date.json');

            // Date → yyyy-mm-ddを変換する
            var dt = new Date();
            var formattedDt = dt.toFormat("YYYY-MM-DD");
            var japanizedDt = dt.toFormat("YYYY年MM月DD日")

            // 祝日出ない場合、ふつうの日と格納
            var holiday = typeof holidayRes.data[formattedDt] === "undefined" ? "" : "(" + holidayRes.data[formattedDt] + ")"
            var weather = weatherRes.data.forecasts[0].telop;
            var description = weatherRes.data.description.bodyText

            //メッセージの作成
            const titleText = japanizedDt + holiday;
            const messageText = "\n\n" + weather + "\n\n" + description;

            // メールに関する情報を設定
            const msg = {
                to: fromTo,
                from: fromTo,
                subject: titleText,
                text: messageText,
            };

            // メールの送信
            await sgMail.send(msg);

        } catch (error) {
            throw error;
        }
    })
```


### パッケージインストール
ターミナル上で、


- SendGrid用のパッケージ
- APIを叩くためのHTTPクライアントのパッケージ
- 日付のフォーマット用パッケージ

をインストールをする。


```bash
npm install @sendgrid/mail
npm install axios  
npm install date-utils
```

### デプロイ
ターミナル上で、

```bash
firebase deploy --only functions
```
`✔  Deploy complete!`と表示されたらデプロイ完了！

(毎日8時に実行するのですが、稼働確認のためGCPのテストから関数を実行してみます・・・)

### メールが届いた

![スクリーンショット 2021-12-11 17.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394686/ccc55436-9702-66cb-cb02-24573c8506cd.png)


🎉🎉🎉🎉🎉🎉🎉

### 宣伝

当部ではnoteにおいて、このような情報発信を行っています。

- Flutter,Firebaseの入門者向けの情報、
- 新規事業企画（Fintech、AIなど）
- 研修サービス（ブロックチェーン、コンテナ開発など）
- 新技術調査検証（Kubernetes、スマホアプリ開発、FIDO2、ローコード開発など）
…etc

ご興味のある方は、ぜひ以下からご覧ください！

https://note.com/note_fsd1