Supabaseでデータ更新があった時にSlack通知を送る

目次

はじめに

サービスを運用する際に問い合わせフォームに新たな問い合わせが行われたら通知してくれる機能が欲しいことは実際の運用でよくあるケースだと思われます。

また、できればアプリ側の責任にせずDB周辺でその機能を完結させ情シスなどが管理しやすい形にしたいところです。

SupabaseではEdge Functionsを利用することでデータベースに新たなデータが追加されたことをトリガーにしてSlack通知を送ることができます。実際にやってみましょう。

Slack Appの作成

Slack APIにアクセスしましょう。

https://api.slack.com/

その後ヘッダーのYour Appを押し、次の画面でCreate an Appをクリックします。

次の画面ではFrom Scratchを押しましょう。

アプリ名とSlackのワークスペースをそれぞれ設定します。

Incoming Webhookの設定

アプリの作成ができたら、Incoming WebhookをONにします。

下のほうにあるAdd new Webhook to Workspaceをクリックし、投稿先のチャンネルを指定します。

連携ができたかどうか確認するために下記のコマンドをたたいてみましょう。

curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' ${webhook url}

Slackに通知が届いたので、ちゃんと接続ができているようです。

Edge Functionsの開発

次にEdge Functionsを開発しましょう。
適当なプロジェクトフォルダを作成します。

supabase init
supabase start

その後、functionの作成を行います。

supabase functions new slack-notify

ファイルの内容を編集します。

// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.

// Setup type definitions for built-in Supabase Runtime APIs
import "jsr:@supabase/functions-js/edge-runtime.d.ts";

console.log("Hello from Functions!");

const SLACK_WEBHOOK_URL = Deno.env.get("SLACK_WEBHOOK_URL") || "ローカルのt機はここにwebhookのURLを入れる";

Deno.serve(async (req) => {
  const payload = await req.json();
  const { record } = payload;

  // Slackに送信するメッセージを作成
  const message = {
    text:
      `新しい問い合わせが届きました:\n名前: ${record.name}\nメール: ${record.email}\n内容: ${record.message}`,
  };

  // Slack Incoming Webhookを使用して通知を送信
  const response = await fetch(SLACK_WEBHOOK_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(message),
  });

  if (response.ok) {
    return new Response(JSON.stringify({ success: true }), {
      headers: { "Content-Type": "application/json" },
      status: 200,
    });
  } else {
    return new Response(JSON.stringify({ success: false }), {
      headers: { "Content-Type": "application/json" },
      status: 500,
    });
  }
});

/* To invoke locally:

  1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start)
  2. Make an HTTP request:

  curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/slack-notify' \
    --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
    --header 'Content-Type: application/json' \
    --data '{"type":"INSERT","table":"inquiries","record":{"id":1,"name":"テスト太郎","email":"test@example.com","message":"これはテストメッセージです。"}}'

*/

functionをローカルで起動し、実際に動いているか下記で確認しましょう。

supabase functions serve

curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/slack-notify' \
    --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \
    --header 'Content-Type: application/json' \
    --data '{"type":"INSERT","table":"inquiries","record":{"id":1,"name":"テスト太郎","email":"test@example.com","message":"これはテストメッセージです。"}}'

通知が送られたらOKです。

デプロイ

Supabaseプロジェクトとリンクさせます。

supabase link --project-ref ${プロジェクトID}

WebhookのURLを環境変数として利用できるようにコマンドで送信します。

npx supabase secrets set SLACK_WEBHOOK_URL=${Slack Appから取得したWebhook URL}

デプロイします。

supabase functions deploy

Supabaseのトリガー設定

SQL Editorで下記を実行しましょう。

CREATE EXTENSION IF NOT EXISTS http WITH SCHEMA extensions;

CREATE OR REPLACE FUNCTION notify_new_contact()
RETURNS TRIGGER AS $$
DECLARE
  result json;
BEGIN
  SELECT status, content::json INTO result
  FROM http((
    'POST',
    'https://${プロジェクトID}.supabase.co/functions/v1/slack-notify',
    ARRAY[
      http_header('Authorization', 'Bearer ${anon key}'),
      http_header('Content-Type', 'application/json')
    ],
    'application/json',
    jsonb_build_object('record', row_to_json(NEW))::text
  )::http_request);
  
  -- レスポンスのログを記録(オプション)
  RAISE NOTICE 'HTTP Response: %', result;
  
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- トリガーの作成
CREATE TRIGGER new_contact_notification
AFTER INSERT ON contact
FOR EACH ROW
EXECUTE FUNCTION notify_new_contact();

通知の確認

ここまでで通知の仕組みは作成できました。

実際にcontactテーブルにデータが挿入されたときにSlackに通知が来るか確認してみましょう。

こんな感じで適当に入力して試してみます。

送信すると少したってSlackに通知が来ました!

参考資料

ローカルでのEdge Functioinsの作成方法:https://supabase.com/docs/guides/functions/quickstart

ローカル開発環境のデプロイ方法:https://supabase.com/docs/guides/functions/deploy

Slack APIのドキュメント:https://api.slack.com/docs

今回のgitリポジトリ:https://github.com/TodoONada/supabase-slack-notify

SupabaseのTIPSリンク集
  • システム開発、アプリ開発
  • マッチングアプリ開発
  • インフラ構築支援等、なんでもご相談ください。
よかったらシェアしてね!
  • URLをコピーしました!
目次