[Firebase] FunctionsからSlack通知を飛ばす

## はじめに
特定の条件をトリガーにしてFunctionsからSlack通知を飛ばしたい願望がある方へ。
今回は例としてお問い合わせが来たタイミングでSlack通知をする実装を紹介します。
意外と簡単に実装できてびっくりしました。

## 事前準備 WebhookUrlの取得
SlackのwebhookUrlはここから取得できます。
※チャンネルごとにUrlが違うので注意。

https://sukimachihq.slack.com/apps/new/A0F7XDUAZ--incoming-webhook-


## package.jsonに@slack/webhookを追加
```package.json
"dependencies": {
    "@slack/webhook": "^6.1.0", 
    "firebase-admin": "^11.0.1",
    "firebase-functions": "^3.24.0"
}
```

https://www.npmjs.com/package/@slack/webhook

## まずはミニマムで実装する
```ts
import * as functions from "firebase-functions";
import { IncomingWebhook } from "@slack/webhook"

export const sendSlack = functions
  .region("asia-northeast1")
  .firestore.document("contact/{id}")
  .onCreate(async (snap, context) => { // 問い合わせが保存されたタイミングで中の処理が走る
 
    const message = {
       text: `${data["contactDetail"]}`,
       username: "お問い合わせbot"
    }
    const webhook = new IncomingWebhook("WebhookのUrl");
    await webhook.send(message);  // Slackに送信
}
```

問い合わせが来るとこんな感じで通知されます
![スクリーンショット 2022-10-05 23.41.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/d7969c13-d8dc-3966-87bf-0ed3b3b97dba.png)

## カスタマイズしてみる
* アイコンを変える
* 色をつける
* 実行環境に応じてメンションをつける
* 実行環境に応じて管理画面へのリンクをつける
* Functionsの実行環境を記載する
* 本番と開発環境ごとに通知するチャンネルをわける

![スクリーンショット 2022-10-05 23.58.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/5c69282f-6f82-5dc2-6ce1-17a6bdeb8814.png)

```ts
import * as functions from "firebase-functions";
import { IncomingWebhook } from "@slack/webhook"

export const sendSlack = functions
  .region("asia-northeast1")
  .firestore.document("contact/{id}")
  .onCreate(async (snap, context) => {
    const data = snap.data();

    const isDebug = process.env["GCLOUD_PROJECT"] === "debugProjectId";
    const isEmulator = process.env["FUNCTIONS_EMULATOR"] === "true";

    const mentionTarget = isDebug ? "@U044P1QSUA2" : "!here";  // 記法に注意
    const adminUrl = isDebug ? "開発用管理画面Url" : "本番用管理画面URL";
    const environment = () => {
      switch (true) {
          case !isDebug:{
              return "本番環境";
          }
          case isEmulator: {
              return "Emulator";
          }  
          default: {
              return "開発環境";
          }  
      }
    }

    const body = {
      text: `<${mentionTarget}> <${adminUrl}|Open Detail>`,
      username: "お問い合わせbot",
      icon_emoji: ":robot_face:",
      attachments: [{
        color: "#CECE00",
        fields:[
          {
            title: "お問い合わせ内容",
            value: `${data["contactDetail"]}`
          },
          {
            title: "実行環境",
            value: `${environment()}`
          }
        ]
      }],
    };

    // WebhookUrlはGitにあげずになるべく環境変数で管理したほうがいい
    const webhookUrl = isDebug ? "開発用チャンネルのUrl" : "本番用チャンネルのURL";
    const webhook = new IncomingWebhook(webhookUrl);
    await webhook.send(body);
  });
```

### 実行環境の判別方法について
こちらで解説してます。

https://qiita.com/kilalabu/items/8a6fe02bd0281fe433f5


### メンションつけるときの注意
実際のメンションと書き方は違うので注意。
|記法|メンション|
|----|---|
|<!here>|@here|
|<@user_id>|@kuwa|

こちらの記事がわかりやすかったです。

https://qiita.com/ryo-yamaoka/items/7677ee4486cf395ce9bc


## その他参考URL
https://www.topgate.co.jp/notify-slack-by-cloud-functions

https://www.memory-lovers.blog/entry/2021/07/26/180000